日常更新

from mac mini(m1)
This commit is contained in:
liubiren 2025-12-11 17:36:11 +08:00
parent 9df91dac94
commit 8be4c60d7e
2 changed files with 615 additions and 594 deletions

View File

@ -103,7 +103,9 @@ class CacheClient:
try: try:
# 创建缓存数据库连接 # 创建缓存数据库连接
self.connection = sqlite3.connect( self.connection = sqlite3.connect(
database=(Path(__file__).parent.resolve() / database), # 当前目录下创建缓存数据库 database=(
Path(__file__).parent.resolve() / database
), # 当前目录下创建缓存数据库
check_same_thread=False, check_same_thread=False,
timeout=30, # 缓存数据库锁超时时间单位默认为30秒避免并发锁死 timeout=30, # 缓存数据库锁超时时间单位默认为30秒避免并发锁死
) )
@ -310,6 +312,7 @@ class Arguments(BaseModel):
:param stream: 是否启用流式传输 :param stream: 是否启用流式传输
:param guid: 全局唯一标识 :param guid: 全局唯一标识
""" """
# 统一资源定位符 # 统一资源定位符
url: HttpUrl = Field(default=...) url: HttpUrl = Field(default=...)
# 查询参数 # 查询参数
@ -456,17 +459,13 @@ class HTTPClient:
# 重构表单数据 # 重构表单数据
if arguments.get("data") is not None: if arguments.get("data") is not None:
arguments["data"] = { arguments["data"] = {
k: v k: v for k, v in arguments["data"].items() if v is not None
for k, v in arguments["data"].items()
if v is not None
} }
# 重构JSON数据 # 重构JSON数据
if arguments.get("json_data") is not None: if arguments.get("json_data") is not None:
arguments["json_data"] = { arguments["json_data"] = {
k: v k: v for k, v in arguments["json_data"].items() if v is not None
for k, v in arguments["json_data"].items()
if v is not None
} }
# 重构文件数据 # 重构文件数据

View File

