This commit is contained in:
parent
0110be4b16
commit
f30b837212
|
|
@ -1,4 +0,0 @@
|
||||||
[settings]
|
|
||||||
order_by_type = true
|
|
||||||
multi_line_output = 3
|
|
||||||
indent = " "
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"python.languageServer": "None"
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
认证器
|
认证器模块
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
|
|
||||||
259
票据理赔自动化/case.py
259
票据理赔自动化/case.py
|
|
@ -1,10 +1,13 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""通用模块"""
|
"""通用模块"""
|
||||||
|
|
||||||
from typing import Any, Dict, List
|
|
||||||
from decimal import Decimal, ROUND_HALF_UP
|
from decimal import Decimal, ROUND_HALF_UP
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
from datetime import datetime
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
import pandas
|
import pandas
|
||||||
|
|
||||||
from common import masterdata, rules_engine
|
from common import masterdata, rules_engine
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -28,17 +31,75 @@ def case_adjust(dossier: Dict[str, Any]) -> None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# 赔案理算记录
|
# 赔案理算记录
|
||||||
adjustments = (
|
receipts_adjustments = (
|
||||||
pandas.DataFrame(data=dossier["receipts_layer"]).assing(
|
(
|
||||||
adjustments=lambda dataframe: dataframe.apply(
|
pandas.DataFrame(data=dossier["receipts_layer"]).assign(
|
||||||
lambda row: receipt_adjust(
|
receipt_adjustments=lambda dataframe: dataframe.apply(
|
||||||
row=row, liabilities=dossier["liabilities_layer"]
|
lambda row: receipt_adjust(
|
||||||
),
|
row=row, liabilities=dossier["liabilities_layer"]
|
||||||
axis="columns",
|
),
|
||||||
) # 票据理算
|
axis="columns",
|
||||||
|
) # 票据理算
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.explode(column="receipt_adjustments", ignore_index=True)
|
||||||
|
.pipe(
|
||||||
|
lambda dataframe: pandas.concat(
|
||||||
|
[
|
||||||
|
dataframe.drop(
|
||||||
|
[
|
||||||
|
"receipt_adjustments",
|
||||||
|
],
|
||||||
|
axis="columns",
|
||||||
|
),
|
||||||
|
pandas.json_normalize(dataframe["receipt_adjustments"]),
|
||||||
|
],
|
||||||
|
axis="columns",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
dossier["receipts_layer"] = receipts_adjustments.to_dict(orient="records")
|
||||||
|
|
||||||
|
print(dossier["receipts_layer"])
|
||||||
|
|
||||||
|
# 赔案理算金额
|
||||||
|
dossier["adjustment_layer"].update(
|
||||||
|
{
|
||||||
|
"adjustment_amount": (
|
||||||
|
receipts_adjustments["adjustment_amount"]
|
||||||
|
.sum()
|
||||||
|
.quantize(
|
||||||
|
Decimal("0.00"),
|
||||||
|
rounding=ROUND_HALF_UP,
|
||||||
|
)
|
||||||
|
), # 理算金额
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# 实例化JINJA2
|
||||||
|
environment = Environment(
|
||||||
|
loader=FileSystemLoader(file_path := Path(__file__).parent)
|
||||||
|
)
|
||||||
|
# 添加过滤器
|
||||||
|
environment.filters["DateTime"] = lambda i: (
|
||||||
|
i.strftime("%Y-%m-%d") if i != datetime(9999, 12, 31) else "长期"
|
||||||
|
)
|
||||||
|
# 加载赔案档案模版
|
||||||
|
template = environment.get_template("template.html")
|
||||||
|
|
||||||
|
with open(
|
||||||
|
file_path / f"dossiers/{dossier["report_layer"]["case_number"]}.html",
|
||||||
|
"w",
|
||||||
|
encoding="utf-8",
|
||||||
|
) as file:
|
||||||
|
file.write(
|
||||||
|
template.render(
|
||||||
|
{
|
||||||
|
"dossier": dossier,
|
||||||
|
}
|
||||||
|
)
|
||||||
)
|
)
|
||||||
).explode("adjustments", ignore_index=True)
|
|
||||||
print(adjustments)
|
|
||||||
|
|
||||||
|
|
||||||
def receipt_adjust(
|
def receipt_adjust(
|
||||||
|
|
@ -46,72 +107,140 @@ def receipt_adjust(
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
理算票据
|
理算票据
|
||||||
:param row: 一张票据数据
|
:param row: 票据数据
|
||||||
:param liabilities: 理算责任
|
:param liabilities: 理算责任
|
||||||
:return: 理算记录
|
:return: 理算记录
|
||||||
"""
|
"""
|
||||||
# 初始化票据理算记录
|
# 初始化票据理算记录
|
||||||
adjustments = []
|
receipt_adjustments = []
|
||||||
# 初始化剩余个人自费金额
|
|
||||||
remaining_personal_self_payment = row["personal_self_payment"]
|
|
||||||
# 初始化剩余个人自付金额
|
|
||||||
remaining_non_medical_payment = row["non_medical_payment"]
|
|
||||||
# 初始化剩余合理金额
|
|
||||||
remaining_reasonable_amount = row["reasonable_amount"]
|
|
||||||
|
|
||||||
# 出险事故
|
# 初始化票据剩余可理算金额
|
||||||
accident = row["accident"]
|
remaining_adjustable_amount = (
|
||||||
# 出险人
|
row["personal_self_payment"]
|
||||||
accident_person = row["payer"]
|
+ row["non_medical_payment"]
|
||||||
# 出险日期
|
+ row["reasonable_amount"]
|
||||||
accident_date = row["date"]
|
).quantize( # type: ignore[reportAttributeAccessIssue]
|
||||||
|
Decimal("0.00"),
|
||||||
|
rounding=ROUND_HALF_UP,
|
||||||
|
)
|
||||||
|
|
||||||
# 查验状态
|
# 遍历所有理赔责任,根据出险人、出险事故、查验状态和出险日期匹配理赔责任
|
||||||
verification = row["verification"]
|
|
||||||
|
|
||||||
# 初始化理赔责任理算金额
|
|
||||||
adjustment_amount = Decimal("0.00")
|
|
||||||
# 初始化理赔责任理赔金额
|
|
||||||
claim_amount = Decimal("0.00")
|
|
||||||
|
|
||||||
# 遍历所有理赔责任,根据出险事故、出险人、出险日期和查验状态匹配责任
|
|
||||||
for liability in liabilities:
|
for liability in liabilities:
|
||||||
if (
|
if (
|
||||||
accident == liability["accident"]
|
row["payer"] in [liability["insured_person"] for liability in liabilities]
|
||||||
and accident_person == liability["insured_person"]
|
and row["accident"] == liability["accident"]
|
||||||
|
and row["verification"] in ["真票", "无法查验"]
|
||||||
and liability["commencement_date"]
|
and liability["commencement_date"]
|
||||||
<= accident_date
|
<= row["date"]
|
||||||
<= liability["termination_date"]
|
<= liability["termination_date"]
|
||||||
and verification == "真票"
|
|
||||||
):
|
):
|
||||||
# 理赔责任理算金额
|
# 个单余额
|
||||||
adjustment_amount = (
|
|
||||||
row["personal_self_payment"]
|
|
||||||
* liability["personal_self_ratio"] # 个人自费金额
|
|
||||||
+ row["non_medical_payment"]
|
|
||||||
* liability["non_medical_ratio"] # 个人自付金额
|
|
||||||
+ row["reasonable_amount"] * liability["reasonable_ratio"] # 合理金额
|
|
||||||
).quantize(
|
|
||||||
Decimal("0.00"),
|
|
||||||
rounding=ROUND_HALF_UP,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 据变动保单唯一标识查询最新一条保额变动记录的变动后金额(理赔责任的理赔保单余额)
|
|
||||||
remaining_amount = masterdata.query_remaining_amount(
|
remaining_amount = masterdata.query_remaining_amount(
|
||||||
policy_guid=liability["policy_guid"],
|
person_policy_guid=liability["person_policy_guid"],
|
||||||
)
|
|
||||||
# 理赔责任理赔金额
|
|
||||||
claim_amount = min(
|
|
||||||
remaining_amount,
|
|
||||||
adjustment_amount,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 初始化票据理算记录
|
# 个人自费可理算金额
|
||||||
adjustment = {
|
personal_self_adjustable_amount = (
|
||||||
"liability": liability["liability"], # 理赔责任名称
|
row["personal_self_payment"]
|
||||||
"type": row["就诊类型"],
|
* liability["personal_self_ratio"]
|
||||||
"amount": row["合理金额"],
|
* Decimal("0.01")
|
||||||
"payable": 0.0,
|
)
|
||||||
|
# 个人自付可理算金额
|
||||||
|
non_medical_adjustable_amount = (
|
||||||
|
row["non_medical_payment"]
|
||||||
|
* liability["non_medical_ratio"]
|
||||||
|
* Decimal("0.01")
|
||||||
|
)
|
||||||
|
# 合理可理算金额
|
||||||
|
reasonable_adjustable_amount = (
|
||||||
|
row["reasonable_amount"]
|
||||||
|
* liability["reasonable_ratio"]
|
||||||
|
* Decimal("0.01")
|
||||||
|
)
|
||||||
|
|
||||||
|
# 理算金额
|
||||||
|
adjustment_amount = max(
|
||||||
|
Decimal("0.00"),
|
||||||
|
min(
|
||||||
|
remaining_adjustable_amount,
|
||||||
|
remaining_amount,
|
||||||
|
adjustable_amount := (
|
||||||
|
(
|
||||||
|
personal_self_adjustable_amount
|
||||||
|
+ non_medical_adjustable_amount
|
||||||
|
+ reasonable_adjustable_amount
|
||||||
|
).quantize(
|
||||||
|
Decimal("0.00"),
|
||||||
|
rounding=ROUND_HALF_UP,
|
||||||
|
)
|
||||||
|
), # 可理算金额
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# 若理算金额大于0则新增保额扣减记录
|
||||||
|
if adjustment_amount > Decimal("0.00"):
|
||||||
|
masterdata.add_coverage_change(
|
||||||
|
person_policy_guid=liability["person_policy_guid"],
|
||||||
|
before_change_amount=remaining_amount,
|
||||||
|
change_amount=adjustment_amount,
|
||||||
|
)
|
||||||
|
|
||||||
|
receipt_adjustments.append(
|
||||||
|
{
|
||||||
|
"person_policy": liability["person_policy"], # 个单号
|
||||||
|
"liability": liability["liability"], # 理赔责任名称
|
||||||
|
"personal_self_payment": row[
|
||||||
|
"personal_self_payment"
|
||||||
|
], # 个人自费金额
|
||||||
|
"personal_self_ratio": liability[
|
||||||
|
"personal_self_ratio"
|
||||||
|
], # 个人自费比例
|
||||||
|
"personal_self_adjustable_amount": personal_self_adjustable_amount, # 个人自费可理算金额
|
||||||
|
"non_medical_payment": row["non_medical_payment"], # 个人自付金额
|
||||||
|
"non_medical_ratio": liability["non_medical_ratio"], # 个人自付比例
|
||||||
|
"non_medical_adjustable_amount": non_medical_adjustable_amount, # 个人自付可理算金额
|
||||||
|
"reasonable_amount": row["reasonable_amount"], # 合理可理算金额
|
||||||
|
"reasonable_ratio": liability["reasonable_ratio"], # 合理部分比例
|
||||||
|
"reasonable_adjustable_amount": reasonable_adjustable_amount, # 合理可理算金额
|
||||||
|
"adjustment_amount": adjustment_amount, # 理算金额
|
||||||
|
"adjustment_explanation": f"""
|
||||||
|
1、应理算金额:{remaining_adjustable_amount:.2f};
|
||||||
|
2、个单余额:{remaining_amount:.2f};
|
||||||
|
3、可理算金额:{adjustable_amount:.2f},其中:
|
||||||
|
1)个人自费可理算金额:{personal_self_adjustable_amount:.2f}={row['personal_self_payment']:.2f}*{liability['personal_self_ratio']:.2f}%;
|
||||||
|
2)个人自付可理算金额:{non_medical_adjustable_amount:.2f}={row['non_medical_payment']:.2f}*{liability['non_medical_ratio']:.2f}%;
|
||||||
|
3)合理部分可理算金额:{reasonable_adjustable_amount:.2f}={row['reasonable_amount']:.2f}*{liability['reasonable_ratio']:.2f}%;
|
||||||
|
4、理算金额:{adjustment_amount:.2f},即上述应理算金额、个人余额和可理算金额的最小值。
|
||||||
|
""".replace(
|
||||||
|
"\n", ""
|
||||||
|
).replace(
|
||||||
|
" ", ""
|
||||||
|
), # 理算说明
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
remaining_adjustable_amount -= adjustment_amount
|
||||||
|
# 若剩余可理算金额小于等于0则跳出循环
|
||||||
|
if remaining_adjustable_amount <= Decimal("0.00"):
|
||||||
|
break
|
||||||
|
|
||||||
|
if not receipt_adjustments:
|
||||||
|
receipt_adjustments.append(
|
||||||
|
{
|
||||||
|
"person_policy": None, # 个单号
|
||||||
|
"liability": None, # 理赔责任名称
|
||||||
|
"personal_self_payment": None, # 个人自费金额
|
||||||
|
"personal_self_ratio": None, # 个人自费比例
|
||||||
|
"personal_self_adjustable_amount": None, # 个人自费可理算金额
|
||||||
|
"non_medical_payment": None, # 个人自付金额
|
||||||
|
"non_medical_ratio": None, # 个人自付比例
|
||||||
|
"non_medical_adjustable_amount": None, # 个人自付可理算金额
|
||||||
|
"reasonable_amount": None, # 合理可理算金额
|
||||||
|
"reasonable_ratio": None, # 合理部分比例
|
||||||
|
"reasonable_adjustable_amount": None, # 合理可理算金额
|
||||||
|
"adjustment_amount": Decimal("0.00"), # 理赔责任理算金额
|
||||||
|
"adjustment_explanation": "票据不予理算", # 理算说明
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return adjustments
|
return receipt_adjustments
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"""通用模块"""
|
"""通用模块"""
|
||||||
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import sys
|
||||||
|
|
||||||
from masterdata import MasterData
|
from masterdata import MasterData
|
||||||
|
|
||||||
sys.path.append(Path(__file__).parent.parent.as_posix())
|
sys.path.append(Path(__file__).parent.parent.as_posix())
|
||||||
from utils.rules_engine import RulesEngine
|
from utils.rules_engine import RulesEngine
|
||||||
|
|
||||||
|
|
||||||
# 实例化主数据
|
# 实例化主数据
|
||||||
masterdata = MasterData(database=Path(__file__).parent / "database.db")
|
masterdata = MasterData(database=Path(__file__).parent / "database.db")
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
|
@ -3,27 +3,27 @@
|
||||||
影像件处理模块
|
影像件处理模块
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import json
|
|
||||||
import re
|
|
||||||
import sys
|
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from decimal import ROUND_HALF_UP, Decimal
|
from decimal import Decimal, ROUND_HALF_UP
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
import json
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy
|
|
||||||
import pandas
|
|
||||||
from common import masterdata, rules_engine
|
|
||||||
from fuzzywuzzy import fuzz
|
from fuzzywuzzy import fuzz
|
||||||
from jionlp import parse_location
|
from jionlp import parse_location
|
||||||
|
import numpy
|
||||||
|
import pandas
|
||||||
|
|
||||||
from utils.authenticator import Authenticator
|
from common import masterdata, rules_engine
|
||||||
from utils.request import Request
|
|
||||||
|
|
||||||
sys.path.append(Path(__file__).parent.parent.as_posix())
|
sys.path.append(Path(__file__).parent.parent.as_posix())
|
||||||
|
from utils.authenticator import Authenticator
|
||||||
|
from utils.request import Request
|
||||||
|
|
||||||
|
|
||||||
# 实例化认证器
|
# 实例化认证器
|
||||||
|
|
@ -139,12 +139,10 @@ def image_read(
|
||||||
:return: 影像件图像数组
|
:return: 影像件图像数组
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
with open(image_path, "rb") as file:
|
# 先使用读取影像件,再解码为单通道灰度图数组对象
|
||||||
image_bytes = file.read() # 读取影像件字节流
|
|
||||||
|
|
||||||
# 先将影像件字节流转为 numpy.ndarray 对象,再解码为单通道灰度图数组对象
|
|
||||||
image_ndarray = cv2.imdecode(
|
image_ndarray = cv2.imdecode(
|
||||||
buf=numpy.frombuffer(image_bytes, numpy.uint8), flags=cv2.IMREAD_GRAYSCALE
|
buf=numpy.fromfile(file=image_path, dtype=numpy.uint8),
|
||||||
|
flags=cv2.IMREAD_GRAYSCALE,
|
||||||
)
|
)
|
||||||
if image_ndarray is None:
|
if image_ndarray is None:
|
||||||
raise RuntimeError(f"影像件不存在")
|
raise RuntimeError(f"影像件不存在")
|
||||||
|
|
@ -600,7 +598,9 @@ def receipt_recognize(
|
||||||
"token": authenticator.get_token(servicer="szkt"), # 获取深圳快瞳访问令牌
|
"token": authenticator.get_token(servicer="szkt"), # 获取深圳快瞳访问令牌
|
||||||
"imgBase64": f"data:image/{image["image_format"].lstrip(".")};base64,{image["image_base64"]}", # 将影像件格式和BASE64编码嵌入数据统一资源标识符
|
"imgBase64": f"data:image/{image["image_format"].lstrip(".")};base64,{image["image_base64"]}", # 将影像件格式和BASE64编码嵌入数据统一资源标识符
|
||||||
},
|
},
|
||||||
guid=md5(string=(url + image["image_guid"]).encode("utf-8")).hexdigest().upper(),
|
guid=md5(string=(url + image["image_guid"]).encode("utf-8"))
|
||||||
|
.hexdigest()
|
||||||
|
.upper(),
|
||||||
)
|
)
|
||||||
# 若查验状态为真票或红票则直接整合至赔案档案
|
# 若查验状态为真票或红票则直接整合至赔案档案
|
||||||
if response.get("status") == 200 and response.get("code") == 10000:
|
if response.get("status") == 200 and response.get("code") == 10000:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ from pathlib import Path
|
||||||
|
|
||||||
from case import case_adjust
|
from case import case_adjust
|
||||||
from image import image_classify, image_recognize
|
from image import image_classify, image_recognize
|
||||||
from jinja2 import Environment, FileSystemLoader
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
# 初始化文件路径
|
# 初始化文件路径
|
||||||
|
|
@ -20,27 +19,18 @@ if __name__ == "__main__":
|
||||||
folder_path = file_path / "directory"
|
folder_path = file_path / "directory"
|
||||||
folder_path.mkdir(parents=True, exist_ok=True) # 若文件夹路径不存在则创建
|
folder_path.mkdir(parents=True, exist_ok=True) # 若文件夹路径不存在则创建
|
||||||
|
|
||||||
# 实例化JINJA2环境
|
|
||||||
environment = Environment(loader=FileSystemLoader(file_path))
|
|
||||||
# 添加DATE过滤器
|
|
||||||
environment.filters["date"] = lambda date: (
|
|
||||||
date.strftime("%Y-%m-%d") if date else "长期"
|
|
||||||
)
|
|
||||||
# 加载赔案档案模版
|
|
||||||
template = environment.get_template("template.html")
|
|
||||||
|
|
||||||
# 遍历文件夹中赔案文件夹并创建赔案档案
|
# 遍历文件夹中赔案文件夹并创建赔案档案
|
||||||
for case_path in [x for x in folder_path.iterdir() if x.is_dir()]:
|
for case_path in [x for x in folder_path.iterdir() if x.is_dir()]:
|
||||||
# 初始化赔案档案(推送至TPA时,保险公司会提保险分公司名称、报案时间和影像件等,TPA签收后生成赔案号)
|
# 初始化赔案档案(推送至TPA时,保险公司会提保险分公司名称、报案时间和影像件等,TPA签收后生成赔案号)
|
||||||
dossier = {
|
dossier = {
|
||||||
"report_layer": {
|
"report_layer": {
|
||||||
"report_time": datetime(
|
|
||||||
2025, 7, 25, 12, 0, 0
|
|
||||||
), # 指定报案时间,默认为 datetime对象
|
|
||||||
"case_number": case_path.stem, # 默认为赔案文件夹名称
|
"case_number": case_path.stem, # 默认为赔案文件夹名称
|
||||||
"insurer_company": (
|
"insurer_company": (
|
||||||
insurer_company := "中银保险有限公司苏州分公司"
|
insurer_company := "中银保险有限公司苏州分公司"
|
||||||
), # 默认为中银保险有限公司苏州分公司
|
), # 默认为中银保险有限公司苏州分公司
|
||||||
|
"report_time": datetime(
|
||||||
|
2025, 7, 25, 12, 0, 0
|
||||||
|
), # 指定报案时间,默认为 datetime对象
|
||||||
}, # 报案层
|
}, # 报案层
|
||||||
"images_layer": [], # 影像件层
|
"images_layer": [], # 影像件层
|
||||||
"insured_person_layer": {}, # 出险人层
|
"insured_person_layer": {}, # 出险人层
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
主数据模块
|
主数据模块
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from decimal import ROUND_HALF_UP, Decimal
|
from decimal import Decimal, ROUND_HALF_UP
|
||||||
|
from hashlib import md5
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional
|
import sys
|
||||||
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
sys.path.append(Path(__file__).parent.parent.as_posix())
|
sys.path.append(Path(__file__).parent.parent.as_posix())
|
||||||
from utils.sqlite import SQLite
|
from utils.sqlite import SQLite
|
||||||
|
|
@ -104,8 +105,6 @@ class MasterData(SQLite):
|
||||||
non_medical_ratio TEXT NOT NULL,
|
non_medical_ratio TEXT NOT NULL,
|
||||||
--合理理算比例
|
--合理理算比例
|
||||||
reasonable_ratio TEXT NOT NULL,
|
reasonable_ratio TEXT NOT NULL,
|
||||||
--理赔保单唯一标识
|
|
||||||
claim_policy_guid TEXT NOT NULL,
|
|
||||||
--个单唯一标识
|
--个单唯一标识
|
||||||
person_policy_guid TEXT NOT NULL
|
person_policy_guid TEXT NOT NULL
|
||||||
)
|
)
|
||||||
|
|
@ -128,8 +127,8 @@ class MasterData(SQLite):
|
||||||
after_change_amount TEXT NOT NULL,
|
after_change_amount TEXT NOT NULL,
|
||||||
--变动时间
|
--变动时间
|
||||||
change_time TEXT NOT NULL,
|
change_time TEXT NOT NULL,
|
||||||
--变动保单唯一标识
|
--个单唯一标识
|
||||||
change_policy_guid TEXT NOT NULL
|
person_policy_guid TEXT NOT NULL
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
@ -200,7 +199,7 @@ class MasterData(SQLite):
|
||||||
liabilities.personal_self_ratio,
|
liabilities.personal_self_ratio,
|
||||||
liabilities.non_medical_ratio,
|
liabilities.non_medical_ratio,
|
||||||
liabilities.reasonable_ratio,
|
liabilities.reasonable_ratio,
|
||||||
liabilities.claim_policy_guid
|
liabilities.person_policy_guid
|
||||||
FROM insured_persons
|
FROM insured_persons
|
||||||
INNER JOIN person_policies
|
INNER JOIN person_policies
|
||||||
ON insured_persons.person_policy_guid = person_policies.guid
|
ON insured_persons.person_policy_guid = person_policies.guid
|
||||||
|
|
@ -212,10 +211,10 @@ class MasterData(SQLite):
|
||||||
INNER JOIN liabilities
|
INNER JOIN liabilities
|
||||||
ON person_policies.guid = liabilities.person_policy_guid
|
ON person_policies.guid = liabilities.person_policy_guid
|
||||||
INNER JOIN coverage_changes
|
INNER JOIN coverage_changes
|
||||||
ON liabilities.claim_policy_guid = coverage_changes.change_policy_guid
|
ON liabilities.person_policy_guid = coverage_changes.person_policy_guid
|
||||||
AND coverage_changes.change_time = (SELECT MAX(change_time)
|
AND coverage_changes.change_time = (SELECT MAX(change_time)
|
||||||
FROM coverage_changes
|
FROM coverage_changes
|
||||||
WHERE liabilities.claim_policy_guid = change_policy_guid)
|
WHERE liabilities.person_policy_guid = person_policy_guid)
|
||||||
WHERE group_policies.insurer_company = ?
|
WHERE group_policies.insurer_company = ?
|
||||||
AND insured_persons.insured_person = ?
|
AND insured_persons.insured_person = ?
|
||||||
AND insured_persons.identity_type = ?
|
AND insured_persons.identity_type = ?
|
||||||
|
|
@ -312,11 +311,11 @@ class MasterData(SQLite):
|
||||||
|
|
||||||
def query_remaining_amount(
|
def query_remaining_amount(
|
||||||
self,
|
self,
|
||||||
policy_guid: str,
|
person_policy_guid: str,
|
||||||
) -> Decimal:
|
) -> Decimal:
|
||||||
"""
|
"""
|
||||||
根据变动保单唯一标识查询最新一条保额变动记录的变动后金额
|
根据个单唯一标识查询最新一条保额变动记录的变动后金额
|
||||||
:param policy_guid: 变动保单唯一标识
|
:param person_policy_guid: 个单唯一标识
|
||||||
:return: 变动后金额
|
:return: 变动后金额
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
|
|
@ -325,11 +324,11 @@ class MasterData(SQLite):
|
||||||
sql="""
|
sql="""
|
||||||
SELECT after_change_amount
|
SELECT after_change_amount
|
||||||
FROM coverage_changes
|
FROM coverage_changes
|
||||||
WHERE change_policy_guid = ?
|
WHERE person_policy_guid = ?
|
||||||
ORDER BY change_time DESC
|
ORDER BY change_time DESC
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
""",
|
""",
|
||||||
parameters=(policy_guid,),
|
parameters=(person_policy_guid,),
|
||||||
)
|
)
|
||||||
if not result:
|
if not result:
|
||||||
raise RuntimeError("查无数据")
|
raise RuntimeError("查无数据")
|
||||||
|
|
@ -341,3 +340,63 @@ class MasterData(SQLite):
|
||||||
|
|
||||||
except Exception as exception:
|
except Exception as exception:
|
||||||
raise RuntimeError(f"{str(exception)}") from exception
|
raise RuntimeError(f"{str(exception)}") from exception
|
||||||
|
|
||||||
|
def add_coverage_change(
|
||||||
|
self,
|
||||||
|
person_policy_guid: str,
|
||||||
|
before_change_amount: Decimal,
|
||||||
|
change_amount: Decimal,
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
新增保额扣减记录
|
||||||
|
:param person_policy_guid: 个单唯一标识
|
||||||
|
:param before_change_amount: 变动前金额
|
||||||
|
:param change_amount: 变动金额
|
||||||
|
:return: 无
|
||||||
|
"""
|
||||||
|
if before_change_amount != self.query_remaining_amount(
|
||||||
|
person_policy_guid=person_policy_guid,
|
||||||
|
):
|
||||||
|
raise ValueError("变动前金额不等于最新一条保额变动记录的变动后金额")
|
||||||
|
|
||||||
|
# 变动后金额
|
||||||
|
after_change_amount = (before_change_amount - change_amount).quantize(
|
||||||
|
Decimal("0.00"),
|
||||||
|
rounding=ROUND_HALF_UP,
|
||||||
|
)
|
||||||
|
if after_change_amount < Decimal("0.00"):
|
||||||
|
raise ValueError("变动后金额小于0")
|
||||||
|
|
||||||
|
# 当前时间
|
||||||
|
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
|
||||||
|
|
||||||
|
# 构建保额变动唯一标识
|
||||||
|
guid = (
|
||||||
|
md5(
|
||||||
|
string=f"{person_policy_guid} 保额扣减 {before_change_amount:.2f} {change_amount:.2f} {after_change_amount:.2f} {current_time}".encode(
|
||||||
|
"utf-8"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.hexdigest()
|
||||||
|
.upper()
|
||||||
|
)
|
||||||
|
|
||||||
|
with self:
|
||||||
|
if not self.execute(
|
||||||
|
sql="""
|
||||||
|
INSERT INTO coverage_changes
|
||||||
|
(guid, change_type, before_change_amount, change_amount, after_change_amount, change_time, person_policy_guid)
|
||||||
|
VALUES
|
||||||
|
(?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""",
|
||||||
|
parameters=(
|
||||||
|
guid,
|
||||||
|
"保额扣减",
|
||||||
|
f"{before_change_amount:.2f}",
|
||||||
|
f"{change_amount:.2f}",
|
||||||
|
f"{after_change_amount:.2f}",
|
||||||
|
current_time,
|
||||||
|
person_policy_guid,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
raise RuntimeError("新增保额扣减记录发生异常")
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue