1d776432 by 周伟奇

add asp

1 parent 356977cd
......@@ -1438,12 +1438,15 @@ SE_AFC_CON_MAP = {
'见证人日期': (7, 8, '见证人签字', '日期'),
'还款计划表': (3, 3, '还款计划表', None),
'ASP项目详情-重要条款': (None, 1, '附加产品融资贷款本金总金额明细', None),
'ASP项目详情': (None, 4, '附加产品融资贷款本金总金额明细', None),
}
SE_AFC_CON_FIELD = ['合同编号-每页', '所购车辆价格-小写-重要条款', '车架号-重要条款', '贷款本金金额-重要条款', '贷款期限-重要条款',
'车辆贷款本金金额-重要条款', '附加产品融资贷款本金总额-重要条款', '所购车辆价格', '车架号', '经销商',
'贷款本金金额', '车辆贷款本金金额', '附加产品融资贷款本金总额', '贷款期限', '还款账号', '户名', '开户行',
'还款计划表', '见证人签字', '见证人日期']
'还款计划表', '见证人签字', '见证人日期', 'ASP项目详情-重要条款', '购置税校验', 'ASP项目详情']
# '项目1', '用途总金额', '贷款本金', '附加产品融资贷款本金总金额', '购置税校验'
......@@ -1470,7 +1473,10 @@ ROLE_LIST = [
('保证人日期2', 'Guarantor', 1, '有', False, False),
]
GZS_REASON_1 = '此申请有ASP产品,需人工核查'
GZS_REASON_2 = 'ASP购置税金额小于系统金额'
GZS_NAME = '车辆购置税'
ASP_SUM_NAME = '附加产品融资贷款本金总金额'
GZS_STATUS = ['Y', 'N', 'O']
SCHEDULE_SPLIT_STR = '、'
......@@ -1668,6 +1674,9 @@ HT_COMPARE_LOGIC = {
'见证人日期': ('见证人日期', 'se_date_contain_compare', {}, '合同见证人签字日期不符合逻辑'),
'还款计划表': ('还款计划表', 'se_schedule_compare', {}, '还款计划表与系统不一致'),
'ASP项目详情-重要条款': ('ASP项目详情-重要条款', 'se_asp_compare', {}, '(重要条款)ASP名称或者金额与系统不一致'),
'ASP项目详情': ('ASP项目详情', 'se_asp_compare', {}, 'ASP名称或者金额与系统不一致'),
}
......
......@@ -548,7 +548,7 @@ class Command(BaseCommand, LoggerMixin):
head_fields.append(a)
else:
head_fields = []
for a, b in side_field_order:
for a, b in field_order:
if isinstance(b, str):
head_fields.append(a)
row = []
......
......@@ -863,6 +863,8 @@ class Command(BaseCommand, LoggerMixin):
for key, (pno_not_asp, pno_asp, key1, key2) in consts.SE_AFC_CON_MAP.items():
pno = pno_asp if is_asp else pno_not_asp
if pno is None:
if isinstance(pno_asp, int):
continue
end_idx = 9 if is_asp else 8
for i in range(1, end_idx):
res.setdefault(key, list()).append(page_info_dict.get(str(i), {}).get(key1, ''))
......
......@@ -117,19 +117,6 @@ def img_process(section_img_path, section_position, section_angle):
return image
# class FakePOS:
#
# def __init__(self,
# application_id,
# first_submmison_date,
# application_version,
# customer_type):
# self.application_id = application_id
# self.first_submmison_date = first_submmison_date
# self.application_version = application_version
# self.customer_type = customer_type
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]
......@@ -146,11 +133,6 @@ def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_nu
def get_order_dict(src_dict, order_tuple):
# if consts.SECOND_ID_TYPE_FIELD in src_dict:
# if src_dict.get(consts.SECOND_ID_TYPE_FIELD) not in consts.SECOND_ID_TYPE_COMPARE:
# src_dict.pop(consts.SECOND_ID_TYPE_FIELD, None)
# src_dict.pop(consts.SECOND_ID_FIELD, None)
order_dict = OrderedDict({})
for field in order_tuple:
if field in src_dict:
......@@ -940,7 +922,7 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list):
('businessLicenseDueDate', id_info.get('idExpiryDate', '')),
]
license_dict[consts.BL_EN] = bl_field_input
# all_id_num.append(id_num)
all_id_num.append(id_num)
if individual_info.get('customersubType', '') == 'Corporate':
company_info_list.append((customer_name, id_num))
......@@ -1100,19 +1082,20 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list):
schedule_list.append(tmp_str)
schedule_list_str = consts.SCHEDULE_SPLIT_STR.join(schedule_list)
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], str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', '0.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], cms_info.get('dealerName', '')),
(consts.SE_AFC_CON_FIELD[10], str(cms_info.get('financialInformation', {}).get('originationPrincipal', '0.0'))),
(consts.SE_AFC_CON_FIELD[11], str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', '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),
......@@ -1121,48 +1104,51 @@ def get_se_cms_compare_info(last_obj, application_entity, detect_list):
(consts.SE_AFC_CON_FIELD[17], schedule_list_str),
]
# asp_list = []
# for asp_info in cms_info.get('associatedServices', []):
# asp_list.append(
# (
# asp_info.get('associatedServices', ''),
# asp_info.get('price', 0.0),
# asp_info.get('financed', 0.0)
# )
# )
if str(cms_info.get('financialInformation', {}).get('associatedServicePrincipal', '0.00')) == '0.00':
afc_contract_input.pop(5)
afc_contract_input.pop(5)
afc_contract_input.pop(9)
afc_contract_input.pop(9)
# if len(asp_list) > 0:
# fin_total = 0
# gzs_status = consts.GZS_STATUS[1]
# for asp_name, asp_price, asp_fin in asp_list:
# if gzs_status == consts.GZS_STATUS[1]:
# if consts.GZS_NAME in asp_name:
# gzs_status = consts.GZS_STATUS[0]
# if gzs_status == consts.GZS_STATUS[0]:
# if consts.GZS_NAME not in asp_name:
# gzs_status = consts.GZS_STATUS[2]
# afc_contract_input.extend(
# [
# (consts.SE_AFC_CON_FIELD[18], asp_name),
# (consts.SE_AFC_CON_FIELD[19], str(asp_price)),
# (consts.SE_AFC_CON_FIELD[20], str(asp_fin)),
# ]
# )
# fin_total += asp_fin
# afc_contract_input.append((consts.SE_AFC_CON_FIELD[21], str(fin_total)))
#
# # CMS Vehicle Price / 1.13 * 10 %
# gzs_list = [gzs_status]
# if gzs_status != consts.GZS_STATUS[1]:
# gzs_value = str(cms_info.get('financialInformation', {}).get('vehiclePrincipal', 0.0) * 0.1 / 1.13)
# gzs_list.append(gzs_value)
# afc_contract_input.append((consts.SE_AFC_CON_FIELD[22], consts.SPLIT_STR.join(gzs_list)))
else:
asp_list = []
gzs_status = consts.GZS_STATUS[1]
gzs_price = '0.00'
for asp_info in cms_info.get('associatedServices', []):
tmp_asp_name = asp_info.get('associatedServices')
if isinstance(tmp_asp_name, str) and len(tmp_asp_name) > 0:
if gzs_status == consts.GZS_STATUS[1] and tmp_asp_name.find(consts.GZS_NAME) != -1:
gzs_status = consts.GZS_STATUS[2]
gzs_price = asp_info.get('price', '0.00')
asp_list.append(
(
tmp_asp_name,
asp_info.get('price', '0.00'),
asp_info.get('financed', '0.00')
)
)
fin_total = 0
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,
'',
format(fin_total, '.2f')
)
)
afc_contract_input.append((consts.SE_AFC_CON_FIELD[20], asp_list))
afc_contract_input.append((consts.SE_AFC_CON_FIELD[22], asp_list))
# CMS Vehicle Price / 1.13 * 10 %
gzs_list = [gzs_status]
if gzs_status != consts.GZS_STATUS[1]:
gzs_value = float(vehicle_principal_str) * 0.1 / 1.13
gzs_list.append(gzs_value)
gzs_list.append(float(gzs_price))
afc_contract_input.append((consts.SE_AFC_CON_FIELD[21], gzs_list))
# '借款人签字及时间', 'Borrower', 0, 0, True
online_sign = cms_info.get('contractSource', 'Online Sign') == 'Online Sign'
......@@ -1365,173 +1351,6 @@ def get_se_compare_info(last_obj, application_entity, detect_list):
return compare_info
# def rebuild_compare_info(last_obj, application_id):
# {
# "content": {
# "financeCompany": "宝马汽车金融有限公司",
# "contractNo": "CH-B100000123",
# "status": "HIL",
# "branch": "宝马汽车金融有限公司",
# "fpCampaign": "Q1_2021_BMW_BASIC",
# "applicationVersion": 1,
# "submissionDate": {},
# "mortgageType": "Mortgage Contract",
# "dealerRegion": "West",
# "insuranceRealNameCity": false,
# "totalFinanceAmount": 1234.56,
# "terms": 24,
# "dealerName": "乐山长宝汽车销售服务有限公司",
# "tier": "2",
# "province": "四川省",
# "fapiaoIssuerDealer": "乐山长宝汽车销售服务有限公司",
# "customerName": "蔡红",
# "customerIdNo": "511102196706080000",
# "vehicleStatus": "Used",
# "applicationSource": "eApp",
# "contractSource": "Online Sign",
# "applicationRating": 100,
# "applicantInformation": [
# {
# "applicantType": "Borrower",
# "customersubType": "TCCOR",
# "selfEmployedSubType": "CSIBM",
# "name": "李四",
# "legalRepName": "张三",
# "dateOfBirth": {},
# "nationality": "中国",
# "establishmentDate": {},
# "IDInformation": [
# {
# "idType": "ITARI",
# "idNum": "111111199404251100",
# "idExpiryDate": {}
# }
# ]
# }
# ],
# "autoApprovedDetails": {
# "aaType": "CAA1"
# },
# "financialInformation": {
# "vehiclePrice": 1234.56,
# "grossPrice": 1234.56,
# "associatedServicePrice": 1234.56,
# "vehiclePrincipal": 1234.56,
# "associatedServicePrincipal": 1234.56,
# "originationPrincipal": 1234.56,
# "totalDownPayment": 1234.56,
# "vehicleDownPaymentRatio": 1234.56,
# "optionAmount": 1234.56,
# "sumOfMSRPAndOption": 1234.56
# },
# "paymentSchedule": [
# {
# "no": 3,
# "grossRentalAmount": 1234.56
# }
# ],
# "associatedServices": [
# {
# "associatedServices": "机动车保险",
# "price": 1234.56,
# "financed": 1234.56,
# "total": 1234.56
# }
# ],
# "vehicleInformation": {
# "vinNo": "LBV23482934DJFKD"
# },
# "bankAccountDetails": {
# "bankName": "中国银行",
# "accountHolderName": "张三",
# "accountNo": "12312123123123124"
# },
# "insuranceDetails": {
# "insuranceType": "ComprehensiveInsurance",
# "insuranceAmount": "60000000",
# "startDate": {},
# "endDate": {}
# },
# "corporateFinancialInformation": {
# "hashCode": "238231",
# "borrowerName": "张三",
# "fiscalYear": 2019,
# "totaAssets": 1234.56,
# "totalLiabilitiesAndOwnersEquity": 1234.56,
# "cashAndCashEquivalentAtEndOfPeriod": 1234.56,
# "netProfit": 1234.56
# },
# "settlemnetVerification": {
# "applicationNo": "CH-B100000123"
# }
# }
# }
# cms_info = json.loads(last_obj.content)
#
# fake_pos = FakePOS(application_id,
# cms_info.get('submissionDate', ''),
# cms_info.get('applicationVersion', 1),
# cms_info.get('applicantInformation', [])[0].get('customersubType', ''))
#
# fake_pos.bank_info = json.dumps(
# {
# 'accountNo': decode_des(cms_info.get('bankAccountDetails', {}).get('accountNo', ''), des_key),
# 'bankName': cms_info.get('bankAccountDetails', {}).get('bankName', ''),
# 'accountHolderName': cms_info.get('bankAccountDetails', {}).get('accountHolderName', ''),
# }
# )
#
# fake_pos.vehicle_info = json.dumps(
# {
# 'vehicleStatus': cms_info.get('vehicleStatus', ''),
# 'vinNo': cms_info.get('vehicleInformation', {}).get('vinNo', ''),
# 'dealer': cms_info.get('dealerName', ''),
# 'vehicleTransactionAmount': str(cms_info.get('totalFinanceAmount', '')),
# }
# )
#
# individual_cus_info = []
# for individual_cus in cms_info.get('applicantInformation', []):
# id_type = id_num = id_date = second_id_type = second_id_num = None
# for idx, id_info in enumerate(individual_cus.get('', [])):
# if idx > 1:
# break
# elif idx == 0:
# id_type = id_info.get('idType')
# id_num = decode_des(id_info.get('idNum'))
# id_date = id_info.get('idExpiryDate')
# else:
# second_id_type = id_info.get('idType')
# second_id_num = decode_des(id_info.get('idNum'))
# individual_cus_info.append(
# {
# 'applicantType': consts.APPLICANT_TYPE_MAP.get(individual_cus.get('applicantType')),
# 'customerType': individual_cus.get('customersubType'),
#
# 'idType': id_type,
# 'idNum': id_num,
# 'idExpiryDate': id_date,
#
# 'customerName': individual_cus.get('name'),
# 'dateOfBirth': individual_cus.get('dateOfBirth', ''),
# 'hukouProvince': cms_info.get('province', ''),
#
# 'secondIdType': second_id_type,
# 'secondIdNum': second_id_num,
#
# 'companyName': individual_cus.get('name'),
# 'selfEmployedSubType': individual_cus.get('selfEmployedSubType', ''),
# }
# )
#
# fake_pos.individual_cus_info = json.dumps(individual_cus_info)
#
# fake_pos.corporate_cus_info = None
#
# return fake_pos
def se_compare_license(license_en, ocr_res_dict, field_list):
ocr_field, compare_logic, special_expiry_date = consts.SE_COMPARE_FIELD[license_en]
......@@ -1710,21 +1529,46 @@ def se_afc_contract_compare(license_en, ocr_res_dict, strip_list):
for name, value in strip_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):
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
elif isinstance(ocr_str_or_list, str) or isinstance(ocr_str_or_list, list):
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)
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]
img_path = 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 isinstance(value, list):
value = json.dumps(value)
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)
result_field_list.append((name, value, consts.RESULT_N, empty_str, empty_str, ErrorType.NF.value,
'{0}未找到'.format(license_en)))
......@@ -1919,7 +1763,10 @@ def se_compare_process(compare_info, ocr_res_dict):
failed_count += 1
successful_at_this_level = False
failure_field.append(name)
cn_reason_list.append(cn_reason)
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,
......@@ -2116,34 +1963,3 @@ def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True
tmp_ca_result.extend(tmp_se_result)
ocr_res_dict[consts.IC_OCR_FIELD] = json.dumps(tmp_ca_result)
se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms)
# @app.task
# def forwarding_station(application_id, entity):
# compare_log.info('{0} [forward start] [application_id={1}] [entity={2}]'.format(e_log_base, application_id, entity))
# doc_class = HILDoc if entity in consts.HIL_SET else AFCDoc
# entity_prefix = consts.HIL_PREFIX if entity in consts.HIL_SET else consts.AFC_PREFIX
# for (classify_1, classify_2), prefix in consts.FILE_NAME_PREFIX_MAP.get(entity):
# try:
# file_list = ecm.search(application_id, entity, prefix.format(application_id)) # TODO 获取最新文件
# except Exception as e:
# compare_log.error('{0} [search failed] [application_id={1}] [entity={2}] [error={3}]'.format(
# e_log_base, application_id, entity, traceback.format_exc()))
# else:
# compare_log.info('{0} [search end] [application_id={1}] [entity={2}] [file_list={3}]'.format(
# e_log_base, application_id, entity, file_list))
# for object_name, object_id in file_list:
# doc = doc_class.objects.create(
# metadata_version_id=object_id,
# application_id=application_id,
# document_name=object_name,
# document_scheme='SETTLEMENT',
# data_source='POS',
# upload_finish_time=datetime.now(),
# )
# task = consts.SPLIT_STR.join([entity_prefix, str(doc.id), str(classify_1), str(classify_2)])
# enqueue_res = rh.enqueue([task], False)
# compare_log.info('{0} [upload success] [res={1}] [application_id={2}] [entity={3}] [object_name={4}] '
# '[object_id={5}] [doc_id={6}]'.format(e_log_base, enqueue_res, application_id, entity,
# object_name, object_id, doc.id))
# compare_log.info('{0} [forward end] [application_id={1}] [entity={2}]'.format(e_log_base, application_id, entity))
......
......@@ -185,6 +185,34 @@ class Comparison:
else:
return self.RESULT_N
def se_asp_compare(self, input_list, ocr_str_or_list, **kwargs):
if isinstance(ocr_str_or_list, list):
try:
for asp_name, asp_price, asp_fin in input_list[:-1]:
for row_list in ocr_str_or_list:
if len(row_list) != 3:
continue
if row_list[0].find(asp_name) == -1:
continue
if float(row_list[1].replace(',', '')) == float(asp_price) and \
float(row_list[2].replace(',', '')) == float(asp_fin):
break
else:
return self.RESULT_N
_, _, sum_fin = input_list[-1]
if float(ocr_str_or_list[-1][-1].replace(',', '')) == float(sum_fin):
return self.RESULT_Y
else:
return self.RESULT_N
except Exception as e:
return self.RESULT_N
else:
return self.RESULT_N
def se_gzs_compare(self, input_str, ocr_str_or_list, **kwargs):
pass
def se_name_compare(self, input_str, ocr_str, **kwargs):
if kwargs.get('is_passport'):
input_tmp = input_str.upper().replace(' ', '')
......@@ -265,7 +293,17 @@ class Comparison:
if kwargs.get('today', False):
return self.build_res(self.is_after_today(ocr_str))
else:
return self.build_res(input_str == ocr_str)
res = self.build_res(input_str == ocr_str)
if res == self.RESULT_Y:
return res
else:
try:
ocr_date = datetime.strptime(ocr_str, "%Y-%m-%d")
input_date = datetime.strptime(input_str, "%Y-%m-%d")
return self.build_res(input_date == ocr_date)
except Exception as e:
return self.RESULT_N
def ca_date_compare(self, input_str, ocr_str, **kwargs):
if kwargs.get('long', False):
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!