@ -26,7 +26,6 @@ from zen import ZenDecision, ZenEngine
from utils.client import Authenticator, HTTPClient from utils.client import Authenticator, HTTPClient
# from utils.ocr import fuzzy_match # from utils.ocr import fuzzy_match
@ -478,7 +477,12 @@ if __name__ == "__main__":
# noinspection PyShadowingNames # noinspection PyShadowingNames
def image_recognize( def image_recognize(
image_index, image_guid, image_format, image_base64, insurance_branch, image_type image_index,
image_guid,
image_format,
image_base64,
insurance_branch,
image_type,
) -> None: ) -> None:
""" """
影像件识别并整合至赔案档案 影像件识别并整合至赔案档案
@ -624,24 +628,26 @@ if __name__ == "__main__":
url=(url := "https://ai.inspirvision.cn/s/api/ocr/invoiceCheckAll"), url=(url := "https://ai.inspirvision.cn/s/api/ocr/invoiceCheckAll"),
headers={"X-RequestId-Header": image_guid}, headers={"X-RequestId-Header": image_guid},
data={ data={
"token": authenticator.get_token(servicer="szkt"), # 获取深圳快瞳访问令牌 "token": authenticator.get_token(
servicer="szkt"
), # 获取深圳快瞳访问令牌
"imgBase64": f"data:image/{image_format.lstrip(".")};base64,{image_base64}", "imgBase64": f"data:image/{image_format.lstrip(".")};base64,{image_base64}",
}, },
guid=md5((url + image_guid).encode("utf-8")) guid=md5((url + image_guid).encode("utf-8")).hexdigest().upper(),
.hexdigest()
.upper(),
) )
# 若查验为真票或红票则直接整合至赔案档案 # 若查验成功则直接整合至赔案档案
if response.get("status") == 200 and response.get("code") == 10000: if response.get("status") == 200 and response.get("code") == 10000:
# noinspection PyTypeChecker # noinspection PyTypeChecker
match response["data"]["productCode"]: match response["data"]["productCode"]:
# 增值税发票,目前深圳快瞳支持全电和全电纸质增值税发票查验 # 增值税发票,目前深圳快瞳支持全电和全电纸质增值税发票查验
case "003082": case "003082":
# noinspection PyTypeChecker # noinspection PyTypeChecker
receipt.update({ receipt.update(
{
"查验状态": ( "查验状态": (
"真票" "真票"
if response["data"]["details"]["invoiceTypeNo"] == "0" if response["data"]["details"]["invoiceTypeNo"]
== "0"
else "红票" else "红票"
), ),
"票据号码": response["data"]["details"]["number"], "票据号码": response["data"]["details"]["number"],
@ -656,12 +662,13 @@ if __name__ == "__main__":
"%Y-%m-%d" "%Y-%m-%d"
), # 深圳快瞳票据查验接口中开票日期由字符串(%Y年%m月%d日转为日期 ), # 深圳快瞳票据查验接口中开票日期由字符串(%Y年%m月%d日转为日期
"校验码": response["data"]["details"]["check_code"], "校验码": response["data"]["details"]["check_code"],
"开票金额": Decimal(response["data"]["details"]["total"]).quantize( "开票金额": Decimal(
response["data"]["details"]["total"]
).quantize(
Decimal("0.00"), Decimal("0.00"),
rounding=ROUND_HALF_UP, rounding=ROUND_HALF_UP,
), # 深圳快瞳票据查验接口中开票金额由字符串转为Decimal保留两位小数 ), # 深圳快瞳票据查验接口中开票金额由字符串转为Decimal保留两位小数
"姓名": response["data"]["details"]["buyer"], "姓名": response["data"]["details"]["buyer"],
"购药及就医机构": response["data"]["details"]["seller"],
"备注": ( "备注": (
response["data"]["details"]["remark"] response["data"]["details"]["remark"]
if response["data"]["details"]["remark"] if response["data"]["details"]["remark"]
@ -676,11 +683,10 @@ if __name__ == "__main__":
else None else None
), # 深圳快瞳票据查验接口中明细规则由空字符转为None ), # 深圳快瞳票据查验接口中明细规则由空字符转为None
"单位": ( "单位": (
item["unit"] item["unit"] if item["unit"] else None
if item["unit"]
else None
), # 深圳快瞳票据查验接口中明细单位由空字符转为None ), # 深圳快瞳票据查验接口中明细单位由空字符转为None
"数量": (Decimal(item["quantity"]).quantize( "数量": (
Decimal(item["quantity"]).quantize(
Decimal("0.00"), Decimal("0.00"),
rounding=ROUND_HALF_UP, rounding=ROUND_HALF_UP,
) )
@ -695,13 +701,20 @@ if __name__ == "__main__":
rounding=ROUND_HALF_UP, rounding=ROUND_HALF_UP,
), # 深圳快瞳票据查验接口中明细金额税额由字符串转为Decimal保留两位小数求和 ), # 深圳快瞳票据查验接口中明细金额税额由字符串转为Decimal保留两位小数求和
} }
for item in response["data"]["details"].get("items", []) for item in response["data"]["details"].get(
"items", []
)
], ],
}) "购药及就医机构": (
institution := response["data"]["details"]["seller"]
),
}
)
# 门诊/住院收费票据 # 门诊/住院收费票据
case "003081": case "003081":
# noinspection PyTypeChecker # noinspection PyTypeChecker
receipt.update({ receipt.update(
{
"查验状态": ( "查验状态": (
"真票" "真票"
if response["data"]["flushedRed"] == "true" if response["data"]["flushedRed"] == "true"
@ -713,21 +726,22 @@ if __name__ == "__main__":
if response["data"]["billCode"] if response["data"]["billCode"]
else None else None
), # 部分地区医疗收费票据无发票代码深圳快瞳票据查验接口中票据代码由空字符转为None ), # 部分地区医疗收费票据无发票代码深圳快瞳票据查验接口中票据代码由空字符转为None
"开票日期": parse(response["data"][ "开票日期": parse(
"invoiceDate" response["data"]["invoiceDate"]
]).strftime( ).strftime(
"%Y-%m-%d" "%Y-%m-%d"
), # 深圳快瞳票据查验接口中开票日期由字符串(%Y-%m-%d转为日期 ), # 深圳快瞳票据查验接口中开票日期由字符串(%Y-%m-%d转为日期
"校验码": response["data"]["checkCode"], "校验码": response["data"]["checkCode"],
"票据金额": Decimal(response["data"]["amount"]).quantize( "票据金额": Decimal(
response["data"]["amount"]
).quantize(
Decimal("0.00"), Decimal("0.00"),
rounding=ROUND_HALF_UP, rounding=ROUND_HALF_UP,
), ),
"姓名": response["data"]["payer"], "姓名": response["data"]["payer"],
"购药及就医机构": response["data"]["receivablesInstitution"], "购药及就医机构": response["data"][
"receivablesInstitution"
],
"医保支付": format( "医保支付": format(
Decimal( Decimal(
response["data"].get("medicarePay", "0.00") response["data"].get("medicarePay", "0.00")
@ -766,7 +780,9 @@ if __name__ == "__main__":
), # 深圳快瞳票据查验中就部分地区无自付一 ), # 深圳快瞳票据查验中就部分地区无自付一
"自付二": format( "自付二": format(
Decimal( Decimal(
response["data"].get("classificationPays", "0.00") response["data"].get(
"classificationPays", "0.00"
)
).quantize( ).quantize(
Decimal("0.00"), Decimal("0.00"),
rounding=ROUND_HALF_UP, rounding=ROUND_HALF_UP,
@ -784,7 +800,11 @@ if __name__ == "__main__":
), ),
"住院日期": ( "住院日期": (
parse(date.split("-")[0]).strftime("%Y-%m-%d") parse(date.split("-")[0]).strftime("%Y-%m-%d")
if (date := response["data"].get("hospitalizationDate")) if (
date := response["data"].get(
"hospitalizationDate"
)
)
else None else None
), # 深圳快瞳票据查验中就收费票据住院日期格式为%Y%m%d-%Y%m%d即住院日期-出院日期 ), # 深圳快瞳票据查验中就收费票据住院日期格式为%Y%m%d-%Y%m%d即住院日期-出院日期
"出院日期": ( "出院日期": (
@ -817,15 +837,18 @@ if __name__ == "__main__":
} }
for item in response["data"]["feedetails"] for item in response["data"]["feedetails"]
], ],
}) }
)
# 若查验为假票或无法查验
else:
if response.get("status") == 400 and (
response.get("code") == 10100 or response.get("code") == 10001
):
receipt["查验结果"] = "假票"
else:
receipt["查验结果"] = "无法查验"
try:
# 若请求深圳快瞳票据查验接口或解析发生异常,则根据影像件类型请求深圳快瞳增值税发票/收费票据识别接口
# 影像件类型
image_type = kwargs.get("image_type", globals()["image_type"])
if image_type is None:
return None
match image_type: match image_type:
case "增值税发票": case "增值税发票":
@ -837,12 +860,14 @@ if __name__ == "__main__":
), ),
headers={"X-RequestId-Header": image_guid}, headers={"X-RequestId-Header": image_guid},
data={ data={
"token": globals()["authenticator"].get_token( "token": globals()[
servicer="szkt" "authenticator"
), ].get_token(servicer="szkt"),
"imgBase64": f"data:image/{image_format};base64,{image_base64}", "imgBase64": f"data:image/{image_format};base64,{image_base64}",
}, },
guid=hashlib.md5((url + image_guid).encode("utf-8")) guid=hashlib.md5(
(url + image_guid).encode("utf-8")
)
.hexdigest() .hexdigest()
.upper(), .upper(),
) )
@ -865,9 +890,9 @@ if __name__ == "__main__":
"票据号码": (number := data.get("发票号码")), "票据号码": (number := data.get("发票号码")),
"票据代码": data.get("发票代码"), "票据代码": data.get("发票代码"),
"开票日期": ( "开票日期": (
datetime.strptime(date, "%Y年%m月%d").strftime( datetime.strptime(
"%Y-%m-%d" date, "%Y年%m月%d"
) ).strftime("%Y-%m-%d")
if re.match( if re.match(
r"\d{4}\d{1,2}月\d{1,2}日", r"\d{4}\d{1,2}月\d{1,2}日",
(date := data.get("开票日期")), (date := data.get("开票日期")),
@ -893,14 +918,18 @@ if __name__ == "__main__":
".2f", ".2f",
), ),
"备注": ( "备注": (
remark if (remark := data.get("备注")) else None remark
if (remark := data.get("备注"))
else None
), ),
"项目": ( "项目": (
[ [
{ {
"名称": name, "名称": name,
"规格": ( "规格": (
specification if specification else None specification
if specification
else None
), ),
"单位": unit if unit else None, "单位": unit if unit else None,
"数量": ( "数量": (
@ -916,7 +945,8 @@ if __name__ == "__main__":
), ),
"金额": format( "金额": format(
( (
Decimal(amount) + Decimal(tax) Decimal(amount)
+ Decimal(tax)
).quantize( ).quantize(
Decimal("0.00"), Decimal("0.00"),
rounding=ROUND_HALF_UP, rounding=ROUND_HALF_UP,
@ -927,7 +957,9 @@ if __name__ == "__main__":
for name, specification, unit, quantity, amount, tax in zip( for name, specification, unit, quantity, amount, tax in zip(
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^项目名称(\d+)?$", r"^项目名称(\d+)?$",
component["desc"], component["desc"],
@ -935,7 +967,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^规格型号(\d+)?$", r"^规格型号(\d+)?$",
component["desc"], component["desc"],
@ -943,7 +977,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^单位(\d+)?$", r"^单位(\d+)?$",
component["desc"], component["desc"],
@ -951,7 +987,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^数量(\d+)?$", r"^数量(\d+)?$",
component["desc"], component["desc"],
@ -959,7 +997,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^金额(\d+)?$", r"^金额(\d+)?$",
component["desc"], component["desc"],
@ -967,7 +1007,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^税额(\d+)?$", r"^税额(\d+)?$",
component["desc"], component["desc"],
@ -997,7 +1039,9 @@ if __name__ == "__main__":
for name, quantity, amount in zip( for name, quantity, amount in zip(
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^项目名称明细(\d+)?$", r"^项目名称明细(\d+)?$",
component["desc"], component["desc"],
@ -1005,7 +1049,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^项目数量明细(\d+)?$", r"^项目数量明细(\d+)?$",
component["desc"], component["desc"],
@ -1013,7 +1059,9 @@ if __name__ == "__main__":
], ],
[ [
component["value"] component["value"]
for component in response["data"] for component in response[
"data"
]
if re.match( if re.match(
r"^项目金额明细(\d+)?$", r"^项目金额明细(\d+)?$",
component["desc"], component["desc"],
@ -1024,27 +1072,11 @@ if __name__ == "__main__":
), ),
"查验状态": "无法查验", "查验状态": "无法查验",
} }
# 若查验为假票或无法查验
else:
if response.get("status") == 400 and (response.get("code") == 10100 or response.get("code") == 10001):
receipt["查验结果"] = "假票"
else:
receipt["查验结果"] = "无法查验"
return extraction
except: except:
return None pass
case _:
try:
# 请求深圳快瞳收费票据识别接口 # 请求深圳快瞳收费票据识别接口
response = globals()["http_client"].post( response = globals()["http_client"].post(
url=( url=(url := "https://ai.inspirvision.cn/s/api/ocr/medical"),
url := "https://ai.inspirvision.cn/s/api/ocr/medical"
),
headers={"X-RequestId-Header": image_guid}, headers={"X-RequestId-Header": image_guid},
data={ data={
"token": globals()["authenticator"].get_token( "token": globals()["authenticator"].get_token(
@ -1058,8 +1090,7 @@ if __name__ == "__main__":
) )
# 若深圳快瞳收费票据识别响应非成功则返回NONE # 若深圳快瞳收费票据识别响应非成功则返回NONE
if not ( if not (
response.get("status") == 200 response.get("status") == 200 and response.get("code") == 0
and response.get("code") == 0
): ):
return None return None
@ -1071,9 +1102,7 @@ if __name__ == "__main__":
), ),
"票据号码": ( "票据号码": (
receipt := ( receipt := (
response["data"]["insured"][ response["data"]["insured"]["receipt_outpatient"]
"receipt_outpatient"
]
or response["data"]["insured"][ or response["data"]["insured"][
"receipt_hospitalization" "receipt_hospitalization"
] ]
@ -1089,9 +1118,7 @@ if __name__ == "__main__":
], # 深圳快瞳收费票据识别中就开票日期格式为%Y-%m-%d ], # 深圳快瞳收费票据识别中就开票日期格式为%Y-%m-%d
"校验码": fuzzy_match( "校验码": fuzzy_match(
target="校验码", target="校验码",
components=receipt["global_detail"][ components=receipt["global_detail"]["region_specific"],
"region_specific"
],
specify_key="name", specify_key="name",
return_key="word.value", return_key="word.value",
), ),
@ -1145,9 +1172,7 @@ if __name__ == "__main__":
), ),
".2f", ".2f",
) )
if isinstance( if isinstance((field := receipt.get("self_pay")), dict)
(field := receipt.get("self_pay")), dict
)
else None else None
), ),
"自付一": ( "自付一": (
@ -1184,27 +1209,21 @@ if __name__ == "__main__":
), ),
".2f", ".2f",
) )
if isinstance( if isinstance(field := (receipt.get("self_cost")), dict)
field := (receipt.get("self_cost")), dict
)
else None else None
), ),
"住院日期": ( "住院日期": (
datetime.strptime( datetime.strptime(field["value"], "%Y%m%d").strftime(
field["value"], "%Y%m%d" "%Y-%m-%d"
).strftime("%Y-%m-%d")
if isinstance(
field := (receipt.get("starttime")), dict
) )
if isinstance(field := (receipt.get("starttime")), dict)
else None else None
), ),
"出院日期": ( "出院日期": (
datetime.strptime( datetime.strptime(field["value"], "%Y%m%d").strftime(
field["value"], "%Y%m%d" "%Y-%m-%d"
).strftime("%Y-%m-%d")
if isinstance(
field := (receipt.get("endtime")), dict
) )
if isinstance(field := (receipt.get("endtime")), dict)
else None else None
), ),
"医疗机构类型": receipt["others"][ "医疗机构类型": receipt["others"][
@ -1239,9 +1258,7 @@ if __name__ == "__main__":
), ),
".2f", ".2f",
) )
if isinstance( if isinstance((field := item["number"]), dict)
(field := item["number"]), dict
)
else None else None
), ),
"金额": ( "金额": (
@ -1355,7 +1372,12 @@ if __name__ == "__main__":
# 影像件识别并整合至赔案档案 # 影像件识别并整合至赔案档案
image_recognize( image_recognize(
image_index, image_guid, image_format, image_base64, insurance_branch, image_type image_index,
image_guid,
image_format,
image_base64,
insurance_branch,
image_type,
) )
""" """