diff --git a/src/apps/doc/consts.py b/src/apps/doc/consts.py index a12f0a9..428f1a5 100644 --- a/src/apps/doc/consts.py +++ b/src/apps/doc/consts.py @@ -1178,6 +1178,7 @@ DDA_OCR_FIELD = 'bs_ocr' HMH_OCR_FIELD = 'hmh_ocr' JYPZ_OCR_FIELD = 'jypz_ocr' HT_FIELD = 'ht_ocr' +BD_FIELD = 'bd_ocr' RESULT_MAPPING = { MVI_CLASSIFY: MVI_OCR_FIELD, @@ -1195,6 +1196,7 @@ RESULT_MAPPING = { HMH_CLASSIFY: HMH_OCR_FIELD, JYPZ_CLASSIFY: JYPZ_OCR_FIELD, CONTRACT_CLASSIFY: HT_FIELD, + INSURANCE_CLASSIFY: BD_FIELD, } CA_ADD_COMPARE_FIELDS = (IC_OCR_FIELD, BL_OCR_FIELD) @@ -1213,6 +1215,7 @@ COMPARE_FIELDS = (MVI_OCR_FIELD, HMH_OCR_FIELD, JYPZ_OCR_FIELD, HT_FIELD, + BD_FIELD, ) # 身份证 @@ -1394,6 +1397,8 @@ SE_LAYOUT_VALUE = '旧版-旧打印、新版-新打印' SE_GB_NEW_FIELD = ['vinNo'] SE_GB_USED_FIELD = ['customerName', 'idNum', 'date'] SE_HMH_FIELD = ['借款人/承租人姓名', '借款人/承租人证件号', '申请号', '渠道', '签字'] +SE_BD_FIELD = ['被保险人姓名', '被保险人证件号码', '车架号', '机动车损失保险金额', '第三者责任保险金额', '绝对免赔率', '保险起始日期', '保险截止日期', '保单章', '第一受益人', '保险费合计'] +JDMPV_VALUE = ['-', '--', '0%', '0.00', '/', '0'] SE_BANK_FIELD = ['accountNo', 'bankName'] SE_DDA_FIELD = ['applicationId(1)', 'applicationId(2)', 'bankName', 'companyName', 'customerName', 'idNum', 'accountHolderName', 'accountNo'] @@ -1502,6 +1507,7 @@ DDA_EN = 'DDA' HMH_EN = 'Mortgage Waiver Letter' JYPZ_EN = 'Used Car Document' AFC_CONTRACT_EN = 'AFC Contract' +BD_EN = 'Insurance' SKIP_CARD = {SME_BL_EN} @@ -1643,6 +1649,20 @@ HMH_COMPARE_LOGIC = { '签字': ('借款人签字/盖章', 'se_common_compare', {}, '抵押登记豁免函签字需人工核查'), } +BD_COMPARE_LOGIC = { + '被保险人姓名': ('被保险人姓名', 'se_name_compare', {}, '保单被保险人姓名与系统不一致'), + '被保险人证件号码': ('被保险人证件号码', 'se_common_compare', {}, '保单被保险人证件号码与系统不一致'), + '车架号': ('车架号', 'se_common_compare', {}, '保单车架号与系统不一致'), + '机动车损失保险金额': ('机动车损失保险金额', 'se_amount_lte_compare', {}, '保单车损险异常'), + '第三者责任保险金额': ('机动车第三者责任保险金额', 'se_amount_lte_compare', {}, '保单三者险异常'), + '绝对免赔率': ('机动车损失保险绝对免赔率/绝对免赔额', 'se_one_compare', {}, '保单无绝对免赔项'), + '保险起始日期': ('保险起始日期', 'se_bd_date_compare', {'start': True}, '保单起始时间有误'), + '保险截止日期': ('保险截止日期', 'se_bd_date_compare', {}, '保单截止时间有误'), + '保单章': ('保单章', 'se_common_compare', {}, '保单无保单章'), + '第一受益人': ('特别约定第一受益人', 'se_common_compare', {}, '保单第一受益人有误,需人工核查'), + '保险费合计': ('保险费合计', 'se_amount_compare', {}, '保单保费疑似无法覆盖ASP保险融资'), +} + HT_COMPARE_LOGIC = { '合同编号-每页': ('合同编号-每页', 'se_list_compare', {}, '合同编号与系统不一致'), '所购车辆价格-小写-重要条款': ('所购车辆价格-小写-重要条款', 'se_amount_str_compare', {}, '合同首页中车辆价格与系统不一致'), @@ -1710,7 +1730,8 @@ SE_COMPARE_FIELD = { DDA_EN: (DDA_OCR_FIELD, DDA_COMPARE_LOGIC, False), HMH_EN: (HMH_OCR_FIELD, HMH_COMPARE_LOGIC, False), JYPZ_EN: (JYPZ_OCR_FIELD, JYPZ_COMPARE_LOGIC, False), - AFC_CONTRACT_EN: (HT_FIELD, HT_COMPARE_LOGIC, False) + AFC_CONTRACT_EN: (HT_FIELD, HT_COMPARE_LOGIC, False), + BD_EN: (BD_FIELD, BD_COMPARE_LOGIC, False), } diff --git a/src/apps/doc/models.py b/src/apps/doc/models.py index 1dceb74..5474a42 100644 --- a/src/apps/doc/models.py +++ b/src/apps/doc/models.py @@ -314,6 +314,7 @@ class AFCOCRResult(models.Model): hmh_ocr = models.TextField(null=True, verbose_name="豁免函") jypz_ocr = models.TextField(null=True, verbose_name="二手车交易凭证") ht_ocr = models.TextField(null=True, verbose_name="AFC合同") + bd_ocr = models.TextField(null=True, verbose_name="保单") update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') @@ -344,6 +345,7 @@ class HILOCRResult(models.Model): hmh_ocr = models.TextField(null=True, verbose_name="豁免函") jypz_ocr = models.TextField(null=True, verbose_name="二手车交易凭证") ht_ocr = models.TextField(null=True, verbose_name="AFC合同") + bd_ocr = models.TextField(null=True, verbose_name="保单") update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') @@ -373,6 +375,7 @@ class AFCSEOCRResult(models.Model): hmh_ocr = models.TextField(null=True, verbose_name="豁免函") jypz_ocr = models.TextField(null=True, verbose_name="二手车交易凭证") ht_ocr = models.TextField(null=True, verbose_name="AFC合同") + bd_ocr = models.TextField(null=True, verbose_name="保单") update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') @@ -403,6 +406,7 @@ class HILSEOCRResult(models.Model): hmh_ocr = models.TextField(null=True, verbose_name="豁免函") jypz_ocr = models.TextField(null=True, verbose_name="二手车交易凭证") ht_ocr = models.TextField(null=True, verbose_name="AFC合同") + bd_ocr = models.TextField(null=True, verbose_name="保单") update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') diff --git a/src/celery_compare/tasks.py b/src/celery_compare/tasks.py index 9a13d5b..203d4c5 100644 --- a/src/celery_compare/tasks.py +++ b/src/celery_compare/tasks.py @@ -879,8 +879,8 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): main_role_info = {} company_info_list = [] + # 个人信息证件--------------------------------------------------------------------------------------------------------- province = cms_info.get('province', '') - for individual_info in cms_info.get('applicantInformation', []): all_id_num = [] @@ -908,6 +908,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): field_input.append(('idExpiryDate', id_info.get('idExpiryDate', ''))) license_dict[license_en] = field_input all_id_num.append(id_num) + # 营业执照 -------------------------------------------------------------------------------------------------- elif id_info.get('idType') in ['Unified Social Credit Code', 'Tax Number', 'Business License Number']: # ['companyName', 'legalRepName', 'businessLicenseNo', 'organizationCreditCode', # 'taxRegistrationCertificateNo', 'establishmentDate', 'businessLicenseDueDate'] @@ -926,6 +927,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): if individual_info.get('customersubType', '') == 'Corporate': company_info_list.append((customer_name, id_num)) + # SME营业执照--------------------------------------------------------------------------------------------------- if individual_info.get('customersubType', '').startswith('Self Employed'): sep_field_input = [ ('legalRepName', customer_name), @@ -972,6 +974,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): first_submmison_date = cms_info.get('submissionDate', '') vin_no = cms_info.get('vehicleInformation', {}).get('vinNo', '') amount = str(cms_info.get('financialInformation', {}).get('vehiclePrice', '0.0')) + # 新车发票---------------------------------------------------------------------------------------------------------- if vehicle_status == 'New': vehicle_field_input.append(('vinNo', vin_no)) vehicle_field_input.append(('dealer', '、'.join([cms_info.get('dealerName', ''), cms_info.get('fapiaoIssuerDealer', '')]))) @@ -994,6 +997,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): ]))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[6], consts.SE_LAYOUT_VALUE)) vehicle_info[consts.MVI_EN] = vehicle_field_input + # 二手车发票、交易凭证、绿本------------------------------------------------------------------------------------------ else: gb_field_input = [ ('vinNo', vin_no), @@ -1033,6 +1037,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): vehicle_info[consts.UCI_EN] = vehicle_field_input compare_info['vehicleInfo'] = vehicle_info + # 银行卡------------------------------------------------------------------------------------------------------- bank_info = {} bank_name = cms_info.get('bankAccountDetails', {}).get('bankName', '') account_no = decode_des(cms_info.get('bankAccountDetails', {}).get('accountNo', ''), des_key) @@ -1044,6 +1049,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): ] bank_info[consts.BC_EN] = bank_field_input + # DDA------------------------------------------------------------------------------------------------------------ if is_gsyh or not detect_list[-1]: dda_field_input = [ ('applicationId(1)', last_obj.application_id), @@ -1058,9 +1064,10 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): bank_info[consts.DDA_EN] = dda_field_input compare_info['bankInfo'] = bank_info + # 抵押登记豁免函---------------------------------------------------------------------------------------------------- + other_info = {} full_no = cms_info.get('settlemnetVerification', {}).get('applicationNo', '') if cms_info.get('mortgageType', '') == 'Mortgage Free' or cms_info.get('mortgageType', '') == 'MortgageFree': - other_info = {} hmh_field_input = [ (consts.SE_HMH_FIELD[0], hmh_name), (consts.SE_HMH_FIELD[1], hmh_id), @@ -1069,11 +1076,96 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): (consts.SE_HMH_FIELD[4], consts.SE_STAMP_VALUE), ] other_info[consts.HMH_EN] = hmh_field_input + + # ASP ------------------------------------------------------------------------------------------------------- + asp_list = [] + gzs_status = consts.GZS_STATUS[1] + gzs_list = [gzs_status] + gzs_price = '0.00' + is_asp = False + insurance_price = None + if str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.00')) != '0.00': + is_asp = True + # for asp_info in cms_info.get('associatedServices', []): + for asp_info in cms_info.get('associatedServices', {}).get('SubassociatedServices', []): + tmp_asp_name = asp_info.get('associatedServices') + if isinstance(tmp_asp_name, str) and len(tmp_asp_name) > 0: + if gzs_status == consts.GZS_STATUS[1] and tmp_asp_name.find(consts.GZS_NAME) != -1: + gzs_status = consts.GZS_STATUS[2] + gzs_price = asp_info.get('price', '0.00') + asp_list.append( + ( + tmp_asp_name, + asp_info.get('price', '0.00'), + asp_info.get('financed', '0.00') + ) + ) + # 保单费合计 + if tmp_asp_name.find('机动车辆保险') != -1: + insurance_price = asp_info.get('price', '0.00') + + # fin_total = 0 + fin_total_tmp = cms_info.get('associatedServices', {}).get('financed total', '0.00') + fin_total = '0.00' if fin_total_tmp.strip() == '' else fin_total_tmp + for asp_name, _, asp_fin in asp_list: + if gzs_status == consts.GZS_STATUS[2] and asp_name.find(consts.GZS_NAME) == -1: + gzs_status = consts.GZS_STATUS[0] + # fin_total += float(asp_fin) + asp_list.append( + ( + consts.ASP_SUM_NAME, + '', + fin_total, + # format(fin_total, '.2f'), + ) + ) + + # CMS Vehicle Price / 1.13 * 10 % + if gzs_status != consts.GZS_STATUS[1]: + gzs_value = float(amount) * 0.1 / 1.13 + gzs_list.append(gzs_value) + gzs_list.append(float(gzs_price)) + + # 保单 ----------------------------------------------------------------------------------------------------------- + is_insurance = 0 + insurance_type = cms_info.get('insuranceDetails', {}).get('insuranceType', '') + if insurance_type == 'Waive Insurance' and isinstance(insurance_price, str): + is_insurance = 1 + elif insurance_type == 'Comprehensive Insurance': + is_insurance = 2 + if is_insurance != 0: + fp_campaign = cms_info.get('fpCampaign', '') + if fp_campaign.find('OCU') == -1: + ssx_amount = amount + else: + ssx_amount = format(float(amount) * 0.8, '.2f') + if fp_campaign.find('Joy_Plus') == -1: + dszx_amount = '200000' + else: + dszx_amount = '500000' + bd_field_input = [ + (consts.SE_BD_FIELD[0], hmh_name), + (consts.SE_BD_FIELD[1], hmh_id), + (consts.SE_BD_FIELD[2], vin_no), + (consts.SE_BD_FIELD[3], ssx_amount), + (consts.SE_BD_FIELD[4], dszx_amount), + (consts.SE_BD_FIELD[5], consts.JDMPV_VALUE), + (consts.SE_BD_FIELD[6], cms_info.get('insuranceDetails', {}).get('startDate', '')), + (consts.SE_BD_FIELD[7], cms_info.get('insuranceDetails', {}).get('endDate', '')), + (consts.SE_BD_FIELD[8], consts.SE_STAMP_VALUE), + (consts.SE_BD_FIELD[9], consts.SE_STAMP_VALUE), + ] + if is_insurance == 1: + bd_field_input.append((consts.SE_BD_FIELD[10], insurance_price)) + other_info[consts.BD_EN] = bd_field_input + + if len(other_info) > 0: compare_info['other'] = other_info if application_entity in consts.HIL_SET: return compare_info, cms_info.get('applicationVersion', 1) + # AFC合同----------------------------------------------------------------------------------------------------------- contract_info = {} schedule_list = [] @@ -1105,55 +1197,15 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list): (consts.SE_AFC_CON_FIELD[17], schedule_list_str), ] - if str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.00')) == '0.00': + if is_asp: + afc_contract_input.append((consts.SE_AFC_CON_FIELD[20], asp_list)) + afc_contract_input.append((consts.SE_AFC_CON_FIELD[22], asp_list)) + afc_contract_input.append((consts.SE_AFC_CON_FIELD[21], gzs_list)) + else: afc_contract_input.pop(5) afc_contract_input.pop(5) afc_contract_input.pop(9) afc_contract_input.pop(9) - else: - asp_list = [] - gzs_status = consts.GZS_STATUS[1] - gzs_price = '0.00' - # for asp_info in cms_info.get('associatedServices', []): - for asp_info in cms_info.get('associatedServices', {}).get('SubassociatedServices', []): - tmp_asp_name = asp_info.get('associatedServices') - if isinstance(tmp_asp_name, str) and len(tmp_asp_name) > 0: - if gzs_status == consts.GZS_STATUS[1] and tmp_asp_name.find(consts.GZS_NAME) != -1: - gzs_status = consts.GZS_STATUS[2] - gzs_price = asp_info.get('price', '0.00') - asp_list.append( - ( - tmp_asp_name, - asp_info.get('price', '0.00'), - asp_info.get('financed', '0.00') - ) - ) - - # fin_total = 0 - fin_total_tmp = cms_info.get('associatedServices', {}).get('financed total', '0.00') - fin_total = '0.00' if fin_total_tmp.strip() == '' else fin_total_tmp - for asp_name, _, asp_fin in asp_list: - if gzs_status == consts.GZS_STATUS[2] and asp_name.find(consts.GZS_NAME) == -1: - gzs_status = consts.GZS_STATUS[0] - # fin_total += float(asp_fin) - asp_list.append( - ( - consts.ASP_SUM_NAME, - '', - fin_total, - # format(fin_total, '.2f'), - ) - ) - afc_contract_input.append((consts.SE_AFC_CON_FIELD[20], asp_list)) - afc_contract_input.append((consts.SE_AFC_CON_FIELD[22], asp_list)) - - # CMS Vehicle Price / 1.13 * 10 % - gzs_list = [gzs_status] - if gzs_status != consts.GZS_STATUS[1]: - gzs_value = float(amount) * 0.1 / 1.13 - gzs_list.append(gzs_value) - gzs_list.append(float(gzs_price)) - afc_contract_input.append((consts.SE_AFC_CON_FIELD[21], gzs_list)) # '借款人签字及时间', 'Borrower', 0, 0, True online_sign = cms_info.get('contractSource', 'Online Sign') == 'Online Sign' @@ -1445,6 +1497,8 @@ def se_compare_license(license_en, ocr_res_dict, field_list): special_expiry_date_slice = True else: img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY, '') if result == consts.RESULT_N else empty_str + if isinstance(value, list): + value = json.dumps(value, ensure_ascii=False) error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value result_field_list.append((name, value, result, ocr_str, img_path, error_type, compare_logic[name][3])) else: @@ -1452,6 +1506,8 @@ def se_compare_license(license_en, ocr_res_dict, field_list): if not is_find: for name, value in field_list: + if isinstance(value, list): + value = json.dumps(value, ensure_ascii=False) result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value, '{0}未找到'.format(license_en))) if is_find: diff --git a/src/common/tools/comparison.py b/src/common/tools/comparison.py index 07027a0..6f70031 100644 --- a/src/common/tools/comparison.py +++ b/src/common/tools/comparison.py @@ -363,6 +363,15 @@ class Comparison: input_tmp = input_str.replace('元', '').replace(',', '') return self.build_res(ocr_tmp == input_tmp) + def se_amount_lte_compare(self, input_str, ocr_str, **kwargs): + try: + float_input = float(input_str) + float_ocr = float(ocr_str) + except Exception as e: + return self.RESULT_N + else: + return self.build_res(float_ocr >= float_input) + def se_amount_compare(self, input_str, ocr_str, **kwargs): if input_str == ocr_str: return self.RESULT_Y @@ -375,6 +384,12 @@ class Comparison: else: return self.build_res(float_ocr == float_input) + def se_one_compare(self, input_list, ocr_str, **kwargs): + if isinstance(input_list, list): + if ocr_str in input_list: + return self.RESULT_Y + return self.RESULT_N + def se_company_compare(self, input_str, ocr_str, **kwargs): input_tmp = re.sub(self.re_obj, '', input_str).strip() ocr_tmp = re.sub(self.re_obj, '', ocr_str).strip() @@ -439,6 +454,24 @@ class Comparison: else: return self.build_res(compare_date <= ocr_date) + def se_bd_date_compare(self, input_str, ocr_str, **kwargs): + try: + input_date = datetime.strptime(input_str, "%Y-%m-%d").date() + ocr_date = datetime.strptime(ocr_str, "%Y-%m-%d").date() + if kwargs.get('start', False): + if input_date != ocr_date: + return self.RESULT_N + + six_month_date = (datetime.today() - relativedelta(months=6)).date() + today_date = datetime.today().date() + return self.build_res(six_month_date <= ocr_date <= today_date) + else: + if input_date == ocr_date or ocr_date == input_date + relativedelta(days=1): + return self.RESULT_Y + return self.RESULT_N + except Exception as e: + return self.RESULT_N + cp = Comparison() diff --git a/src/common/tools/mssql_script11.py b/src/common/tools/mssql_script11.py new file mode 100644 index 0000000..9047677 --- /dev/null +++ b/src/common/tools/mssql_script11.py @@ -0,0 +1,27 @@ +import pyodbc + +hil_sql = """ + ALTER TABLE hil_ocr_result ADD bd_ocr nvarchar(max); + ALTER TABLE hil_se_ocr_result ADD bd_ocr nvarchar(max); +""" + +afc_sql = """ + ALTER TABLE afc_ocr_result ADD bd_ocr nvarchar(max); + ALTER TABLE afc_se_ocr_result ADD bd_ocr nvarchar(max); +""" + +hil_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True) + +hil_cursor = hil_cnxn.cursor() +hil_cursor.execute(hil_sql) + +hil_cursor.close() +hil_cnxn.close() + +afc_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True) + +afc_cursor = afc_cnxn.cursor() +afc_cursor.execute(afc_sql) + +afc_cursor.close() +afc_cnxn.close()