Commit 9e9909c6 authored by pengxiong's avatar pengxiong

init

parent 0483b2b5
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<content url="file://$MODULE_DIR$/../fund_report" />
<orderEntry type="jdk" jdkName="Python 3.7" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="tamp_course_order" />
......
......@@ -8,23 +8,25 @@
# -----------------------------------------------------------------------------
# import logging
import logging
import redis
import os
import sys
import yaml
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.pool import NullPool
env = sys.argv[-1]
env = sys.argv[-1] if sys.argv[-1] in ["dev", "test", "prod"] else "test"
work_dir = os.getcwd()
CFG_FILEPATH = work_dir + '/app/config/config.yaml'
template_folder = work_dir+'/app/templates'
config = yaml.load(open(CFG_FILEPATH, 'r'), Loader=yaml.FullLoader)
pdf_folder = os.path.join(work_dir,"app/pdf", config[env]['PDF']['pdf_folder'])
http_dir = config[env]['PDF']['http_dir']
temp_img_save_folder = work_dir + '/app/templates/temp_img/productionenv/ReportTempImg/'
pdf_save_folder = work_dir + '/app/pdf/productionenv/AppHoldReport/'
template_folder = config[env]['oss']['imgs_url_prefix']
pdf_folder = config[env]['oss']['pdf_url_prefix']
tamp_product_engine = create_engine(
'mysql+mysqldb://{user}:{password}@{host}:{port}/{db}?charset={charset}'.format(
......@@ -35,10 +37,7 @@ tamp_product_engine = create_engine(
password=config[env]['MySQL']['password'],
charset="utf8"
),
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=100, # 连接池大小
pool_timeout=5,
pool_recycle=600
poolclass=NullPool
)
tamp_order_engine = create_engine(
'mysql+mysqldb://{user}:{password}@{host}:{port}/{db}?charset={charset}'.format(
......@@ -49,10 +48,7 @@ tamp_order_engine = create_engine(
password=config[env]['MySQL']['password'],
charset="utf8"
),
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=100, # 连接池大小
pool_timeout=5,
pool_recycle=600
poolclass=NullPool
)
tamp_user_engine = create_engine(
......@@ -64,10 +60,7 @@ tamp_user_engine = create_engine(
password=config[env]['MySQL']['password'],
charset="utf8"
),
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=100, # 连接池大小
pool_timeout=5,
pool_recycle=600
poolclass=NullPool
)
tamp_fund_engine = create_engine(
......@@ -79,10 +72,7 @@ tamp_fund_engine = create_engine(
password=config[env]['MySQL']['password'],
charset="utf8"
),
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=100, # 连接池大小
pool_timeout=5,
pool_recycle=600
poolclass=NullPool
)
tamp_diagnose_app_engine = create_engine(
......@@ -93,7 +83,8 @@ tamp_diagnose_app_engine = create_engine(
user=config[env]['MySQL']['user'],
password=config[env]['MySQL']['password'],
charset="utf8"
)
),
poolclass=NullPool
)
......@@ -104,12 +95,17 @@ redis = redis.StrictRedis(
password=config[env]['redis']['password']
)
# logging.basicConfig(level=logging.INFO,
# filename=work_dir + config[env]['log']['filename'],
# filemode=config[env]['log']['filemode'],
# format=config[env]['log']['format'],
# datefmt=config[env]['log']['datefmt']
# )
redis_host=config[env]['redis']['host'],
redis_port=config[env]['redis']['port'],
redis_db=config[env]['redis']['db'],
redis_password=config[env]['redis']['password']
logging.basicConfig(level=logging.INFO,
filename=work_dir + config[env]['log']['filename'],
filemode=config[env]['log']['filemode'],
format=config[env]['log']['format'],
datefmt=config[env]['log']['datefmt']
)
class TAMP_SQL(object):
"""[sqlalchemy 封装]
......
......@@ -3,15 +3,20 @@ dev:
tamp_product_db: tamp_product
tamp_order_db: tamp_order
tamp_user_db: tamp_user
tamp_fund_db: tamp_fund
tamp_diagnose_app_db: tamp_diagnose_app
host: 47.101.189.151
port: 31931
user: root
password: mysql
user: dev
password: qimeng123
redis:
host: localhost
port: 6379
db: 0
password:
oss:
imgs_url_prefix: https://devtamper.tanpuyun.com/hangjiapc/report/productionenv/ReportTempImg/
pdf_url_prefix: https://devtamper.tanpuyun.com/hangjiapc/report/productionenv/AppHoldReport/
account: LTAI4FzkGhAMecinBCKwuoUW
password: KJpPWg9U0kYO71yB41gqYbrFNJ4hso
log:
......@@ -26,14 +31,21 @@ test:
tamp_product_db: tamp_product
tamp_order_db: tamp_order
tamp_user_db: tamp_user
host: tools.caixiaoquan.com
tamp_fund_db: tamp_fund
tamp_diagnose_app_db: tamp_diagnose_app
host: 118.190.63.109
# host: tools.caixiaoquan.com
port: 3306
user: root
password: '@imeng123'
redis:
host: localhost
port: 6379
host: 118.190.63.109
port: 56379
db: 0
password: 'qimeng123'
oss:
imgs_url_prefix: https://testtamper.tanpuyun.com/hangjiapc/report/productionenv/ReportTempImg/
pdf_url_prefix: https://testtamper.tanpuyun.com/hangjiapc/report/productionenv/AppHoldReport/
log:
filename: /logs/fund_report.log
filemode: a
......@@ -53,10 +65,13 @@ prod:
user: tamp_fund
password: '@imeng408'
redis:
host: localhost
host: r-uf6atruhdbq89enqz0.redis.rds.aliyuncs.com
port: 6379
db: 0
password: '@imeng123'
oss:
imgs_url_prefix: https://tamper.tanpuyun.com/hangjiapc/report/productionenv/ReportTempImg/
pdf_url_prefix: https://tamper.tanpuyun.com/hangjiapc/report/productionenv/AppHoldReport/
account: LTAI4FzkGhAMecinBCKwuoUW
password: KJpPWg9U0kYO71yB41gqYbrFNJ4hso
log:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -10,12 +10,13 @@ import datetime
import time
from flask_restful import Resource, reqparse
from flask import request, render_template
from flask import request, render_template, g
from flask import make_response
from app.api.engine import config
from app.utils.auth import login_require
from app.utils.html_to_pdf import html_to_pdf
from app.api.engine import pdf_folder, redis, env, TAMP_SQL, tamp_diagnose_app_engine, http_dir
from app.api.engine import pdf_folder, redis, env, TAMP_SQL, tamp_diagnose_app_engine
from app.utils.jinjia2html_v2 import DataIntegrate
......@@ -26,90 +27,18 @@ class ReportHandlers(Resource):
"""."""
self.parser = reqparse.RequestParser()
@login_require
def get(self):
"""."""
# self.parser.add_argument('ifa_id', type=str, required=True, help='ifa_id不能为空')
self.parser.add_argument('customer_id', type=str, required=True, help='customer_id不能为空')
args = self.parser.parse_args()
token = request.headers.get('Authorization', '')
token = 's:sid:' + token.split(' ')[1]
ifa_id = redis.get(token).decode()
if not ifa_id:
return {"code":40005,"data":None,"lang":"zh_CN","msg":"请登陆"}
if '\''in ifa_id:
ifa_id = ifa_id.replace('\'', '')
if '\"'in ifa_id:
ifa_id = ifa_id.replace('\"', '')
customer_id = args['customer_id']
pdf_name = str(ifa_id) + str(customer_id) + '.pdf'
with TAMP_SQL(tamp_diagnose_app_engine) as tamp_diagnose_app:
tamp_diagnose_app_session = tamp_diagnose_app.session
sql = "update hold_report set update_time='{}', update_status='{}' where ifa_id='{}' and customer_id='{}'".format(
datetime.datetime.now(),
1,
ifa_id,
customer_id
)
tamp_diagnose_app_session.execute(sql)
start = time.time()
check = 0
try:
dt = DataIntegrate(ifa_id=ifa_id, customer_id=customer_id, pdf_name=pdf_name)
dt.render_data()
check = 1
except OSError:
check = 1
except:
check = 0
print('耗时{}秒'.format(round(time.time() - start, 2)))
if check == 0:
with TAMP_SQL(tamp_diagnose_app_engine) as tamp_diagnose_app:
tamp_diagnose_app_session = tamp_diagnose_app.session
sql = "update hold_report set update_time='{}', update_status='{}' where ifa_id='{}' and customer_id='{}'".format(
datetime.datetime.now(),
0,
ifa_id,
customer_id
)
tamp_diagnose_app_session.execute(sql)
return {"code":-1, "msg": "内部错误"}
# auth = oss2.Auth(config[env]['oss']['account'], config[env]['oss']['password'])
# # Endpoint以杭州为例,其它Region请按实际情况填写。
# bucket = oss2.Bucket(auth, 'http://oss-cn-shanghai.aliyuncs.com', config[env]['oss']['env'])
# 生成下载文件的签名URL,有效时间为60s。
# path = bucket.sign_url('GET', config[env]['oss']['path'] + pdf_name, config[env]['oss']['validtime'])
with TAMP_SQL(tamp_diagnose_app_engine) as tamp_diagnose_app:
tamp_diagnose_app_session = tamp_diagnose_app.session
sql = "update hold_report set update_time='{}', update_status='{}', file='{}' where ifa_id='{}' and customer_id='{}'".format(
datetime.datetime.now(),
2,
pdf_name,
ifa_id,
customer_id
)
tamp_diagnose_app_session.execute(sql)
with TAMP_SQL(tamp_diagnose_app_engine) as tamp_diagnose_app:
tamp_diagnose_app_session = tamp_diagnose_app.session
sql = "SELECT id, file, customer_id, ifa_id, update_status, update_time from hold_report where ifa_id='{}' and customer_id='{}'".format(
ifa_id,
customer_id,
)
ret = tamp_diagnose_app_session.execute(sql).fetchone()
data = {"id":ret[0],"file": http_dir + ret[1],"customer_id":ret[2],
"ifa_id":ret[3],"update_status":ret[4],
"update_time":ret[5].strftime("%Y-%m-%d %H:%M:%S")}
ifa_id = g.ifa_id
# 默认模版制作持仓报告
resp = {
"code": 0,
"data": data,
"data": [],
"lang": "zh_CN",
"msg": "成功"
}
......
# coding: utf-8
import datetime
from sqlalchemy import Column, DECIMAL, Date, DateTime, Index, String, Table, Text, text
from sqlalchemy.dialects.mysql import BIGINT, INTEGER
from sqlalchemy.ext.declarative import declarative_base
from app.api.engine import TAMP_SQL, tamp_user_engine, tamp_diagnose_app_engine, pdf_folder
from app.model.base import Base
from app.model.base import BaseModel
class Customer(Base, BaseModel):
__tablename__ = 'customer'
id = Column(String(64), primary_key=True, comment='id')
customer_name = Column(String(64), index=True, comment='客户姓名')
name = Column(String(64))
valueSex = Column(INTEGER(11), comment='性别 -- 1.男 2.女')
valueBirth = Column(DateTime, comment='生日')
phone = Column(String(20), comment='手机')
email = Column(String(120), comment='邮箱')
landline = Column(String(20), comment='座机')
address = Column(String(120), comment='家庭地址')
fax = Column(String(20), comment='传真')
qq = Column(String(20))
wechat = Column(String(30), comment='微信号')
wechatNickName = Column(String(30), comment='微信昵称')
weibo = Column(String(30), comment='微博')
work = Column(String(50), comment='工作')
staff = Column(String(50), comment='职务')
school = Column(String(50), comment='毕业学校')
nativeplace = Column(String(30), comment='籍贯')
valueMarry = Column(INTEGER(11), comment='婚姻状况1.未婚 2.已婚 3.离异')
familyList = Column(String(500), comment='家庭成员')
favor = Column(String(100), comment='兴趣爱好')
concatTime = Column(String(30), comment='方便联系时间')
wealth = Column(String(30), comment='财产')
extra = Column(String(120))
total_assets = Column(DECIMAL(22, 6))
floating_earnings = Column(DECIMAL(22, 6))
create_by = Column(String(64))
create_time = Column(DateTime)
update_by = Column(String(64))
update_time = Column(DateTime)
delete_tag = Column(INTEGER(11))
member_since = Column(DateTime)
last_seen = Column(DateTime)
remark = Column(Text, comment='备注')
group_id = Column(INTEGER(11), index=True, comment='组id')
company_address = Column(String(200), comment='单位地址')
other_address = Column(String(200), comment='其他地址')
class CustomerAsset(Base, BaseModel):
__tablename__ = 'customer_assets'
id = Column(String(64), primary_key=True, nullable=False, comment='客户id')
total_market = Column(DECIMAL(22, 6), comment='总市值')
total_principal = Column(DECIMAL(22, 6), comment='总本金')
accumulated_earnings = Column(DECIMAL(22, 6), comment='累计收益')
floating_earnings_proportion = Column(DECIMAL(22, 6), comment='累计收益率')
delete_tag = Column(INTEGER(11))
ifa_id = Column(String(64), primary_key=True, nullable=False, comment='理财师id')
seven_profit_rate = Column(DECIMAL(22, 6), comment='最近7天收益率')
thirty_profit_rate = Column(DECIMAL(22, 6), comment='最近30天收益率')
ninety_profit_rate = Column(DECIMAL(22, 6), comment='最近90天收益率')
half_year_profit_rate = Column(DECIMAL(22, 6), comment='最近半年收益率')
year_profit_rate = Column(DECIMAL(22, 6), comment='今年收益率')
class FundReportManange(Base, BaseModel):
__tablename__ = 'fund_report_manange'
id = Column(String(64), primary_key=True, comment='id')
ifa_id = Column(String(64), comment='理财师id')
default_template = Column(Text, comment='默认模板')
custom_template = Column(Text, comment='自定义模版')
create_by = Column(String(64))
create_time = Column(DateTime)
update_by = Column(String(64))
update_time = Column(DateTime)
delete_tag = Column(INTEGER(2), server_default=text("'0'"))
name = Column(String(300), comment='模版名称')
type = Column(INTEGER(2), comment='模版类型1持仓报告2诊断报告')
default = Column(INTEGER(2), server_default=text("'0'"))
def to_dict(self, allow_field=None):
all_field = [r.name for r in self.__table__.columns]
if allow_field:
allow_field = set(allow_field) & set(allow_field)
else:
allow_field = all_field
data = {c: int(getattr(self, c).timestamp()) if isinstance(getattr(self, c), datetime.datetime) else getattr(self, c) for c in allow_field}
with TAMP_SQL(tamp_user_engine) as tamp_user:
tamp_user_session = tamp_user.session
sql = "select ui_username_mp from user_info where id = '{}'".format(self.ifa_id)
res = tamp_user_session.execute(sql)
if res:
data['author_name'] = res.fetchone()[0]
else:
data['author_name'] = ''
if self.default_template:
data['sys_default'] = 1
else:
data['sys_default'] = 0
return data
class Group(Base, BaseModel):
__tablename__ = 'group'
__table_args__ = (
Index('describe', 'describe', 'ifauser_id', unique=True),
)
id = Column(INTEGER(11), primary_key=True)
describe = Column(String(50))
createtime = Column(DateTime)
ifauser_id = Column(String(64))
class HoldReport(Base, BaseModel):
__tablename__ = 'hold_report'
id = Column(INTEGER(11), primary_key=True)
customer_id = Column(String(64))
ifa_id = Column(String(64))
update_time = Column(DateTime)
update_status = Column(INTEGER(11))
file = Column(String(128))
be_viewed = Column(INTEGER(2), comment='0未查看1已查看')
report_data = Column(Text)
name = Column(String(100))
create_time = Column(DateTime)
def to_dict(self, allow_field=None):
all_field = [r.name for r in self.__table__.columns]
if allow_field:
allow_field = set(allow_field) & set(allow_field)
else:
allow_field = all_field
file = ''
if self.file:
file = pdf_folder + self.file
data = {c: int(getattr(self, c).timestamp()) if isinstance(getattr(self, c), datetime.datetime) else getattr(self, c) for c in allow_field}
data['file'] = file
return data
class HoldDiagnoseReport(Base, BaseModel):
__tablename__ = 'hold_diagnose_report'
id = Column(INTEGER(11), primary_key=True)
customer_id = Column(String(64))
ifa_id = Column(String(64))
update_time = Column(DateTime)
update_status = Column(INTEGER(11))
file = Column(String(128))
be_viewed = Column(INTEGER(2), comment='0未查看1已查看')
report_data = Column(Text)
name = Column(String(100))
create_time = Column(DateTime)
def to_dict(self, allow_field=None):
all_field = [r.name for r in self.__table__.columns]
if allow_field:
allow_field = set(allow_field) & set(allow_field)
else:
allow_field = all_field
file = ''
if self.file:
file = pdf_folder + self.file
data = {c: int(getattr(self, c).timestamp()) if isinstance(getattr(self, c), datetime.datetime) else getattr(self, c) for c in allow_field}
data['file'] = file
return data
class PeriodicReport(Base, BaseModel):
__tablename__ = 'periodic_report'
id = Column(INTEGER(11), primary_key=True)
customer_id = Column(String(64))
ifa_id = Column(String(64))
update_time = Column(DateTime)
update_status = Column(INTEGER(11))
file = Column(String(128))
be_viewed = Column(INTEGER(2), comment='0未查看1已查看')
report_data = Column(Text)
name = Column(String(100))
create_time = Column(DateTime)
def to_dict(self, allow_field=None):
all_field = [r.name for r in self.__table__.columns]
if allow_field:
allow_field = set(allow_field) & set(allow_field)
else:
allow_field = all_field
file = ''
if self.file:
file = pdf_folder + self.file
data = {c: int(getattr(self, c).timestamp()) if isinstance(getattr(self, c), datetime.datetime) else getattr(self, c) for c in allow_field}
data['file'] = file
return data
class ReportView(Base, BaseModel):
__tablename__ = 'report_view'
id = Column(INTEGER(11), primary_key=True)
customer_id = Column(String(64))
ifa_id = Column(String(64))
update_time = Column(DateTime)
update_status = Column(INTEGER(11))
file = Column(String(128))
be_viewed = Column(INTEGER(2), comment='0未查看1已查看')
report_data = Column(Text)
name = Column(String(100))
customer_name = Column(String(100))
author_name = Column(String(100))
type = Column(INTEGER(2))
create_time = Column(DateTime)
def to_dict(self, allow_field=None):
all_field = [r.name for r in self.__table__.columns]
if allow_field:
allow_field = set(allow_field) & set(allow_field)
else:
allow_field = all_field
file = ''
if self.file:
file = pdf_folder + self.file
data = {c: int(getattr(self, c).timestamp()) if isinstance(getattr(self, c), datetime.datetime) else getattr(self, c) for c in allow_field}
data['file'] = file
return data
class IfaCustomer(Base, BaseModel):
__tablename__ = 'ifa_customer'
id = Column(String(64), primary_key=True)
customer_id = Column(String(64))
ifa_id = Column(String(64))
fund_count = Column(INTEGER(11))
revision = Column(INTEGER(11))
create_by = Column(String(64))
create_time = Column(DateTime)
update_by = Column(String(64))
update_time = Column(DateTime)
delete_tag = Column(INTEGER(11))
class IfaFundCollection(Base, BaseModel):
__tablename__ = 'ifa_fund_collection'
__table_args__ = (
Index('unique', 'fund_id', 'ifa_id', 'delete_tag'),
)
id = Column(INTEGER(11), primary_key=True, comment='id')
fund_id = Column(String(64))
ifa_id = Column(String(64))
create_time = Column(DateTime)
create_by = Column(String(255))
update_time = Column(DateTime)
update_by = Column(DateTime)
delete_tag = Column(INTEGER(4), server_default=text("'0'"))
type = Column(INTEGER(4))
class IfauserFund(Base, BaseModel):
__tablename__ = 'ifauser_fund'
id = Column(INTEGER(11), primary_key=True)
type = Column(INTEGER(11), index=True)
fund_id = Column(String(30), index=True)
fund_name = Column(String(30))
ifauser_id = Column(String(64))
customer_count = Column(INTEGER(11))
sum = Column(DECIMAL(22, 6))
class Operation(Base, BaseModel):
__tablename__ = 'operations'
id = Column(INTEGER(11), primary_key=True)
operator_id = Column(String(64), index=True)
describe = Column(Text)
timestamp = Column(DateTime, index=True)
ip = Column(Text)
class RelocateSuggestion(Base, BaseModel):
__tablename__ = 'relocate_suggestion'
id = Column(String(64), primary_key=True)
fund_id = Column(String(64))
substrategy = Column(INTEGER(11))
fund_name = Column(String(255))
percent = Column(DECIMAL(22, 6))
group_id = Column(String(255))
delete_tag = Column(INTEGER(11))
type = Column(INTEGER(11))
register_number = Column(String(20))
class RelocateSuggestionGroup(Base, BaseModel):
__tablename__ = 'relocate_suggestion_group'
id = Column(String(64), primary_key=True)
group_name = Column(String(255))
ifa_id = Column(String(255))
customer_id = Column(String(255))
create_time = Column(DateTime)
create_by = Column(String(255))
update_time = Column(DateTime)
update_by = Column(String(255))
delete_tag = Column(INTEGER(11))
class UserHoldFundAsset(Base, BaseModel):
__tablename__ = 'user_hold_fund_assets'
id = Column(String(64), primary_key=True)
reference_market = Column(DECIMAL(22, 6), comment='市值')
holding_net = Column(DECIMAL(22, 6), comment='累计收益率')
profit_or_loss = Column(DECIMAL(22, 6), comment='累计收益')
delete_tag = Column(INTEGER(11))
annual_profit_rate = Column(DECIMAL(22, 6), comment='年化收益率')
seven_profit = Column(DECIMAL(22, 6), comment='最近7天收益')
seven_profit_rate = Column(DECIMAL(22, 6), comment='最近7天收益率')
seven_annual_profit_rate = Column(DECIMAL(22, 6), comment='最近7天年化收益率')
thirty_profit = Column(DECIMAL(22, 6), comment='最近30天收益')
thirty_profit_rate = Column(DECIMAL(22, 6), comment='最近30天收益率')
thirty_annual_profit_rate = Column(DECIMAL(22, 6), comment='最近30天年化收益率')
ninety_profit = Column(DECIMAL(22, 6), comment='最近90天收益')
ninety_profit_rate = Column(DECIMAL(22, 6), comment='最近90天收益率')
ninety_annual_profit_rate = Column(DECIMAL(22, 6), comment='最近90天年化收益率')
half_year_profit = Column(DECIMAL(22, 6), comment='最近半年收益')
half_year_profit_rate = Column(DECIMAL(22, 6), comment='最近半年收益率')
half_year_annual_profit_rate = Column(DECIMAL(22, 6), comment='最近半年年化收益率')
year_profit = Column(DECIMAL(22, 6), comment='今年收益')
year_profit_rate = Column(DECIMAL(22, 6), comment='今年收益率')
year_annual_profit_rate = Column(DECIMAL(22, 6), comment='今年年化收益率')
class UserHoldFundFromApp(Base, BaseModel):
__tablename__ = 'user_hold_fund_from_app'
id = Column(String(64), primary_key=True)
type = Column(INTEGER(11), index=True, comment='0 公募 1 私募 2 优选')
fund_id = Column(String(64), index=True)
fund_name = Column(String(30))
customer_id = Column(String(64), index=True, comment='customer id')
subscription_fee = Column(DECIMAL(22, 6), comment='申购费')
nav = Column(DECIMAL(22, 6), comment='购买时候的净值')
create_by = Column(String(64))
create_time = Column(DateTime)
update_by = Column(String(64))
update_time = Column(DateTime)
delete_tag = Column(INTEGER(11))
confirm_amount = Column(DECIMAL(22, 6), comment='确认金额')
confirm_share = Column(DECIMAL(22, 6), comment='确认份额')
order_source = Column(INTEGER(11))
order_type = Column(INTEGER(1), comment='1、申购或追加 2、赎回 4 暂时其他')
remark = Column(String(255), comment='订单备注')
user_id = Column(String(64), index=True, server_default=text("''"), comment='ifa的id')
folio_name = Column(String(64), comment='组合名称,默认是default')
confirm_share_date = Column(Date, comment='确认份额日期')
pay_date = Column(Date, comment='订单支付时间')
......@@ -150,7 +150,7 @@
.box1 {
display: {{box1}};
position: relative;
padding: 150px 0 200px 36px;
padding: 100px 0 150px 36px;
}
.box1 .catalog_line {
......@@ -218,14 +218,6 @@
line-height: 56px;
color: #333333;
font-weight: bold;
text-align: baseline;
}
.page .page_title .page_time {
font-size: 16px;
line-height: 20px;
color: #333333;
font-weight: normal;
}
.page .page_head .page_logo {
......@@ -250,7 +242,7 @@
/* 投资总览 */
.box2{
display: {{box2}};
display: {{box2}}
}
.box2 .box2_content {
padding: 47px 34px 61px 34px;
......@@ -311,13 +303,6 @@
margin: 0 0 15px 0;
}
.tss2 .tss2_title .page_time {
font-size: 16px;
line-height: 20px;
color: #333333;
font-weight: normal;
}
.tss2 .tss2_content {
margin: 18px 0 0 0;
border: 1px solid #E4E4E4;
......@@ -481,7 +466,7 @@
}
.par .par_item .par_content.relative_chart table td {
padding: 14px 0 14px 0;
padding: 7px 0 7px 0;
text-align: center;
}
......@@ -633,7 +618,7 @@
}
.box4 .box4_content {
padding: 47px 34px 61px 34px;
/*page-break-after:always;*/
page-break-after:always;
}
/* 个基点评 */
......@@ -642,7 +627,7 @@
}
.box5 .box5_content {
padding: 47px 34px 61px 34px;
/*page-break-after:always;*/
page-break-after:always;
}
.geji_list_wrap .self_item {
......@@ -825,7 +810,7 @@
}
.box6 .box6_content {
padding: 47px 34px 61px 34px;
/*page-break-after:always;*/
page-break-after:always;
}
/* 新增基金 */
......@@ -834,7 +819,7 @@
}
.box7 .box7_content {
padding: 47px 34px 61px 34px;
/*page-break-after:always;*/
page-break-after:always;
}
/* 结尾 */
......@@ -949,17 +934,18 @@
<!-- 封面 -->
<div class="box0 clearfix">
<div class="cover_head dtable">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="cover_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="cover_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="cover_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="cover_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="cover_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="cover_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
<img src={{sh}} alt="" class="cover_back fr">
<div class="cover_title dtable">
......@@ -971,13 +957,18 @@
{{customer_name}}
</span>
<span class="cover_sir">
{%if valueSex == "1"%}
<span>先生</span>
{%endif%}
{%if valueSex == "2"%}
<span>女士</span>
{%endif%}
</span>
</div>
<img class="cover_img" src={{red_rect}} >
<div class="cover_title_text dcell">
资产<br>
存续报告
{{cover_title1}}<br>
{{cover_title2}}
<div class="cover_date">
<div class="cover_time">
{{year_month}}
......@@ -1002,22 +993,30 @@
</div>
</div>
<div class="catalog_item dcell">
<div class="catalog_li">
<div class="catalog_li" style="display: {{box2}}">
<div class="catalog_dot"></div>
<div class="catalog_name">投资总览</div>
</div>
<div class="catalog_li">
<div class="catalog_li" style="display: {{box3}}">
<div class="catalog_dot"></div>
<div class="catalog_name">目标与业绩</div>
</div>
<div class="catalog_li">
<div class="catalog_li" style="display: {{box4}}">
<div class="catalog_dot"></div>
<div class="catalog_name">业绩的明细</div>
</div>
<!-- <div class="catalog_li">-->
<!-- <div class="catalog_dot"></div>-->
<!-- <div class="catalog_name">优化建议</div>-->
<!-- </div>-->
<div class="catalog_li" style="display: {{box5}}">
<div class="catalog_dot"></div>
<div class="catalog_name">个基点评</div>
</div>
<div class="catalog_li" style="display: {{box6}}">
<div class="catalog_dot"></div>
<div class="catalog_name">优化组合建议</div>
</div>
<div class="catalog_li" style="display: {{box7}}">
<div class="catalog_dot"></div>
<div class="catalog_name">新增基金</div>
</div>
</div>
</div>
</div>
......@@ -1028,27 +1027,27 @@
<div class="box2" style="page-break-before:always;">
<div class="page dtable">
<div class="page_title dcell">
投资总览<span class="page_time">(最新净值日:{{latest_worth_day}})</span>
投资总览
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="box2_content">
<!-- 组合投资表现 -->
<div class="tss1" style="margin: 0;">
<div class="tss1" style="margin: 0;display: {{box2_section1}}">
<div class="tss1_title">
组合投资表现
</div>
......@@ -1110,7 +1109,7 @@
</div>
<!-- 资产盈亏情况 -->
<div class="tss1">
<div class="tss1" style="display: {{box2_section2}}">
<div class="tss1_title">
资产盈亏情况
</div>
......@@ -1142,7 +1141,7 @@
</div>
<!-- 组合月度及累计回报率曲线 -->
<div class="tss2">
<div class="tss2" style="display: {{box2_section3}}">
<div class="tss2_title">
组合月度及累计回报率曲线
</div>
......@@ -1152,7 +1151,7 @@
</div>
<!-- 组合月度及累计回报率曲线 -->
<div class="tss3">
<div class="tss3" style="display: {{box2_section4}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
月度收益
......@@ -1214,10 +1213,10 @@
<td>
盈亏
</td>
<td>
<td class="text_red">
{{value["1"]["profit"]}}
</td>
<td >
<td class="text_green">
{{value["2"]["profit"]}}
</td>
<td>
......@@ -1255,10 +1254,10 @@
<td>
期末资产
</td>
<td>
<td class="text_red">
{{value["1"]["net_amount"]}}
</td>
<td>
<td class="text_green">
{{value["2"]["net_amount"]}}
</td>
<td>
......@@ -1310,27 +1309,27 @@
{%else%}
目标与业绩({{folio}})
{%endif%}
<span class="page_time">(最新净值日:{{latest_worth_day}})</span>
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="box3_content">
<!-- 投资目标 -->
<div class="tss3" style="margin: 0;">
<div class="tss3" style="margin: 0;display: {{box3_section1}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
投资目标
......@@ -1355,21 +1354,21 @@
<th>目标最大回撤(%)</th>
</tr>
<tr>
<td>{{group_result["cost_of_investment"]}}</td>
<td>--</td>
<td>--</td>
<td>{{group_result["plan_cost_of_investment"]}}</td>
<td>{{group_result["target_annualised_return"]}}</td>
<td>{{group_result["target_max_withdrawal"]}}</td>
</tr>
</table>
</div>
<!-- 指标对比 -->
<div class="tss3">
<div class="tss3" style="display: {{box3_section2}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
指标对比<span class="tss3_start_time">(起始日期{{start_date}})</span>
</div>
<div class="tss3_now_time dcell">
最新净值日:{{latest_worth_day}}
截止日:最新净值日({{latest_worth_day}})
</div>
</div>
<table border="1">
......@@ -1407,7 +1406,7 @@
</div>
<!-- 收益比较、相关性分析 -->
<div class="par clearfix" cellpadding="38">
<div class="par clearfix" cellpadding="38" style="display: {{box3_section3}}">
<div class="par_item fl">
<div class="par_title">
收益比较
......@@ -1416,7 +1415,7 @@
<img src={{group_result["old_return_compare_pic"]}} alt="" class="par_img">
</div>
</div>
<div class="par_item fr">
<div class="par_item fr" style="display: {{box3_section4}}">
<div class="par_title">
相关性分析
</div>
......@@ -1538,30 +1537,31 @@
业绩的明细
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="box4_content">
<!-- 持仓收益汇总 -->
<div class="tss3" style="margin: 0;">
<div class="tss3" style="margin: 0;display: {{box4_section1}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
持仓收益汇总
</div>
<div class="tss3_now_time dcell">
最新净值日:({{latest_worth_day}})
截止日:最新净值日({{latest_worth_day}})
</div>
</div>
<div style="position: relative;">
......@@ -1621,13 +1621,13 @@
</div>
<!-- 基金净值 -->
<div class="tss3">
<div class="tss3" style="display: {{box4_section2}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
基金净值
</div>
<div class="tss3_now_time dcell">
最新净值日:({{latest_worth_day}})
截止日:最新净值日({{latest_worth_day}})
</div>
</div>
<table border="1">
......@@ -1669,28 +1669,28 @@
</div>
<!-- 贡献分解 -->
<div class="page dtable" style="page-break-before:always;">
<div class="page dtable" style="page-break-before:always;display: {{box4_section3}}">
<div class="page_title dcell">
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="tss2">
<div class="tss2_title clearfix">
<div class="tss2_title">
贡献分解
<span class="page_time">(最新净值日:{{latest_worth_day}})</span>
</div>
<div class="tss2_content">
<img src={{group_result["contribution_decomposition"]}} alt="" class="tss2_img">
......@@ -1700,7 +1700,7 @@
</div>
</div>
<!-- <div class="box_line"></div>-->
<div class="box_line"></div>
<!-- 个基点评 -->
<div class="box5">
......@@ -1709,17 +1709,18 @@
个基点评
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
......@@ -1731,17 +1732,18 @@
<div class="page_title dcell">
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
{% endif %}
......@@ -1790,17 +1792,18 @@
<div class="page_title dcell">
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
{% endif %}
......@@ -1824,7 +1827,7 @@
</div>
</div>
<!-- <div class="box_line"></div>-->
<div class="box_line"></div>
<!-- 优化组合建议 -->
<div class="box6">
......@@ -1833,24 +1836,25 @@
优化组合建议
</div>
<div class="page_head dcell">
<div class="dcell">
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="box6_content">
<!-- 调仓建议 -->
<div class="tss3" style="margin: 0;">
<div class="tss3" style="margin: 0;display: {{box6_section1}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
调仓建议
......@@ -1884,13 +1888,13 @@
</div>
<!-- 指标对比 -->
<div class="tss3">
<div class="tss3" style="display: {{box6_section2}}">
<div class="tss3_head dtable">
<div class="tss3_title dcell">
指标对比<span class="tss3_start_time">(起始日期2019-11-06</span>
指标对比<span class="tss3_start_time">(起始日期{{start_date}}</span>
</div>
<div class="tss3_now_time dcell">
最新净值日:{{latest_worth_day}}
截止日:最新净值日({{latest_worth_day}})
</div>
</div>
<table border="1">
......@@ -1929,21 +1933,22 @@
<div class="page_title dcell">
</div>
<div class="page_head dcell">
<div class="dcell">
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="par clearfix" cellpadding="38">
<div class="par_item fl">
<div class="par_item fl" style="display: {{box6_section3}}">
<div class="par_title">
收益比较
</div>
......@@ -1951,7 +1956,7 @@
<img src={{group_result["return_compare_pic"]}} alt="" class="par_img">
</div>
</div>
<div class="par_item fr">
<div class="par_item fr" style="display: {{box6_section4}}">
<div class="par_title">
相关性分析
</div>
......@@ -2064,7 +2069,7 @@
</div>
</div>
<!-- <div class="box_line"></div>-->
<div class="box_line"></div>
<!-- 新增基金 -->
<div class="box7">
......@@ -2073,17 +2078,18 @@
新增基金
</div>
<div class="page_head dcell">
<div class="dcell">
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
......@@ -2096,17 +2102,18 @@
<div class="page_title dcell">
</div>
<div class="page_head dcell">
<div class="dcell">
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="self_item">
......@@ -2152,19 +2159,22 @@
<div class="comment_tri"></div>
</div>
<div class="comment_content">
{% for item in group_result["new_group_evaluation"] %}
<div class="comment_item">
<div class="comment_dot"></div>
<div class="comment_text">
{{group_result["new_group_evaluation"]}}
{{item}}
</div>
</div>
</div>
{%endfor%}
</div>
</div>
</div>
</div>
<!-- <div class="box_line"></div>-->
<div class="box_line"></div>
{%endfor%}
<!-- 结尾 -->
<div class="box8">
......@@ -2173,17 +2183,18 @@
<div class="page_title dcell">
</div>
<div class="page_head dcell">
<!-- <div class="dcell">-->
<!-- <img src={{logo}} alt="" class="page_logo">-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_line"></div>-->
<!-- </div>-->
<!-- <div class="dcell">-->
<!-- <div class="page_text">-->
<!-- {{brand_name}}-->
<!-- </div>-->
<!-- </div>-->
<div class="dcell" style="display: {{logo_display}}">
<img src={{logo}} alt="" class="page_logo">
</div>
<div class="dcell" style="display: {{logo_display}}">
<div class="page_line"></div>
</div>
<div class="dcell" style="display: {{brand_name_display}}">
<div class="page_text">
{{brand_name}}<br>
工作室
</div>
</div>
</div>
</div>
<div class="box8_content">
......@@ -2193,7 +2204,7 @@
<div class="financial_scene">
<img src={{scene}} alt="" class="financial_scene_img">
<div class="financial_scene_text">
我们挣的是⻆度和变化的钱而不是纠正市场错误的钱,市场永远是正确的,关键是在其正确被反复证明后的逆向而行,一定是避开它的正确被展开的过程。
{{financial_text}}
</div>
<div class="financial_scene_author">
......@@ -2207,41 +2218,41 @@
</div> -->
</div>
<!-- <div class="statement_content">-->
<!-- <div class="statement_block">-->
<!-- <div class="statement_title">-->
<!-- 探普研究院声明-->
<!-- </div>-->
<!-- <div class="statement_p">-->
<!-- 本诊断报告所表述的任何观点均准确地反应了研究人员的看法;该研究人员所得报酬的任何组成部分无论是过去、现在、或者将来均不会直接或间接地与研究报告所表述的建议或观点相联系。-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="statement_block">-->
<!-- <div class="statement_title">-->
<!-- 一般性声明-->
<!-- </div>-->
<!-- <div class="statement_p">-->
<!-- 本报告对于收件人而言属于高度机密,只有收件人才能使用。本报告并非意图发送、发布给在-->
<!-- 当地法律或监管规则下不允许向其发送、发布该研究报告的人员。本研究报告仅供参考之用,在任何地区均不应被视为买卖任何证券、金融工具、基金、以及其他理财产品的要约或要约邀请。探普研究院并不因收件人收到本报告而视其为客户。本报告所包含的观点及建议并未考虑个别客户的特殊状况、目标或需要,不应视为对特定客户关于特定证券或金融工具、基金、以及其他理财产品的购买建议或策略。对于本报告中提及的任何证券、金融工具、基金、以及其他理财产品,本报告的-->
<!-- 收件人须保持自身的独立判断。-->
<!-- </div>-->
<!-- <div class="statement_p">-->
<!-- 本报告所载资料的来源被认为是可靠的,但探普研究院不保证其准确性或完整性,并不对使用本报告所包含的材料产生任何直接或间接损失或与此有关的其他损失承担任何责任。本报告提及的任何证券、金融工具、基金或其他理财产品均可能含有巨大的风险,可能不易变卖以及不适合所有的投资者。本报告所提及的证券、金融工具、基金或其他理财产品的价格、价值以及收益可能会受-->
<!-- 汇率影响而波动。过往的业绩也不能代表未来的表现。-->
<!-- </div>-->
<!-- <div class="statement_p">-->
<!-- 本报告所载的资料、观点以及预测分析均反映了探普研究院在最初报告发布日期当日的判断,可以在不发出通知的情况下做出更改、亦可因使用不同假设和标准、采用不同观点和分析方法而与市场上其他机构、部门、单位、个人在制作类似的其他材料时所给出的意见不同或者相反。探普研究院以及关联公司、单位并不承担提示本报告收件人注意该等材料的责任。负责撰写本报告研究人员薪酬并不基于任何金融产品的销售情况而定,但其薪酬可能会与我司的整体收入有关。-->
<!-- </div>-->
<!-- <div class="statement_p">-->
<!-- 若以探普研究院以外的机构或个人发送本报告,则由该机构或个人为此发送行为承担全部责任。该机构或个人应联系相关机构以交易本报告中提及的证券、金融工具、基金、其他理财产品获悉更详细信息。本报告不构成探普研究院向发送本报告的机构或个人的客户提供的投资建议,探普研究院以及关联单位、公司中的各个高级职员、董事、员工亦不为(前述机构或个人)因使用本报告或报告载明的内容产生的直接或间接损失承担任何责任。-->
<!-- </div>-->
<!-- </div>-->
<!-- <div class="statement_block">-->
<!-- <div class="statement_title2">-->
<!-- 未经探普研究院事先书面授权,任何人不得以任何目的复制、发送或者销售本报告。探普研究院 2020 版权所有,保留一切权利。-->
<!-- </div>-->
<!-- </div>-->
<!-- </div>-->
<div class="statement_content">
<div class="statement_block">
<div class="statement_title">
探普研究院声明
</div>
<div class="statement_p">
本诊断报告所表述的任何观点均准确地反应了研究人员的看法;该研究人员所得报酬的任何组成部分无论是过去、现在、或者将来均不会直接或间接地与研究报告所表述的建议或观点相联系。
</div>
</div>
<div class="statement_block">
<div class="statement_title">
一般性声明
</div>
<div class="statement_p">
本报告对于收件人而言属于高度机密,只有收件人才能使用。本报告并非意图发送、发布给在
当地法律或监管规则下不允许向其发送、发布该研究报告的人员。本研究报告仅供参考之用,在任何地区均不应被视为买卖任何证券、金融工具、基金、以及其他理财产品的要约或要约邀请。探普研究院并不因收件人收到本报告而视其为客户。本报告所包含的观点及建议并未考虑个别客户的特殊状况、目标或需要,不应视为对特定客户关于特定证券或金融工具、基金、以及其他理财产品的购买建议或策略。对于本报告中提及的任何证券、金融工具、基金、以及其他理财产品,本报告的
收件人须保持自身的独立判断。
</div>
<div class="statement_p">
本报告所载资料的来源被认为是可靠的,但探普研究院不保证其准确性或完整性,并不对使用本报告所包含的材料产生任何直接或间接损失或与此有关的其他损失承担任何责任。本报告提及的任何证券、金融工具、基金或其他理财产品均可能含有巨大的风险,可能不易变卖以及不适合所有的投资者。本报告所提及的证券、金融工具、基金或其他理财产品的价格、价值以及收益可能会受
汇率影响而波动。过往的业绩也不能代表未来的表现。
</div>
<div class="statement_p">
本报告所载的资料、观点以及预测分析均反映了探普研究院在最初报告发布日期当日的判断,可以在不发出通知的情况下做出更改、亦可因使用不同假设和标准、采用不同观点和分析方法而与市场上其他机构、部门、单位、个人在制作类似的其他材料时所给出的意见不同或者相反。探普研究院以及关联公司、单位并不承担提示本报告收件人注意该等材料的责任。负责撰写本报告研究人员薪酬并不基于任何金融产品的销售情况而定,但其薪酬可能会与我司的整体收入有关。
</div>
<div class="statement_p">
若以探普研究院以外的机构或个人发送本报告,则由该机构或个人为此发送行为承担全部责任。该机构或个人应联系相关机构以交易本报告中提及的证券、金融工具、基金、其他理财产品获悉更详细信息。本报告不构成探普研究院向发送本报告的机构或个人的客户提供的投资建议,探普研究院以及关联单位、公司中的各个高级职员、董事、员工亦不为(前述机构或个人)因使用本报告或报告载明的内容产生的直接或间接损失承担任何责任。
</div>
</div>
<div class="statement_block">
<div class="statement_title2">
未经探普研究院事先书面授权,任何人不得以任何目的复制、发送或者销售本报告。探普研究院 2020 版权所有,保留一切权利。
</div>
</div>
</div>
</div>
</div>
......
# -*- encoding: utf-8 -*-
# -----------------------------------------------------------------------------
# @File Name : auth.py
# @Time : 2021/1/15 下午4:54
# @Author : X. Peng
# @Email : acepengxiong@163.com
# @Software : PyCharm
# -----------------------------------------------------------------------------
from flask import request, g
from app.api.engine import redis
def login_require(func):
def auth(*args, **kwargs):
token = request.headers.get('Authorization', '')
token = 's:sid:' + token.split(' ')[1]
ifa_id = redis.get(token)
if not ifa_id:
return {"code": '9005', "message": "请登录", "attributes": []}
g.ifa_id = ifa_id.decode().replace('\"', '')
return func(*args, **kwargs)
return auth
\ No newline at end of file
import datetime
from celery import Celery
from sqlalchemy import and_, or_
from app.api.engine import TAMP_SQL, tamp_diagnose_app_engine, template_folder, redis_host, redis_port, redis_db, redis_password
from app.model.tamp_diagnose_app import HoldReport, HoldDiagnoseReport, PeriodicReport, Customer, ReportView
from app.utils.jinjia2html_v2 import DataIntegrate
celery_app = Celery(__name__)
celery_conf = "redis://:{}@{}:{}/{}".format(redis_password,redis_host[0],redis_port[0],"1")
celery_app.conf.update({"broker_url": celery_conf, "result_backend": celery_conf})
@celery_app.task
def save_pdf(id, ifa_id, customer_id, pdf_name, type, report_data):
"""
加法
:param x:
:param y:
:return:
"""
try:
dt = DataIntegrate(ifa_id=ifa_id, customer_id=customer_id, pdf_name=pdf_name, type=type)
dt.render_data(data=report_data)
except:
pass
with TAMP_SQL(tamp_diagnose_app_engine) as tamp_diagnose_app:
tamp_diagnose_session = tamp_diagnose_app.session
res = None
if type == 1:
res = tamp_diagnose_session.query(HoldReport).filter(and_(
HoldReport.id == id,
HoldReport.ifa_id == ifa_id,
))
elif type == 2:
res = tamp_diagnose_session.query(HoldDiagnoseReport).filter(and_(
HoldDiagnoseReport.id == id,
HoldDiagnoseReport.ifa_id == ifa_id,
))
elif type == 3:
res = tamp_diagnose_session.query(PeriodicReport).filter(and_(
PeriodicReport.id == id,
PeriodicReport.ifa_id == ifa_id,
))
else:
return False
if res.all():
res.update({
'file': pdf_name,
'update_status': 2,
'update_time': datetime.datetime.now()
})
return True
import json
import sys
import time
import uuid
from jinja2 import PackageLoader, Environment
from app.api.engine import work_dir, pdf_folder, template_folder
from app.api.engine import work_dir, pdf_folder, template_folder, pdf_save_folder
from app.config.default_template_params import hold_default_template, diagnose_default_template
from app.service.portfolio_diagnose import PortfolioDiagnose
from app.service.result_service_v2 import UserCustomerResultAdaptor
import numpy as np
......@@ -18,12 +21,14 @@ from app.utils.radar_chart import gen_radar_chart
class DataIntegrate:
def __init__(self, ifa_id='USER_INFO15914346866762', customer_id='202009281545001', pdf_name=str(uuid.uuid4()) + '.pdf'):
def __init__(self, ifa_id='USER_INFO15917850824287', customer_id='6716613802534121472', pdf_name=str(uuid.uuid4()) + '.pdf', type=1):
self.user_customer = UserCustomerResultAdaptor(ifa_id, customer_id)
self.customer_name = self.user_customer.customer_real_name
self.ifa_name = self.user_customer.ifa_real_name
# self.pdf_name = self.ifa_name + "_" + self.customer_name + "_" + '.pdf'
self.pdf_name = pdf_name
# 1持仓报告2诊断报告
self.type = type
# 全部数据
self.df = self.user_customer.calculate_total_data()
# 组合结果数据
......@@ -40,8 +45,6 @@ class DataIntegrate:
# 月度回报表格
self.get_month_table_return()
# # 渲染模版
# self.render_data()
# 分组和计算个基点评以及新增基金等结果
def get_group_result(self):
......@@ -54,8 +57,7 @@ class DataIntegrate:
'suggestions_result_asset': {},
'return_compare_pic': [],
'indicator_compare': [],
'new_group_evaluation': [],
"correlation": group_result["correlation"]
'new_group_evaluation': []
}
# 旧持仓组合点评
......@@ -65,24 +67,25 @@ class DataIntegrate:
# 目标与业绩
self.objectives_performance(group_result, cur_group_portfolio_result)
# 个基点评
# self.single_fund_comment(portfolio_diagnose, cur_group_portfolio_result)
self.single_fund_comment(portfolio_diagnose, cur_group_portfolio_result)
# 旧收益比较
self.get_old_compare_pic(cur_group_portfolio_result)
# 旧相关性
self.get_old_correlation(cur_group_portfolio_result)
# # 新增基金
# self.propose_fund(portfolio_diagnose, cur_group_portfolio_result)
# # 新收益比较
# self.get_transfer_suggestions(portfolio_diagnose, group_name, cur_group_portfolio_result)
# # 新相关性
# self.get_new_correlation(portfolio_diagnose, cur_group_portfolio_result)
self.get_old_correlation(portfolio_diagnose, cur_group_portfolio_result)
if self.type == 2:
# 新增基金
self.propose_fund(portfolio_diagnose, cur_group_portfolio_result)
# 新收益比较
self.get_transfer_suggestions(portfolio_diagnose, group_name, cur_group_portfolio_result)
# 新相关性
self.get_new_correlation(portfolio_diagnose, cur_group_portfolio_result)
self.all_folio_result[group_name] = cur_group_portfolio_result
def get_portfolio_diagnose(self, portfolio, client_type=1, invest_amount=10000000):
portfolio_diagnose = PortfolioDiagnose(client_type=client_type, portfolio=portfolio, invest_amount=float(invest_amount),
start_date=self.user_customer.start_date)
# portfolio_diagnose.optimize()
portfolio_diagnose.optimize()
return portfolio_diagnose
# 全部数据综述结果
......@@ -136,14 +139,6 @@ class DataIntegrate:
res.append(r)
for i in range(len(portfolio_evaluation)):
if portfolio_evaluation[i]['status'] == '保留':
portfolio_evaluation[i]['status'] = '<div class="self_type fl">保留</div>'
elif portfolio_evaluation[i]['status'] == '增仓':
portfolio_evaluation[i]['status'] = '<div class="self_type fl red">增仓</div>'
elif portfolio_evaluation[i]['status'] == '换仓':
portfolio_evaluation[i]['status'] = '<div class="self_type fl green">换仓</div>'
elif portfolio_evaluation[i]['status'] == '减仓':
portfolio_evaluation[i]['status'] = '<div class="self_type fl green">减仓</div>'
single_fund_data_list.append({
'fund_name': portfolio_evaluation[i]['name'],
'status': portfolio_evaluation[i]['status'],
......@@ -170,9 +165,9 @@ class DataIntegrate:
cur_group_portfolio_result["return_compare_data"]["origin_combination"],
cur_group_portfolio_result["return_compare_data"]["index"])
def get_old_correlation(self, cur_group_portfolio_result):
def get_old_correlation(self, portfolio_diagnose, cur_group_portfolio_result):
"""旧相关性分析."""
old_correlation = cur_group_portfolio_result["correlation"]
old_correlation = portfolio_diagnose.old_correlation
old_correlation_columns = old_correlation.columns.tolist()
old_correlation_values = old_correlation.values.tolist()
cur_group_portfolio_result["old_correlation"] = list(zip(range(1, len(old_correlation_columns)+1), old_correlation_columns, old_correlation_values))
......@@ -221,48 +216,27 @@ class DataIntegrate:
cur_group_portfolio_result["group_hoding_info"] = group_result["group_hoding_info"]
cur_group_portfolio_result["group_hoding_info_total"] = group_result["group_hoding_info_total"]
def render_data(self):
# 全部数据
data = {
# 封面 值为None不不显示,为block显示
'box0': 'block',
# 目录
'box1': 'block',
# 投资总览
'box2': 'block',
# 目标与业绩
'box3': 'block',
# 业绩的明细
'box4': 'block',
# 个基点评
'box5': None,
# 优化组合建议
'box6': None,
# 新增基金
'box7': None,
# 结尾
'box8': 'block',
'cover_back': template_folder + '/v2/img/cover-back.png',
'logo': template_folder + '/v2/img/logo.png',
'scene': template_folder + '/v2/img/scene.png',
'team': template_folder + '/v2/img/default-user.png',
'red_rect': template_folder + '/v2/img/red-rect.png',
'sh': template_folder + '/v2/img/sh.png',
def get_template_data(self, default_template=None):
""""""
if self.type == 1:
# 持仓报告数据
data = {
# 全局数据
'customer_name': self.customer_name,
'year_month': self.user_customer.end_date.strftime("%Y-%m-%d"),
'valueSex': self.user_customer.valueSex,
'month': self.user_customer.month_start_date.strftime("%m"),
'start_date': self.user_customer.start_date.strftime("%Y-%m-%d"),
'latest_worth_day': self.user_customer.last_nav_date,
'brand_name': '资产管<br>理中心',
'customer_old': 42,
'customer_level': '平衡型',
# 综述数据
'now_allocation_amount': '{:,}'.format(self.total_cost), 'now_yield': self.now_yield, 'index_yield': self.index_yield,
'now_allocation_amount': '{:,}'.format(self.total_cost), 'now_yield': self.now_yield,
'index_yield': self.index_yield,
'now_annualised_return': self.now_annualised_return,
'now_withdrawal': self.now_withdrawal, 'index_withdrawal': self.index_withdrawal, 'expected_withdrawal': 20,
'now_year_income': '{:,}'.format(self.now_year_income), 'now_month_income': '{:,}'.format(self.now_month_income),
'now_withdrawal': self.now_withdrawal, 'index_withdrawal': self.index_withdrawal,
'expected_withdrawal': 20,
'now_year_income': '{:,}'.format(self.now_year_income),
'now_month_income': '{:,}'.format(self.now_month_income),
'final_balance': '{:,}'.format(self.final_balance), 'total_profit': '{:,}'.format(self.total_profit),
'total_profit_temp': self.total_profit,
'now_year_income_temp': self.now_year_income, 'now_month_income_temp': self.now_month_income,
......@@ -274,50 +248,56 @@ class DataIntegrate:
# 组合数据
'all_folio_result': self.all_folio_result,
}
if default_template:
self.data = {**default_template, **data}
else:
self.data = {**hold_default_template, **data}
elif self.type == 2:
# 诊断报告数据
data = {
# 全局数据
'customer_name': self.customer_name,
'year_month': self.user_customer.month_start_date.strftime("%Y-%m-%d"),
'valueSex': self.user_customer.valueSex,
'month': self.user_customer.month_start_date.strftime("%m"),
'start_date': self.user_customer.start_date.strftime("%Y-%m-%d"),
'latest_worth_day': self.user_customer.last_nav_date,
'customer_level': '平衡型',
# 综述数据
'now_allocation_amount': '{:,}'.format(self.total_cost), 'now_yield': self.now_yield,
'index_yield': self.index_yield,
'now_annualised_return': self.now_annualised_return,
'now_withdrawal': self.now_withdrawal, 'index_withdrawal': self.index_withdrawal,
'expected_withdrawal': 20,
'now_year_income': '{:,}'.format(self.now_year_income),
'now_month_income': '{:,}'.format(self.now_month_income),
'final_balance': '{:,}'.format(self.final_balance), 'total_profit': '{:,}'.format(self.total_profit),
'total_profit_temp': self.total_profit,
'now_year_income_temp': self.now_year_income, 'now_month_income_temp': self.now_month_income,
'monthly_return_performance_pic': self.monthly_return_performance_pic,
'month_rise': self.month_rise, 'year_totoal_rate_of_return': self.year_totoal_rate_of_return,
'monthly_table_return': self.monthly_table_return,
# 组合数据
'all_folio_result': self.all_folio_result,
}
if default_template:
self.data = {**default_template, **data}
else:
self.data = {**hold_default_template, **data}
return self.data
# 'totoal_rate_of_return': self.totoal_rate_of_return,
# 'annualised_return': self.annualised_return, 'cost_of_investment': self.cost_of_investment,
#
#
# 'index_comparison': {'section_return': self.totoal_rate_of_return, 'annualized_returns': self.annualised_return,
# 'volatility': self.volatility, 'max_withdrawal': self.max_withdrawal,
# 'sharpe_ratio': self.sharpe_ratio},
# 'index_comparison_500': {'section_return': self.index_section_return,
# 'annualized_returns': self.index_annualised_return,
# 'volatility': self.index_volatility, 'max_withdrawal': self.index_max_withdrawal,
# 'sharpe_ratio': self.index_sharpe_ratio},
#
# 'group_nav_info': self.group_nav_info,
# 'group_hoding_info': self.group_hoding_info,
# 'group_hoding_info_total': self.group_hoding_info_total,
# 'old_evaluation': self.old_evaluation,
# 'old_indicator_compare': self.old_indicator_compare,
# 'contribution_decomposition': self.contribution_decomposition,
# 'single_fund_data_list': self.single_fund_data_list,
# 'old_correlation': self.old_correlation,
# 'old_return_compare_pic': self.old_return_compare_pic,
# # 'new_correlation': self.new_correlation,
# # 'propose_fund_data_list': self.propose_fund_data_list,
# # 'suggestions_result': self.suggestions_result,
# # 'suggestions_result_asset': self.suggestions_result_asset,
# # 'return_compare_pic': self.return_compare_pic,
# # 'indicator_compare': self.indicator_compare,
# # 'new_group_evaluation': self.new_group_evaluation
# 'new_correlation': [],
# 'propose_fund_data_list': [],
# 'suggestions_result': {},
# 'suggestions_result_asset': {},
# 'return_compare_pic': [],
# 'indicator_compare': [],
# 'new_group_evaluation': []
}
def render_data(self, data=None):
# 全部数据
if data:
self.data = data
# 开始渲染html模板
env = Environment(loader=PackageLoader('app', 'templates')) # 创建一个包加载器对象
# template = env.get_template('monthReport.html') # 获取一个模板文件
template = env.get_template('/v2/monthReportV2.1.html') # 获取一个模板文件
monthReport_html = template.render(data) # 渲染
monthReport_html = template.render(self.data).replace('None', 'none') # 渲染
# 保存 monthReport_html
# save_file = "app/html/monthReport.html"
# with open(save_file, 'w', encoding="utf-8") as f:
......@@ -326,11 +306,12 @@ class DataIntegrate:
# save_file = "app/html/v2/monthReportV2.html"
# with open(save_file, 'w', encoding="utf-8") as f:
# f.write(monthReport_html)
html_to_pdf(monthReport_html, pdf_folder + self.pdf_name)
html_to_pdf(monthReport_html, pdf_save_folder + self.pdf_name)
if __name__ == '__main__':
start = time.time()
dt = DataIntegrate(ifa_id='212498904817250304', customer_id='CUSTOMER16086497662396')
dt = DataIntegrate(ifa_id='USER_INFO15917850824287', customer_id='6716613802534121472', type=1)
data = dt.get_template_data()
dt.render_data()
print('耗时{}秒'.format(round(time.time()-start, 2)))
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment