parent
5300d95622
commit
3570036c3e
|
|
@ -1,61 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
|
||||
脚本说明:基于MySQL、MongoDB、Request和飞书等API封装成常用功能
|
||||
|
||||
备注:
|
||||
后续需要考虑优化,后续utils中脚本尽可能相互独立
|
||||
|
||||
"""
|
||||
|
||||
# 导入模块
|
||||
|
||||
import json
|
||||
|
||||
|
||||
import pandas
|
||||
|
||||
import warnings
|
||||
|
||||
import numpy
|
||||
|
||||
from pydantic import BaseModel, ValidationError, AfterValidator, Field, HttpUrl
|
||||
|
||||
from typing import Optional, Union, Unpack, Literal, Dict, TypedDict, Annotated
|
||||
|
||||
from requests_toolbelt import MultipartEncoder
|
||||
|
||||
import cv2
|
||||
|
||||
from requests import Session, Response
|
||||
|
||||
from requests.adapters import HTTPAdapter
|
||||
|
||||
from urllib.parse import (
|
||||
urlparse,
|
||||
urlsplit,
|
||||
urlunsplit,
|
||||
parse_qs,
|
||||
quote,
|
||||
quote_plus,
|
||||
unquote,
|
||||
urlencode,
|
||||
)
|
||||
|
||||
from urllib.request import Request as request, urlopen
|
||||
|
||||
from urllib.util.retry import Retry
|
||||
|
||||
from urllib.error import HTTPError
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
|
||||
import os
|
||||
|
||||
import threading
|
||||
|
||||
import time
|
||||
|
||||
from functools import wraps
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
封装ZenEngine
|
||||
"""
|
||||
|
||||
# 导入模块
|
||||
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
||||
from zen import ZenDecision, ZenEngine
|
||||
|
||||
|
||||
class RuleEngine:
|
||||
"""
|
||||
规则引擎,实现打开并读取规则,根据规则和输入评估并输出
|
||||
"""
|
||||
|
||||
def __init__(self, rules_path: Path):
|
||||
"""
|
||||
初始化规则引擎
|
||||
:param rules_path: 规则文件夹路径(path对象)
|
||||
"""
|
||||
rules_path = Path(rules_path)
|
||||
rules_path.mkdir(parents=True, exist_ok=True) # 若规则文件夹不存在则创建
|
||||
|
||||
# 初始化规则缓存
|
||||
self.decisions = {}
|
||||
for decision_path in rules_path.glob("*.json"):
|
||||
# 打开并读取规则文件并实例化规则
|
||||
self.decisions[decision_path.stem] = self._get_decision(decision_path)
|
||||
|
||||
@staticmethod
|
||||
def _get_decision(decision_path: Path) -> ZenDecision:
|
||||
"""
|
||||
打开并读取规则文件并实例化规则
|
||||
:param decision_path: 规则文件路径(path对象)
|
||||
:return: 实例化规则
|
||||
"""
|
||||
|
||||
def loader(path):
|
||||
with open(path, "r", encoding="utf-8") as file:
|
||||
return file.read()
|
||||
|
||||
return ZenEngine({"loader": loader}).get_decision(decision_path.as_posix())
|
||||
|
||||
def evaluate(self, decision: str, inputs: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
调用规则并评估
|
||||
:param decision: 规则
|
||||
:param inputs: 输入
|
||||
:return: 输出
|
||||
"""
|
||||
if decision not in self.decisions:
|
||||
raise ValueError(f"规则不存在:{decision}")
|
||||
|
||||
return self.decisions[decision].evaluate(self._format_value(inputs))["result"]
|
||||
|
||||
def _format_value(self, value: Any) -> Any:
|
||||
"""
|
||||
格式化值为字符串
|
||||
:param value: 值
|
||||
:return: 格式化后值
|
||||
"""
|
||||
match value:
|
||||
case int():
|
||||
return str(value)
|
||||
case Decimal():
|
||||
# noinspection PyTypeChecker
|
||||
return format(value, f".{abs(value.as_tuple().exponent)}f")
|
||||
case datetime():
|
||||
return value.strftime("%Y-%m-%d %H:%M:%S")
|
||||
case list():
|
||||
return [self._format_value(e) for e in value]
|
||||
case dict():
|
||||
return {k: self._format_value(v) for k, v in value.items()}
|
||||
case _:
|
||||
return value
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
830
票据理赔自动化/main.py
830
票据理赔自动化/main.py
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,226 @@
|
|||
{
|
||||
"contentType": "application/vnd.gorules.decision",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "6716ac00-2b7a-4599-b4a7-2a19a2a63b17",
|
||||
"name": "decisionTable1",
|
||||
"type": "decisionTableNode",
|
||||
"content": {
|
||||
"rules": [
|
||||
{
|
||||
"_id": "172b5ab5-25c4-4785-9cf9-d106730ee55d",
|
||||
"_description": "",
|
||||
"268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43": "true",
|
||||
"3320dce8-b9ca-415b-8b3c-adcfebb06f79": "\"证件有效起期大于等于报案时间\"",
|
||||
"3404e5f2-f063-40d1-b27a-d3ecfb41c652": "\"中银保险有限公司苏州分公司\"",
|
||||
"c5488920-2ae6-4123-92be-cd53cbc401f6": "startOf(date(insured_person_layer.commencement_date), \"day\") >= date(report_layer.report_time)",
|
||||
"c9e2be65-c7a5-463b-8d62-0a5f503c844e": "\"R001-1\""
|
||||
},
|
||||
{
|
||||
"_id": "4497043e-4dfa-4edf-a65f-1fa4a998067d",
|
||||
"_description": "",
|
||||
"268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43": "false",
|
||||
"3320dce8-b9ca-415b-8b3c-adcfebb06f79": "",
|
||||
"3404e5f2-f063-40d1-b27a-d3ecfb41c652": "\"中银保险有限公司苏州分公司\"",
|
||||
"c5488920-2ae6-4123-92be-cd53cbc401f6": "startOf(date(insured_person_layer.commencement_date), \"day\") <= date(report_layer.report_time)",
|
||||
"c9e2be65-c7a5-463b-8d62-0a5f503c844e": "\"R001-0\""
|
||||
},
|
||||
{
|
||||
"_id": "bf01e2f6-572f-47f5-8773-d5b81a02e7c8",
|
||||
"_description": "",
|
||||
"268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43": "true",
|
||||
"3320dce8-b9ca-415b-8b3c-adcfebb06f79": "\"证件有效止期小于等于报案时间\"",
|
||||
"3404e5f2-f063-40d1-b27a-d3ecfb41c652": "\"中银保险有限公司苏州分公司\"",
|
||||
"c5488920-2ae6-4123-92be-cd53cbc401f6": "endOf(date(insured_person_layer.termination_date), \"day\") <= date(report_layer.report_time)",
|
||||
"c9e2be65-c7a5-463b-8d62-0a5f503c844e": "\"R002-1\""
|
||||
},
|
||||
{
|
||||
"_id": "2a7d3c73-840b-4dc8-8363-07f81fa27579",
|
||||
"_description": "",
|
||||
"268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43": "false",
|
||||
"3320dce8-b9ca-415b-8b3c-adcfebb06f79": "",
|
||||
"3404e5f2-f063-40d1-b27a-d3ecfb41c652": "\"中银保险有限公司苏州分公司\"",
|
||||
"c5488920-2ae6-4123-92be-cd53cbc401f6": "endOf(date(insured_person_layer.termination_date), \"day\") >= date(report_layer.report_time)",
|
||||
"c9e2be65-c7a5-463b-8d62-0a5f503c844e": "\"R002-0\""
|
||||
},
|
||||
{
|
||||
"_id": "9fa2cd42-2297-4719-bf35-559026e0dc20",
|
||||
"_description": "",
|
||||
"268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43": "true",
|
||||
"3320dce8-b9ca-415b-8b3c-adcfebb06f79": "\"领款人和被保险人不一致\"",
|
||||
"3404e5f2-f063-40d1-b27a-d3ecfb41c652": "\"中银保险有限公司苏州分公司\"",
|
||||
"c5488920-2ae6-4123-92be-cd53cbc401f6": "insured_person_layer.account != insured_person_layer.insured_person",
|
||||
"c9e2be65-c7a5-463b-8d62-0a5f503c844e": "\"R003-1\""
|
||||
},
|
||||
{
|
||||
"_id": "76fe12c1-70fc-4221-9c78-6ea4d2d9af24",
|
||||
"_description": "",
|
||||
"268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43": "false",
|
||||
"3320dce8-b9ca-415b-8b3c-adcfebb06f79": "",
|
||||
"3404e5f2-f063-40d1-b27a-d3ecfb41c652": "\"中银保险有限公司苏州分公司\"",
|
||||
"c5488920-2ae6-4123-92be-cd53cbc401f6": "insured_person_layer.account == insured_person_layer.insured_person",
|
||||
"c9e2be65-c7a5-463b-8d62-0a5f503c844e": "\"R003-0\""
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "3404e5f2-f063-40d1-b27a-d3ecfb41c652",
|
||||
"name": "保险分公司",
|
||||
"field": "report_layer.insurer_company"
|
||||
},
|
||||
{
|
||||
"id": "c5488920-2ae6-4123-92be-cd53cbc401f6",
|
||||
"name": "规则"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"id": "268ca3e3-4f15-4c6a-a8f2-bbb5338c1f43",
|
||||
"name": "命中",
|
||||
"field": "hit"
|
||||
},
|
||||
{
|
||||
"id": "c9e2be65-c7a5-463b-8d62-0a5f503c844e",
|
||||
"name": "规则代码",
|
||||
"field": "code"
|
||||
},
|
||||
{
|
||||
"id": "3320dce8-b9ca-415b-8b3c-adcfebb06f79",
|
||||
"name": "命是说明",
|
||||
"field": "explanation"
|
||||
}
|
||||
],
|
||||
"hitPolicy": "collect",
|
||||
"inputField": null,
|
||||
"outputPath": "hits",
|
||||
"passThrough": false,
|
||||
"executionMode": "single"
|
||||
},
|
||||
"position": {
|
||||
"x": 430,
|
||||
"y": 292.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "5c628b40-4007-449e-84db-e8bdf3d6899d",
|
||||
"name": "request",
|
||||
"type": "inputNode",
|
||||
"content": {
|
||||
"schema": ""
|
||||
},
|
||||
"position": {
|
||||
"x": 110,
|
||||
"y": 292.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "2ee64660-9abd-4b56-b6ed-97d892041cfd",
|
||||
"name": "response",
|
||||
"type": "outputNode",
|
||||
"content": {
|
||||
"schema": ""
|
||||
},
|
||||
"position": {
|
||||
"x": 1390,
|
||||
"y": 292.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "d0835a6d-72a3-4c21-a3de-b38d962d8518",
|
||||
"name": "decisionTable2",
|
||||
"type": "decisionTableNode",
|
||||
"content": {
|
||||
"rules": [
|
||||
{
|
||||
"_id": "09f82f88-75be-42b2-bd40-23457ec5aed9",
|
||||
"_description": "命中规则数为0,例如保险分公司未配置规则",
|
||||
"722fc57b-5166-4457-b9f0-c3437c6159b4": "len(hits) == 0",
|
||||
"b2b97b2a-5e59-4c23-a116-7e49e59e65c3": "",
|
||||
"bd0ca899-7c74-40e4-9b61-1c058ef5e83f": ""
|
||||
},
|
||||
{
|
||||
"_id": "843e7960-c5d8-4867-a283-b2641d31f3d7",
|
||||
"_description": "",
|
||||
"722fc57b-5166-4457-b9f0-c3437c6159b4": "count(hits, #.hit) == 0",
|
||||
"b2b97b2a-5e59-4c23-a116-7e49e59e65c3": "\"赔付\"",
|
||||
"bd0ca899-7c74-40e4-9b61-1c058ef5e83f": ""
|
||||
},
|
||||
{
|
||||
"_id": "e5dbd162-d188-4170-9b6b-9fc7077c47bf",
|
||||
"_description": "",
|
||||
"722fc57b-5166-4457-b9f0-c3437c6159b4": "",
|
||||
"b2b97b2a-5e59-4c23-a116-7e49e59e65c3": "\"拒付\"",
|
||||
"bd0ca899-7c74-40e4-9b61-1c058ef5e83f": "explanations"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
{
|
||||
"id": "722fc57b-5166-4457-b9f0-c3437c6159b4",
|
||||
"name": "命中",
|
||||
"field": "hits"
|
||||
}
|
||||
],
|
||||
"outputs": [
|
||||
{
|
||||
"id": "b2b97b2a-5e59-4c23-a116-7e49e59e65c3",
|
||||
"name": "拒付",
|
||||
"field": "refuse"
|
||||
},
|
||||
{
|
||||
"id": "bd0ca899-7c74-40e4-9b61-1c058ef5e83f",
|
||||
"name": "拒付说明",
|
||||
"field": "explanation"
|
||||
}
|
||||
],
|
||||
"hitPolicy": "first",
|
||||
"inputField": null,
|
||||
"outputPath": null,
|
||||
"passThrough": false,
|
||||
"executionMode": "single"
|
||||
},
|
||||
"position": {
|
||||
"x": 1070,
|
||||
"y": 292.5
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "476b8b59-221c-4ff6-b3e2-dfeec58eee10",
|
||||
"name": "function",
|
||||
"type": "functionNode",
|
||||
"content": {
|
||||
"source": "import zen from 'zen';\n\n/** @type {Handler} **/\nexport const handler = async (input) => {\n const explanations = input.hits.reduce((arr, obj) => {\n const element = obj[\"explanation\"];\n if (element) {\n arr.push(element);\n }\n return arr; \n }, []);\n return {\n hits: input.hits,\n explanations: explanations,\n };\n};\n",
|
||||
"omitNodes": true
|
||||
},
|
||||
"position": {
|
||||
"x": 750,
|
||||
"y": 292.5
|
||||
}
|
||||
}
|
||||
],
|
||||
"edges": [
|
||||
{
|
||||
"id": "02f2d409-3077-46fd-95f4-6b4b441fa99f",
|
||||
"type": "edge",
|
||||
"sourceId": "5c628b40-4007-449e-84db-e8bdf3d6899d",
|
||||
"targetId": "6716ac00-2b7a-4599-b4a7-2a19a2a63b17"
|
||||
},
|
||||
{
|
||||
"id": "3c17140a-e97a-40d7-a0d2-f0696051bde8",
|
||||
"type": "edge",
|
||||
"sourceId": "d0835a6d-72a3-4c21-a3de-b38d962d8518",
|
||||
"targetId": "2ee64660-9abd-4b56-b6ed-97d892041cfd"
|
||||
},
|
||||
{
|
||||
"id": "778027ba-7228-4d94-a778-a26f7c3ea9bb",
|
||||
"type": "edge",
|
||||
"sourceId": "6716ac00-2b7a-4599-b4a7-2a19a2a63b17",
|
||||
"targetId": "476b8b59-221c-4ff6-b3e2-dfeec58eee10"
|
||||
},
|
||||
{
|
||||
"id": "a8422289-e0cb-4529-8c8a-1edceeac98ae",
|
||||
"type": "edge",
|
||||
"sourceId": "476b8b59-221c-4ff6-b3e2-dfeec58eee10",
|
||||
"targetId": "d0835a6d-72a3-4c21-a3de-b38d962d8518"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue