首次提交
This commit is contained in:
140
.gitignore
vendored
Normal file
140
.gitignore
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
### Python template
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
photo_review/service/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
14
auto_generator.py
Normal file
14
auto_generator.py
Normal file
@@ -0,0 +1,14 @@
|
||||
# 自动生成数据库表和sqlalchemy对应的Model
|
||||
import subprocess
|
||||
|
||||
from config.mysql import DB_URL
|
||||
|
||||
table = input("请输入表名:")
|
||||
out_file = f"photo_review/entity/{table}.py"
|
||||
command = f"sqlacodegen {DB_URL} --outfile={out_file} --tables={table}"
|
||||
|
||||
try:
|
||||
subprocess.run(command, shell=True, check=True)
|
||||
print(f"{table}.py文件生成成功!请手动调整Base的声明!")
|
||||
except Exception as e:
|
||||
print(f"生成{table}.py文件时发生错误: {e}")
|
||||
41
config/log.py
Normal file
41
config/log.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# 配置字典
|
||||
LOGGING_CONFIG = {
|
||||
'version': 1, # 必需,指定配置格式的版本
|
||||
'disable_existing_loggers': False, # 是否禁用已经存在的logger实例
|
||||
|
||||
# formatters定义了不同格式的日志样式
|
||||
'formatters': {
|
||||
'standard': {
|
||||
'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s',
|
||||
'datefmt': '%Y-%m-%d %H:%M:%S',
|
||||
},
|
||||
},
|
||||
|
||||
# handlers定义了不同类型的日志处理器
|
||||
'handlers': {
|
||||
'console': {
|
||||
'class': 'logging.StreamHandler', # 控制台处理器
|
||||
'level': 'DEBUG',
|
||||
'formatter': 'standard',
|
||||
'stream': 'ext://sys.stdout', # 输出到标准输出,默认编码跟随系统,一般为UTF-8
|
||||
},
|
||||
'file': {
|
||||
'class': 'logging.handlers.RotatingFileHandler', # 文件处理器,支持日志滚动
|
||||
'level': 'INFO',
|
||||
'formatter': 'standard',
|
||||
'filename': 'log/fcb_photo_review.log', # 日志文件路径
|
||||
'maxBytes': 1024 * 1024 * 5, # 文件最大大小,这里为5MB
|
||||
'backupCount': 5, # 保留的备份文件数量
|
||||
'encoding': 'utf-8', # 显式指定文件编码为UTF-8以支持中文
|
||||
},
|
||||
},
|
||||
|
||||
# loggers定义了日志记录器,这里是根记录器
|
||||
'loggers': {
|
||||
'': { # 根记录器
|
||||
'handlers': ['console', 'file'], # 关联的处理器
|
||||
'level': 'DEBUG', # 根记录器的级别
|
||||
'propagate': False, # 是否向上级传播日志信息
|
||||
},
|
||||
},
|
||||
}
|
||||
23
config/mysql.py
Normal file
23
config/mysql.py
Normal file
@@ -0,0 +1,23 @@
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
# 数据库地址
|
||||
HOSTNAME = '192.168.5.226'
|
||||
# 端口号
|
||||
PORT = '3308'
|
||||
# 库名
|
||||
DATABASE = 'wzxtest'
|
||||
# 用户名
|
||||
USERNAME = 'root'
|
||||
# 密码
|
||||
PASSWORD = 'test9Root'
|
||||
# 把配置信息和以上的连接数据组合
|
||||
DB_URL = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}'
|
||||
|
||||
# 是否打印执行的sql
|
||||
SHOW_SQL = False
|
||||
|
||||
Engine = create_engine(DB_URL, echo=SHOW_SQL)
|
||||
Base = declarative_base(Engine)
|
||||
MysqlSession = sessionmaker(bind=Engine)
|
||||
11
main.py
Normal file
11
main.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import logging.config
|
||||
|
||||
from config.log import LOGGING_CONFIG
|
||||
from photo_review.photo_review import main
|
||||
|
||||
# 项目必须从此处启动,否则代码中的相对路径可能导致错误的发生
|
||||
if __name__ == '__main__':
|
||||
logging.config.dictConfig(LOGGING_CONFIG)
|
||||
log = logging.getLogger()
|
||||
log.info("照片审核开始")
|
||||
main()
|
||||
0
photo_review/__init__.py
Normal file
0
photo_review/__init__.py
Normal file
0
photo_review/entity/__init__.py
Normal file
0
photo_review/entity/__init__.py
Normal file
29
photo_review/entity/bd_yljg.py
Normal file
29
photo_review/entity/bd_yljg.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import Column, DateTime, String, text
|
||||
from sqlalchemy.dialects.mysql import INTEGER, TINYINT
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class BdYljg(Base):
|
||||
__tablename__ = 'bd_yljg'
|
||||
|
||||
pk_yljg = Column(INTEGER(11), primary_key=True, comment='医疗机构主键')
|
||||
code = Column(String(12), nullable=False, unique=True, comment='编码')
|
||||
name = Column(String(200), comment='名称')
|
||||
cpym = Column(String(40), comment='拼音码')
|
||||
pk_yldj = Column(INTEGER(11), comment='医疗机构等级')
|
||||
pk_father = Column(INTEGER(11), comment='上级医疗机构')
|
||||
address = Column(String(300), comment='地址')
|
||||
pk_region = Column(INTEGER(11), comment='行政区划主键')
|
||||
depiction = Column(String(100), comment='备注')
|
||||
creator = Column(String(20), comment='创建人')
|
||||
creationtime = Column(DateTime, server_default=text("CURRENT_TIMESTAMP"), comment='创建时间')
|
||||
modifier = Column(String(20), comment='最后修改人')
|
||||
modifiedtime = Column(DateTime, comment='最后修改时间')
|
||||
enablestate = Column(TINYINT(4), server_default=text("'1'"), comment='启用状态')
|
||||
create_by = Column(String(100), comment='创建人')
|
||||
create_time = Column(DateTime, server_default=text("CURRENT_TIMESTAMP"), comment='创建时间')
|
||||
update_by = Column(String(100), comment='更新人')
|
||||
update_time = Column(DateTime, comment='更新时间')
|
||||
del_flag = Column(TINYINT(1), server_default=text("'0'"), comment='删除标记')
|
||||
27
photo_review/entity/bd_ylks.py
Normal file
27
photo_review/entity/bd_ylks.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import CHAR, Column, DateTime, String, text
|
||||
from sqlalchemy.dialects.mysql import INTEGER, TINYINT
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class BdYlks(Base):
|
||||
__tablename__ = 'bd_ylks'
|
||||
|
||||
pk_ylks = Column(INTEGER(11), primary_key=True, comment='科室主键')
|
||||
code = Column(String(12), nullable=False, index=True, comment='编码')
|
||||
name = Column(String(200), comment='名称')
|
||||
cpym = Column(String(40), comment='拼音码')
|
||||
pk_father = Column(INTEGER(11))
|
||||
cIsBottom = Column(CHAR(1), comment='是否底层')
|
||||
depiction = Column(String(100), comment='备注')
|
||||
creator = Column(String(20), comment='创建人')
|
||||
creationtime = Column(DateTime, comment='创建时间')
|
||||
modifier = Column(String(20), comment='最后修改人')
|
||||
modifiedtime = Column(DateTime, comment='最后修改时间')
|
||||
enablestate = Column(TINYINT(4), server_default=text("'1'"), comment='启用状态')
|
||||
create_by = Column(String(100), comment='创建人')
|
||||
create_time = Column(DateTime, server_default=text("CURRENT_TIMESTAMP"), comment='创建时间')
|
||||
update_by = Column(String(100), comment='更新人')
|
||||
update_time = Column(DateTime, comment='更新时间')
|
||||
del_flag = Column(TINYINT(1), server_default=text("'0'"), comment='删除标记')
|
||||
23
photo_review/entity/zx_ie_cost.py
Normal file
23
photo_review/entity/zx_ie_cost.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import Column, DECIMAL, Date, DateTime, String
|
||||
from sqlalchemy.dialects.mysql import INTEGER
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class ZxIeCost(Base):
|
||||
__tablename__ = 'zx_ie_cost'
|
||||
|
||||
pk_ie_cost = Column(INTEGER(11), primary_key=True, comment='费用明细信息抽取主键')
|
||||
pk_phhd = Column(INTEGER(11), nullable=False, unique=True, comment='报销案子主键')
|
||||
name = Column(String(30), comment='患者姓名')
|
||||
admission_date_str = Column(String(255), comment='入院日期字符串')
|
||||
admission_date = Column(Date, comment='入院日期')
|
||||
discharge_date_str = Column(String(255), comment='出院日期字符串')
|
||||
discharge_date = Column(Date, comment='出院日期')
|
||||
medical_expenses_str = Column(String(255), comment='费用总额字符串')
|
||||
medical_expenses = Column(DECIMAL(18, 2), comment='费用总额')
|
||||
createtime = Column(DateTime, comment='创建时间')
|
||||
creator = Column(String(255), comment='创建人')
|
||||
modifiedtime = Column(DateTime, comment='修改时间')
|
||||
modifier = Column(String(255), comment='修改人')
|
||||
26
photo_review/entity/zx_ie_discharge.py
Normal file
26
photo_review/entity/zx_ie_discharge.py
Normal file
@@ -0,0 +1,26 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import Column, Date, DateTime, String
|
||||
from sqlalchemy.dialects.mysql import INTEGER
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class ZxIeDischarge(Base):
|
||||
__tablename__ = 'zx_ie_discharge'
|
||||
|
||||
pk_ie_discharge = Column(INTEGER(11), primary_key=True, comment='出院记录信息抽取主键')
|
||||
pk_phhd = Column(INTEGER(11), nullable=False, unique=True, comment='报销案子主键')
|
||||
hospital = Column(String(255), comment='医院')
|
||||
pk_yljg = Column(INTEGER(11), comment='医院主键')
|
||||
department = Column(String(255), comment='科别')
|
||||
pk_ylks = Column(INTEGER(11), comment='科别主键')
|
||||
name = Column(String(30), comment='患者姓名')
|
||||
admission_date_str = Column(String(255), comment='入院日期字符串')
|
||||
admission_date = Column(Date, comment='入院日期')
|
||||
discharge_date_str = Column(String(255), comment='出院日期字符串')
|
||||
discharge_date = Column(Date, comment='出院日期')
|
||||
doctor = Column(String(30), comment='主治医师')
|
||||
createtime = Column(DateTime, comment='创建时间')
|
||||
creator = Column(String(255), comment='创建人')
|
||||
modifiedtime = Column(DateTime, comment='修改时间')
|
||||
modifier = Column(String(255), comment='修改人')
|
||||
30
photo_review/entity/zx_ie_settlement.py
Normal file
30
photo_review/entity/zx_ie_settlement.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import Column, DECIMAL, Date, DateTime, String
|
||||
from sqlalchemy.dialects.mysql import INTEGER
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class ZxIeSettlement(Base):
|
||||
__tablename__ = 'zx_ie_settlement'
|
||||
|
||||
pk_ie_settlement = Column(INTEGER(11), primary_key=True, comment='结算清单信息抽取主键')
|
||||
pk_phhd = Column(INTEGER(11), nullable=False, unique=True, comment='报销案子主键')
|
||||
name = Column(String(30), comment='患者姓名')
|
||||
admission_date_str = Column(String(255), comment='入院日期字符串')
|
||||
admission_date = Column(Date, comment='入院日期')
|
||||
discharge_date_str = Column(String(255), comment='出院日期字符串')
|
||||
discharge_date = Column(Date, comment='出院日期')
|
||||
medical_expenses_str = Column(String(255), comment='费用总额字符串')
|
||||
medical_expenses = Column(DECIMAL(18, 2), comment='费用总额')
|
||||
personal_cash_payment_str = Column(String(255), comment='个人现金支付字符串')
|
||||
personal_cash_payment = Column(DECIMAL(18, 2), comment='个人现金支付')
|
||||
personal_account_payment_str = Column(String(255), comment='个人账户支付字符串')
|
||||
personal_account_payment = Column(DECIMAL(18, 2), comment='个人账户支付')
|
||||
personal_funded_amount_str = Column(String(255), comment='自费金额字符串')
|
||||
personal_funded_amount = Column(DECIMAL(18, 2), comment='自费金额')
|
||||
medical_insurance_type = Column(String(255), comment='医保类型')
|
||||
createtime = Column(DateTime, comment='创建时间')
|
||||
creator = Column(String(255), comment='创建人')
|
||||
modifiedtime = Column(DateTime, comment='修改时间')
|
||||
modifier = Column(String(255), comment='修改人')
|
||||
115
photo_review/entity/zx_phhd.py
Normal file
115
photo_review/entity/zx_phhd.py
Normal file
@@ -0,0 +1,115 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import Column, DECIMAL, Date, DateTime, Index, String, text
|
||||
from sqlalchemy.dialects.mysql import BIT, CHAR, INTEGER, TINYINT, VARCHAR
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class ZxPhhd(Base):
|
||||
__tablename__ = 'zx_phhd'
|
||||
__table_args__ = (
|
||||
Index('zx_phhd_idx7', 'pk_yljg', 'cjsd_id'),
|
||||
Index('zx_phhd_idx5', 'cStatus', 'checker', 'checktime')
|
||||
)
|
||||
|
||||
pk_phhd = Column(INTEGER(11), primary_key=True, comment='病案主键')
|
||||
cPhhd_id = Column(VARCHAR(20), unique=True, comment='拍一拍单据号')
|
||||
billdate = Column(DateTime, index=True)
|
||||
pk_person = Column(INTEGER(11), server_default=text("'0'"), comment='人员主键')
|
||||
pk_corp = Column(INTEGER(11), index=True, server_default=text("'0'"), comment='单位主键')
|
||||
cRyid = Column(VARCHAR(20), comment='人员编码')
|
||||
cJBH = Column(VARCHAR(20), comment='结报号')
|
||||
cXm = Column(String(12), comment='姓名')
|
||||
cSfzh = Column(VARCHAR(20), index=True, comment='身份证号')
|
||||
czh = Column(VARCHAR(20), comment='小组')
|
||||
cXb = Column(VARCHAR(2), comment='性别')
|
||||
dCsny = Column(Date, comment='出身时间')
|
||||
fAge = Column(INTEGER(4), server_default=text("'0'"), comment='年龄')
|
||||
pk_yljg = Column(INTEGER(11), server_default=text("'0'"), comment='医院pk')
|
||||
pk_ylks = Column(INTEGER(11), server_default=text("'0'"), comment='科室pk')
|
||||
cDoctor = Column(VARCHAR(20), comment='医生')
|
||||
dZYRQ = Column(DateTime, comment='入院日期')
|
||||
dCYRQ = Column(DateTime)
|
||||
cZYH = Column(VARCHAR(20), comment='住院号')
|
||||
iMZTS = Column(INTEGER(4), server_default=text("'0'"), comment='住院天数')
|
||||
fFSYLFY = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='发生医疗费用')
|
||||
fZcfwfy = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='政策范围内费用')
|
||||
fxnhbcje = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='新农合补助金额')
|
||||
fqtbcje = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='其它补助金额')
|
||||
fBCJE = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='补偿金额')
|
||||
fgrzfje1 = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='个人支付金额1')
|
||||
fgezfje2 = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='个人支付金额2')
|
||||
fgrzfje = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='个人自费金额')
|
||||
fZfje = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='自付金额')
|
||||
fXianje = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='限额')
|
||||
fMaxbcje = Column(DECIMAL(18, 2), server_default=text("'0.00'"), comment='最高支付')
|
||||
cJBBM = Column(VARCHAR(20), server_default=text("'-'"), comment='疾病编码')
|
||||
cJbbm_cyzd = Column(VARCHAR(20), comment='疾病编码出院诊断')
|
||||
cSsczmc = Column(VARCHAR(100), comment='手术操作名称')
|
||||
problem_note = Column(String(400))
|
||||
depiction = Column(VARCHAR(300), comment='备注')
|
||||
creator = Column(VARCHAR(30), index=True, comment='创建人')
|
||||
creationtime = Column(DateTime, index=True, server_default=text("CURRENT_TIMESTAMP"), comment='创建时间')
|
||||
modifier = Column(VARCHAR(30), comment='最后修改人')
|
||||
modifiedtime = Column(DateTime, server_default=text("CURRENT_TIMESTAMP"), comment='最后修改时间')
|
||||
cStatus = Column(CHAR(1), server_default=text("'0'"), comment='状态')
|
||||
vercode = Column(VARCHAR(4), comment='版本编码')
|
||||
cSource_flag = Column(VARCHAR(4), server_default=text("'1'"), comment='病案来源')
|
||||
ref_id1 = Column(VARCHAR(20))
|
||||
ref_id2 = Column(VARCHAR(20))
|
||||
ref_pk1 = Column(INTEGER(11))
|
||||
checker = Column(VARCHAR(30), comment='创建人')
|
||||
checktime = Column(DateTime, comment='创建时间')
|
||||
paint_user = Column(VARCHAR(30))
|
||||
paint_date = Column(DateTime)
|
||||
filetype_id = Column(VARCHAR(10), comment='文件类型id')
|
||||
cMphone = Column(VARCHAR(11), comment='移动电话')
|
||||
cmiss_rectype = Column(VARCHAR(10), comment='遗漏记录类型')
|
||||
cmiss_remark = Column(VARCHAR(200), comment='遗漏备注 ')
|
||||
bhg_remark = Column(VARCHAR(200), comment='不合格原因')
|
||||
cmis_jsd_flag = Column(BIT(1))
|
||||
cmis_jsd_page = Column(VARCHAR(40), comment='结算单遗漏页码')
|
||||
cmis_cyjl_flag = Column(BIT(1))
|
||||
cmis_cyjl_page = Column(VARCHAR(40), comment='出院记录遗漏页码')
|
||||
cmis_fyqd_flag = Column(BIT(1))
|
||||
cmis_fyqd_page = Column(VARCHAR(40), comment='费用清单遗漏页码')
|
||||
cmis_evidence = Column(VARCHAR(60), comment='相关证明材料')
|
||||
del_reason = Column(CHAR(1), server_default=text("'0'"), comment='删除原因')
|
||||
deln_reason = Column(VARCHAR(2), comment='删除原因')
|
||||
train_flag = Column(VARCHAR(10), server_default=text("'0'"), comment='培训标志')
|
||||
cjsd_id = Column(VARCHAR(30), comment='结算单号码')
|
||||
sms_content = Column(String(1000), comment='短信内容')
|
||||
judge_backup = Column(VARCHAR(100))
|
||||
remind_num = Column(INTEGER(11), server_default=text("'0'"), comment='提醒次数')
|
||||
input_cxm = Column(String(20), comment='姓名核对')
|
||||
yb_type = Column(VARCHAR(10), comment='医保类别')
|
||||
bucode = Column(VARCHAR(4), server_default=text("'1'"), comment='业务单元')
|
||||
subcorpname = Column(VARCHAR(80), comment='子公司')
|
||||
deptname = Column(VARCHAR(80), comment='部门')
|
||||
psncode = Column(VARCHAR(16), comment='工号')
|
||||
period_code = Column(VARCHAR(10), comment='会计期间')
|
||||
cbznote = Column(VARCHAR(500))
|
||||
corp_list = Column(VARCHAR(200), comment='其它补助单位及年度')
|
||||
perjudge_flag = Column(CHAR(1), server_default=text("'0'"), comment='人员信息判断标志')
|
||||
priority_num = Column(TINYINT(4), server_default=text("'0'"), comment='优先领取')
|
||||
addin_xybz = Column(BIT(1))
|
||||
addin_tybz = Column(BIT(1))
|
||||
finish_flag = Column(BIT(1))
|
||||
exsuccess_flag = Column(BIT(1))
|
||||
pk_soncorp = Column(INTEGER(11), server_default=text("'0'"), comment='镇下村单位pk值')
|
||||
return_times = Column(INTEGER(11), server_default=text("'0'"), comment='退回次数')
|
||||
phuser_type = Column(CHAR(1), server_default=text("'1'"), comment='拍传人类型(1-自拍,2代拍,3管理员代拍)')
|
||||
examine_note = Column(VARCHAR(400), comment='抽查意见')
|
||||
examine_user = Column(VARCHAR(30), comment='抽查人')
|
||||
examine_date = Column(DateTime, comment='抽查时间')
|
||||
channel_code = Column(VARCHAR(10), comment='上传渠道')
|
||||
einvoice_flag = Column(BIT(1))
|
||||
drgs_flag = Column(CHAR(1), server_default=text("'0'"), comment='病种类型(0-无,1-单病种,2-drg)')
|
||||
applyDate = Column(DateTime)
|
||||
admissionDate = Column(Date, comment='入院日期')
|
||||
dischargeDate = Column(Date, comment='出院日期')
|
||||
reapplyDate = Column(Date, comment='重新上传日期')
|
||||
exreq_times = Column(INTEGER(11), server_default=text("'0'"), comment='请求次数')
|
||||
drug_source = Column(CHAR(1), server_default=text("'0'"), comment='药品来源(1-外购药,0--没有)')
|
||||
addin_passpaydate = Column(BIT(1))
|
||||
apply_classid = Column(CHAR(1), server_default=text("'0'"), comment='申请人员类别(1-农民工,0-默认)')
|
||||
46
photo_review/entity/zx_phrec.py
Normal file
46
photo_review/entity/zx_phrec.py
Normal file
@@ -0,0 +1,46 @@
|
||||
# coding: utf-8
|
||||
from sqlalchemy import CHAR, Column, DateTime, LargeBinary, String, text
|
||||
from sqlalchemy.dialects.mysql import BIT, INTEGER, TINYINT
|
||||
|
||||
from config.mysql import Base
|
||||
|
||||
|
||||
class ZxPhrec(Base):
|
||||
__tablename__ = 'zx_phrec'
|
||||
|
||||
pk_phrec = Column(INTEGER(11), primary_key=True, comment='病案清主键')
|
||||
pk_phhd = Column(INTEGER(11), index=True, comment='病案主键')
|
||||
cRectype = Column(CHAR(1), comment='记录类型(1-入院小结,2--出院小结,3--手术记录 4清单)')
|
||||
rowno = Column(TINYINT(4), server_default=text("'1'"), comment='序号')
|
||||
cfjaddress = Column(String(200), comment='附件地址')
|
||||
cfjaddress2 = Column(String(500), comment='附件地址2')
|
||||
cfjaddress3 = Column(String(500), comment='附件地址3')
|
||||
cfjblob = Column(LargeBinary, comment='附件')
|
||||
cfjblob2 = Column(LargeBinary, comment='附件2')
|
||||
cfjblob3 = Column(LargeBinary, comment='附件3')
|
||||
subsys_id = Column(String(4), comment='分系统代码')
|
||||
depiction = Column(String(100), comment='备注')
|
||||
isreupload = Column(CHAR(1), server_default=text("'0'"))
|
||||
checker = Column(String(10), comment='创建人')
|
||||
checktime = Column(DateTime, comment='创建时间')
|
||||
creator = Column(String(30), comment='创建人')
|
||||
creationtime = Column(DateTime, index=True, comment='创建时间')
|
||||
modifier = Column(String(30), comment='最后修改人')
|
||||
modifiedtime = Column(DateTime, comment='最后修改时间')
|
||||
cSource_flag = Column(String(4), server_default=text("'1'"), comment='病案来源')
|
||||
cStatus = Column(CHAR(1), server_default=text("'0'"), comment='状态')
|
||||
link_flag = Column(CHAR(1), server_default=text("'1'"), comment='是否采用链接')
|
||||
filetype_id = Column(String(10), server_default=text("'jpg'"), comment='文件类型id')
|
||||
cmiss_flag = Column(INTEGER(4), server_default=text("'0'"), comment='遗漏补拍标记')
|
||||
paint_flag = Column(CHAR(1), server_default=text("'0'"), comment='涂抹标志')
|
||||
paint_user = Column(String(30))
|
||||
paint_date = Column(DateTime)
|
||||
byz_xmbz_flag = Column(BIT(1))
|
||||
byz_zyrqcyjl_flag = Column(BIT(1))
|
||||
byz_zyhcyjl_flag = Column(BIT(1))
|
||||
byz_ftyccyjl_flag = Column(BIT(1))
|
||||
byz_ftycfyqd_flag = Column(BIT(1))
|
||||
byz_ftycjsd_flag = Column(BIT(1))
|
||||
unsharp_flag = Column(BIT(1))
|
||||
judge_backup = Column(String(40))
|
||||
ps_flag = Column(CHAR(1), server_default=text("'0'"), comment='图片是否ps过(0-无,1-ps过)')
|
||||
197
photo_review/photo_review.py
Normal file
197
photo_review/photo_review.py
Normal file
@@ -0,0 +1,197 @@
|
||||
from time import sleep
|
||||
|
||||
from paddlenlp import Taskflow
|
||||
|
||||
from config.mysql import MysqlSession
|
||||
from photo_review.entity.bd_yljg import BdYljg
|
||||
from photo_review.entity.bd_ylks import BdYlks
|
||||
from photo_review.entity.zx_ie_cost import ZxIeCost
|
||||
from photo_review.entity.zx_ie_discharge import ZxIeDischarge
|
||||
from photo_review.entity.zx_ie_settlement import ZxIeSettlement
|
||||
from photo_review.entity.zx_phhd import ZxPhhd
|
||||
from photo_review.entity.zx_phrec import ZxPhrec
|
||||
from photo_review.util.data_util import handle_date, handle_decimal
|
||||
from photo_review.util.ucloud import get_private_url
|
||||
|
||||
|
||||
# 关键信息提取
|
||||
def information_extraction(schema, pictures, task_path):
|
||||
results = {}
|
||||
for picture in pictures:
|
||||
pic_path = get_private_url(picture)
|
||||
if pic_path:
|
||||
ie = Taskflow("information_extraction", schema=schema, model="uie-x-base", task_path=task_path)
|
||||
result = ie({"doc": pic_path})
|
||||
results.update(result[0])
|
||||
return results
|
||||
|
||||
|
||||
# 从keys中获取第一个不为空的value
|
||||
def get_value_in_keys(source, keys):
|
||||
for key in keys:
|
||||
value = source.get(key)
|
||||
if value:
|
||||
value = value[0].get("text")
|
||||
if value:
|
||||
return value
|
||||
return None
|
||||
|
||||
|
||||
# 从keys中获取所有value组成list
|
||||
def get_values_of_keys(source, keys):
|
||||
result = []
|
||||
for key in keys:
|
||||
value = source.get(key)
|
||||
if value:
|
||||
value = value[0].get("text")
|
||||
if value:
|
||||
result.append(value)
|
||||
return result
|
||||
|
||||
|
||||
def save_or_update_ie(table, pk_phhd, data):
|
||||
data = {k: v for k, v in data.items() if v is not None and v != ""}
|
||||
obj = table(**data)
|
||||
session = MysqlSession()
|
||||
db_data = session.query(table).filter_by(pk_phhd=pk_phhd).one_or_none()
|
||||
if db_data:
|
||||
for k, v in data.items():
|
||||
setattr(db_data, k, v)
|
||||
else:
|
||||
session.add(obj)
|
||||
session.commit()
|
||||
session.close()
|
||||
|
||||
|
||||
def photo_review(pk_phhd):
|
||||
settlement_list = []
|
||||
discharge_record = []
|
||||
cost_list = []
|
||||
|
||||
session = MysqlSession()
|
||||
phrecs = session.query(ZxPhrec.pk_phrec, ZxPhrec.cRectype, ZxPhrec.cfjaddress) \
|
||||
.filter(ZxPhrec.pk_phhd == pk_phhd) \
|
||||
.all()
|
||||
session.close()
|
||||
for phrec in phrecs:
|
||||
if phrec.cRectype == "1":
|
||||
settlement_list.append(phrec.cfjaddress)
|
||||
elif phrec.cRectype == "3":
|
||||
discharge_record.append(phrec.cfjaddress)
|
||||
elif phrec.cRectype == "4":
|
||||
cost_list.append(phrec.cfjaddress)
|
||||
|
||||
name_key = ["姓名", "交款人"]
|
||||
admission_date_key = ["入院日期", "住院时间", "开始日期", "费用发生时间", "入院时间", "住院日期"]
|
||||
discharge_date_key = ["出院日期", "结束日期", "出院时间"]
|
||||
medical_expenses_key = ["费用总额", "总费用", "医疗费用总额", "总计", "合计", "金额合计", "总金额", "本次住院费用总金额", "价税合计",
|
||||
"合计金额", "费用合计", "项目合计"]
|
||||
personal_cash_payment_key = ["个人现金支付", "个人支付金额", "个人现金支出", "现金支付", "实际现金", "个人负担总金额", "本次现金",
|
||||
"医院收取病人金额", "个人付现", "个人现金", "自费金额"]
|
||||
personal_account_payment_key = ["个人账户支付", "账户支付", "个人账户支出", "个账支付", "账户支出"]
|
||||
personal_funded_amount_key = ["自费", "全自费金额", "个人自费", "范围外费用", "超限价自费费用", "目录外自费", "自费总额", "自费费用"]
|
||||
medical_insurance_type_key = ["医保类型"]
|
||||
hospital_key = ["医院", "就诊医院", "医院名称", "医学中心"]
|
||||
department_key = ["科别", "病人科室", "住院科别", "科室", "住院科室", "科室名称"]
|
||||
doctor_key = ["主治医师", "住院医师", "医师", "主治及以上医师签名", "主治医生签名", "医生签名", "主治医师签名", "医师签名", "上级医师",
|
||||
"主诊医师", "经治医师", "副主任中医师号"]
|
||||
|
||||
# 基本医保结算单
|
||||
settlement_list_schema = \
|
||||
name_key + admission_date_key + discharge_date_key + medical_expenses_key + personal_cash_payment_key \
|
||||
+ personal_account_payment_key + personal_funded_amount_key + medical_insurance_type_key
|
||||
# 出院记录
|
||||
discharge_record_schema = \
|
||||
hospital_key + department_key + name_key + admission_date_key + discharge_date_key + doctor_key
|
||||
# 费用清单
|
||||
cost_list_schema = name_key + admission_date_key + discharge_date_key + medical_expenses_key
|
||||
|
||||
settlement_list_ie_result = information_extraction(settlement_list_schema, settlement_list,
|
||||
"config/model/settlement_list_model")
|
||||
settlement_data = {
|
||||
"pk_phhd": pk_phhd,
|
||||
"name": get_value_in_keys(settlement_list_ie_result, name_key),
|
||||
"admission_date_str": get_value_in_keys(settlement_list_ie_result, admission_date_key),
|
||||
"discharge_date_str": get_value_in_keys(settlement_list_ie_result, discharge_date_key),
|
||||
"medical_expenses_str": get_value_in_keys(settlement_list_ie_result, medical_expenses_key),
|
||||
"personal_cash_payment_str": get_value_in_keys(settlement_list_ie_result, personal_cash_payment_key),
|
||||
"personal_account_payment_str": get_value_in_keys(settlement_list_ie_result, personal_account_payment_key),
|
||||
"personal_funded_amount_str": get_value_in_keys(settlement_list_ie_result, personal_funded_amount_key),
|
||||
"medical_insurance_type": get_value_in_keys(settlement_list_ie_result, medical_insurance_type_key)
|
||||
}
|
||||
settlement_data["admission_date"] = handle_date(settlement_data["admission_date_str"])
|
||||
settlement_data["admission_date"] = handle_date(settlement_data["admission_date_str"])
|
||||
settlement_data["discharge_date"] = handle_date(settlement_data["discharge_date_str"])
|
||||
settlement_data["medical_expenses"] = handle_decimal(settlement_data["medical_expenses_str"])
|
||||
settlement_data["personal_cash_payment"] = handle_decimal(settlement_data["personal_cash_payment_str"])
|
||||
settlement_data["personal_account_payment"] = handle_decimal(settlement_data["personal_account_payment_str"])
|
||||
settlement_data["personal_funded_amount"] = handle_decimal(settlement_data["personal_funded_amount_str"])
|
||||
save_or_update_ie(ZxIeSettlement, pk_phhd, settlement_data)
|
||||
|
||||
discharge_record_ie_result = information_extraction(discharge_record_schema, discharge_record,
|
||||
"config/model/discharge_record_model")
|
||||
discharge_data = {
|
||||
"pk_phhd": pk_phhd,
|
||||
"hospital": get_value_in_keys(discharge_record_ie_result, hospital_key),
|
||||
"department": get_value_in_keys(discharge_record_ie_result, department_key),
|
||||
"name": get_value_in_keys(discharge_record_ie_result, name_key),
|
||||
"admission_date_str": get_value_in_keys(discharge_record_ie_result, admission_date_key),
|
||||
"discharge_date_str": get_value_in_keys(discharge_record_ie_result, discharge_date_key),
|
||||
"doctor": get_value_in_keys(discharge_record_ie_result, doctor_key)
|
||||
}
|
||||
discharge_data["admission_date"] = handle_date(discharge_data["admission_date_str"])
|
||||
discharge_data["discharge_date"] = handle_date(discharge_data["discharge_date_str"])
|
||||
hospital_value = get_values_of_keys(discharge_record_ie_result, hospital_key)
|
||||
if hospital_value:
|
||||
session = MysqlSession()
|
||||
yljg = session.query(BdYljg.pk_yljg, BdYljg.name) \
|
||||
.filter(BdYljg.name.in_(hospital_value)).limit(1).one_or_none()
|
||||
session.close()
|
||||
if yljg:
|
||||
discharge_data["pk_yljg"] = yljg.pk_yljg
|
||||
discharge_data["hospital"] = yljg.name
|
||||
department_value = get_values_of_keys(discharge_record_ie_result, department_key)
|
||||
if department_value:
|
||||
session = MysqlSession()
|
||||
ylks = session.query(BdYlks.pk_ylks, BdYlks.name) \
|
||||
.filter(BdYlks.name.in_(department_value)).limit(1).one_or_none()
|
||||
session.close()
|
||||
if ylks:
|
||||
discharge_data["pk_ylks"] = ylks.pk_ylks
|
||||
discharge_data["department"] = ylks.name
|
||||
save_or_update_ie(ZxIeDischarge, pk_phhd, discharge_data)
|
||||
|
||||
cost_list_ie_result = information_extraction(cost_list_schema, cost_list, "config/model/cost_list_model")
|
||||
cost_data = {
|
||||
"pk_phhd": pk_phhd,
|
||||
"name": get_value_in_keys(cost_list_ie_result, name_key),
|
||||
"admission_date_str": get_value_in_keys(cost_list_ie_result, admission_date_key),
|
||||
"discharge_date_str": get_value_in_keys(cost_list_ie_result, discharge_date_key),
|
||||
"medical_expenses_str": get_value_in_keys(cost_list_ie_result, medical_expenses_key)
|
||||
}
|
||||
cost_data["admission_date"] = handle_date(cost_data["admission_date_str"])
|
||||
cost_data["discharge_date"] = handle_date(cost_data["discharge_date_str"])
|
||||
cost_data["medical_expenses"] = handle_date(cost_data["medical_expenses_str"])
|
||||
save_or_update_ie(ZxIeCost, pk_phhd, cost_data)
|
||||
|
||||
|
||||
def main():
|
||||
# 最后处理的报销案子pk
|
||||
last_pk_phhd = 0
|
||||
# 持续检测新案子
|
||||
while 1:
|
||||
session = MysqlSession()
|
||||
phhds = session.query(ZxPhhd.pk_phhd) \
|
||||
.filter(ZxPhhd.pk_phhd > last_pk_phhd) \
|
||||
.filter(ZxPhhd.cStatus == '2') \
|
||||
.limit(1) \
|
||||
.all()
|
||||
session.close()
|
||||
if phhds:
|
||||
for phhd in phhds:
|
||||
pk_phhd = phhd.pk_phhd
|
||||
photo_review(pk_phhd)
|
||||
last_pk_phhd = pk_phhd
|
||||
else:
|
||||
# 没有查询到新案子,等待 5 分钟后再查
|
||||
sleep(5 * 60)
|
||||
0
photo_review/util/__init__.py
Normal file
0
photo_review/util/__init__.py
Normal file
50
photo_review/util/data_util.py
Normal file
50
photo_review/util/data_util.py
Normal file
@@ -0,0 +1,50 @@
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
# 处理金额类数据
|
||||
def handle_decimal(string):
|
||||
if not string:
|
||||
return ""
|
||||
return re.sub(r'[^0-9.]', '', string)
|
||||
|
||||
|
||||
# 处理日期类数据
|
||||
def handle_date(string):
|
||||
if not string:
|
||||
return ""
|
||||
|
||||
string = string.replace("年", "-").replace("月", "-").replace("日", "")
|
||||
string = re.sub(r'[^0-9-]', '', string)
|
||||
if is_valid_date_format(string):
|
||||
return string
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
# 判断是否是合法的日期格式
|
||||
def is_valid_date_format(date_str):
|
||||
if len(date_str) < 6:
|
||||
return False
|
||||
|
||||
# 定义可能的日期格式
|
||||
formats = [
|
||||
# yyyy-MM-dd
|
||||
'%Y-%m-%d',
|
||||
# yy-MM-dd
|
||||
'%y-%m-%d',
|
||||
# yyyyMMdd
|
||||
'%Y%m%d',
|
||||
# yyMMdd
|
||||
'%y%m%d',
|
||||
]
|
||||
|
||||
# 遍历所有格式,尝试解析日期
|
||||
for fmt in formats:
|
||||
try:
|
||||
datetime.strptime(date_str, fmt)
|
||||
return True
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
return False
|
||||
27
photo_review/util/ucloud.py
Normal file
27
photo_review/util/ucloud.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# https://github.com/ucloud/ufile-sdk-python
|
||||
import logging
|
||||
|
||||
from ufile import filemanager
|
||||
|
||||
public_key = "4Z7QYI7qml36QRjcCjKrls7aHl1R6H6uq"
|
||||
private_key = "FIdW1Kev1Ge3K7GHXzSLyGG1wTnaG6LE9BxmIVubcCaG"
|
||||
bucket = "drg100"
|
||||
upload_suffix = ".cn-sh2.ufileos.com"
|
||||
download_suffix = ".cn-sh2.ufileos.com"
|
||||
|
||||
|
||||
def get_private_url(key):
|
||||
get_ufile_handler = filemanager.FileManager(public_key, private_key, upload_suffix, download_suffix)
|
||||
|
||||
# 判断文件是否存在
|
||||
_, resp = get_ufile_handler.head_file(bucket, key)
|
||||
if resp.status_code != 200:
|
||||
logging.warning("uCloud中未找到(%s)! status: %d error: %s", key, resp.status_code, resp.error)
|
||||
return None
|
||||
|
||||
# 获取公有空间下载url
|
||||
# url = get_ufile_handler.public_download_url(bucket, key)
|
||||
|
||||
# 获取私有空间下载url, expires为下载链接有效期,单位为秒
|
||||
url = get_ufile_handler.private_download_url(bucket, key, expires=60)
|
||||
return url
|
||||
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
paddlenlp==2.6.1
|
||||
sqlacodegen==2.3.0.post1
|
||||
ufile==3.2.9
|
||||
BIN
test/visual_model_test/img/PH20240401000003_3_001938_2.jpg
Normal file
BIN
test/visual_model_test/img/PH20240401000003_3_001938_2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 MiB |
BIN
test/visual_model_test/img/PH20240511000638_1_094306_1.jpg
Normal file
BIN
test/visual_model_test/img/PH20240511000638_1_094306_1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
BIN
test/visual_model_test/img/PH20240511000648_4_094542_2.jpg
Normal file
BIN
test/visual_model_test/img/PH20240511000648_4_094542_2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.9 MiB |
67
test/visual_model_test/visual_model_test.py
Normal file
67
test/visual_model_test/visual_model_test.py
Normal file
@@ -0,0 +1,67 @@
|
||||
# 可视化的模型对比测试
|
||||
import re
|
||||
import time
|
||||
from pprint import pprint
|
||||
|
||||
from paddlenlp import Taskflow
|
||||
from paddlenlp.utils.doc_parser import DocParser
|
||||
|
||||
|
||||
def visual_model_test(task_path, test_img, schema):
|
||||
img = re.split(r'[\\/]', test_img)[-1]
|
||||
img_name = ""
|
||||
img_type = "jpg"
|
||||
last_dot_index = img.rfind(".")
|
||||
if last_dot_index != -1:
|
||||
img_name = img[:last_dot_index]
|
||||
img_type = img[last_dot_index + 1:]
|
||||
|
||||
# 默认模型
|
||||
ie = Taskflow("information_extraction", schema=schema, model="uie-x-base")
|
||||
results = ie({"doc": test_img})
|
||||
pprint(results[0])
|
||||
DocParser.write_image_with_results(
|
||||
test_img,
|
||||
result=results[0],
|
||||
save_path="./img_result/" + img_name + "_default." + img_type)
|
||||
# 自己训练的模型
|
||||
my_ie = Taskflow("information_extraction", schema=schema, model="uie-x-base", task_path=task_path)
|
||||
my_results = my_ie({"doc": test_img})
|
||||
pprint(my_results[0])
|
||||
DocParser.write_image_with_results(
|
||||
test_img,
|
||||
result=my_results[0],
|
||||
save_path="./img_result/" + img_name + "_my." + img_type)
|
||||
|
||||
|
||||
def main(model_type):
|
||||
# 开始时间
|
||||
start_time = time.time()
|
||||
|
||||
# 结算清单
|
||||
if model_type == "settlement":
|
||||
task_path = "../../config/model/settlement_list_model"
|
||||
test_img_path = "img/PH20240511000638_1_094306_1.jpg"
|
||||
schema = ["姓名", "入院日期", "出院日期", "费用总额", "个人现金支付", "个人账户支付", "自费", "医保类型"]
|
||||
elif model_type == "discharge":
|
||||
task_path = "../../config/model/discharge_record_model"
|
||||
test_img_path = "img/PH20240401000003_3_001938_2.jpg"
|
||||
schema = ["医院", "科别", "姓名", "入院日期", "出院日期", "主治医生"]
|
||||
elif model_type == "cost":
|
||||
task_path = "../../config/model/cost_list_model"
|
||||
test_img_path = "img/PH20240511000648_4_094542_2.jpg"
|
||||
schema = ["姓名", "入院日期", "出院日期", "费用总额"]
|
||||
else:
|
||||
print("请输入正确的类型!")
|
||||
return
|
||||
visual_model_test(task_path, test_img_path, schema)
|
||||
|
||||
# 结束时间
|
||||
end_time = time.time()
|
||||
pprint(f"处理时长:{end_time - start_time}秒")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main("settlement")
|
||||
# main("discharge")
|
||||
# main("cost")
|
||||
Reference in New Issue
Block a user