8ae1670d by 周伟奇

comparison v1

1 parent 30a0ce9d
...@@ -1019,15 +1019,108 @@ BASE_XML_TEXT = """<?xml version="1.0" encoding="utf-8"?> ...@@ -1019,15 +1019,108 @@ BASE_XML_TEXT = """<?xml version="1.0" encoding="utf-8"?>
1019 CDATA_TEXT = """<![CDATA[<Exec xmlns="http://tempuri.org/"><strXMLParm>&lt;Request&gt;&lt;Framework&gt;&lt;UserName&gt;SFCHINA\qqcout0&lt;/UserName&gt;&lt;GUID&gt;70d0efcb-3bc2-4018-ac4e-681c8f3131b6&lt;/GUID&gt;&lt;DetailedTracingEnabled&gt;False&lt;/DetailedTracingEnabled&gt;&lt;ServiceName&gt;AMSWebService&lt;/ServiceName&gt;&lt;SupportsRedirection&gt;true&lt;/SupportsRedirection&gt;&lt;ServiceType&gt;Service&lt;/ServiceType&gt;&lt;/Framework&gt;&lt;Parms&gt;&lt;InputXML type="string"&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt;&amp;lt;InputXML&amp;gt; &amp;lt;Result&amp;gt; {0} &amp;lt;/Result&amp;gt;&amp;lt;AuthorizationData&amp;gt;&amp;lt;ServiceComponent&amp;gt;OCR&amp;lt;/ServiceComponent&amp;gt;&amp;lt;RoleId/&amp;gt;&amp;lt;CompanyId/&amp;gt;&amp;lt;/AuthorizationData&amp;gt;&amp;lt;/InputXML&amp;gt;&lt;/InputXML&gt;&lt;/Parms&gt;&lt;/Request&gt;</strXMLParm></Exec>]]>""" 1019 CDATA_TEXT = """<![CDATA[<Exec xmlns="http://tempuri.org/"><strXMLParm>&lt;Request&gt;&lt;Framework&gt;&lt;UserName&gt;SFCHINA\qqcout0&lt;/UserName&gt;&lt;GUID&gt;70d0efcb-3bc2-4018-ac4e-681c8f3131b6&lt;/GUID&gt;&lt;DetailedTracingEnabled&gt;False&lt;/DetailedTracingEnabled&gt;&lt;ServiceName&gt;AMSWebService&lt;/ServiceName&gt;&lt;SupportsRedirection&gt;true&lt;/SupportsRedirection&gt;&lt;ServiceType&gt;Service&lt;/ServiceType&gt;&lt;/Framework&gt;&lt;Parms&gt;&lt;InputXML type="string"&gt;&amp;lt;?xml version="1.0" encoding="utf-16"?&amp;gt;&amp;lt;InputXML&amp;gt; &amp;lt;Result&amp;gt; {0} &amp;lt;/Result&amp;gt;&amp;lt;AuthorizationData&amp;gt;&amp;lt;ServiceComponent&amp;gt;OCR&amp;lt;/ServiceComponent&amp;gt;&amp;lt;RoleId/&amp;gt;&amp;lt;CompanyId/&amp;gt;&amp;lt;/AuthorizationData&amp;gt;&amp;lt;/InputXML&amp;gt;&lt;/InputXML&gt;&lt;/Parms&gt;&lt;/Request&gt;</strXMLParm></Exec>]]>"""
1020 1020
1021 RESULT_MAPPING = { 1021 RESULT_MAPPING = {
1022 MVI_CLASSIFY: 'mvi_ocr', 1022 # MVI_CLASSIFY: 'mvi_ocr',
1023 IC_CLASSIFY: 'ic_ocr', 1023 IC_CLASSIFY: 'ic_ocr',
1024 RP_CLASSIFY: 'rp_ocr', 1024 RP_CLASSIFY: 'rp_ocr',
1025 BC_CLASSIFY: 'bc_ocr', 1025 # BC_CLASSIFY: 'bc_ocr',
1026 BL_CLASSIFY: 'bl_ocr', 1026 BL_CLASSIFY: 'bl_ocr',
1027 UCI_CLASSIFY: 'uci_ocr', 1027 # UCI_CLASSIFY: 'uci_ocr',
1028 EEP_CLASSIFY: 'eep_ocr', 1028 EEP_CLASSIFY: 'eep_ocr',
1029 DL_CLASSIFY: 'dl_ocr', 1029 DL_CLASSIFY: 'dl_ocr',
1030 PP_CLASSIFY: 'pp_ocr', 1030 PP_CLASSIFY: 'pp_ocr',
1031 MVC_CLASSIFY: 'mvc_ocr', 1031 MVC_CLASSIFY: 'mvc_ocr',
1032 VAT_CLASSIFY: 'vat_ocr', 1032 # VAT_CLASSIFY: 'vat_ocr',
1033 } 1033 }
1034
1035 COMPARE_FIELDS = ('ic_ocr', 'rp_ocr', 'bl_ocr', 'eep_ocr', 'dl_ocr', 'pp_ocr', 'mvc_ocr')
1036
1037 # 身份证
1038 ITPRC = {
1039 'customerChineseName': ('姓名', 'common_compare', {}),
1040 'idNum': ('公民身份号码', 'common_compare', {}),
1041 # 20200410-20250410 OCR识别为长期,向GCAP发送:2099-12-31 00:00:00.0
1042 'idExpiryDate': ('有效期限', 'date_compare', {'long': True, 'ocr_split': True, 'input_replace': ''}),
1043 }
1044
1045 # 护照
1046 ITPSP = {
1047 'customerChineseName': ('英文姓名', 'common_compare', {}),
1048 'idNum': ('护照号码', 'common_compare', {}),
1049 'idExpiryDate': ('有效期至', 'date_compare', {'input_replace': ''}), # 20250410
1050 'dateOfBirth': ('出生日期', 'date_compare', {'input_replace': ''}), # 20250410
1051 }
1052
1053 # 港澳台通行证
1054 ITHKM_ITTID = {
1055 'customerChineseName': ('中文名', 'common_compare', {}),
1056 'idNum': ('证件号码', 'common_compare', {}),
1057 'idExpiryDate': ('有效期限', 'date_compare', {'ocr_split': True, 'input_replace': '.'}), # 2013.10.24-2023.10.23
1058 'dateOfBirth': ('出生日期', 'date_compare', {'input_replace': '.'}), # 2023.10.23
1059 # 'secondIdNum': ''
1060 }
1061
1062 # 居住证
1063 ITRES = {
1064 'customerChineseName': ('姓名', 'common_compare', {}),
1065 'idNum': ('公民身份号码', 'common_compare', {}),
1066 'idExpiryDate': ('有效期限', 'date_compare', {'ocr_split': True, 'input_replace': ''}), # 20200410-20250410
1067 'secondIdNum': ('通行证号码', 'common_compare', {})
1068 }
1069
1070 ID_TYPE_COMPARE = {
1071 'ITPRC': {'model_field': 'ic_ocr', 'compare_field': ITPRC},
1072 'ITPSP': {'model_field': 'pp_ocr', 'compare_field': ITPSP},
1073 'ITHKM': {'model_field': 'eep_ocr', 'compare_field': ITHKM_ITTID},
1074 'ITTID': {'model_field': 'eep_ocr', 'compare_field': ITHKM_ITTID},
1075 'ITRES': {'model_field': 'rp_ocr', 'compare_field': ITRES},
1076 }
1077
1078 # 1. 分别对比 POS车架号 vs 车辆登记正,POS车架号 vs 行驶证
1079 # a)两种比对 均一致:Y
1080 # b)其中一个 不一致:N,向GCAP发送:不一致的OCR识别结果
1081 # c)两中比对 均不一致:N,向GCAP发送:车辆登记证 & 行驶证识别结果
1082 # 车辆登记证
1083 PCUSD_MVC = {
1084 'vinNo': ('9.车辆识别代号/车架号', 'common_compare', {}),
1085 'manufactureDate': ('32.车辆出厂日期', 'common_compare', {}),
1086 'firstRegistrationDate': ('3.登记日期', 'common_compare', {}),
1087 }
1088
1089 # 行驶证
1090 PCUSD_DL = {
1091 'vinNo': ('车辆识别代码', 'common_compare', {}),
1092 # 'manufactureDate': '',
1093 # 'firstRegistrationDate': '',
1094 }
1095
1096 # 营业执照
1097 TCCOR = {
1098 'customerChineseName': ('企业名称', 'common_compare', {}),
1099 'legalRepName': ('经营者姓名', 'common_compare', {}),
1100 'idNum': ('注册号', 'common_compare', {}),
1101 'businessLicenseNo': ('注册号', 'common_compare', {}),
1102 'taxRegistrationCode': ('注册号', 'common_compare', {}),
1103 'incorporationDate': ('成立日期', 'date_compare', {'ocr_replace': True}), # 2017年07月11日
1104 # 2017年07月11日至长期 1. OCR识别为长期,向GCAP发送:2099-12-31 00:00:00.0
1105 'businessLicenseDueDate': ('营业期限', 'date_compare', {'long': True, 'ocr_replace': True}),
1106 'capitalRegAmount': ('注册资本', 'rmb_compare', {}), # 壹拾万元整 将OCR识别结果(人民币大写)转化为数字
1107 }
1108
1109 TCSEP = {
1110 'companyName': ('企业名称', 'common_compare', {}),
1111 'registeredCapital': ('注册资本', 'rmb_compare', {}), # 壹拾万元整 将OCR识别结果(人民币大写)转化为数字
1112 'selfEmployedSubType': ('企业类型', 'type_compare', {}), # 有限责任公司
1113 }
1114
1115 # 1. POS数据OCR识别结果对应关系如下:
1116 # a)Individual Businessman CSIBM => 个体工商户
1117 # b)Small and Micro Enterprise Owners CSSME => 个人独资企业、有限合伙企业、股份合作制、有限责任公司(***)【只需比对“有限责任公司”即可】
1118 # c)Others CSOTH => 识别结果不一致时,向GCAP发送 OCR的识别结果
1119
1120 RESULT_Y = 'Y'
1121 RESULT_N = 'N'
1122 RESULT_NA = 'NA'
1123
1124
1125
1126
......
...@@ -12,3 +12,7 @@ class OCR2Exception(Exception): ...@@ -12,3 +12,7 @@ class OCR2Exception(Exception):
12 12
13 class OCR4Exception(Exception): 13 class OCR4Exception(Exception):
14 pass 14 pass
15
16
17 class GCAPException(Exception):
18 pass
......
...@@ -888,53 +888,54 @@ class Command(BaseCommand, LoggerMixin): ...@@ -888,53 +888,54 @@ class Command(BaseCommand, LoggerMixin):
888 os.remove(excel_path) 888 os.remove(excel_path)
889 finally: 889 finally:
890 # TODO 识别结果存一张表,方便跑报表 890 # TODO 识别结果存一张表,方便跑报表
891 try: 891 if doc.document_scheme == consts.DOC_SCHEME_LIST[0]:
892 # 更新OCR累计识别结果表
893 result_class = HILOCRResult if business_type == consts.HIL_PREFIX else AFCOCRResult
894 res_obj = result_class.objects.filter(application_id=doc.application_id).first()
895 if res_obj is None:
896 res_obj = result_class()
897 res_obj.application_id = doc.application_id
898 for classify, field in consts.RESULT_MAPPING.items():
899 license_list = license_summary.get(classify)
900 if not license_list:
901 continue
902 if classify == consts.IC_CLASSIFY and ic_merge:
903 license_list[0].update(license_list[1])
904 license_list.pop(1)
905 elif classify == consts.RP_CLASSIFY and rp_merge:
906 license_list[0].update(license_list[1])
907 license_list.pop(1)
908 if not hasattr(res_obj, field):
909 continue
910 old_res_str = getattr(res_obj, field)
911 if old_res_str is None:
912 last_res_str = json.dumps(license_list)
913 else:
914 old_res_list = json.loads(old_res_str)
915 old_res_list.extend(license_list)
916 last_res_str = json.dumps(old_res_list)
917 setattr(res_obj, field, last_res_str)
918 res_obj.save()
919 except Exception as e:
920 self.online_log.error(
921 '{0} [process error (ocr result save)] [task={1}] [error={2}]'.format(
922 self.log_base, task_str, traceback.format_exc()))
923 else:
924 self.online_log.info('{0} [ocr result save success] [task={1}] [res_id={2}]'.format(
925 self.log_base, task_str, res_obj.id))
926 # 触发比对
927 try: 892 try:
928 pass 893 # 更新OCR累计识别结果表
929 # compare.apply_async((doc.application_id, business_type, None, res_obj.id), 894 result_class = HILOCRResult if business_type == consts.HIL_PREFIX else AFCOCRResult
930 # queue='queue_compare') 895 res_obj = result_class.objects.filter(application_id=doc.application_id).first()
896 if res_obj is None:
897 res_obj = result_class()
898 res_obj.application_id = doc.application_id
899 for classify, field in consts.RESULT_MAPPING.items():
900 license_list = license_summary.get(classify)
901 if not license_list:
902 continue
903 if classify == consts.IC_CLASSIFY and ic_merge:
904 license_list[0].update(license_list[1])
905 license_list.pop(1)
906 elif classify == consts.RP_CLASSIFY and rp_merge:
907 license_list[0].update(license_list[1])
908 license_list.pop(1)
909 if not hasattr(res_obj, field):
910 continue
911 old_res_str = getattr(res_obj, field)
912 if old_res_str is None:
913 last_res_str = json.dumps(license_list)
914 else:
915 old_res_list = json.loads(old_res_str)
916 old_res_list.extend(license_list)
917 last_res_str = json.dumps(old_res_list)
918 setattr(res_obj, field, last_res_str)
919 res_obj.save()
931 except Exception as e: 920 except Exception as e:
932 self.online_log.error( 921 self.online_log.error(
933 '{0} [process error (comparison info send)] [task={1}] [error={2}]'.format( 922 '{0} [process error (ocr result save)] [task={1}] [error={2}]'.format(
934 self.log_base, task_str, traceback.format_exc())) 923 self.log_base, task_str, traceback.format_exc()))
935 else: 924 else:
936 self.online_log.info('{0} [comparison info send success] [task={1}] ' 925 self.online_log.info('{0} [ocr result save success] [task={1}] [res_id={2}]'.format(
937 '[res_id={2}]'.format(self.log_base, task_str, res_obj.id)) 926 self.log_base, task_str, res_obj.id))
927 # 触发比对
928 try:
929 pass
930 # compare.apply_async((doc.application_id, business_type, None, res_obj.id),
931 # queue='queue_compare')
932 except Exception as e:
933 self.online_log.error(
934 '{0} [process error (comparison info send)] [task={1}] [error={2}]'.format(
935 self.log_base, task_str, traceback.format_exc()))
936 else:
937 self.online_log.info('{0} [comparison info send success] [task={1}] '
938 '[res_id={2}]'.format(self.log_base, task_str, res_obj.id))
938 finally: 939 finally:
939 try: 940 try:
940 img_save_path = os.path.join(doc_data_path, 'img') 941 img_save_path = os.path.join(doc_data_path, 'img')
......
...@@ -3,6 +3,7 @@ from requests.auth import HTTPBasicAuth ...@@ -3,6 +3,7 @@ from requests.auth import HTTPBasicAuth
3 from settings import conf 3 from settings import conf
4 from common.tools.dict_to_xml import dicttoxml, escape_xml 4 from common.tools.dict_to_xml import dicttoxml, escape_xml
5 from apps.doc import consts 5 from apps.doc import consts
6 from apps.doc.exceptions import GCAPException
6 7
7 8
8 class GCAP: 9 class GCAP:
...@@ -19,11 +20,10 @@ class GCAP: ...@@ -19,11 +20,10 @@ class GCAP:
19 comparison_xml = dicttoxml(comparison_res, root=False, attr_type=False) 20 comparison_xml = dicttoxml(comparison_res, root=False, attr_type=False)
20 return consts.BASE_XML_TEXT.format(consts.CDATA_TEXT.format(escape_xml(comparison_xml))).encode('utf-8') 21 return consts.BASE_XML_TEXT.format(consts.CDATA_TEXT.format(escape_xml(comparison_xml))).encode('utf-8')
21 22
22 def send(self, comparison_res): 23 def send(self, data):
23 data = self.dict_to_xml(comparison_res)
24 response = requests.post(self.url, headers=self.headers, data=data, verify=False, auth=self.auth) 24 response = requests.post(self.url, headers=self.headers, data=data, verify=False, auth=self.auth)
25 return response 25 if response.status_code != 200:
26 26 raise GCAPException('GCAP response with code: {0}'.format(response.status_code))
27
28 27
29 28
29 gcap = GCAP()
......
1 import json
1 import logging 2 import logging
3 import traceback
2 from . import app 4 from . import app
3 from apps.doc.models import AFCDoc 5 from apps.doc.models import AFCOCRResult, HILOCRResult, AFCComparisonInfo, HILComparisonInfo
6 from apps.doc import consts
7 from apps.doc.ocr.gcap import gcap
8 from apps.doc.exceptions import GCAPException
9 from common.tools.comparison import cp
4 10
5 compare_log = logging.getLogger('compare') 11 compare_log = logging.getLogger('compare')
12 log_base = '[CA Compare]'
6 13
7 14
8 @app.task 15 @app.task
...@@ -10,8 +17,190 @@ def compare(application_id, application_entity, uniq_seq, ocr_res_id): ...@@ -10,8 +17,190 @@ def compare(application_id, application_entity, uniq_seq, ocr_res_id):
10 # POS: application_id, application_entity, uniq_seq, None 17 # POS: application_id, application_entity, uniq_seq, None
11 # OCR: application_id, business_type(application_entity), None, ocr_res_id 18 # OCR: application_id, business_type(application_entity), None, ocr_res_id
12 19
20 compare_log.info('{0} [receive task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
21 log_base, application_entity, application_id, uniq_seq, ocr_res_id))
22
13 # 根据application_id查找最新的比对信息,如果没有,结束 23 # 根据application_id查找最新的比对信息,如果没有,结束
14 # 分析比对信息,需要比对的license 24 comparison_class = HILComparisonInfo if application_entity == consts.HIL_PREFIX else AFCComparisonInfo
25 last_obj = comparison_class.objects.filter(application_id=application_id).last()
26 if last_obj is None:
27 compare_log.info('{0} [comparison info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
28 log_base, application_entity, application_id, uniq_seq, ocr_res_id
29 ))
30 return
31
15 # 根据application_id查找OCR累计结果指定license字段,如果没有,结束 32 # 根据application_id查找OCR累计结果指定license字段,如果没有,结束
16 # 比对信息,将比对结果发送GCAP 33 result_class = HILOCRResult if application_entity == consts.HIL_PREFIX else AFCOCRResult
17 pass 34 if ocr_res_id is None:
35 ocr_res_dict = result_class.objects.filter(application_id=application_id).values(*consts.COMPARE_FIELDS).first()
36 else:
37 ocr_res_dict = result_class.objects.filter(id=ocr_res_id).values(*consts.COMPARE_FIELDS).first()
38 if ocr_res_dict is None:
39 compare_log.info('{0} [ocr info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
40 log_base, application_entity, application_id, uniq_seq, ocr_res_id
41 ))
42 return
43
44 # 比对信息
45 comparison_res = {
46 'OCR_Input': {
47 'uniqSeq': last_obj.uniq_seq,
48 'applicationId': application_id,
49 'applicationEntity': application_entity,
50 'applicationVersion': last_obj.application_version,
51 'vehicleStatus': last_obj.vehicle_status,
52 # 'wholeResult': 'Y',
53 'wholeResultMessage': '',
54 'applicationLink': '',
55 }
56 }
57
58 res_set = set()
59
60 is_sep = True if last_obj.customer_type == consts.CUSTOMER_TYPE[5] else False
61
62 individual_cus_info_list = json.loads(last_obj.individual_cus_info)
63 for individual_cus_info in individual_cus_info_list:
64 individual_cus_info['customerType'] = last_obj.customer_type
65 # sep营业执照
66 if is_sep and individual_cus_info.get('companyName') is not None:
67 sep_is_find = False
68 sep_ocr_res_str = ocr_res_dict.get('bl_ocr')
69 if sep_ocr_res_str is not None:
70 sep_ocr_list = json.loads(sep_ocr_res_str)
71 for sep_ocr in sep_ocr_list:
72 company_name = sep_ocr.get(consts.TCSEP.get('companyName')[0])
73 if company_name is None or company_name != individual_cus_info.get('companyName'):
74 continue
75 sep_is_find = True
76 for sep_field, sep_tuple in consts.TCSEP.items():
77 sep_res = getattr(cp, sep_tuple[1])(
78 individual_cus_info.get(sep_field), sep_ocr.get(sep_tuple[0]), sep_tuple[2])
79 individual_cus_info[sep_field + 'Result'] = sep_res
80 res_set.add(sep_res)
81 break
82 if not sep_is_find:
83 res_set.add(consts.RESULT_N)
84 for field in consts.TCSEP.keys():
85 individual_cus_info[field + 'Result'] = consts.RESULT_N
86
87 # 个人信息证件
88 id_type = individual_cus_info.get('idType')
89 compare_target = consts.ID_TYPE_COMPARE.get(id_type)
90 if compare_target is None:
91 continue
92 is_find = False
93 ocr_res_str = ocr_res_dict.get(compare_target.get('model_field'))
94 if ocr_res_str is not None:
95 ocr_res_list = json.loads(ocr_res_str)
96 compare_target_dict = compare_target.get('compare_field')
97 for ocr_res in ocr_res_list:
98 base_name = ocr_res.get(compare_target_dict.get('customerChineseName')[0])
99 if base_name is None or base_name != individual_cus_info.get('customerChineseName'): # TODO 特殊姓名比对
100 continue
101 is_find = True
102 for compare_field, compare_tuple in compare_target.get('compare_field').items():
103 compare_res = getattr(cp, compare_tuple[1])(
104 individual_cus_info.get(compare_field), ocr_res.get(compare_tuple[0]), compare_tuple[2])
105 individual_cus_info[compare_field + 'Result'] = compare_res
106 res_set.add(compare_res)
107 break
108 if not is_find:
109 res_set.add(consts.RESULT_N)
110 for field in compare_target.get('compare_field').keys():
111 individual_cus_info[field + 'Result'] = consts.RESULT_N
112
113 comparison_res['individualCusInfo'] = individual_cus_info_list
114
115 if last_obj.corporate_cus_info is not None:
116 corporate_cus_info = json.loads(last_obj.corporate_cus_info)
117 corporate_cus_info['customerType'] = last_obj.customer_type
118
119 is_bl_find = False
120 bl_ocr_res_str = ocr_res_dict.get('bl_ocr')
121 if bl_ocr_res_str is not None:
122 bl_ocr_list = json.loads(bl_ocr_res_str)
123 for bl_ocr in bl_ocr_list:
124 company_name = bl_ocr.get(consts.TCCOR.get('customerChineseName')[0])
125 if company_name is None or company_name != corporate_cus_info.get('customerChineseName'):
126 continue
127 is_bl_find = True
128 for bl_field, bl_tuple in consts.TCCOR.items():
129 bl_res = getattr(cp, bl_tuple[1])(
130 corporate_cus_info.get(bl_field), bl_ocr.get(bl_tuple[0]), bl_tuple[2])
131 corporate_cus_info[bl_field + 'Result'] = bl_res
132 res_set.add(bl_res)
133 break
134 if not is_bl_find:
135 res_set.add(consts.RESULT_N)
136 for field in consts.TCCOR.keys():
137 corporate_cus_info[field + 'Result'] = consts.RESULT_N
138
139 comparison_res['corporateCusInfo'] = corporate_cus_info
140
141 if last_obj.vehicle_status == consts.VEHICLE_STATUS[0] and last_obj.usedcar_info is not None:
142 usedcar_info = json.loads(last_obj.usedcar_info)
143
144 is_usedcar_find = False
145 mvc_ocr_res_str = ocr_res_dict.get('mvc_ocr')
146 if mvc_ocr_res_str is not None:
147 mvc_ocr_list = json.loads(mvc_ocr_res_str)
148 for mvc_ocr in mvc_ocr_list:
149 vin_no = mvc_ocr.get(consts.PCUSD_MVC.get('vinNo')[0])
150 if vin_no is None or vin_no != usedcar_info.get('vinNo'):
151 continue
152 is_usedcar_find = True
153 for mvc_field, mvc_tuple in consts.PCUSD_MVC.items():
154 mvc_res = getattr(cp, mvc_tuple[1])(
155 usedcar_info.get(mvc_field), mvc_ocr.get(mvc_tuple[0]), mvc_tuple[2])
156 usedcar_info[mvc_field + 'Result'] = mvc_res
157 res_set.add(mvc_res)
158
159 dl_find = False
160 dl_ocr_res_str = ocr_res_dict.get('dl_ocr')
161 if dl_ocr_res_str is not None:
162 dl_ocr_list = json.loads(dl_ocr_res_str)
163 for dl_ocr in dl_ocr_list:
164 dl_vin_no = dl_ocr.get(consts.PCUSD_DL.get('vinNo')[0])
165 if dl_vin_no is None or dl_vin_no != usedcar_info.get('vinNo'):
166 continue
167 dl_find = True
168 break
169 if not dl_find:
170 res_set.add(consts.RESULT_N)
171 usedcar_info['vinNo' + 'Result'] = consts.RESULT_N
172 break
173 if not is_usedcar_find:
174 res_set.add(consts.RESULT_N)
175 for field in consts.PCUSD_MVC.keys():
176 usedcar_info[field + 'Result'] = consts.RESULT_N
177 comparison_res['usedCarInfo'] = usedcar_info
178
179 comparison_res['wholeResult'] = consts.RESULT_N if consts.RESULT_N in res_set else consts.RESULT_Y
180 print(comparison_res)
181
182 # 将比对结果发送GCAP
183 # try:
184 # data = gcap.dict_to_xml(comparison_res)
185 # except Exception as e:
186 # compare_log.error('{0} [dict to xml failed] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
187 # '[error={5}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id,
188 # traceback.format_exc()))
189 # else:
190 # try:
191 # for times in range(consts.RETRY_TIMES):
192 # try:
193 # gcap.send(data)
194 # except Exception as e:
195 # gcap_exc = str(e)
196 # else:
197 # break
198 # else:
199 # raise GCAPException(gcap_exc)
200 # except Exception as e:
201 # compare_log.error('{0} [gcap failed] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] '
202 # '[error={5}]'.format(log_base, application_entity, application_id, uniq_seq,
203 # ocr_res_id, traceback.format_exc()))
204 # else:
205 # compare_log.info('{0} [task success] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}]'.format(
206 # log_base, application_entity, application_id, uniq_seq, ocr_res_id))
......
1 import re
2 from .rmb_upper import to_rmb_upper
3
4
5 class Comparison:
6
7 def __init__(self):
8 self.CSIBM = 'CSIBM'
9 self.CSSME = 'CSSME'
10 self.CSOTH = 'CSOTH'
11
12 self.TYPE_MAPPING = (
13 (r'个体工商户', self.CSIBM),
14 (r'有限责任公司', self.CSSME),
15 (r'个人独资企业', self.CSSME),
16 (r'有限合伙企业', self.CSSME),
17 (r'股份合作制', self.CSSME),
18 )
19
20 self.RESULT_Y = 'Y'
21 self.RESULT_N = 'N'
22 self.RESULT_NA = 'NA' # TODO NA情况
23
24 def build_res(self, result):
25 if result:
26 return self.RESULT_Y
27 else:
28 return self.RESULT_N
29
30 def common_compare(self, input_str, ocr_str, **kwargs):
31 return self.build_res(input_str == ocr_str)
32
33 def date_compare(self, input_str, ocr_str, **kwargs):
34 if kwargs.get('long', False) and '长期' in ocr_str:
35 return '2099-12-31'
36 if kwargs.get('ocr_split', False):
37 ocr_str = ocr_str.split('-')[-1]
38 if kwargs.get('ocr_replace', False):
39 ocr_str = ocr_str.replace('年', '-').replace('月', '-').replace('日', '')
40 if kwargs.get('input_replace') is not None:
41 input_str = input_str.replace('-', kwargs.get('replace'))
42 return self.build_res(input_str == ocr_str)
43
44 def rmb_compare(self, input_str, ocr_str, **kwargs):
45 input_rmb_upper = to_rmb_upper(float(input_str))
46 return self.build_res(input_rmb_upper == ocr_str)
47
48 def type_compare(self, input_str, ocr_str, **kwargs):
49 for map_tuple in self.TYPE_MAPPING:
50 if re.search(map_tuple[0], ocr_str) is not None:
51 compare_str = map_tuple[1]
52 break
53 else:
54 compare_str = self.CSOTH
55
56 return self.build_res(input_str == compare_str)
57
58
59 cp = Comparison()
60
61
1 from io import StringIO
2 import math
3
4 _RMB_DIGITS = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖' ]
5 _SECTION_CHARS = ['', '拾', '佰', '仟', '万' ]
6
7
8 def to_rmb_upper(price):
9 price = round(price, 2)
10 integer_part = int(price)
11 wanyi_part = integer_part // 1000000000000
12 yi_part = integer_part % 1000000000000 // 100000000
13 wan_part = integer_part % 100000000 // 10000
14 qian_part = integer_part % 10000
15 dec_part = int(round(price * 100 % 100))
16
17 strio = StringIO()
18
19 zero_count = 0
20 #处理万亿以上的部分
21 if integer_part >= 1000000000000 and wanyi_part > 0:
22 zero_count = _parse_integer(strio, wanyi_part, zero_count, True)
23 strio.write('万')
24
25 #处理亿到千亿的部分
26 if integer_part >= 100000000 and yi_part > 0:
27 is_first_section = integer_part >= 100000000 and integer_part < 1000000000000
28 zero_count = _parse_integer(strio, yi_part, zero_count, is_first_section)
29 strio.write('亿')
30
31 #处理万的部分
32 if integer_part >= 10000 and wan_part > 0:
33 is_first_section = integer_part >= 1000 and integer_part < 10000000
34 zero_count = _parse_integer(strio, wan_part, zero_count, is_first_section)
35 strio.write('万')
36
37 #处理千及以后的部分
38 if qian_part > 0:
39 is_first_section = integer_part < 1000
40 zero_count = _parse_integer(strio, qian_part, zero_count, is_first_section)
41 else:
42 zero_count += 1
43 if integer_part > 0:
44 strio.write('元')
45
46 #处理小数
47 if dec_part > 0:
48 _parse_decimal(strio, integer_part, dec_part, zero_count)
49 elif dec_part == 0 and integer_part > 0:
50 strio.write('整')
51 else:
52 strio.write('零元整')
53
54 return strio.getvalue()
55
56
57 def _parse_integer(strio, value, zero_count = 0, is_first_section = False):
58 assert value > 0 and value <= 9999
59 ndigits = int(math.floor(math.log10(value))) + 1
60 if value < 1000 and not is_first_section:
61 zero_count += 1
62 for i in range(0, ndigits):
63 factor = int(pow(10, ndigits - 1 - i))
64 digit = int(value / factor)
65 if digit != 0:
66 if zero_count > 0:
67 strio.write('零')
68 strio.write(_RMB_DIGITS[digit])
69 strio.write(_SECTION_CHARS[ndigits - i - 1])
70 zero_count = 0
71 else:
72 zero_count += 1
73 value -= value // factor * factor
74 return zero_count
75
76
77 def _parse_decimal(strio, integer_part, value, zero_count):
78 assert value > 0 and value <= 99
79 jiao = value // 10
80 fen = value % 10
81 if zero_count > 0 and (jiao > 0 or fen > 0) and integer_part > 0:
82 strio.write('零')
83 if jiao > 0:
84 strio.write(_RMB_DIGITS[jiao])
85 strio.write('角')
86 if zero_count == 0 and jiao == 0 and fen > 0 and integer_part > 0:
87 strio.write('零')
88 if fen > 0:
89 strio.write(_RMB_DIGITS[fen])
90 strio.write('分')
91 else:
92 strio.write('整')
...\ No newline at end of file ...\ No newline at end of file
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!