import json import os import cv2 import time import logging import traceback import numpy as np from datetime import datetime, timedelta from collections import OrderedDict from . import app from settings import conf from apps.doc.models import ( AFCOCRResult, AFCSEOCRResult, HILOCRResult, HILSEOCRResult, AFCComparisonInfo, AFCSEComparisonInfo, AFCSECMSInfo, HILComparisonInfo, HILSEComparisonInfo, HILSECMSInfo, Configs, HILCompareReport, AFCCompareReport, AFCSECompareResult, AFCCACompareResult, HILSECompareResult, HILCACompareResult, HILAutoSettlement, AFCAutoSettlement, ) from apps.doc import consts from apps.doc.ocr.gcap import gcap from apps.doc.ocr.cms import cms from apps.doc.exceptions import GCAPException from apps.doc.named_enum import RequestTeam, RequestTrigger, ProcessName, ErrorType from common.tools.comparison import cp from common.tools.des import decode_des compare_log = logging.getLogger('compare') log_base = '[Compare]' # e_log_base = '[e-contract]' empty_str = '' empty_error_type = 1000 des_key = conf.CMS_DES_KEY def rotate_bound(image, angle): # grab the dimensions of the image and then determine the # center (h, w) = image.shape[:2] (cX, cY) = (w // 2, h // 2) # grab the rotation matrix (applying the negative of the # angle to rotate clockwise), then grab the sine and cosine # (i.e., the rotation components of the matrix) M = cv2.getRotationMatrix2D((cX, cY), angle, 1.0) cos = np.abs(M[0, 0]) sin = np.abs(M[0, 1]) # compute the new bounding dimensions of the image nW = int((h * sin) + (w * cos)) nH = int((h * cos) + (w * sin)) # adjust the rotation matrix to take into account translation M[0, 2] += (nW / 2) - cX M[1, 2] += (nH / 2) - cY # perform the actual rotation and return the image return cv2.warpAffine(image, M, (nW, nH)) def build_coordinates(section_position_dict): if isinstance(section_position_dict, dict): h_min = section_position_dict.get('top', 0) w_min = section_position_dict.get('left', 0) h_max = h_min + section_position_dict.get('height', 0) w_max = w_min + section_position_dict.get('width', 0) if h_max > h_min and w_max > w_min: return True, (h_min, h_max, w_min, w_max) else: return False, () return False, () def field_build_coordinates(field_position_info): field_position_dict = field_position_info.get(consts.FIELD_POSITION_KEY, {}) field_quad_list = field_position_info.get(consts.FIELD_QUAD_KEY, []) if isinstance(field_quad_list, list) and len(field_quad_list) == 8: w_list = [field_quad_list[0], field_quad_list[2], field_quad_list[4], field_quad_list[6]] h_list = [field_quad_list[1], field_quad_list[3], field_quad_list[5], field_quad_list[7]] h_min = min(h_list) h_max = max(h_list) w_min = min(w_list) w_max = max(w_list) if h_max > h_min and w_max > w_min: return True, (h_min, h_max, w_min, w_max) if isinstance(field_position_dict, dict): h_min = field_position_dict.get('top', 0) w_min = field_position_dict.get('left', 0) h_max = h_min + field_position_dict.get('height', 0) w_max = w_min + field_position_dict.get('width', 0) if h_max > h_min and w_max > w_min: return True, (h_min, h_max, w_min, w_max) else: return False, () return False, () def img_process(section_img_path, section_position, section_angle): image = cv2.imread(section_img_path) is_valid, coord_tuple = build_coordinates(section_position) if is_valid: image = image[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :] if isinstance(section_angle, int) or isinstance(section_angle, float): if section_angle != 0: return rotate_bound(image, section_angle) return image def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name): id_field = second_compare_list[1][1] name_field = second_compare_list[0][1] ocr_res_str = ocr_res_dict.get(second_ocr_field) if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) for ocr_res in ocr_res_list: ocr_second_id_num = ocr_res.get(id_field) if ocr_second_id_num == second_id_num: ocr_name = ocr_res.get(name_field) if ocr_name == name: return True return False def get_order_dict(src_dict, order_tuple): order_dict = OrderedDict({}) for field in order_tuple: if field in src_dict: order_dict[field] = src_dict[field] return order_dict def do_not_compare(info_dict, compare_list): for compare_tuple in compare_list: info_dict[compare_tuple[4]] = consts.RESULT_NA if compare_tuple[0] in info_dict: del info_dict[compare_tuple[0]] def field_compare(info_dict, ocr_res_dict, ocr_field, compare_list, res_set, has_expiry_date=False, sep_name=None, capital_ignore=False): is_find = False ocr_res_str = ocr_res_dict.get(ocr_field) if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) # length = len(ocr_res_list) # sep营业执照根据法人过滤 if isinstance(sep_name, str): tmp_list = [] for ocr_res in ocr_res_list: ocr_sep_name = ocr_res.get(consts.LEGAL_REP_NAME) if isinstance(ocr_sep_name, str) and ocr_sep_name == sep_name: tmp_list.append(ocr_res) else: tmp_list = ocr_res_list length = len(tmp_list) # 过期期限特殊处理 if has_expiry_date: expiry_dates = [] key = compare_list[2][1] for ocr_res in tmp_list: # for ocr_res in ocr_res_list: if ocr_res.get(key): expiry_dates.append(ocr_res.get(key)) else: expiry_dates = [] for res_idx in range(length-1, -1, -1): # for ocr_res in ocr_res_list: if is_find: break ocr_res = tmp_list[res_idx] for idx, compare_tuple in enumerate(compare_list): input_str = info_dict.get(compare_tuple[0]) ocr_str = ocr_res.get(compare_tuple[1]) compare_res, ocr_output = getattr(cp, compare_tuple[2])( input_str, ocr_str, idx, **compare_tuple[3]) # print('type: {0}, idx: {1}, field: {2}, input: {3}, ocr: {4}, res: {5}, out: {6}'.format(ocr_field, idx, compare_tuple[0], input_str, ocr_str, compare_res, ocr_output)) if idx == 0 and compare_res in [consts.RESULT_N, consts.RESULT_NA] and length > 1: break is_find = True # 过期期限特殊处理 if idx == 2 and has_expiry_date and compare_res == consts.RESULT_NA: for expiry_date in expiry_dates: expiry_date_compare_res, expiry_date_ocr_output = getattr(cp, compare_tuple[2])( input_str, expiry_date, idx, **compare_tuple[3] ) if expiry_date_compare_res == consts.RESULT_Y: compare_res = consts.RESULT_Y ocr_output = expiry_date_ocr_output ocr_str = expiry_date break info_dict[compare_tuple[4]] = compare_res if input_str is not None: if ocr_str is None or ocr_output is None: del info_dict[compare_tuple[0]] else: info_dict[compare_tuple[0]] = ocr_output if capital_ignore and idx == 1: pass elif capital_ignore and idx == 2 and input_str is None: pass else: res_set.add(compare_res) if not is_find: res_set.add(consts.RESULT_N) for compare_tuple in compare_list: info_dict[compare_tuple[4]] = consts.RESULT_NA if compare_tuple[0] in info_dict: del info_dict[compare_tuple[0]] def usedcar_info_compare(info_dict, ocr_res_dict, ocr_field, compare_list, res_set): no_match_vino = [] is_find = False key_right = False ocr_res_str = ocr_res_dict.get(ocr_field) if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) # 3、4页/副页去除 # if ocr_field == consts.MVC_OCR_FIELD: tmp_list = [] for res in ocr_res_list: if res.get(compare_list[0][1]) is not None: tmp_list.append(res) length = len(tmp_list) for res_idx in range(length-1, -1, -1): if is_find: break ocr_res = tmp_list[res_idx] for idx, compare_tuple in enumerate(compare_list): input_str = info_dict.get(compare_tuple[0]) ocr_str = ocr_res.get(compare_tuple[1]) compare_res, ocr_output = getattr(cp, compare_tuple[2])( input_str, ocr_str, idx, **compare_tuple[3]) # print('type: {0}, idx: {1}, field: {2}, input: {3}, ocr: {4}, res: {5}, out: {6}'.format(ocr_field, idx, compare_tuple[0], input_str, ocr_str, compare_res, ocr_output)) if idx == 0 and compare_res in [consts.RESULT_N, consts.RESULT_NA]: if ocr_str is not None: no_match_vino.append(ocr_str) if length > 1: break is_find = True if idx == 0 and compare_res == consts.RESULT_Y: key_right = True info_dict[compare_tuple[4]] = compare_res if input_str is not None: if idx != 0: if ocr_str is None or ocr_output is None: del info_dict[compare_tuple[0]] else: info_dict[compare_tuple[0]] = ocr_output res_set.add(compare_res) if not is_find: res_set.add(consts.RESULT_N) for idx, compare_tuple in enumerate(compare_list): info_dict[compare_tuple[4]] = consts.RESULT_NA if idx == 0: continue if compare_tuple[0] in info_dict: del info_dict[compare_tuple[0]] return is_find and key_right, no_match_vino def get_ca_compare_info(last_obj): compare_info = {} individual_info_dict = {} for individual_info in json.loads(last_obj.individual_cus_info): license_dict = {} if individual_info['idType'] in consts.CA_FIRST_ID_FIELD_MAPPING: license_en, field_list = consts.CA_FIRST_ID_FIELD_MAPPING[individual_info['idType']] field_input = [] for field in field_list: if field in individual_info: field_input.append((field, individual_info.get(field, ''))) license_dict[license_en] = field_input if individual_info.get('secondIdType') in consts.CA_SECOND_ID_FIELD_MAPPING: second_license_en, second_field_list = consts.CA_SECOND_ID_FIELD_MAPPING[individual_info['secondIdType']] if second_license_en not in license_dict: second_field_input = [] for second_field, write_field in second_field_list: if second_field in individual_info: second_field_input.append((write_field, individual_info.get(second_field, ''))) license_dict[second_license_en] = second_field_input if individual_info['customerType'] == consts.CUSTOMER_TYPE[5]: sep_field_input = [] for sep_field in consts.CA_SEP_FIELD: if sep_field in individual_info: sep_field_input.append((sep_field, individual_info.get(sep_field, ''))) license_dict[consts.BL_EN] = sep_field_input if len(license_dict) > 0: individual_info_dict.setdefault(individual_info['applicantType'], []).append(license_dict) compare_info['individualCusInfo'] = individual_info_dict if isinstance(last_obj.corporate_cus_info, str): corporate_info_dict = json.loads(last_obj.corporate_cus_info) corporate_info = {} bl_field_input = [] for bl_field, write_field in consts.CA_CORPORATE_FIELD: bl_field_input.append((write_field, corporate_info_dict.get(bl_field, ''))) corporate_info[consts.BL_EN] = bl_field_input compare_info['corporateCusInfo'] = corporate_info if last_obj.vehicle_status == consts.VEHICLE_STATUS[0] and isinstance(last_obj.usedcar_info, str): usedcar_info_dict = json.loads(last_obj.usedcar_info) usedcar_info = {} mvc_field_input = [] for mvc_field in consts.CA_MVC_FIELD: mvc_field_input.append((mvc_field, usedcar_info_dict.get(mvc_field, ''))) usedcar_info[consts.MVC_EN] = mvc_field_input dl_field_input = [] for dl_field in consts.CA_DL_FIELD: dl_field_input.append((dl_field, usedcar_info_dict.get(dl_field, ''))) usedcar_info[consts.DL_EN] = dl_field_input compare_info['usedCarInfo'] = usedcar_info return compare_info def ca_compare_license(license_en, ocr_res_dict, field_list): ocr_field, compare_logic, special_expiry_date = consts.CA_COMPARE_FIELD[license_en] is_find = False special_expiry_date_slice = False result_field_list = [] section_img_info = dict() field_img_path_dict = dict() ocr_res_str = ocr_res_dict.get(ocr_field) if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) # 副页去除 3/4页去除 if ocr_field == consts.DL_OCR_FIELD or ocr_field == consts.MVC_OCR_FIELD: tmp_list = [] for res in ocr_res_list: if compare_logic['vinNo'][0] in res: tmp_list.append(res) ocr_res_list = tmp_list length = len(ocr_res_list) # 身份证、居住证 过期期限特殊处理 if special_expiry_date: expiry_dates = set() expiry_dates_img_path = set() key = compare_logic.get('idExpiryDate')[0] for ocr_res in ocr_res_list: if key in ocr_res: expiry_dates.add(ocr_res[key]) expiry_dates_img_path.add(ocr_res.get(consts.IMG_PATH_KEY_2, '')) else: expiry_dates = set() expiry_dates_img_path = set() for res_idx in range(length-1, -1, -1): if is_find: break for idx, (name, value) in enumerate(field_list): ocr_str = ocr_res_list[res_idx].get(compare_logic[name][0]) if not isinstance(ocr_str, str): result = consts.RESULT_N ocr_str = empty_str else: result = getattr(cp, compare_logic[name][1])(value, ocr_str, **compare_logic[name][2]) if idx == 0 and result == consts.RESULT_N and length > 1: break is_find = True section_img_info[consts.SECTION_IMG_PATH_KEY] = ocr_res_list[res_idx].get(consts.SECTION_IMG_PATH_KEY, '') section_img_info[consts.ALL_POSITION_KEY] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY, {}) if special_expiry_date: section_img_info[consts.SECTION_IMG_PATH_KEY_2] = ocr_res_list[res_idx].get( consts.SECTION_IMG_PATH_KEY_2, '') section_img_info[consts.ALL_POSITION_KEY_2] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, {}) # 过期期限特殊处理 if special_expiry_date and name == 'idExpiryDate' and result == consts.RESULT_N: for expiry_date in expiry_dates: expiry_date_res = getattr(cp, compare_logic[name][1])(value, expiry_date, **compare_logic[name][2]) if expiry_date_res == consts.RESULT_Y: ocr_str = expiry_date result = expiry_date_res break if result == consts.RESULT_N: if consts.IMG_PATH_KEY_2 in ocr_res_list[res_idx]: img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY_2, '') special_expiry_date_slice = True else: img_path = expiry_dates_img_path.pop() if len(expiry_dates_img_path) > 0 else empty_str else: img_path = empty_str else: img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY, '') if result == consts.RESULT_N else empty_str 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)) if not is_find: for name, value in field_list: result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value)) if is_find: if special_expiry_date_slice: special_section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY_2, '') if os.path.exists(special_section_img_path): field = 'idExpiryDate' special_info = section_img_info.get(consts.ALL_POSITION_KEY_2, {}) special_section_position = special_info.get(consts.POSITION_KEY, {}) special_section_angle = special_info.get(consts.ANGLE_KEY, 0) try: last_img = img_process(special_section_img_path, special_section_position, special_section_angle) except Exception as e: field_img_path_dict[field] = special_section_img_path else: pre, suf = os.path.splitext(special_section_img_path) try: res_field = compare_logic[field][0] is_valid, coord_tuple = field_build_coordinates(special_info.get(res_field, {})) if is_valid: save_path = '{0}_{1}{2}'.format(pre, field, suf) field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :] cv2.imwrite(save_path, field_img) field_img_path_dict[field] = save_path else: field_img_path_dict[field] = special_section_img_path except Exception as e: field_img_path_dict[field] = special_section_img_path section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY, '') if os.path.exists(section_img_path): failed_field = [] base_img_path = empty_str for name, _, result, _, img_path, _ in result_field_list: if result == consts.RESULT_N: if special_expiry_date_slice and name == 'idExpiryDate': continue failed_field.append(name) if base_img_path == empty_str: base_img_path = img_path if len(failed_field) > 0: info = section_img_info.get(consts.ALL_POSITION_KEY, {}) section_position = info.get(consts.POSITION_KEY, {}) section_angle = info.get(consts.ANGLE_KEY, 0) try: last_img = img_process(section_img_path, section_position, section_angle) except Exception as e: for field in failed_field: field_img_path_dict[field] = base_img_path else: pre, suf = os.path.splitext(section_img_path) for field in failed_field: try: if license_en == consts.PP_EN: res_field = consts.PP_SLICE_MAP[field] else: res_field = compare_logic[field][0] is_valid, coord_tuple = field_build_coordinates(info.get(res_field, {})) if is_valid: save_path = '{0}_{1}{2}'.format(pre, field, suf) field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :] cv2.imwrite(save_path, field_img) field_img_path_dict[field] = save_path else: field_img_path_dict[field] = base_img_path except Exception as e: field_img_path_dict[field] = base_img_path return result_field_list, field_img_path_dict def ca_compare_process(compare_info, ocr_res_dict): # individualCusInfo # corporateCusInfo # usedCarInfo compare_result = [] total_fields = 0 failed_count = 0 for info_key, info_value in compare_info.items(): if info_key == 'individualCusInfo': for idx, license_list in info_value.items(): for license_dict in license_list: for license_en, field_list in license_dict.items(): result_field_list, field_img_path_dict = ca_compare_license(license_en, ocr_res_dict, field_list) for name, value, result, ocr_str, img_path, error_type in result_field_list: total_fields += 1 if result == consts.RESULT_N: failed_count += 1 compare_result.append( { consts.HEAD_LIST[0]: info_key, consts.HEAD_LIST[1]: idx, consts.HEAD_LIST[2]: license_en, consts.HEAD_LIST[3]: name, consts.HEAD_LIST[4]: value, consts.HEAD_LIST[5]: ocr_str, consts.HEAD_LIST[6]: result, consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str), consts.HEAD_LIST[8]: img_path, consts.HEAD_LIST[9]: error_type, } ) else: for license_en, field_list in info_value.items(): result_field_list, field_img_path_dict = ca_compare_license(license_en, ocr_res_dict, field_list) for name, value, result, ocr_str, img_path, error_type in result_field_list: total_fields += 1 if result == consts.RESULT_N: failed_count += 1 compare_result.append( { consts.HEAD_LIST[0]: info_key, consts.HEAD_LIST[1]: "0", consts.HEAD_LIST[2]: license_en, consts.HEAD_LIST[3]: name, consts.HEAD_LIST[4]: value, consts.HEAD_LIST[5]: ocr_str, consts.HEAD_LIST[6]: result, consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str), consts.HEAD_LIST[8]: img_path, consts.HEAD_LIST[9]: error_type, } ) return compare_result, total_fields, failed_count def ca_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict): start_time = datetime.now() try: # 比对逻辑 compare_info = get_ca_compare_info(last_obj) compare_result, total_fields, failed_count = ca_compare_process(compare_info, ocr_res_dict) compare_log.info('{0} [CA] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format( log_base, application_entity, application_id, ocr_res_id, compare_result)) except Exception as e: compare_log.error('{0} [CA] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) else: # 将比对结果写入数据库 try: result_table = HILCACompareResult if application_entity == consts.HIL_PREFIX else AFCCACompareResult res_obj = result_table.objects.filter(application_id=application_id).first() if res_obj is None: res_obj = result_table() res_obj.application_id = application_id res_obj.compare_count = total_fields res_obj.failed_count = failed_count res_obj.is_finish = failed_count == 0 res_obj.version = '{0}{1}{2}'.format(consts.INFO_SOURCE[0], consts.SPLIT_STR, last_obj.application_version) # res_obj.reason1_count = reason1_count res_obj.result = json.dumps(compare_result) res_obj.update_time = start_time res_obj.save() compare_log.info('{0} [CA] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) except Exception as e: compare_log.error('{0} [CA] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) compare_failed = False application_link = '{0}/showList/showList?entity={1}&scheme={2}&case_id={3}'.format( conf.BASE_URL, application_entity, consts.COMPARE_DOC_SCHEME_LIST[0], application_id) # 比对信息 try: comparison_res = OrderedDict({ 'OCR_Input': { 'uniqSeq': last_obj.uniq_seq, 'applicationId': application_id, 'applicationEntity': application_entity, 'applicationVersion': last_obj.application_version, 'vehicleStatus': last_obj.vehicle_status, 'wholeResult': 'N', 'wholeResultMessage': empty_str, 'applicationLink': application_link.replace('&', '&'), } }) res_set = set() # is_sep = True if last_obj.customer_type == consts.CUSTOMER_TYPE[5] else False individual_cus_info_list = json.loads(last_obj.individual_cus_info) order_individual_cus_info_list = [] for individual_cus_info in individual_cus_info_list: order_individual_cus_info = get_order_dict(individual_cus_info, consts.IN_ORDER) cus_type = order_individual_cus_info.get('customerType') # 获取sep下营业执照法人代表 if cus_type == consts.CUSTOMER_TYPE[5]: sep_name = order_individual_cus_info.get('customerChineseName') if isinstance(sep_name, str): sep_name = sep_name.strip() if sep_name == empty_str: sep_name = None else: sep_name = None # 个人信息证件 id_type = order_individual_cus_info.get('idType') if id_type not in consts.ID_TYPE_COMPARE: do_not_compare(order_individual_cus_info, consts.ITPRC) else: ocr_field, compare_list, has_expiry_date = consts.ID_TYPE_COMPARE.get(id_type) field_compare(order_individual_cus_info, ocr_res_dict, ocr_field, compare_list, res_set, has_expiry_date=has_expiry_date) # 第二证件 second_id_type = order_individual_cus_info.get('secondIdType') if second_id_type is not None: if second_id_type not in consts.SECOND_ID_TYPE_COMPARE: do_not_compare(order_individual_cus_info, consts.SECOND_ITPRC) else: second_ocr_field, second_compare_list = consts.SECOND_ID_TYPE_COMPARE.get(second_id_type) field_compare(order_individual_cus_info, ocr_res_dict, second_ocr_field, second_compare_list, res_set) # 姓名比对 second_id_res = order_individual_cus_info.pop(consts.SECOND_ID_RES, consts.RESULT_NA) if second_id_res == consts.RESULT_Y: second_id_num = order_individual_cus_info.get(consts.SECOND_ID_FIELD) name = order_individual_cus_info.get(consts.NAME_FIELD) if isinstance(second_id_num, str) and isinstance(name, str): second_ocr_field, second_compare_list, _ = consts.ID_TYPE_COMPARE.get(second_id_type) name_right = name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name) if not name_right: res_set.add(consts.RESULT_N) second_id_res = consts.RESULT_N order_individual_cus_info[consts.SECOND_ID_FIELD] = '{0}-{1}'.format(second_id_num, name) # 重新排列 new_dict = OrderedDict({}) for key, value in order_individual_cus_info.items(): new_dict[key] = value if key == consts.ID_RES: new_dict[consts.SECOND_ID_RES] = second_id_res order_individual_cus_info = new_dict # sep营业执照 if cus_type == consts.CUSTOMER_TYPE[5]: field_compare(order_individual_cus_info, ocr_res_dict, consts.BL_OCR_FIELD, consts.TCSEP, res_set, sep_name=sep_name, capital_ignore=True) order_individual_cus_info_list.append(order_individual_cus_info) comparison_res['OCR_Input']['individualCusInfo'] = order_individual_cus_info_list if last_obj.vehicle_status == consts.VEHICLE_STATUS[0] and last_obj.usedcar_info is not None: usedcar_info = json.loads(last_obj.usedcar_info) order_usedcar_info = get_order_dict(usedcar_info, consts.UC_ORDER) mvc_find, mvc_vinos = usedcar_info_compare(order_usedcar_info, ocr_res_dict, consts.MVC_OCR_FIELD, consts.PCUSD_MVC, res_set) # if order_usedcar_info[consts.PCUSD_MVC[0][0] + 'Result'] == consts.RESULT_Y: dl_find, dl_vinos = usedcar_info_compare(order_usedcar_info, ocr_res_dict, consts.DL_OCR_FIELD, consts.PCUSD_DL, res_set) if mvc_find is True and dl_find is False: vino = dl_vinos[-1] if len(dl_vinos) > 0 else empty_str order_usedcar_info[consts.PCUSD_MVC[0][0]] = '{0}-{1} {2} {3}-{4}'.format( consts.PREFIX_MVC, consts.RESULT_Y, consts.SPLIT, consts.PREFIX_DL, vino) order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_N elif mvc_find is False and dl_find is True: vino = mvc_vinos[-1] if len(mvc_vinos) > 0 else empty_str order_usedcar_info[consts.PCUSD_MVC[0][0]] = '{0}-{1} {2} {3}-{4}'.format( consts.PREFIX_MVC, vino, consts.SPLIT, consts.PREFIX_DL, consts.RESULT_Y) order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_N elif mvc_find is False and dl_find is False: if len(mvc_vinos) == 0 and len(dl_vinos) == 0: order_usedcar_info[consts.PCUSD_MVC[0][0]] = None order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_NA else: mvc_vino = mvc_vinos[-1] if len(mvc_vinos) > 0 else empty_str dl_vino = dl_vinos[-1] if len(dl_vinos) > 0 else empty_str vino = '{0}-{1} {2} {3}-{4}'.format( consts.PREFIX_MVC, mvc_vino, consts.SPLIT, consts.PREFIX_DL, dl_vino) order_usedcar_info[consts.PCUSD_MVC[0][0]] = vino order_usedcar_info[consts.PCUSD_MVC[0][4]] = consts.RESULT_N comparison_res['OCR_Input']['usedCarInfo'] = order_usedcar_info if last_obj.corporate_cus_info is not None: corporate_cus_info = json.loads(last_obj.corporate_cus_info) order_corporate_cus_info = get_order_dict(corporate_cus_info, consts.CO_ORDER) field_compare(order_corporate_cus_info, ocr_res_dict, consts.BL_OCR_FIELD, consts.TCCOR, res_set) comparison_res['OCR_Input']['corporateCusInfo'] = order_corporate_cus_info comparison_res['OCR_Input'][ 'wholeResult'] = consts.RESULT_N if consts.RESULT_N in res_set or consts.RESULT_NA in res_set else consts.RESULT_Y except Exception as e: compare_failed = True compare_log.error('{0} [CA] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] [error={4}]'.format( log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) else: compare_log.info('{0} [CA] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [compare_res={4}]'.format( log_base, application_entity, application_id, ocr_res_id, comparison_res)) is_gcap_send = Configs.objects.filter(id=1).first() if is_gcap_send is not None and is_gcap_send.value == 'N': compare_log.info('{0} [CA] [gcap closed] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) return # 时间延迟 send_time = last_obj.create_time + timedelta(seconds=15) while datetime.now() < send_time: compare_log.info('{0} [CA] [time wait 5s] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) time.sleep(5) # 将比对结果发送GCAP try: data = gcap.dict_to_xml(comparison_res) except Exception as e: compare_log.error('{0} [CA] [dict to xml failed] [entity={1}] [id={2}] [ocr_res_id={3}] [error={4}]'.format( log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) else: try: for times in range(consts.RETRY_TIMES): try: res_text = gcap.send(data) except Exception as e: gcap_exc = str(e) else: break else: raise GCAPException(gcap_exc) except Exception as e: compare_log.error('{0} [CA] [gcap failed] [entity={1}] [id={2}] [ocr_res_id={3}] [error={4}]'.format( log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) else: compare_log.info('{0} [CA] [gcap success] [entity={1}] [id={2}] [ocr_res_id={3}] [response={4}]'.format( log_base, application_entity, application_id, ocr_res_id, res_text)) compare_log.info('{0} [CA] [task success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) # report try: end_time = datetime.now() if compare_failed: successful_at_this_level = False failure_reason = 'Compare process error' total_fields = 0 else: successful_at_this_level = True if comparison_res['OCR_Input'][ 'wholeResult'] == consts.RESULT_Y else False field_failed = { 'individualCusInfo': [], 'corporateCusInfo': [], 'usedCarInfo': [] } individual_list = comparison_res.get('OCR_Input', {}).get('individualCusInfo', []) total_fields = 0 for individual in individual_list: field_list = [] if individual.get('idType') in consts.ID_TYPE_COMPARE: total_fields += 4 if not successful_at_this_level: for field_name, _, _, _, result_field in consts.ITPRC: if individual.get(result_field) != consts.RESULT_Y: field_list.append(field_name) if individual.get('secondIdType') in consts.SECOND_ID_TYPE_COMPARE: total_fields += 1 if not successful_at_this_level: if individual.get(consts.SECOND_ID_RES) != consts.RESULT_Y: field_list.append(consts.SECOND_ID_FIELD) if individual.get('customerType') == consts.CUSTOMER_TYPE[5]: total_fields += 3 if not successful_at_this_level: for field_name, _, _, _, result_field in consts.TCSEP: if individual.get(result_field) != consts.RESULT_Y: field_list.append(field_name) if len(field_list) > 0: field_failed['individualCusInfo'].append(';'.join(field_list)) corporate_res = comparison_res.get('OCR_Input', {}).get('corporateCusInfo') if corporate_res is not None: total_fields += 8 if not successful_at_this_level: corporate_field_list = [] for field_name, _, _, _, result_field in consts.TCCOR: if corporate_res.get(result_field) != consts.RESULT_Y: corporate_field_list.append(field_name) if len(corporate_field_list) > 0: field_failed['corporateCusInfo'].append(';'.join(corporate_field_list)) used_car_res = comparison_res.get('OCR_Input', {}).get('usedCarInfo') if used_car_res is not None: total_fields += 3 if not successful_at_this_level: used_car_field_list = [] for field_name, _, _, _, result_field in consts.PCUSD_MVC: if used_car_res.get(result_field) != consts.RESULT_Y: used_car_field_list.append(field_name) if len(used_car_field_list) > 0: field_failed['usedCarInfo'].append(';'.join(used_car_field_list)) if not successful_at_this_level: reason_list = [] for key, value in field_failed.items(): if len(value) > 0: value_str = json.dumps(value) reason_list.append('{0}: {1}'.format(key, value_str)) failure_reason = '、'.join(reason_list) else: failure_reason = empty_str request_trigger = RequestTrigger.SUBMITING.value if ocr_res_id is None else RequestTrigger.UPLOADING.value report_class = HILCompareReport if application_entity == consts.HIL_PREFIX else AFCCompareReport report_class.objects.create( case_number=application_id, request_team=RequestTeam.ACCEPTANCE.value, request_trigger=request_trigger, transaction_start=start_time, transaction_end=end_time, successful_at_this_level=successful_at_this_level, failure_reason=failure_reason, process_name=ProcessName.CACOMPARE.value, total_fields=total_fields, workflow_name=last_obj.customer_type, ) compare_log.info( '{0} [CA] [report save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) except Exception as e: compare_log.error('{0} [CA] [report save error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) def get_se_cms_compare_info_auto(last_obj, application_entity, auto=True): cms_info = json.loads(last_obj.content) compare_info = {} individual_info_dict = {} main_role_info = {} company_info_list = [] dealer_name_list = cms_info.get('dealerName', '').split() dealer_name = '' if len(dealer_name_list) == 0 else dealer_name_list[-1] # 个人信息证件------------------------------------------------------------------------------------------------------ # is_cdfl = True # 车贷分离 is_cdfl_bo = False # 车贷分离,主借 is_cdfl_co = False # 车贷分离,共借 # province = cms_info.get('province', '') for individual_info in cms_info.get('applicantInformation', []): all_id_num = [] license_dict = {} customer_name = individual_info.get('name', '').strip() legal_name = individual_info.get('legalRepName', '') establishment_date = individual_info.get('establishmentDate', '') # date_of_birth = individual_info.get('dateOfBirth', '') # 车贷分离判断 is_corporate = individual_info.get('customersubType', '') == 'Corporate' if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[1] and is_corporate: is_cdfl_co = True if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[0] and not is_corporate: is_cdfl_bo = True for id_info in individual_info.get('IDInformation', []): if id_info.get('idType') in consts.SE_CMS_FIRST_ID_FIELD_MAPPING: license_en, is_prc = consts.SE_CMS_FIRST_ID_FIELD_MAPPING[id_info['idType']] # ['customerName', 'idNum', 'dateOfBirth', 'idExpiryDate', 'hukouProvince'] id_num = decode_des(id_info.get('idNum', ''), des_key) field_input = [('customerName', customer_name), ('idNum', id_num), ('idExpiryDate', id_info.get('idExpiryDate', ''))] # if is_prc: # field_input.append(('hukouProvince', province)) # field_input.append(('真伪', consts.IC_RES_MAPPING.get(1))) 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'] id_num = decode_des(id_info.get('idNum', ''), des_key) # bl_field_input = [ # ('companyName', customer_name), # ('legalRepName', legal_name), # ('businessLicenseNo', id_num), # ('organizationCreditCode', id_num), # ('taxRegistrationCertificateNo', id_num), # ('businessLicenseDueDate', id_info.get('idExpiryDate', '')), # ] if is_corporate: company_info_list.append((customer_name, id_num, legal_name)) # else: # bl_field_input.append(('establishmentDate', establishment_date)) # license_dict[consts.BL_EN] = bl_field_input all_id_num.append(id_num) # SME营业执照--------------------------------------------------------------------------------------------------- # if individual_info.get('customersubType', '').startswith('Self Employed'): # sep_field_input = [ # ('legalRepName', customer_name), # ('businessLicenseDueDate', ''), # ] # license_dict[consts.SME_BL_EN] = sep_field_input if len(all_id_num) > 0: main_role_info.setdefault(individual_info['applicantType'], []).append( (customer_name, '、'.join(all_id_num), all_id_num[0]) ) if len(license_dict) > 0: individual_info_dict.setdefault(individual_info['applicantType'], []).append(license_dict) compare_info['applicantInformation'] = individual_info_dict main_name = main_id_all = main_id = '' for applicant_type in consts.APPLICANT_TYPE_ORDER: if applicant_type in main_role_info: main_name, main_id_all, main_id = main_role_info[applicant_type][0] # hmh_name, _, hmh_id = main_role_info[applicant_type][0] break # co_name = co_id = bo_name = bo_id = '' # if is_cdfl: # co_name, _, co_id = main_role_info[consts.APPLICANT_TYPE_ORDER[1]][0] # bo_name, _, bo_id = main_role_info[consts.APPLICANT_TYPE_ORDER[0]][0] co_name = co_id = bo_name = bo_id = '' is_cdfl = is_cdfl_bo and is_cdfl_co if is_cdfl: if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[1], [])) > 0: co_name, _, co_id = main_role_info[consts.APPLICANT_TYPE_ORDER[1]][0] else: co_name = co_id = '' if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[0], [])) > 0: bo_name, _, bo_id = main_role_info[consts.APPLICANT_TYPE_ORDER[0]][0] else: bo_name = bo_id = '' # dda_name_list = [] # dda_num_list = [] if len(company_info_list) > 0: # tmp_idx = 1 company_info = company_info_list[0] else: # tmp_idx = 0 company_info = None # for applicant_type in consts.APPLICANT_TYPE_ORDER[tmp_idx: tmp_idx + 2]: # if applicant_type in main_role_info: # for dda_name_part, _, dda_num_part in main_role_info[applicant_type]: # dda_name_list.append(dda_name_part) # dda_num_list.append(dda_num_part) # dda_name = '、'.join(dda_name_list) # dda_num = '、'.join(dda_num_list) # del main_role_info vehicle_info = {} vehicle_field_input = [] vehicle_status = cms_info.get('vehicleStatus', '') first_submission_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([dealer_name, cms_info.get('fapiaoIssuerDealer', '')]))) vehicle_field_input.append(('vehicleTransactionAmount', amount)) if isinstance(company_info, tuple): vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 else: vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id)) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date)) # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE)) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[4], consts.SE_FPL_VALUE)) bhsj = float(amount) / 1.13 # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[5], consts.SPLIT_STR.join([ # format(bhsj, '.2f'), # format(float(amount) - bhsj, '.2f'), # consts.RESULT_Y # ]))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[7], format(bhsj, '.2f'))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[8], format(float(amount) - bhsj, '.2f'))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[9], consts.RESULT_Y)) 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), # ] # gb34_field_input = [] # jypz_field_input = [] # vehicle_field_input.append(('vinNo', vin_no)) # vehicle_field_input.append(('vehicleTransactionAmount', amount)) # if isinstance(company_info, tuple): # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 # jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 # jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 # gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 # gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 # else: # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all)) # 车贷分离 # jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 # jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all)) # 车贷分离 # gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 # gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else main_id_all)) # 车贷分离 # gb34_field_input.append((consts.SE_GB_USED_FIELD[2], first_submission_date)) # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date)) # # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE)) # jypz_field_input.append(('dealerName', dealer_name)) # jypz_field_input.append(('vinNo', vin_no)) # jypz_field_input.append(('vehicleTransactionAmount', amount)) # jypz_field_input.append((consts.SE_GB_USED_FIELD[-1], first_submission_date)) # # vehicle_info[consts.MVC_EN] = gb_field_input # vehicle_info[consts.MVC34_EN] = gb34_field_input # if not detect_list[0]: # vehicle_info[consts.UCI_EN] = vehicle_field_input # if not detect_list[1]: # vehicle_info[consts.JYPZ_EN] = jypz_field_input # if detect_list[0] and detect_list[1]: # 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) account_holder_name = cms_info.get('bankAccountDetails', {}).get('accountHolderName', '') is_gsyh = True if '工商' in bank_name else False if isinstance(company_info, tuple) and company_info[0] == account_holder_name: pass else: bank_field_input = [ ('accountNo', account_no), ('bankName', bank_name), ('type', consts.BC_TYPE_VALUE), ] 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), # ('applicationId(2)', last_obj.application_id), # ('bankName', bank_name), # ('companyName', consts.HIL_COMPANY_NAME if application_entity in consts.HIL_SET else consts.AFC_COMPANY_NAME), # ('customerName', dda_name), # ('idNum', dda_num), # ('accountHolderName', account_holder_name), # ('accountNo', account_no), # ] # bank_info[consts.DDA_EN] = dda_field_input if len(bank_info) > 0: compare_info['bankInfo'] = bank_info # 银行流水 -------------------------------------------------------------------- if cms_info.get('autoApprovedDetails', {}).get('aaType', '') in ['CAA1', 'CAA2'] and \ cms_info.get('autoApprovedDetails', {}).get('PolicyComments', '') != '此申请无需提供流水': date_timedelta = 60 if auto else 90 bs_role_list = [] for applicant_type in consts.APPLICANT_TYPE_ORDER[:2]: if applicant_type in main_role_info: for bs_role, _, _ in main_role_info[applicant_type]: bs_role_list.append(bs_role) bs_info = dict() bs_field_input = [ (consts.SE_BS_FIELD[0], bs_role_list), (consts.SE_BS_FIELD[1], first_submission_date), (consts.SE_BS_FIELD[2], date_timedelta), ] dbr_bs_role_list = [] for dbr_bs_role, _, _ in main_role_info.get(consts.APPLICANT_TYPE_ORDER[2], []): dbr_bs_role_list.append(dbr_bs_role) if len(dbr_bs_role_list) >= 1: bs_field_input.extend([ (consts.SE_BS_FIELD[3], dbr_bs_role_list[0]), (consts.SE_BS_FIELD[4], first_submission_date), (consts.SE_BS_FIELD[5], date_timedelta), ]) if len(dbr_bs_role_list) >= 2: bs_field_input.extend([ (consts.SE_BS_FIELD[6], dbr_bs_role_list[1]), (consts.SE_BS_FIELD[7], first_submission_date), (consts.SE_BS_FIELD[8], date_timedelta), ]) bs_info[consts.BS_EN] = bs_field_input compare_info['Bank Statement'] = bs_info # 抵押登记豁免函---------------------------------------------------------------------------------------------------- other_info = {} full_no = cms_info.get('settlemnetVerification', {}).get('applicationNo', '') if cms_info.get('mortgageType', '') == 'Mortgage Free' or cms_info.get('mortgageType', '') == 'MortgageFree': hmh_field_input = [ (consts.SE_HMH_FIELD[0], main_name), (consts.SE_HMH_FIELD[1], main_id), (consts.SE_HMH_FIELD[2], full_no), (consts.SE_HMH_FIELD[3], cms_info.get('financeCompany', '')), (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 % 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)) # 保单 ----------------------------------------------------------------------------------------------------------- # is_insurance = 0 # fp_campaign = cms_info.get('fpCampaign', '') fp_group = cms_info.get('fpGroup', '') # 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: # 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 or fp_campaign.find('JoyPlus') == -1: # dszx_amount = '200000' # else: # dszx_amount = '500000' # bd_field_input = [ # (consts.SE_BD_FIELD[0], [co_name, bo_name] if is_cdfl else [main_name, ]), # 车贷分离 # (consts.SE_BD_FIELD[1], [co_id, bo_id] if is_cdfl else [main_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_DYSYR_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 schedule_list = [] total_amount = 0 for schedule_dict in cms_info.get('paymentSchedule', []): tmp_str = "{1}{0}{2}".format(consts.SPLIT_STR, str(schedule_dict.get('no', '')), str(schedule_dict.get('grossRentalAmount', ''))) schedule_list.append(tmp_str) total_amount += float(schedule_dict.get('grossRentalAmount', '0.0')) schedule_list_str = consts.SCHEDULE_SPLIT_STR.join(schedule_list) online_sign = cms_info.get('contractSource', 'Online Sign') == 'Online Sign' contract_info = {} if application_entity in consts.HIL_SET: # HIL合同 售后回租合同 -------------------------------------------------------------------------------------- hil_contract_1_input = [ (consts.SE_HIL_CON_1_FIELD[0], [full_no] if online_sign else full_no), (consts.SE_HIL_CON_1_FIELD[1], full_no), (consts.SE_HIL_CON_1_FIELD[2], vin_no), (consts.SE_HIL_CON_1_FIELD[3], dealer_name), (consts.SE_HIL_CON_1_FIELD[4], amount), (consts.SE_HIL_CON_1_FIELD[5], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))), (consts.SE_HIL_CON_1_FIELD[6], str(cms_info.get('terms', '0'))), (consts.SE_HIL_CON_1_FIELD[7], schedule_list_str), (consts.SE_HIL_CON_1_FIELD[11], account_no), (consts.SE_HIL_CON_1_FIELD[12], account_holder_name), (consts.SE_HIL_CON_1_FIELD[13], bank_name), ] if is_asp: hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[8], asp_list)) hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[9], gzs_list)) if isinstance(company_info, tuple): if is_cdfl: hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[14], company_info[2])) else: hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[10], company_info[2])) for key_hil1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST_1: if not e_write and not online_sign: continue key = cdfl_key if is_cdfl else key_hil1 is_find = False if app_type in main_role_info: if len(main_role_info[app_type]) >= id_idx+1: is_find = True if isinstance(field_idx, int): hil_contract_1_input.append((key, main_role_info[app_type][id_idx][field_idx])) else: hil_contract_1_input.append((key, field_idx)) if not is_find and is_force: hil_contract_1_input.append((key, empty_str)) contract_info[consts.HIL_CONTRACT_1_EN] = hil_contract_1_input # HIL合同 车辆处置协议 -------------------------------------------------------------------------------------- if fp_group.find('Joy Select') != -1 or fp_group.find('JoySelect') != -1: hil_contract_3_input = [ (consts.SE_HIL_CON_3_FIELD[0], [full_no] if online_sign else full_no), (consts.SE_HIL_CON_3_FIELD[1], main_name), (consts.SE_HIL_CON_3_FIELD[2], main_id), (consts.SE_HIL_CON_3_FIELD[3], dealer_name), (consts.SE_HIL_CON_3_FIELD[4], full_no), (consts.SE_HIL_CON_3_FIELD[5], main_name), (consts.SE_HIL_CON_3_FIELD[6], main_id), ] # if online_sign: # hil_contract_3_input.append((consts.SE_HIL_CON_3_FIELD[7], main_name)) contract_info[consts.HIL_CONTRACT_3_EN] = hil_contract_3_input # HIL合同 车辆租赁抵押合同 -------------------------------------------------------------------------------------- hil_contract_2_input = [ (consts.SE_HIL_CON_2_FIELD[0], full_no), (consts.SE_HIL_CON_2_FIELD[1], full_no), (consts.SE_HIL_CON_2_FIELD[2], vin_no), (consts.SE_HIL_CON_2_FIELD[3], format(total_amount, '.2f')), (consts.SE_HIL_CON_2_FIELD[4], str(cms_info.get('terms', '0'))), ] for key, app_type_hil2, cdfl_app_type, id_idx, field_idx, is_force, e_write, co_skip in consts.ROLE_LIST_2: if co_skip and isinstance(company_info, tuple): continue if not e_write and not online_sign: continue app_type = cdfl_app_type if is_cdfl else app_type_hil2 is_find = False if app_type in main_role_info: if len(main_role_info[app_type]) >= id_idx+1: is_find = True if isinstance(field_idx, int): hil_contract_2_input.append((key, main_role_info[app_type][id_idx][field_idx])) else: hil_contract_2_input.append((key, field_idx)) if not is_find and is_force: hil_contract_2_input.append((key, empty_str)) contract_info[consts.HIL_CONTRACT_2_EN] = hil_contract_2_input compare_info['contract'] = contract_info return compare_info, cms_info.get('autoApprovedDetails', {}).get('aaType', ''), is_gsyh else: # AFC合同------------------------------------------------------------------------------------------------------ vehicle_principal_str = str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', '0.0')) afc_contract_input = [ (consts.SE_AFC_CON_FIELD[0], full_no), (consts.SE_AFC_CON_FIELD[1], amount), (consts.SE_AFC_CON_FIELD[2], vin_no), (consts.SE_AFC_CON_FIELD[3], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[4], str(cms_info.get('terms', '0'))), (consts.SE_AFC_CON_FIELD[5], vehicle_principal_str), (consts.SE_AFC_CON_FIELD[6], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[7], amount), (consts.SE_AFC_CON_FIELD[8], vin_no), (consts.SE_AFC_CON_FIELD[9], dealer_name), (consts.SE_AFC_CON_FIELD[10], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[11], vehicle_principal_str), (consts.SE_AFC_CON_FIELD[12], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[13], str(cms_info.get('terms', '0'))), (consts.SE_AFC_CON_FIELD[14], account_no), (consts.SE_AFC_CON_FIELD[15], account_holder_name), (consts.SE_AFC_CON_FIELD[16], bank_name), (consts.SE_AFC_CON_FIELD[17], schedule_list_str), ] 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) # '借款人签字及时间', 'Borrower', 0, 0, True for key_afc1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST: if not e_write and not online_sign: continue key = cdfl_key if is_cdfl else key_afc1 is_find = False if app_type in main_role_info: if len(main_role_info[app_type]) >= id_idx+1: is_find = True if isinstance(field_idx, int): afc_contract_input.append((key, main_role_info[app_type][id_idx][field_idx])) else: afc_contract_input.append((key, field_idx)) if not is_find and is_force: afc_contract_input.append((key, empty_str)) if online_sign: afc_contract_input.append((consts.SE_AFC_CON_FIELD[18], consts.SE_STAMP_VALUE)) afc_contract_input.append((consts.SE_AFC_CON_FIELD[19], empty_str)) contract_info[consts.AFC_CONTRACT_EN] = afc_contract_input compare_info['contract'] = contract_info return compare_info, cms_info.get('autoApprovedDetails', {}).get('aaType', ''), is_gsyh def get_se_cms_compare_info(last_obj, application_entity, detect_list, auto=False): cms_info = json.loads(last_obj.content) compare_info = {} individual_info_dict = {} main_role_info = {} company_info_list = [] dealer_name_list = cms_info.get('dealerName', '').split() dealer_name = '' if len(dealer_name_list) == 0 else dealer_name_list[-1] # 个人信息证件------------------------------------------------------------------------------------------------------ is_cdfl_bo = False # 车贷分离,主借 is_cdfl_co = False # 车贷分离,共借 # province = cms_info.get('province', '') for individual_info in cms_info.get('applicantInformation', []): all_id_num = [] license_dict = {} customer_name = individual_info.get('name', '').strip() legal_name = individual_info.get('legalRepName', '') establishment_date = individual_info.get('establishmentDate', '') # date_of_birth = individual_info.get('dateOfBirth', '') # 车贷分离判断 is_corporate = individual_info.get('customersubType', '') == 'Corporate' if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[1] and is_corporate: is_cdfl_co = True if individual_info['applicantType'] == consts.APPLICANT_TYPE_ORDER[0] and not is_corporate: is_cdfl_bo = True for id_info in individual_info.get('IDInformation', []): if id_info.get('idType') in consts.SE_CMS_FIRST_ID_FIELD_MAPPING: license_en, is_prc = consts.SE_CMS_FIRST_ID_FIELD_MAPPING[id_info['idType']] # ['customerName', 'idNum', 'dateOfBirth', 'idExpiryDate', 'hukouProvince'] id_num = decode_des(id_info.get('idNum', ''), des_key) field_input = [('customerName', customer_name), ('idNum', id_num), ('idExpiryDate', id_info.get('idExpiryDate', ''))] # if is_prc: # field_input.append(('hukouProvince', province)) # field_input.append(('真伪', consts.IC_RES_MAPPING.get(1))) 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'] id_num = decode_des(id_info.get('idNum', ''), des_key) bl_field_input = [ ('companyName', customer_name), ('legalRepName', legal_name), ('businessLicenseNo', id_num), ('organizationCreditCode', id_num), ('taxRegistrationCertificateNo', id_num), ('businessLicenseDueDate', id_info.get('idExpiryDate', '')), ] if is_corporate: company_info_list.append((customer_name, id_num, legal_name)) else: bl_field_input.append(('establishmentDate', establishment_date)) license_dict[consts.BL_EN] = bl_field_input all_id_num.append(id_num) # SME营业执照--------------------------------------------------------------------------------------------------- # if individual_info.get('customersubType', '').startswith('Self Employed'): # sep_field_input = [ # ('legalRepName', customer_name), # ('businessLicenseDueDate', ''), # ] # license_dict[consts.SME_BL_EN] = sep_field_input if len(all_id_num) > 0: main_role_info.setdefault(individual_info['applicantType'], []).append( (customer_name, '、'.join(all_id_num), all_id_num[0]) ) if len(license_dict) > 0: individual_info_dict.setdefault(individual_info['applicantType'], []).append(license_dict) compare_info['applicantInformation'] = individual_info_dict main_name = main_id_all = main_id = '' for applicant_type in consts.APPLICANT_TYPE_ORDER: if applicant_type in main_role_info: main_name, main_id_all, main_id = main_role_info[applicant_type][0] # hmh_name, _, hmh_id = main_role_info[applicant_type][0] break co_name = co_id = bo_name = bo_id = '' is_cdfl = is_cdfl_bo and is_cdfl_co if is_cdfl: if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[1], [])) > 0: co_name, _, co_id = main_role_info[consts.APPLICANT_TYPE_ORDER[1]][0] else: co_name = co_id = '' if len(main_role_info.get(consts.APPLICANT_TYPE_ORDER[0], [])) > 0: bo_name, _, bo_id = main_role_info[consts.APPLICANT_TYPE_ORDER[0]][0] else: bo_name = bo_id = '' # dda_name_list = [] # dda_num_list = [] if len(company_info_list) > 0: # tmp_idx = 1 company_info = company_info_list[0] else: # tmp_idx = 0 company_info = None # for applicant_type in consts.APPLICANT_TYPE_ORDER[tmp_idx: tmp_idx + 2]: # if applicant_type in main_role_info: # for dda_name_part, _, dda_num_part in main_role_info[applicant_type]: # dda_name_list.append(dda_name_part) # dda_num_list.append(dda_num_part) # dda_name = '、'.join(dda_name_list) # dda_num = '、'.join(dda_num_list) # del main_role_info vehicle_info = {} vehicle_field_input = [] vehicle_status = cms_info.get('vehicleStatus', '') first_submission_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([dealer_name, cms_info.get('fapiaoIssuerDealer', '')]))) vehicle_field_input.append(('vehicleTransactionAmount', amount)) if isinstance(company_info, tuple): vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 else: vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id)) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date)) # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE)) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[4], consts.SE_FPL_VALUE)) bhsj = float(amount) / 1.13 # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[5], consts.SPLIT_STR.join([ # format(bhsj, '.2f'), # format(float(amount) - bhsj, '.2f'), # consts.RESULT_Y # ]))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[7], format(bhsj, '.2f'))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[8], format(float(amount) - bhsj, '.2f'))) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[9], consts.RESULT_Y)) 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), ] gb34_field_input = [] jypz_field_input = [] vehicle_field_input.append(('vinNo', vin_no)) vehicle_field_input.append(('vehicleTransactionAmount', amount)) if isinstance(company_info, tuple): vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else company_info[0])) # 车贷分离 gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else company_info[1])) # 车贷分离 else: vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all)) # 车贷分离 jypz_field_input.append((consts.SE_NEW_ADD_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 jypz_field_input.append((consts.SE_NEW_ADD_FIELD[1], co_id if is_cdfl else main_id_all)) # 车贷分离 gb34_field_input.append((consts.SE_GB_USED_FIELD[0], co_name if is_cdfl else main_name)) # 车贷分离 gb34_field_input.append((consts.SE_GB_USED_FIELD[1], co_id if is_cdfl else main_id_all)) # 车贷分离 gb34_field_input.append((consts.SE_GB_USED_FIELD[2], first_submission_date)) vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[2], first_submission_date)) # vehicle_field_input.append((consts.SE_NEW_ADD_FIELD[3], consts.SE_STAMP_VALUE)) jypz_field_input.append(('dealerName', dealer_name)) jypz_field_input.append(('vinNo', vin_no)) jypz_field_input.append(('vehicleTransactionAmount', amount)) jypz_field_input.append((consts.SE_GB_USED_FIELD[-1], first_submission_date)) vehicle_info[consts.MVC_EN] = gb_field_input vehicle_info[consts.MVC34_EN] = gb34_field_input if not detect_list[0]: vehicle_info[consts.UCI_EN] = vehicle_field_input if not detect_list[1]: vehicle_info[consts.JYPZ_EN] = jypz_field_input if detect_list[0] and detect_list[1]: 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) account_holder_name = cms_info.get('bankAccountDetails', {}).get('accountHolderName', '') is_gsyh = True if '工商' in bank_name else False if isinstance(company_info, tuple) and company_info[0] == account_holder_name: pass else: bank_field_input = [ ('accountNo', account_no), ('bankName', bank_name), ('type', consts.BC_TYPE_VALUE), ] 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), # ('applicationId(2)', last_obj.application_id), # ('bankName', bank_name), # ('companyName', consts.HIL_COMPANY_NAME if application_entity in consts.HIL_SET else consts.AFC_COMPANY_NAME), # ('customerName', dda_name), # ('idNum', dda_num), # ('accountHolderName', account_holder_name), # ('accountNo', account_no), # ] # bank_info[consts.DDA_EN] = dda_field_input if len(bank_info) > 0: compare_info['bankInfo'] = bank_info # 银行流水 -------------------------------------------------------------------- if cms_info.get('autoApprovedDetails', {}).get('aaType', '') in ['CAA1', 'CAA2'] and \ cms_info.get('autoApprovedDetails', {}).get('PolicyComments', '') != '此申请无需提供流水': date_timedelta = 60 if auto else 90 bs_role_list = [] for applicant_type in consts.APPLICANT_TYPE_ORDER[:2]: if applicant_type in main_role_info: for bs_role, _, _ in main_role_info[applicant_type]: bs_role_list.append(bs_role) bs_info = dict() bs_field_input = [ (consts.SE_BS_FIELD[0], bs_role_list), (consts.SE_BS_FIELD[1], first_submission_date), (consts.SE_BS_FIELD[2], date_timedelta), ] dbr_bs_role_list = [] for dbr_bs_role, _, _ in main_role_info.get(consts.APPLICANT_TYPE_ORDER[2], []): dbr_bs_role_list.append(dbr_bs_role) if len(dbr_bs_role_list) >= 1: bs_field_input.extend([ (consts.SE_BS_FIELD[3], dbr_bs_role_list[0]), (consts.SE_BS_FIELD[4], first_submission_date), (consts.SE_BS_FIELD[5], date_timedelta), ]) if len(dbr_bs_role_list) >= 2: bs_field_input.extend([ (consts.SE_BS_FIELD[6], dbr_bs_role_list[1]), (consts.SE_BS_FIELD[7], first_submission_date), (consts.SE_BS_FIELD[8], date_timedelta), ]) bs_info[consts.BS_EN] = bs_field_input compare_info['Bank Statement'] = bs_info # 抵押登记豁免函---------------------------------------------------------------------------------------------------- other_info = {} full_no = cms_info.get('settlemnetVerification', {}).get('applicationNo', '') if cms_info.get('mortgageType', '') == 'Mortgage Free' or cms_info.get('mortgageType', '') == 'MortgageFree': hmh_field_input = [ (consts.SE_HMH_FIELD[0], main_name), (consts.SE_HMH_FIELD[1], main_id), (consts.SE_HMH_FIELD[2], full_no), (consts.SE_HMH_FIELD[3], cms_info.get('financeCompany', '')), (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 % 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)) # 保单 ----------------------------------------------------------------------------------------------------------- is_insurance = 0 fp_campaign = cms_info.get('fpCampaign', '') fp_group = cms_info.get('fpGroup', '') 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: 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 or fp_campaign.find('JoyPlus') == -1: dszx_amount = '200000' else: dszx_amount = '500000' bd_field_input = [ (consts.SE_BD_FIELD[0], [co_name, bo_name] if is_cdfl else [main_name, ]), # 车贷分离 (consts.SE_BD_FIELD[1], [co_id, bo_id] if is_cdfl else [main_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_DYSYR_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 schedule_list = [] total_amount = 0 for schedule_dict in cms_info.get('paymentSchedule', []): tmp_str = "{1}{0}{2}".format(consts.SPLIT_STR, str(schedule_dict.get('no', '')), str(schedule_dict.get('grossRentalAmount', ''))) schedule_list.append(tmp_str) total_amount += float(schedule_dict.get('grossRentalAmount', '0.0')) schedule_list_str = consts.SCHEDULE_SPLIT_STR.join(schedule_list) online_sign = cms_info.get('contractSource', 'Online Sign') == 'Online Sign' contract_info = {} if application_entity in consts.HIL_SET: # HIL合同 售后回租合同 -------------------------------------------------------------------------------------- hil_contract_1_input = [ (consts.SE_HIL_CON_1_FIELD[0], [full_no] if online_sign else full_no), (consts.SE_HIL_CON_1_FIELD[1], full_no), (consts.SE_HIL_CON_1_FIELD[2], vin_no), (consts.SE_HIL_CON_1_FIELD[3], dealer_name), (consts.SE_HIL_CON_1_FIELD[4], amount), (consts.SE_HIL_CON_1_FIELD[5], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))), (consts.SE_HIL_CON_1_FIELD[6], str(cms_info.get('terms', '0'))), (consts.SE_HIL_CON_1_FIELD[7], schedule_list_str), (consts.SE_HIL_CON_1_FIELD[11], account_no), (consts.SE_HIL_CON_1_FIELD[12], account_holder_name), (consts.SE_HIL_CON_1_FIELD[13], bank_name), ] if is_asp: hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[8], asp_list)) hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[9], gzs_list)) if isinstance(company_info, tuple): if is_cdfl: hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[14], company_info[2])) else: hil_contract_1_input.append((consts.SE_HIL_CON_1_FIELD[10], company_info[2])) for key_hil1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST_1: if not e_write and not online_sign: continue key = cdfl_key if is_cdfl else key_hil1 is_find = False if app_type in main_role_info: if len(main_role_info[app_type]) >= id_idx+1: is_find = True if isinstance(field_idx, int): hil_contract_1_input.append((key, main_role_info[app_type][id_idx][field_idx])) else: hil_contract_1_input.append((key, field_idx)) if not is_find and is_force: hil_contract_1_input.append((key, empty_str)) contract_info[consts.HIL_CONTRACT_1_EN] = hil_contract_1_input # HIL合同 车辆处置协议 -------------------------------------------------------------------------------------- if fp_group.find('Joy Select') != -1 or fp_group.find('JoySelect') != -1: hil_contract_3_input = [ (consts.SE_HIL_CON_3_FIELD[0], [full_no] if online_sign else full_no), (consts.SE_HIL_CON_3_FIELD[1], main_name), (consts.SE_HIL_CON_3_FIELD[2], main_id), (consts.SE_HIL_CON_3_FIELD[3], dealer_name), (consts.SE_HIL_CON_3_FIELD[4], full_no), (consts.SE_HIL_CON_3_FIELD[5], main_name), (consts.SE_HIL_CON_3_FIELD[6], main_id), ] if online_sign: hil_contract_3_input.append((consts.SE_HIL_CON_3_FIELD[7], main_name)) contract_info[consts.HIL_CONTRACT_3_EN] = hil_contract_3_input # HIL合同 车辆租赁抵押合同 -------------------------------------------------------------------------------------- hil_contract_2_input = [ (consts.SE_HIL_CON_2_FIELD[0], full_no), (consts.SE_HIL_CON_2_FIELD[1], full_no), (consts.SE_HIL_CON_2_FIELD[2], vin_no), (consts.SE_HIL_CON_2_FIELD[3], format(total_amount, '.2f')), (consts.SE_HIL_CON_2_FIELD[4], str(cms_info.get('terms', '0'))), ] for key, app_type_hil2, cdfl_app_type, id_idx, field_idx, is_force, e_write, co_skip in consts.ROLE_LIST_2: if co_skip and isinstance(company_info, tuple): continue if not e_write and not online_sign: continue app_type = cdfl_app_type if is_cdfl else app_type_hil2 is_find = False if app_type in main_role_info: if len(main_role_info[app_type]) >= id_idx+1: is_find = True if isinstance(field_idx, int): hil_contract_2_input.append((key, main_role_info[app_type][id_idx][field_idx])) else: hil_contract_2_input.append((key, field_idx)) if not is_find and is_force: hil_contract_2_input.append((key, empty_str)) contract_info[consts.HIL_CONTRACT_2_EN] = hil_contract_2_input compare_info['contract'] = contract_info return compare_info, cms_info.get('applicationVersion', 1), is_gsyh else: # AFC合同------------------------------------------------------------------------------------------------------ vehicle_principal_str = str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', '0.0')) afc_contract_input = [ (consts.SE_AFC_CON_FIELD[0], full_no), (consts.SE_AFC_CON_FIELD[1], amount), (consts.SE_AFC_CON_FIELD[2], vin_no), (consts.SE_AFC_CON_FIELD[3], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[4], str(cms_info.get('terms', '0'))), (consts.SE_AFC_CON_FIELD[5], vehicle_principal_str), (consts.SE_AFC_CON_FIELD[6], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[7], amount), (consts.SE_AFC_CON_FIELD[8], vin_no), (consts.SE_AFC_CON_FIELD[9], dealer_name), (consts.SE_AFC_CON_FIELD[10], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[11], vehicle_principal_str), (consts.SE_AFC_CON_FIELD[12], str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.0'))), (consts.SE_AFC_CON_FIELD[13], str(cms_info.get('terms', '0'))), (consts.SE_AFC_CON_FIELD[14], account_no), (consts.SE_AFC_CON_FIELD[15], account_holder_name), (consts.SE_AFC_CON_FIELD[16], bank_name), (consts.SE_AFC_CON_FIELD[17], schedule_list_str), ] 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) # '借款人签字及时间', 'Borrower', 0, 0, True for key_afc1, cdfl_key, app_type, id_idx, field_idx, is_force, e_write in consts.ROLE_LIST: if not e_write and not online_sign: continue key = cdfl_key if is_cdfl else key_afc1 is_find = False if app_type in main_role_info: if len(main_role_info[app_type]) >= id_idx+1: is_find = True if isinstance(field_idx, int): afc_contract_input.append((key, main_role_info[app_type][id_idx][field_idx])) else: afc_contract_input.append((key, field_idx)) if not is_find and is_force: afc_contract_input.append((key, empty_str)) if online_sign: afc_contract_input.append((consts.SE_AFC_CON_FIELD[18], consts.SE_STAMP_VALUE)) afc_contract_input.append((consts.SE_AFC_CON_FIELD[19], empty_str)) contract_info[consts.AFC_CONTRACT_EN] = afc_contract_input compare_info['contract'] = contract_info return compare_info, cms_info.get('applicationVersion', 1), is_gsyh def se_bs_compare(license_en, ocr_res_dict, strip_list, is_auto): # 主共借至少提供一个 # 有担保人,担保人必须提供。主共借没有时,修改comment:人工查看担保人亲属关系 if is_auto: ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD_AUTO[license_en] else: ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD[license_en] ocr_res_str = ocr_res_dict.get(ocr_field) result_field_list = [] field_img_path_dict = dict() if ocr_res_str is not None: pre_field_list = strip_list[:3] dbr1_field_list = strip_list[3:6] dbr2_field_list = strip_list[6:] ocr_res_list = json.loads(ocr_res_str) # length = len(ocr_res_list) # 主共借人 pre_best_res = {} max_correct_count = 0 for ocr_res in ocr_res_list: correct_count = 0 pre_tmp_res_part = {} for idx, (name, value) in enumerate(pre_field_list): ocr_str_or_list = ocr_res.get(compare_logic[name][0]) if isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list) \ or isinstance(ocr_str_or_list, int): result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **compare_logic[name][2]) if isinstance(ocr_str_or_list, list): ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False) else: ocr_str = ocr_str_or_list reason = compare_logic[name][3] else: result = consts.RESULT_N ocr_str = empty_str reason = compare_logic[name][3] if idx == 0 and result == consts.RESULT_N: break if result == consts.RESULT_Y: correct_count += 1 pre_tmp_res_part[name] = (result, ocr_str, reason) if correct_count > 0 and correct_count >= max_correct_count: max_correct_count = correct_count pre_best_res = pre_tmp_res_part # 担保人1 dbr1_best_res = {} if len(dbr1_field_list) > 0: max_correct_count = 0 for ocr_res in ocr_res_list: correct_count = 0 dbr1_tmp_res_part = {} for idx, (name, value) in enumerate(dbr1_field_list): ocr_str_or_list = ocr_res.get(compare_logic[name][0]) if isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list) or isinstance(ocr_str_or_list, int): result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **compare_logic[name][2]) if isinstance(ocr_str_or_list, list): ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False) else: ocr_str = ocr_str_or_list reason = compare_logic[name][3] else: result = consts.RESULT_N ocr_str = empty_str reason = compare_logic[name][3] if idx == 0 and result == consts.RESULT_N: break if result == consts.RESULT_Y: correct_count += 1 dbr1_tmp_res_part[name] = (result, ocr_str, reason) if correct_count > 0 and correct_count >= max_correct_count: max_correct_count = correct_count dbr1_best_res = dbr1_tmp_res_part # 担保人2 dbr2_best_res = {} if len(dbr1_field_list) > 0: max_correct_count = 0 for ocr_res in ocr_res_list: correct_count = 0 dbr2_tmp_res_part = {} for idx, (name, value) in enumerate(dbr2_field_list): ocr_str_or_list = ocr_res.get(compare_logic[name][0]) if isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list) or isinstance(ocr_str_or_list, int): result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **compare_logic[name][2]) if isinstance(ocr_str_or_list, list): ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False) else: ocr_str = ocr_str_or_list reason = compare_logic[name][3] else: result = consts.RESULT_N ocr_str = empty_str reason = compare_logic[name][3] if idx == 0 and result == consts.RESULT_N: break if result == consts.RESULT_Y: correct_count += 1 dbr2_tmp_res_part[name] = (result, ocr_str, reason) if correct_count > 0 and correct_count >= max_correct_count: max_correct_count = correct_count dbr2_best_res = dbr2_tmp_res_part dbr_ok = False # 有担保人 if len(dbr1_field_list) > 0: # 有担保人12 if len(dbr2_field_list) > 0: if len(dbr1_best_res) > 0 and len(dbr2_best_res) > 0: dbr_ok = True # 有担保人1 else: if len(dbr1_best_res) > 0: dbr_ok = True # 无担保人 # else: # pass best_res_empty = False if len(pre_best_res) == 0 and len(dbr1_best_res) == 0 and len(dbr2_best_res) == 0: best_res_empty = True for name, value in pre_field_list: if len(pre_best_res) > 0: result, ocr_str, reason = pre_best_res[name] else: result = consts.RESULT_N ocr_str = empty_str if best_res_empty: reason = consts.SPECIAL_REASON_3 elif dbr_ok: # 有担保人且担保人都提供了流水 reason = consts.SPECIAL_REASON else: reason = compare_logic[pre_field_list[0][0]][3] img_path = empty_str error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value if isinstance(value, list): value = json.dumps(value, ensure_ascii=False) result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason)) if len(dbr1_field_list) > 0: for name, value in dbr1_field_list: if len(dbr1_best_res) > 0: result, ocr_str, reason = dbr1_best_res[name] else: result = consts.RESULT_N ocr_str = empty_str if best_res_empty: reason = consts.SPECIAL_REASON_3 elif len(pre_best_res) > 0: reason = consts.SPECIAL_REASON_2 else: reason = compare_logic[dbr1_field_list[0][0]][3] img_path = empty_str error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value if isinstance(value, list): value = json.dumps(value, ensure_ascii=False) result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason)) if len(dbr2_field_list) > 0: for name, value in dbr2_field_list: if len(dbr2_best_res) > 0: result, ocr_str, reason = dbr2_best_res[name] else: result = consts.RESULT_N ocr_str = empty_str if best_res_empty: reason = consts.SPECIAL_REASON_3 elif len(pre_best_res) > 0: reason = consts.SPECIAL_REASON_2 else: reason = compare_logic[dbr2_field_list[0][0]][3] img_path = empty_str error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value if isinstance(value, list): value = json.dumps(value, ensure_ascii=False) result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason)) else: for name, value in strip_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, consts.SPECIAL_REASON_3)) return result_field_list, field_img_path_dict def se_compare_license(license_en, ocr_res_dict, field_list): ocr_field, compare_logic, special_expiry_date = consts.SE_COMPARE_FIELD[license_en] is_find = False no_ocr_result = False special_expiry_date_slice = False result_field_list = [] section_img_info = dict() field_img_path_dict = dict() ocr_res_str = ocr_res_dict.get(ocr_field) if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) # 3/4页去除 if ocr_field == consts.MVC_OCR_FIELD: tmp_list = [] for res in ocr_res_list: if compare_logic['vinNo'][0] in res: tmp_list.append(res) ocr_res_list = tmp_list length = len(ocr_res_list) # 身份证、居住证 过期期限特殊处理 if special_expiry_date: expiry_dates = dict() key = compare_logic.get('idExpiryDate')[0] for date_tmp_idx, ocr_res in enumerate(ocr_res_list): if key in ocr_res: expiry_dates[ocr_res[key]] = (ocr_res.get(consts.IMG_PATH_KEY_2, ''), date_tmp_idx) else: expiry_dates = dict() for res_idx in range(length-1, -1, -1): if is_find: break for idx, (name, value) in enumerate(field_list): if ocr_field == consts.MVI_OCR_FIELD and name == consts.SE_NEW_ADD_FIELD[9]: ocr_str = getattr(cp, consts.ZW_METHOD)( ocr_res_list[res_idx].get(consts.LOWER_AMOUNT_FIELD, ''), ocr_res_list[res_idx].get(consts.UPPER_AMOUNT_FIELD, ''), ) else: ocr_str = ocr_res_list[res_idx].get(compare_logic[name][0]) if not isinstance(ocr_str, str): result = consts.RESULT_N ocr_str = empty_str no_key = True else: result = getattr(cp, compare_logic[name][1])(value, ocr_str, **compare_logic[name][2]) no_key = False if idx == 0 and result == consts.RESULT_N and length > 1: break is_find = True section_img_info[consts.SECTION_IMG_PATH_KEY] = ocr_res_list[res_idx].get(consts.SECTION_IMG_PATH_KEY, '') section_img_info[consts.ALL_POSITION_KEY] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY, {}) if special_expiry_date: section_img_info[consts.SECTION_IMG_PATH_KEY_2] = ocr_res_list[res_idx].get( consts.SECTION_IMG_PATH_KEY_2, '') section_img_info[consts.ALL_POSITION_KEY_2] = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, {}) # 过期期限特殊处理 if special_expiry_date and name == 'idExpiryDate' and result == consts.RESULT_N: if no_key: for expiry_date, (date_img_path, date_res_idx) in expiry_dates.items(): expiry_date_res = getattr(cp, compare_logic[name][1])(value, expiry_date, **compare_logic[name][2]) if expiry_date_res == consts.RESULT_N: ocr_str = expiry_date img_path = date_img_path special_expiry_date_slice = True section_img_info[consts.SECTION_IMG_PATH_KEY_2] = ocr_res_list[date_res_idx].get( consts.SECTION_IMG_PATH_KEY_2, '') section_img_info[consts.ALL_POSITION_KEY_2] = ocr_res_list[date_res_idx].get( consts.ALL_POSITION_KEY_2, {}) break else: ocr_str = empty_str result = consts.RESULT_Y img_path = empty_str else: img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY_2, '') 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: no_ocr_result = True if not is_find: for name, value in field_list: if isinstance(value, list): value = json.dumps(value, ensure_ascii=False) no_find_str = consts.DDA_NO_FIND if license_en == consts.DDA_EN else '{0}未找到'.format(license_en) result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value, no_find_str)) if is_find: if special_expiry_date_slice: special_section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY_2, '') if os.path.exists(special_section_img_path): field = 'idExpiryDate' special_info = section_img_info.get(consts.ALL_POSITION_KEY_2, {}) special_section_position = special_info.get(consts.POSITION_KEY, {}) special_section_angle = special_info.get(consts.ANGLE_KEY, 0) try: last_img = img_process(special_section_img_path, special_section_position, special_section_angle) except Exception as e: field_img_path_dict[field] = special_section_img_path else: pre, suf = os.path.splitext(special_section_img_path) try: res_field = compare_logic[field][0] is_valid, coord_tuple = field_build_coordinates(special_info.get(res_field, {})) if is_valid: save_path = '{0}_{1}{2}'.format(pre, field, suf) field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :] cv2.imwrite(save_path, field_img) field_img_path_dict[field] = save_path else: field_img_path_dict[field] = special_section_img_path except Exception as e: field_img_path_dict[field] = special_section_img_path section_img_path = section_img_info.get(consts.SECTION_IMG_PATH_KEY, '') if os.path.exists(section_img_path): failed_field = [] base_img_path = empty_str for name, _, result, _, img_path, _, _ in result_field_list: if result == consts.RESULT_N: if special_expiry_date_slice and name == 'idExpiryDate': continue failed_field.append(name) if base_img_path == empty_str: base_img_path = img_path if len(failed_field) > 0: info = section_img_info.get(consts.ALL_POSITION_KEY, {}) section_position = info.get(consts.POSITION_KEY, {}) section_angle = info.get(consts.ANGLE_KEY, 0) try: last_img = img_process(section_img_path, section_position, section_angle) except Exception as e: for field in failed_field: field_img_path_dict[field] = base_img_path else: pre, suf = os.path.splitext(section_img_path) for field in failed_field: try: res_field = compare_logic[field][0] is_valid, coord_tuple = field_build_coordinates(info.get(res_field, {})) if is_valid: save_path = '{0}_{1}{2}'.format(pre, field, suf) field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :] cv2.imwrite(save_path, field_img) field_img_path_dict[field] = save_path else: field_img_path_dict[field] = base_img_path except Exception as e: field_img_path_dict[field] = base_img_path return result_field_list, no_ocr_result, field_img_path_dict def se_contract_compare(license_en, ocr_res_dict, strip_list, is_gsyh): ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD[license_en] ocr_res_str = ocr_res_dict.get(ocr_field) result_field_list = [] field_img_path_dict = dict() ocr_res = dict() if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) ocr_res = ocr_res_list.pop() for name, value in strip_list: # 购置税校验 if name == consts.SE_AFC_CON_FIELD[21]: if len(value) == 3: reason = [] gzs_verify = value[1] >= value[2] if gzs_verify: if value[0] == consts.GZS_STATUS[0]: reason.append(consts.GZS_REASON_1) result = consts.RESULT_N else: result = consts.RESULT_Y else: if value[0] == consts.GZS_STATUS[0]: reason.append(consts.GZS_REASON_1) result = consts.RESULT_N reason.append(consts.GZS_REASON_2) else: result = consts.RESULT_N reason = consts.GZS_REASON_1 ocr_str = empty_str else: ocr_str_or_list = ocr_res.get(compare_logic[name][0]) if ocr_str_or_list is None and license_en == consts.AFC_CONTRACT_EN \ and is_gsyh is True and name in consts.CON_BANK_FIELD: result = consts.RESULT_Y ocr_str = empty_str reason = compare_logic[name][3] elif isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list): if is_gsyh is True and name in consts.CON_BANK_FIELD: update_args = {'is_gsyh': is_gsyh} for k, v in compare_logic[name][2].items(): update_args[k] = v else: update_args = compare_logic[name][2] if isinstance(ocr_str_or_list, list): ocr_str = json.dumps(ocr_str_or_list, ensure_ascii=False) else: ocr_str_or_list = ocr_str_or_list.strip() ocr_str = ocr_str_or_list result = getattr(cp, compare_logic[name][1])(value, ocr_str_or_list, **update_args) reason = compare_logic[name][3] else: result = consts.RESULT_N ocr_str = empty_str reason = compare_logic[name][3] # img_path = empty_str if name not in compare_logic: img_path = empty_str else: img_path = ocr_res.get(consts.IMG_PATH_KEY, {}).get(compare_logic[name][0], empty_str) if result == consts.RESULT_N else empty_str error_type = empty_error_type if result == consts.RESULT_Y else ErrorType.OCR.value if isinstance(value, list): value = json.dumps(value, ensure_ascii=False) result_field_list.append((name, value, result, ocr_str, img_path, error_type, reason)) else: for name, value in strip_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 ocr_res_str is not None: img_map = {} for name, _, result, _, img_path, _, _ in result_field_list: if result == consts.RESULT_N: img_map.setdefault(img_path, []).append(name) for path, field_list in img_map.items(): if os.path.exists(path): pre, suf = os.path.splitext(path) last_img = cv2.imread(path) for field_idx, field in enumerate(field_list): try: save_path = '{0}_{1}{2}'.format(pre, str(field_idx), suf) section_position_list = ocr_res.get(consts.ALL_POSITION_KEY, {}).get(field, []) if isinstance(section_position_list, list) and len(section_position_list) == 4: field_img = last_img[section_position_list[1]: section_position_list[3], section_position_list[0]: section_position_list[2], :] cv2.imwrite(save_path, field_img) field_img_path_dict[field] = save_path else: field_img_path_dict[field] = path except Exception as e: field_img_path_dict[field] = path return result_field_list, field_img_path_dict def se_mvc34_compare(license_en, ocr_res_dict, field_list): ocr_field, compare_logic, _ = consts.SE_COMPARE_FIELD[license_en] ocr_res_str = ocr_res_dict.get(ocr_field) is_find = False result_field_list = [] field_img_path_dict = dict() if ocr_res_str is not None: ocr_res_list = json.loads(ocr_res_str) length = len(ocr_res_list) page34_date_dict = dict() first_res = None for res_idx in range(length-1, -1, -1): if consts.TRANSFER_DATE in ocr_res_list[res_idx]: img_path = ocr_res_list[res_idx].get(consts.IMG_PATH_KEY_2, '') section_img_path = ocr_res_list[res_idx].get(consts.SECTION_IMG_PATH_KEY_2, '') for idx, transfer_date in enumerate(ocr_res_list[res_idx].get(consts.TRANSFER_DATE, [])): try: transfer_name = ocr_res_list[res_idx].get(consts.TRANSFER_NAME, [])[idx] except Exception as e: transfer_name = empty_str try: transfer_num = ocr_res_list[res_idx].get(consts.TRANSFER_NUM, [])[idx] except Exception as e: transfer_num = empty_str try: position_info_date = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, dict()).get( consts.TRANSFER_DATE, [])[idx] except Exception as e: position_info_date = {} try: position_info_name = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, dict()).get( consts.TRANSFER_NAME, [])[idx] except Exception as e: position_info_name = {} try: position_info_num = ocr_res_list[res_idx].get(consts.ALL_POSITION_KEY_2, dict()).get( consts.TRANSFER_NUM, [])[idx] except Exception as e: position_info_num = {} core_info = { consts.TRANSFER_NAME: transfer_name, consts.TRANSFER_NUM: transfer_num, consts.TRANSFER_DATE: transfer_date, consts.IMG_PATH_KEY_2: img_path, consts.SECTION_IMG_PATH_KEY_2: section_img_path, consts.ALL_POSITION_KEY: { consts.TRANSFER_NAME: position_info_name, consts.TRANSFER_NUM: position_info_num, consts.TRANSFER_DATE: position_info_date, }, } page34_date_dict.setdefault(transfer_date, []).append(core_info) if first_res is None: first_res = core_info max_date = None for date_tmp in page34_date_dict.keys(): try: max_date_part = time.strptime(date_tmp, "%Y-%m-%d") except Exception as e: pass else: if max_date is None or max_date_part > max_date: max_date = max_date_part if max_date is not None or first_res is not None: is_find = True ocr_res = first_res if max_date is None else page34_date_dict[time.strftime('%Y-%m-%d', max_date)][0] failed_field = [] base_img_path = ocr_res.get(consts.IMG_PATH_KEY_2, '') for name, value in field_list: ocr_str = ocr_res.get(compare_logic[name][0]) if not isinstance(ocr_str, str): result = consts.RESULT_N ocr_str = empty_str else: result = getattr(cp, compare_logic[name][1])(value, ocr_str, **compare_logic[name][2]) img_path = base_img_path if result == consts.RESULT_N else empty_str 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])) if result == consts.RESULT_N: failed_field.append(name) section_img_path = ocr_res.get(consts.SECTION_IMG_PATH_KEY_2, '') if len(failed_field) > 0 and os.path.exists(section_img_path): info = ocr_res.get(consts.ALL_POSITION_KEY, {}) try: last_img = img_process(section_img_path, {}, 0) except Exception as e: for field in failed_field: field_img_path_dict[field] = base_img_path else: pre, suf = os.path.splitext(section_img_path) for field in failed_field: try: res_field = compare_logic[field][0] is_valid, coord_tuple = field_build_coordinates(info.get(res_field, {})) if is_valid: save_path = '{0}_{1}{2}'.format(pre, field, suf) field_img = last_img[coord_tuple[0]:coord_tuple[1], coord_tuple[2]:coord_tuple[3], :] cv2.imwrite(save_path, field_img) field_img_path_dict[field] = save_path else: field_img_path_dict[field] = base_img_path except Exception as e: field_img_path_dict[field] = base_img_path if not is_find: for name, value in field_list: result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value, '{0}未找到'.format(license_en))) return result_field_list, field_img_path_dict def se_compare_process(compare_info, ocr_res_dict, is_gsyh, is_auto): # individualCusInfo # corporateCusInfo # vehicleInfo # bankInfo compare_result = [] total_fields = 0 failed_count = 0 successful_at_this_level = True failure_reason = {} cn_reason_list = [] for info_key, info_value in compare_info.items(): if info_key in ['individualCusInfo', 'applicantInformation']: for idx, license_list in info_value.items(): for license_dict in license_list: for license_en, field_list in license_dict.items(): strip_list = [] for a, b in field_list: if isinstance(b, str): strip_list.append((a, b.strip())) elif isinstance(b, list): c = [] for i in b: if isinstance(i, str): c.append(i.strip()) else: c.append(i) strip_list.append((a, c)) else: strip_list.append((a, b)) failure_field = [] result_field_list, no_ocr_result, field_img_path_dict = se_compare_license(license_en, ocr_res_dict, strip_list) for name, value, result, ocr_str, img_path, error_type, cn_reason in result_field_list: if license_en not in consts.SKIP_CARD or not no_ocr_result: total_fields += 1 if result == consts.RESULT_N: failed_count += 1 successful_at_this_level = False failure_field.append(name) cn_reason_list.append(cn_reason) compare_result.append( { consts.HEAD_LIST[0]: info_key, consts.HEAD_LIST[1]: idx, consts.HEAD_LIST[2]: license_en, consts.HEAD_LIST[3]: name, consts.HEAD_LIST[4]: value, consts.HEAD_LIST[5]: ocr_str, consts.HEAD_LIST[6]: result, consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str), consts.HEAD_LIST[8]: img_path, consts.HEAD_LIST[9]: error_type, } ) if len(failure_field) > 0: failure_reason.setdefault(info_key, []).append(';'.join(failure_field)) else: for license_en, field_list in info_value.items(): strip_list = [] for a, b in field_list: if isinstance(b, str): strip_list.append((a, b.strip())) elif isinstance(b, list): c = [] for i in b: if isinstance(i, str): c.append(i.strip()) else: c.append(i) strip_list.append((a, c)) else: strip_list.append((a, b)) failure_field = [] if license_en == consts.MVC34_EN: result_field_list, field_img_path_dict = se_mvc34_compare(license_en, ocr_res_dict, strip_list) elif license_en in [consts.HIL_CONTRACT_1_EN, consts.HIL_CONTRACT_2_EN, consts.HIL_CONTRACT_3_EN, consts.AFC_CONTRACT_EN]: result_field_list, field_img_path_dict = se_contract_compare(license_en, ocr_res_dict, strip_list, is_gsyh) elif license_en == consts.BS_EN: result_field_list, field_img_path_dict = se_bs_compare(license_en, ocr_res_dict, strip_list, is_auto) else: result_field_list, _, field_img_path_dict = se_compare_license(license_en, ocr_res_dict, strip_list) for name, value, result, ocr_str, img_path, error_type, cn_reason in result_field_list: total_fields += 1 if result == consts.RESULT_N: if license_en != consts.MVI_EN or name != consts.SE_NEW_ADD_FIELD[9]: successful_at_this_level = False failed_count += 1 failure_field.append(name) if isinstance(cn_reason, str): cn_reason_list.append(cn_reason) elif isinstance(cn_reason, list): cn_reason_list.extend(cn_reason) compare_result.append( { consts.HEAD_LIST[0]: info_key, consts.HEAD_LIST[1]: "0", consts.HEAD_LIST[2]: license_en, consts.HEAD_LIST[3]: name, consts.HEAD_LIST[4]: value, consts.HEAD_LIST[5]: ocr_str, consts.HEAD_LIST[6]: result, consts.HEAD_LIST[7]: field_img_path_dict.get(name, empty_str), consts.HEAD_LIST[8]: img_path, consts.HEAD_LIST[9]: error_type, } ) if len(failure_field) > 0: failure_reason.setdefault(info_key, []).append(';'.join(failure_field)) if failed_count == 0: failure_reason_str = '' cn_failure_reason_str = '' bs_failure_reason_str = '' else: reason_list = [] for key, value in failure_reason.items(): if len(value) > 0: value_str = json.dumps(value) reason_list.append('{0}: {1}'.format(key, value_str)) failure_reason_str = '、'.join(reason_list) tmp_set = set() last_cn_reason_list = [] bs_cn_reason_list = [] for i in cn_reason_list: if i in tmp_set: continue # elif i in consts.BS_REASON: # tmp_set.add(i) # bs_cn_reason_list.append(i) else: tmp_set.add(i) last_cn_reason_list.append(i) cn_failure_reason_str = '\n'.join(last_cn_reason_list) bs_failure_reason_str = '\n'.join(bs_cn_reason_list) return compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str, cn_failure_reason_str, bs_failure_reason_str def se_result_detect(ocr_res_dict): detect_list = [] for license_en in consts.SE_DETECT_CARD: ocr_field, _, _ = consts.SE_COMPARE_FIELD[license_en] ocr_res_str = ocr_res_dict.get(ocr_field) detect_list.append(ocr_res_str is None) return detect_list def se_compare_auto(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, auto_obj): try: # 比对逻辑 # detect_list = se_result_detect(ocr_res_dict) compare_info, aa_type, is_gsyh = get_se_cms_compare_info_auto( last_obj, application_entity) compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str, cn_failure_reason_str, bs_failure_reason_str = se_compare_process(compare_info, ocr_res_dict, is_gsyh, True) compare_log.info('{0} [Auto SE] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format( log_base, application_entity, application_id, ocr_res_id, compare_result)) except Exception as e: compare_log.error('{0} [Auto SE] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) else: # 将比对结果写入数据库 auto settlement # try: auto_obj.aa_type = aa_type auto_obj.ocr_auto_result_pass = successful_at_this_level # auto_obj.ocr_whole_result_pass = full_result auto_obj.ocr_auto_result = json.dumps(compare_result) auto_obj.ocr_latest_comparison_time = datetime.now() auto_obj.rpa_result = None auto_obj.rpa_1st_eye_tat = None auto_obj.rpa_2nd_eye_tat = None auto_obj.rpa_3rd_eye_tat = None auto_obj.rpa_total_tat = None auto_obj.rpa_activated_time = None auto_obj.rpa_get_case_from_ocr_time = None auto_obj.rpa_get_case_from_oc_time = None auto_obj.rpa_payment_authorize_time = None auto_obj.rpa_second_eye_time = None # auto_obj.save() # compare_log.info('{0} [Auto SE] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( # log_base, application_entity, application_id, ocr_res_id)) # except Exception as e: # compare_log.error('{0} [Auto SE] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] ' # '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, # traceback.format_exc())) return successful_at_this_level def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms, auto_result): try: # 比对逻辑 start_time = datetime.now() detect_list = se_result_detect(ocr_res_dict) compare_info, application_version, is_gsyh = get_se_cms_compare_info( last_obj, application_entity, detect_list) compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str, cn_failure_reason_str, bs_failure_reason_str = se_compare_process(compare_info, ocr_res_dict, is_gsyh, False) compare_log.info('{0} [SE] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format( log_base, application_entity, application_id, ocr_res_id, compare_result)) except Exception as e: compare_log.error('{0} [SE] [compare error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) return False else: # 将比对结果写入数据库 try: result_table = HILSECompareResult if application_entity == consts.HIL_PREFIX else AFCSECompareResult res_obj = result_table.objects.filter(application_id=application_id).first() if res_obj is None: res_obj = result_table() res_obj.application_id = application_id res_obj.compare_count = total_fields res_obj.failed_count = failed_count res_obj.is_finish = successful_at_this_level source = consts.INFO_SOURCE[1] if is_cms else consts.INFO_SOURCE[0] res_obj.version = '{0}{1}{2}'.format(source, consts.SPLIT_STR, application_version) # res_obj.reason1_count = reason1_count res_obj.result = json.dumps(compare_result) res_obj.update_time = datetime.now() res_obj.save() compare_log.info('{0} [SE] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) except Exception as e: compare_log.error('{0} [SE] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) # report end_time = datetime.now() try: request_trigger = RequestTrigger.SUBMITING.value if ocr_res_id is None else RequestTrigger.UPLOADING.value report_class = HILCompareReport if application_entity == consts.HIL_PREFIX else AFCCompareReport report_class.objects.create( case_number=application_id, request_team=RequestTeam.SETTLEMENT.value, request_trigger=request_trigger, transaction_start=start_time, transaction_end=end_time, successful_at_this_level=successful_at_this_level, failure_reason=failure_reason_str, process_name=ProcessName.SE_CACOMPARE.value, total_fields=total_fields, workflow_name='' if is_cms else last_obj.customer_type, ) compare_log.info('{0} [SE] [report save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) except Exception as e: compare_log.error('{0} [SE] [report save error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) # cms结果发送 # if is_cms: try: application_link = '{0}/showList/showList?entity={1}&scheme={2}&case_id={3}'.format( conf.BASE_URL, application_entity, consts.COMPARE_DOC_SCHEME_LIST[1], application_id) data = { "SubtenantId": consts.TENANT_MAP[application_entity], "Data": { "Result_Message": "Pass" if successful_at_this_level else "Fail", "AutoCheckResult": "Pass" if auto_result else "Fail", "Failure_Reason": cn_failure_reason_str, "Application_Number": application_id, "Bank_Statement": bs_failure_reason_str, "Link_URL": application_link, "OCR_Version": 1, "Origin": consts.INFO_SOURCE[1] } } response = cms.send(data) except Exception as e: compare_log.error('{0} [SE] [cms error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc())) else: compare_log.info('{0} [SE] [cms success] [entity={1}] [id={2}] [ocr_res_id={3}] [data={4}] ' '[response={5}]'.format(log_base, application_entity, application_id, ocr_res_id, data, response)) return successful_at_this_level @app.task def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False): # POS: application_id, application_entity, uniq_seq, None # OCR: application_id, business_type(application_entity), None, ocr_res_id compare_log.info('{0} [receive task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] [is_ca={5}] ' '[is_cms={6}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca, is_cms)) # 根据application_id查找最新的比对信息,如果没有,结束 if is_ca: comparison_class = HILComparisonInfo if application_entity == consts.HIL_PREFIX else AFCComparisonInfo else: if application_entity == consts.HIL_PREFIX: comparison_class = HILSECMSInfo if is_cms else HILSEComparisonInfo else: comparison_class = AFCSECMSInfo if is_cms else AFCSEComparisonInfo last_obj = comparison_class.objects.filter(application_id=application_id).last() if last_obj is None: compare_log.info('{0} [comparison info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] ' '[is_ca={5}] [is_cms]={6}'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca, is_cms)) return # 根据application_id查找OCR累计结果指定license字段,如果没有,结束 if is_ca: result_class = HILOCRResult if application_entity == consts.HIL_PREFIX else AFCOCRResult ca_ocr_res_dict = dict() else: result_class = HILSEOCRResult if application_entity == consts.HIL_PREFIX else AFCSEOCRResult ca_result_class = HILOCRResult if application_entity == consts.HIL_PREFIX else AFCOCRResult # if ocr_res_id is None: ca_ocr_res_dict = ca_result_class.objects.filter(application_id=application_id).values( *consts.CA_ADD_COMPARE_FIELDS).first() # else: # ca_ocr_res_dict = ca_result_class.objects.filter(id=ocr_res_id).values( # *consts.CA_ADD_COMPARE_FIELDS).first() if ocr_res_id is None: ocr_res_dict = result_class.objects.filter(application_id=application_id).values(*consts.COMPARE_FIELDS).first() else: ocr_res_dict = result_class.objects.filter(id=ocr_res_id).values(*consts.COMPARE_FIELDS).first() if ocr_res_dict is None: compare_log.info('{0} [ocr info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] ' '[is_ca={5}] [is_cms]={6}'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca, is_cms)) return if is_ca: ca_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict) else: for field_name in consts.CA_ADD_COMPARE_FIELDS: if isinstance(ca_ocr_res_dict, dict) and isinstance(ca_ocr_res_dict.get(field_name), str): tmp_ca_result = json.loads(ca_ocr_res_dict.get(field_name)) if isinstance(ocr_res_dict.get(field_name), str): tmp_se_result = json.loads(ocr_res_dict.get(field_name)) tmp_ca_result.extend(tmp_se_result) ocr_res_dict[field_name] = json.dumps(tmp_ca_result) # auto settlement auto_class = HILAutoSettlement if application_entity == consts.HIL_PREFIX else AFCAutoSettlement auto_obj = auto_class.objects.filter(application_id=application_id, on_off=True).first() if auto_obj is not None: auto_result = se_compare_auto(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, auto_obj) else: auto_result = None full_result = se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms, auto_result) if auto_obj is not None: try: auto_obj.ocr_whole_result_pass = full_result auto_obj.save() compare_log.info('{0} [Auto SE] [result save success] [entity={1}] [id={2}] [ocr_res_id={3}]'.format( log_base, application_entity, application_id, ocr_res_id)) except Exception as e: compare_log.error('{0} [Auto SE] [result save error] [entity={1}] [id={2}] [ocr_res_id={3}] ' '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, traceback.format_exc()))