fix merge
Showing
9 changed files
with
544 additions
and
26 deletions
| ... | @@ -1649,3 +1649,69 @@ CA_COMPARE_FIELD = { | ... | @@ -1649,3 +1649,69 @@ CA_COMPARE_FIELD = { |
| 1649 | } | 1649 | } |
| 1650 | 1650 | ||
| 1651 | CONTRACT_SHEET_NAME = '合同' | 1651 | CONTRACT_SHEET_NAME = '合同' |
| 1652 | |||
| 1653 | # ------------------CMS-------------------------------------- | ||
| 1654 | BANK_INFO_MAP = ( | ||
| 1655 | ('accountNo', 'bankAccountDetails.accountNo'), | ||
| 1656 | ('bankName', 'bankAccountDetails.bankName'), | ||
| 1657 | ('accountHolderName', 'bankAccountDetails.accountHolderName'), | ||
| 1658 | ) | ||
| 1659 | |||
| 1660 | VEHICLE_INFO_MAP = ( | ||
| 1661 | ('vehicleStatus', 'vehicleStatus'), | ||
| 1662 | ('vinNo', 'vehicleInformation.vinNo'), | ||
| 1663 | ('dealer', 'dealerName'), | ||
| 1664 | ('vehicleTransactionAmount', 'totalFinanceAmount'), | ||
| 1665 | ) | ||
| 1666 | |||
| 1667 | CORPORATE_INFO_MAP = ( | ||
| 1668 | ('firstIdType', ), | ||
| 1669 | ('firstIdNo', ), | ||
| 1670 | ('companyName', ), | ||
| 1671 | ('legalRepName', ), | ||
| 1672 | ('businessLicenseNo', ), | ||
| 1673 | ('organizationCreditCode', ), | ||
| 1674 | ('taxRegistrationCertificateNo', ), | ||
| 1675 | ('establishmentDate', ), | ||
| 1676 | ('businessLicenseDueDate', ), | ||
| 1677 | ) | ||
| 1678 | |||
| 1679 | INDIVIDUAL_INFO_MAP = ( | ||
| 1680 | ('applicantType', 'applicantInformation.applicantType'), | ||
| 1681 | ('customerType', 'applicantInformation.customersubType'), | ||
| 1682 | |||
| 1683 | ('idType', 'applicantInformation.IDInformation.idType'), | ||
| 1684 | ('customerName', 'applicantInformation.name'), | ||
| 1685 | ('idNum', 'applicantInformation.IDInformation.idNum'), | ||
| 1686 | ('dateOfBirth', 'applicantInformation.dateOfBirth'), | ||
| 1687 | ('idExpiryDate', 'applicantInformation.IDInformation.idExpiryDate'), | ||
| 1688 | ('hukouProvince', ), | ||
| 1689 | ('hukouCity', ), | ||
| 1690 | |||
| 1691 | ('secondIdType', 'applicantInformation.IDInformation.idType'), | ||
| 1692 | ('secondIdNum', 'applicantInformation.IDInformation.idNum'), | ||
| 1693 | |||
| 1694 | ('companyName', ), | ||
| 1695 | ('registeredCapital', ), | ||
| 1696 | ('selfEmployedSubType', ), | ||
| 1697 | ) | ||
| 1698 | |||
| 1699 | CMS_TO_POS = [ | ||
| 1700 | ('bank_info', BANK_INFO_MAP), | ||
| 1701 | ('vehicle_info', VEHICLE_INFO_MAP), | ||
| 1702 | ('corporate_cus_info', CORPORATE_INFO_MAP), | ||
| 1703 | ('individual_cus_info', INDIVIDUAL_INFO_MAP), | ||
| 1704 | ] | ||
| 1705 | |||
| 1706 | TENANT_MAP = { | ||
| 1707 | AFC_PREFIX: 1, | ||
| 1708 | HIL_PREFIX: 2, | ||
| 1709 | } | ||
| 1710 | |||
| 1711 | APPLICANT_TYPE_MAP = { | ||
| 1712 | 'Borrower': 'CUSTR', | ||
| 1713 | 'Co Borrower': 'COAPP', | ||
| 1714 | 'Guarantor': 'GAUTR1', | ||
| 1715 | 'Mortgager': 'GAUTR2' | ||
| 1716 | } | ||
| 1717 | ... | ... |
| ... | @@ -13,9 +13,14 @@ class OCR2Exception(Exception): | ... | @@ -13,9 +13,14 @@ class OCR2Exception(Exception): |
| 13 | class OCR4Exception(Exception): | 13 | class OCR4Exception(Exception): |
| 14 | pass | 14 | pass |
| 15 | 15 | ||
| 16 | |||
| 16 | class LTGTException(Exception): | 17 | class LTGTException(Exception): |
| 17 | pass | 18 | pass |
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | class GCAPException(Exception): | 21 | class GCAPException(Exception): |
| 21 | pass | 22 | pass |
| 23 | |||
| 24 | |||
| 25 | class CMSException(Exception): | ||
| 26 | pass | ... | ... |
| ... | @@ -244,6 +244,33 @@ class HILSEComparisonInfo(models.Model): | ... | @@ -244,6 +244,33 @@ class HILSEComparisonInfo(models.Model): |
| 244 | 244 | ||
| 245 | 245 | ||
| 246 | # 比对信息表 | 246 | # 比对信息表 |
| 247 | class AFCSECMSInfo(models.Model): | ||
| 248 | id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键 | ||
| 249 | application_id = models.CharField(max_length=64, verbose_name="申请id") # 索引 | ||
| 250 | content = models.TextField(verbose_name="CMS信息") | ||
| 251 | update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') | ||
| 252 | create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 索引 | ||
| 253 | |||
| 254 | class Meta: | ||
| 255 | managed = False | ||
| 256 | db_table = 'afc_se_cms_info' | ||
| 257 | situ_db_label = 'afc' | ||
| 258 | |||
| 259 | |||
| 260 | # 比对信息表 | ||
| 261 | class HILSECMSInfo(models.Model): | ||
| 262 | id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键 | ||
| 263 | application_id = models.CharField(max_length=64, verbose_name="申请id") # 索引 | ||
| 264 | content = models.TextField(verbose_name="CMS信息") | ||
| 265 | update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') | ||
| 266 | create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 索引 | ||
| 267 | |||
| 268 | class Meta: | ||
| 269 | managed = False | ||
| 270 | db_table = 'hil_se_cms_info' | ||
| 271 | |||
| 272 | |||
| 273 | # 比对信息表 | ||
| 247 | class HILComparisonInfo(models.Model): | 274 | class HILComparisonInfo(models.Model): |
| 248 | id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键 | 275 | id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键 |
| 249 | uniq_seq = models.CharField(max_length=128, verbose_name="唯一序列号") # 索引? | 276 | uniq_seq = models.CharField(max_length=128, verbose_name="唯一序列号") # 索引? | ... | ... |
src/apps/doc/ocr/cms.py
0 → 100644
| 1 | import requests | ||
| 2 | from settings import conf | ||
| 3 | from common.redis_cache import redis_handler as rh | ||
| 4 | from apps.doc.exceptions import CMSException | ||
| 5 | |||
| 6 | |||
| 7 | class CMS: | ||
| 8 | |||
| 9 | def __init__(self): | ||
| 10 | self.oauth_url = conf.CMS_OAUTH_URL | ||
| 11 | self.url = conf.CMS_URL | ||
| 12 | self.oauth_payload = { | ||
| 13 | 'grant_type': 'client_credentials', | ||
| 14 | 'client_id': conf.CMS_OAUTH_ID, | ||
| 15 | 'client_secret': conf.CMS_OAUTH_SECRET, | ||
| 16 | 'scope': conf.CMS_OAUTH_SCOPE | ||
| 17 | } | ||
| 18 | self.token_type = 'bearer' | ||
| 19 | self.token = None | ||
| 20 | self.token_key = 'access_token' | ||
| 21 | self.expires_key = 'expires_in' | ||
| 22 | self.token_type_key = 'token_type' | ||
| 23 | |||
| 24 | def update_token(self): | ||
| 25 | response = requests.post(self.oauth_url, data=self.oauth_payload, files=[]) | ||
| 26 | if response.status_code != 200: | ||
| 27 | raise CMSException('CMS Oauth response with code: {0}'.format(response.status_code)) | ||
| 28 | token = response.json().get(self.token_key) | ||
| 29 | if not isinstance(token, str): | ||
| 30 | raise CMSException('CMS Oauth can not get token: {0}'.format(response.json())) | ||
| 31 | self.token = token | ||
| 32 | self.token_type = response.json().get(self.token_type_key, self.token_type) | ||
| 33 | expires = response.json().get(self.expires_key, 3600) | ||
| 34 | rh.set_cms_token(self.token, expires) | ||
| 35 | |||
| 36 | def get_token(self): | ||
| 37 | if self.token is None: | ||
| 38 | self.token = rh.get_cms_token() | ||
| 39 | if self.token is None: | ||
| 40 | self.update_token() | ||
| 41 | return self.token | ||
| 42 | |||
| 43 | def send(self, payload): | ||
| 44 | token = self.get_token() | ||
| 45 | headers = { | ||
| 46 | 'Authorization': '{0} {1}'.format(self.token_type.capitalize(), token), | ||
| 47 | 'Content-Type': 'application/json', | ||
| 48 | } | ||
| 49 | response = requests.post(self.url, headers=headers, json=payload) | ||
| 50 | if response.status_code != 200: | ||
| 51 | raise CMSException('CMS Oauth response with code: {0}'.format(response.status_code)) | ||
| 52 | return response.json() | ||
| 53 | |||
| 54 | |||
| 55 | cms = CMS() | ||
| 56 | |||
| 57 | |||
| 58 | |||
| 59 |
| ... | @@ -22,8 +22,10 @@ from .models import ( | ... | @@ -22,8 +22,10 @@ from .models import ( |
| 22 | GCAPRecords, | 22 | GCAPRecords, |
| 23 | AFCComparisonInfo, | 23 | AFCComparisonInfo, |
| 24 | AFCSEComparisonInfo, | 24 | AFCSEComparisonInfo, |
| 25 | AFCSECMSInfo, | ||
| 25 | HILComparisonInfo, | 26 | HILComparisonInfo, |
| 26 | HILSEComparisonInfo, | 27 | HILSEComparisonInfo, |
| 28 | HILSECMSInfo, | ||
| 27 | AFCCompareOfflineReport, | 29 | AFCCompareOfflineReport, |
| 28 | HILCompareOfflineReport, | 30 | HILCompareOfflineReport, |
| 29 | AFCCACompareResult, | 31 | AFCCACompareResult, |
| ... | @@ -327,7 +329,7 @@ info_args = { | ... | @@ -327,7 +329,7 @@ info_args = { |
| 327 | 'customersubType': fields.Str(required=True, validate=validate.Length(max=32)), | 329 | 'customersubType': fields.Str(required=True, validate=validate.Length(max=32)), |
| 328 | 'selfEmployedSubType': fields.Str(required=False, validate=validate.Length(max=32)), | 330 | 'selfEmployedSubType': fields.Str(required=False, validate=validate.Length(max=32)), |
| 329 | 'name': fields.Str(required=True, validate=validate.Length(max=64)), | 331 | 'name': fields.Str(required=True, validate=validate.Length(max=64)), |
| 330 | 'legalRepName': fields.Str(required=True, validate=validate.Length(max=64)), | 332 | 'legalRepName': fields.Str(required=False, validate=validate.Length(max=64)), |
| 331 | 'dateOfBirth': CustomDate(required=False), | 333 | 'dateOfBirth': CustomDate(required=False), |
| 332 | 'nationality': fields.Str(required=False, validate=validate.Length(max=64)), | 334 | 'nationality': fields.Str(required=False, validate=validate.Length(max=64)), |
| 333 | 'establishmentDate': CustomDate(required=False), | 335 | 'establishmentDate': CustomDate(required=False), |
| ... | @@ -358,10 +360,10 @@ payment_schedule = { | ... | @@ -358,10 +360,10 @@ payment_schedule = { |
| 358 | } | 360 | } |
| 359 | 361 | ||
| 360 | associated_services = { | 362 | associated_services = { |
| 361 | 'associatedServices': fields.Str(required=True, validate=validate.Length(max=64)), | 363 | 'associatedServices': fields.Str(required=False, validate=validate.Length(max=64)), |
| 362 | 'price': CustomDecimal(required=True), | 364 | 'price': CustomDecimal(required=False), |
| 363 | 'financed': CustomDecimal(required=True), | 365 | 'financed': CustomDecimal(required=False), |
| 364 | 'total': CustomDecimal(required=True), | 366 | 'total': CustomDecimal(required=False), |
| 365 | } | 367 | } |
| 366 | 368 | ||
| 367 | vehicle_info = { | 369 | vehicle_info = { |
| ... | @@ -382,13 +384,13 @@ insurance_details = { | ... | @@ -382,13 +384,13 @@ insurance_details = { |
| 382 | } | 384 | } |
| 383 | 385 | ||
| 384 | corporate_info = { | 386 | corporate_info = { |
| 385 | 'hashCode': fields.Str(required=True, validate=validate.Length(max=64)), | 387 | 'hashCode': fields.Str(required=False, validate=validate.Length(max=64)), |
| 386 | 'borrowerName': fields.Str(required=True, validate=validate.Length(max=64)), | 388 | 'borrowerName': fields.Str(required=False, validate=validate.Length(max=64)), |
| 387 | 'fiscalYear': fields.Int(required=True), | 389 | 'fiscalYear': fields.Int(required=False), |
| 388 | 'totaAssets': CustomDecimal(required=True), | 390 | 'totaAssets': CustomDecimal(required=False), |
| 389 | 'totalLiabilitiesAndOwnersEquity': CustomDecimal(required=True), | 391 | 'totalLiabilitiesAndOwnersEquity': CustomDecimal(required=False), |
| 390 | 'cashAndCashEquivalentAtEndOfPeriod': CustomDecimal(required=True), | 392 | 'cashAndCashEquivalentAtEndOfPeriod': CustomDecimal(required=False), |
| 391 | 'netProfit': CustomDecimal(required=True), | 393 | 'netProfit': CustomDecimal(required=False), |
| 392 | } | 394 | } |
| 393 | 395 | ||
| 394 | se_verification = { | 396 | se_verification = { |
| ... | @@ -411,13 +413,13 @@ se_cms_content = { | ... | @@ -411,13 +413,13 @@ se_cms_content = { |
| 411 | 'dealerName': fields.Str(required=True, validate=validate.Length(max=512)), | 413 | 'dealerName': fields.Str(required=True, validate=validate.Length(max=512)), |
| 412 | 'tier': fields.Str(required=True, validate=validate.Length(max=64)), | 414 | 'tier': fields.Str(required=True, validate=validate.Length(max=64)), |
| 413 | 'province': fields.Str(required=True, validate=validate.Length(max=64)), | 415 | 'province': fields.Str(required=True, validate=validate.Length(max=64)), |
| 414 | 'fapiaoIssuerDealer': fields.Str(required=True, validate=validate.Length(max=512)), | 416 | 'fapiaoIssuerDealer': fields.Str(required=False, validate=validate.Length(max=512)), |
| 415 | 'customerName': fields.Str(required=True, validate=validate.Length(max=64)), | 417 | 'customerName': fields.Str(required=True, validate=validate.Length(max=64)), |
| 416 | 'customerIdNo': fields.Str(required=True, validate=validate.Length(max=64)), | 418 | 'customerIdNo': fields.Str(required=True, validate=validate.Length(max=64)), |
| 417 | 'vehicleStatus': fields.Str(required=True, validate=validate.Length(max=64)), | 419 | 'vehicleStatus': fields.Str(required=True, validate=validate.Length(max=64)), |
| 418 | 'applicationSource': fields.Str(required=True, validate=validate.Length(max=64)), | 420 | 'applicationSource': fields.Str(required=True, validate=validate.Length(max=64)), |
| 419 | 'contractSource': fields.Str(required=True, validate=validate.Length(max=64)), | 421 | 'contractSource': fields.Str(required=True, validate=validate.Length(max=64)), |
| 420 | 'applicationRating': fields.Int(required=True), | 422 | 'applicationRating': fields.Int(required=False), |
| 421 | 423 | ||
| 422 | 'applicantInformation': fields.List(fields.Nested(info_args), | 424 | 'applicantInformation': fields.List(fields.Nested(info_args), |
| 423 | required=True, validate=validate.Length(min=1, max=4)), | 425 | required=True, validate=validate.Length(min=1, max=4)), |
| ... | @@ -647,7 +649,7 @@ class CompareView(GenericView): | ... | @@ -647,7 +649,7 @@ class CompareView(GenericView): |
| 647 | corporate_cus_info=corporate_cus_info, | 649 | corporate_cus_info=corporate_cus_info, |
| 648 | ) | 650 | ) |
| 649 | # 触发比对 | 651 | # 触发比对 |
| 650 | compare.apply_async((application_id, business_type, uniq_seq, None, True), | 652 | compare.apply_async((application_id, business_type, uniq_seq, None, True, False), |
| 651 | queue='queue_compare') | 653 | queue='queue_compare') |
| 652 | return response.ok() | 654 | return response.ok() |
| 653 | 655 | ||
| ... | @@ -708,7 +710,7 @@ class SECompareView(GenericView): | ... | @@ -708,7 +710,7 @@ class SECompareView(GenericView): |
| 708 | quotationt_info=quotationt_info | 710 | quotationt_info=quotationt_info |
| 709 | ) | 711 | ) |
| 710 | # 触发比对 | 712 | # 触发比对 |
| 711 | compare.apply_async((application_id, business_type, uniq_seq, None, False), | 713 | compare.apply_async((application_id, business_type, uniq_seq, None, False, False), |
| 712 | queue='queue_compare') | 714 | queue='queue_compare') |
| 713 | return response.ok() | 715 | return response.ok() |
| 714 | 716 | ||
| ... | @@ -1091,7 +1093,21 @@ class SECMSView(GenericView): | ... | @@ -1091,7 +1093,21 @@ class SECMSView(GenericView): |
| 1091 | # pos上传比对信息接口 SE | 1093 | # pos上传比对信息接口 SE |
| 1092 | @use_args(se_cms_args, location='data') | 1094 | @use_args(se_cms_args, location='data') |
| 1093 | def post(self, request, args): | 1095 | def post(self, request, args): |
| 1094 | self.running_log.info('cms in') | 1096 | cms_info = args.get('content', {}) |
| 1097 | business_type = consts.AFC_PREFIX if cms_info.get('financeCompany', '').startswith('宝马') else consts.HIL_PREFIX | ||
| 1098 | src_application_id = cms_info.get('settlemnetVerification', {}).get('applicationNo', '') | ||
| 1099 | application_id = src_application_id[:src_application_id.rfind('-')] | ||
| 1100 | content_str = json.dumps(cms_info) | ||
| 1101 | |||
| 1102 | comparison_class = HILSECMSInfo if business_type in consts.HIL_SET else AFCSECMSInfo | ||
| 1103 | comparison_class.objects.create( | ||
| 1104 | application_id=application_id, | ||
| 1105 | content=content_str, | ||
| 1106 | ) | ||
| 1107 | |||
| 1108 | # 触发比对 | ||
| 1109 | compare.apply_async((application_id, business_type, None, None, False, True), | ||
| 1110 | queue='queue_compare') | ||
| 1095 | return response.ok() | 1111 | return response.ok() |
| 1096 | 1112 | ||
| 1097 | post.openapi_doc = ''' | 1113 | post.openapi_doc = ''' | ... | ... |
| ... | @@ -13,8 +13,10 @@ from apps.doc.models import ( | ... | @@ -13,8 +13,10 @@ from apps.doc.models import ( |
| 13 | HILSEOCRResult, | 13 | HILSEOCRResult, |
| 14 | AFCComparisonInfo, | 14 | AFCComparisonInfo, |
| 15 | AFCSEComparisonInfo, | 15 | AFCSEComparisonInfo, |
| 16 | AFCSECMSInfo, | ||
| 16 | HILComparisonInfo, | 17 | HILComparisonInfo, |
| 17 | HILSEComparisonInfo, | 18 | HILSEComparisonInfo, |
| 19 | HILSECMSInfo, | ||
| 18 | Configs, | 20 | Configs, |
| 19 | HILCompareReport, | 21 | HILCompareReport, |
| 20 | AFCCompareReport, | 22 | AFCCompareReport, |
| ... | @@ -25,14 +27,30 @@ from apps.doc.models import ( | ... | @@ -25,14 +27,30 @@ from apps.doc.models import ( |
| 25 | ) | 27 | ) |
| 26 | from apps.doc import consts | 28 | from apps.doc import consts |
| 27 | from apps.doc.ocr.gcap import gcap | 29 | from apps.doc.ocr.gcap import gcap |
| 30 | from apps.doc.ocr.cms import cms | ||
| 28 | from apps.doc.exceptions import GCAPException | 31 | from apps.doc.exceptions import GCAPException |
| 29 | from apps.doc.named_enum import RequestTeam, RequestTrigger, ProcessName, ErrorType | 32 | from apps.doc.named_enum import RequestTeam, RequestTrigger, ProcessName, ErrorType |
| 30 | from common.tools.comparison import cp | 33 | from common.tools.comparison import cp |
| 34 | from common.tools.des import decode_des | ||
| 31 | 35 | ||
| 32 | compare_log = logging.getLogger('compare') | 36 | compare_log = logging.getLogger('compare') |
| 33 | log_base = '[Compare]' | 37 | log_base = '[Compare]' |
| 34 | empty_str = '' | 38 | empty_str = '' |
| 35 | empty_error_type = 1000 | 39 | empty_error_type = 1000 |
| 40 | des_key = conf.CMS_DES_KEY | ||
| 41 | |||
| 42 | |||
| 43 | class FakePOS: | ||
| 44 | |||
| 45 | def __init__(self, | ||
| 46 | application_id, | ||
| 47 | first_submmison_date, | ||
| 48 | application_version, | ||
| 49 | customer_type): | ||
| 50 | self.application_id = application_id | ||
| 51 | self.first_submmison_date = first_submmison_date | ||
| 52 | self.application_version = application_version | ||
| 53 | self.customer_type = customer_type | ||
| 36 | 54 | ||
| 37 | 55 | ||
| 38 | def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name): | 56 | def name_check(ocr_res_dict, second_ocr_field, second_compare_list, second_id_num, name): |
| ... | @@ -882,6 +900,173 @@ def get_se_compare_info(last_obj, application_entity, detect_list): | ... | @@ -882,6 +900,173 @@ def get_se_compare_info(last_obj, application_entity, detect_list): |
| 882 | return compare_info | 900 | return compare_info |
| 883 | 901 | ||
| 884 | 902 | ||
| 903 | def rebuild_compare_info(last_obj, application_id): | ||
| 904 | # { | ||
| 905 | # "content": { | ||
| 906 | # "financeCompany": "宝马汽车金融有限公司", | ||
| 907 | # "contractNo": "CH-B100000123", | ||
| 908 | # "status": "HIL", | ||
| 909 | # "branch": "宝马汽车金融有限公司", | ||
| 910 | # "fpCampaign": "Q1_2021_BMW_BASIC", | ||
| 911 | # "applicationVersion": 1, | ||
| 912 | # "submissionDate": {}, | ||
| 913 | # "mortgageType": "Mortgage Contract", | ||
| 914 | # "dealerRegion": "West", | ||
| 915 | # "insuranceRealNameCity": false, | ||
| 916 | # "totalFinanceAmount": 1234.56, | ||
| 917 | # "terms": 24, | ||
| 918 | # "dealerName": "乐山长宝汽车销售服务有限公司", | ||
| 919 | # "tier": "2", | ||
| 920 | # "province": "四川省", | ||
| 921 | # "fapiaoIssuerDealer": "乐山长宝汽车销售服务有限公司", | ||
| 922 | # "customerName": "蔡红", | ||
| 923 | # "customerIdNo": "511102196706080000", | ||
| 924 | # "vehicleStatus": "Used", | ||
| 925 | # "applicationSource": "eApp", | ||
| 926 | # "contractSource": "Online Sign", | ||
| 927 | # "applicationRating": 100, | ||
| 928 | # "applicantInformation": [ | ||
| 929 | # { | ||
| 930 | # "applicantType": "Borrower", | ||
| 931 | # "customersubType": "TCCOR", | ||
| 932 | # "selfEmployedSubType": "CSIBM", | ||
| 933 | # "name": "李四", | ||
| 934 | # "legalRepName": "张三", | ||
| 935 | # "dateOfBirth": {}, | ||
| 936 | # "nationality": "中国", | ||
| 937 | # "establishmentDate": {}, | ||
| 938 | # "IDInformation": [ | ||
| 939 | # { | ||
| 940 | # "idType": "ITARI", | ||
| 941 | # "idNum": "111111199404251100", | ||
| 942 | # "idExpiryDate": {} | ||
| 943 | # } | ||
| 944 | # ] | ||
| 945 | # } | ||
| 946 | # ], | ||
| 947 | # "autoApprovedDetails": { | ||
| 948 | # "aaType": "CAA1" | ||
| 949 | # }, | ||
| 950 | # "financialInformation": { | ||
| 951 | # "vehiclePrice": 1234.56, | ||
| 952 | # "grossPrice": 1234.56, | ||
| 953 | # "associatedServicePrice": 1234.56, | ||
| 954 | # "vehiclePrincipal": 1234.56, | ||
| 955 | # "associatedServicePrincipal": 1234.56, | ||
| 956 | # "originationPrincipal": 1234.56, | ||
| 957 | # "totalDownPayment": 1234.56, | ||
| 958 | # "vehicleDownPaymentRatio": 1234.56, | ||
| 959 | # "optionAmount": 1234.56, | ||
| 960 | # "sumOfMSRPAndOption": 1234.56 | ||
| 961 | # }, | ||
| 962 | # "paymentSchedule": [ | ||
| 963 | # { | ||
| 964 | # "no": 3, | ||
| 965 | # "grossRentalAmount": 1234.56 | ||
| 966 | # } | ||
| 967 | # ], | ||
| 968 | # "associatedServices": [ | ||
| 969 | # { | ||
| 970 | # "associatedServices": "机动车保险", | ||
| 971 | # "price": 1234.56, | ||
| 972 | # "financed": 1234.56, | ||
| 973 | # "total": 1234.56 | ||
| 974 | # } | ||
| 975 | # ], | ||
| 976 | # "vehicleInformation": { | ||
| 977 | # "vinNo": "LBV23482934DJFKD" | ||
| 978 | # }, | ||
| 979 | # "bankAccountDetails": { | ||
| 980 | # "bankName": "中国银行", | ||
| 981 | # "accountHolderName": "张三", | ||
| 982 | # "accountNo": "12312123123123124" | ||
| 983 | # }, | ||
| 984 | # "insuranceDetails": { | ||
| 985 | # "insuranceType": "ComprehensiveInsurance", | ||
| 986 | # "insuranceAmount": "60000000", | ||
| 987 | # "startDate": {}, | ||
| 988 | # "endDate": {} | ||
| 989 | # }, | ||
| 990 | # "corporateFinancialInformation": { | ||
| 991 | # "hashCode": "238231", | ||
| 992 | # "borrowerName": "张三", | ||
| 993 | # "fiscalYear": 2019, | ||
| 994 | # "totaAssets": 1234.56, | ||
| 995 | # "totalLiabilitiesAndOwnersEquity": 1234.56, | ||
| 996 | # "cashAndCashEquivalentAtEndOfPeriod": 1234.56, | ||
| 997 | # "netProfit": 1234.56 | ||
| 998 | # }, | ||
| 999 | # "settlemnetVerification": { | ||
| 1000 | # "applicationNo": "CH-B100000123" | ||
| 1001 | # } | ||
| 1002 | # } | ||
| 1003 | # } | ||
| 1004 | |||
| 1005 | cms_info = json.loads(last_obj.content) | ||
| 1006 | |||
| 1007 | fake_pos = FakePOS(application_id, | ||
| 1008 | cms_info.get('submissionDate', ''), | ||
| 1009 | cms_info.get('applicationVersion', 1), | ||
| 1010 | cms_info.get('applicantInformation', [])[0].get('customersubType', '')) | ||
| 1011 | |||
| 1012 | fake_pos.bank_info = json.dumps( | ||
| 1013 | { | ||
| 1014 | 'accountNo': decode_des(cms_info.get('bankAccountDetails', {}).get('accountNo', ''), des_key), | ||
| 1015 | 'bankName': cms_info.get('bankAccountDetails', {}).get('bankName', ''), | ||
| 1016 | 'accountHolderName': cms_info.get('bankAccountDetails', {}).get('accountHolderName', ''), | ||
| 1017 | } | ||
| 1018 | ) | ||
| 1019 | |||
| 1020 | fake_pos.vehicle_info = json.dumps( | ||
| 1021 | { | ||
| 1022 | 'vehicleStatus': cms_info.get('vehicleStatus', ''), | ||
| 1023 | 'vinNo': cms_info.get('vehicleInformation', {}).get('vinNo', ''), | ||
| 1024 | 'dealer': cms_info.get('dealerName', ''), | ||
| 1025 | 'vehicleTransactionAmount': str(cms_info.get('totalFinanceAmount', '')), | ||
| 1026 | } | ||
| 1027 | ) | ||
| 1028 | |||
| 1029 | individual_cus_info = [] | ||
| 1030 | for individual_cus in cms_info.get('applicantInformation', []): | ||
| 1031 | id_type = id_num = id_date = second_id_type = second_id_num = None | ||
| 1032 | for idx, id_info in enumerate(individual_cus.get('', [])): | ||
| 1033 | if idx > 1: | ||
| 1034 | break | ||
| 1035 | elif idx == 0: | ||
| 1036 | id_type = id_info.get('idType') | ||
| 1037 | id_num = decode_des(id_info.get('idNum')) | ||
| 1038 | id_date = id_info.get('idExpiryDate') | ||
| 1039 | else: | ||
| 1040 | second_id_type = id_info.get('idType') | ||
| 1041 | second_id_num = decode_des(id_info.get('idNum')) | ||
| 1042 | individual_cus_info.append( | ||
| 1043 | { | ||
| 1044 | 'applicantType': consts.APPLICANT_TYPE_MAP.get(individual_cus.get('applicantType')), | ||
| 1045 | 'customerType': individual_cus.get('customersubType'), | ||
| 1046 | |||
| 1047 | 'idType': id_type, | ||
| 1048 | 'idNum': id_num, | ||
| 1049 | 'idExpiryDate': id_date, | ||
| 1050 | |||
| 1051 | 'customerName': individual_cus.get('name'), | ||
| 1052 | 'dateOfBirth': individual_cus.get('dateOfBirth', ''), | ||
| 1053 | 'hukouProvince': cms_info.get('province', ''), | ||
| 1054 | |||
| 1055 | 'secondIdType': second_id_type, | ||
| 1056 | 'secondIdNum': second_id_num, | ||
| 1057 | |||
| 1058 | 'companyName': individual_cus.get('name'), | ||
| 1059 | 'selfEmployedSubType': individual_cus.get('selfEmployedSubType', ''), | ||
| 1060 | } | ||
| 1061 | ) | ||
| 1062 | |||
| 1063 | fake_pos.individual_cus_info = json.dumps(individual_cus_info) | ||
| 1064 | |||
| 1065 | fake_pos.corporate_cus_info = None | ||
| 1066 | |||
| 1067 | return fake_pos | ||
| 1068 | |||
| 1069 | |||
| 885 | def se_compare_license(license_en, ocr_res_dict, field_list): | 1070 | def se_compare_license(license_en, ocr_res_dict, field_list): |
| 886 | ocr_field, compare_logic, special_expiry_date = consts.SE_COMPARE_FIELD[license_en] | 1071 | ocr_field, compare_logic, special_expiry_date = consts.SE_COMPARE_FIELD[license_en] |
| 887 | 1072 | ||
| ... | @@ -1099,12 +1284,14 @@ def se_result_detect(ocr_res_dict): | ... | @@ -1099,12 +1284,14 @@ def se_result_detect(ocr_res_dict): |
| 1099 | return detect_list | 1284 | return detect_list |
| 1100 | 1285 | ||
| 1101 | 1286 | ||
| 1102 | def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict): | 1287 | def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms): |
| 1103 | try: | 1288 | try: |
| 1104 | # 比对逻辑 | 1289 | # 比对逻辑 |
| 1105 | start_time = datetime.now() | 1290 | start_time = datetime.now() |
| 1106 | detect_list = se_result_detect(ocr_res_dict) | 1291 | detect_list = se_result_detect(ocr_res_dict) |
| 1107 | compare_info = get_se_compare_info(last_obj, application_entity, detect_list) | 1292 | if is_cms: |
| 1293 | last_obj = rebuild_compare_info(last_obj, application_id) | ||
| 1294 | compare_info, is_gsyh = get_se_compare_info(last_obj, application_entity, detect_list) | ||
| 1108 | compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str = se_compare_process( | 1295 | compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str = se_compare_process( |
| 1109 | compare_info, ocr_res_dict) | 1296 | compare_info, ocr_res_dict) |
| 1110 | compare_log.info('{0} [SE] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format( | 1297 | compare_log.info('{0} [SE] [compare success] [entity={1}] [id={2}] [ocr_res_id={3}] [result={4}]'.format( |
| ... | @@ -1160,24 +1347,54 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res | ... | @@ -1160,24 +1347,54 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res |
| 1160 | '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, | 1347 | '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, |
| 1161 | traceback.format_exc())) | 1348 | traceback.format_exc())) |
| 1162 | 1349 | ||
| 1350 | # cms结果发送 | ||
| 1351 | if is_cms: | ||
| 1352 | try: | ||
| 1353 | application_link = '{0}/showList/showList?entity={1}&scheme={2}&case_id={3}'.format( | ||
| 1354 | conf.BASE_URL, application_entity, consts.COMPARE_DOC_SCHEME_LIST[1], application_id) | ||
| 1355 | data = { | ||
| 1356 | "SubtenantId": consts.TENANT_MAP[application_entity], | ||
| 1357 | "Data": { | ||
| 1358 | "Result_Message": "Pass" if successful_at_this_level else "Fail", | ||
| 1359 | "Failure_Reason": failure_reason_str, | ||
| 1360 | "Application_Number": application_id, | ||
| 1361 | "Bank_Statement": "", | ||
| 1362 | "Link_URL": application_link, | ||
| 1363 | "OCR_Version": 1, | ||
| 1364 | "Origin": consts.INFO_SOURCE[1] | ||
| 1365 | } | ||
| 1366 | } | ||
| 1367 | response = cms.send(data) | ||
| 1368 | except Exception as e: | ||
| 1369 | compare_log.error('{0} [SE] [cms error] [entity={1}] [id={2}] [ocr_res_id={3}] ' | ||
| 1370 | '[error={4}]'.format(log_base, application_entity, application_id, ocr_res_id, | ||
| 1371 | traceback.format_exc())) | ||
| 1372 | else: | ||
| 1373 | compare_log.info('{0} [SE] [cms success] [entity={1}] [id={2}] [ocr_res_id={3}] [response={4}]'.format( | ||
| 1374 | log_base, application_entity, application_id, ocr_res_id, response)) | ||
| 1163 | 1375 | ||
| 1164 | @app.task | 1376 | @app.task |
| 1165 | def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True): | 1377 | def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False): |
| 1166 | # POS: application_id, application_entity, uniq_seq, None | 1378 | # POS: application_id, application_entity, uniq_seq, None |
| 1167 | # OCR: application_id, business_type(application_entity), None, ocr_res_id | 1379 | # OCR: application_id, business_type(application_entity), None, ocr_res_id |
| 1168 | 1380 | ||
| 1169 | compare_log.info('{0} [receive task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] [is_ca={5}]'.format( | 1381 | compare_log.info('{0} [receive task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] [is_ca={5}] ' |
| 1170 | log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca)) | 1382 | '[is_cms={6}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, |
| 1383 | is_ca, is_cms)) | ||
| 1171 | 1384 | ||
| 1172 | # 根据application_id查找最新的比对信息,如果没有,结束 | 1385 | # 根据application_id查找最新的比对信息,如果没有,结束 |
| 1173 | if is_ca: | 1386 | if is_ca: |
| 1174 | comparison_class = HILComparisonInfo if application_entity == consts.HIL_PREFIX else AFCComparisonInfo | 1387 | comparison_class = HILComparisonInfo if application_entity == consts.HIL_PREFIX else AFCComparisonInfo |
| 1175 | else: | 1388 | else: |
| 1176 | comparison_class = HILSEComparisonInfo if application_entity == consts.HIL_PREFIX else AFCSEComparisonInfo | 1389 | if application_entity == consts.HIL_PREFIX: |
| 1390 | comparison_class = HILSECMSInfo if is_cms else HILSEComparisonInfo | ||
| 1391 | else: | ||
| 1392 | comparison_class = AFCSECMSInfo if is_cms else AFCSEComparisonInfo | ||
| 1177 | last_obj = comparison_class.objects.filter(application_id=application_id).last() | 1393 | last_obj = comparison_class.objects.filter(application_id=application_id).last() |
| 1178 | if last_obj is None: | 1394 | if last_obj is None: |
| 1179 | compare_log.info('{0} [comparison info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] ' | 1395 | compare_log.info('{0} [comparison info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] ' |
| 1180 | '[is_ca={5}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca)) | 1396 | '[is_ca={5}] [is_cms]={6}'.format(log_base, application_entity, application_id, uniq_seq, |
| 1397 | ocr_res_id, is_ca, is_cms)) | ||
| 1181 | return | 1398 | return |
| 1182 | 1399 | ||
| 1183 | # 根据application_id查找OCR累计结果指定license字段,如果没有,结束 | 1400 | # 根据application_id查找OCR累计结果指定license字段,如果没有,结束 |
| ... | @@ -1191,13 +1408,14 @@ def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True | ... | @@ -1191,13 +1408,14 @@ def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True |
| 1191 | ocr_res_dict = result_class.objects.filter(id=ocr_res_id).values(*consts.COMPARE_FIELDS).first() | 1408 | ocr_res_dict = result_class.objects.filter(id=ocr_res_id).values(*consts.COMPARE_FIELDS).first() |
| 1192 | if ocr_res_dict is None: | 1409 | if ocr_res_dict is None: |
| 1193 | compare_log.info('{0} [ocr info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] ' | 1410 | compare_log.info('{0} [ocr info empty] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] ' |
| 1194 | '[is_ca={5}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca)) | 1411 | '[is_ca={5}] [is_cms]={6}'.format(log_base, application_entity, application_id, |
| 1412 | uniq_seq, ocr_res_id, is_ca, is_cms)) | ||
| 1195 | return | 1413 | return |
| 1196 | 1414 | ||
| 1197 | if is_ca: | 1415 | if is_ca: |
| 1198 | ca_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict) | 1416 | ca_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict) |
| 1199 | else: | 1417 | else: |
| 1200 | se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict) | 1418 | se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms) |
| 1201 | 1419 | ||
| 1202 | 1420 | ||
| 1203 | 1421 | ... | ... |
| ... | @@ -36,6 +36,7 @@ class RedisHandler: | ... | @@ -36,6 +36,7 @@ class RedisHandler: |
| 36 | self.common_queue_key = '{0}:common_queue'.format(self.prefix) | 36 | self.common_queue_key = '{0}:common_queue'.format(self.prefix) |
| 37 | self.priority_queue_key = '{0}:priority_queue'.format(self.prefix) | 37 | self.priority_queue_key = '{0}:priority_queue'.format(self.prefix) |
| 38 | self.session_id_key = '{0}:session_id'.format(self.prefix) | 38 | self.session_id_key = '{0}:session_id'.format(self.prefix) |
| 39 | self.cms_token_key = '{0}:cms_token'.format(self.prefix) | ||
| 39 | 40 | ||
| 40 | def enqueue(self, tasks, is_priority=False): | 41 | def enqueue(self, tasks, is_priority=False): |
| 41 | # 1 | 42 | # 1 |
| ... | @@ -57,3 +58,9 @@ class RedisHandler: | ... | @@ -57,3 +58,9 @@ class RedisHandler: |
| 57 | def get_session_id(self): | 58 | def get_session_id(self): |
| 58 | return self.redis.get(self.session_id_key) | 59 | return self.redis.get(self.session_id_key) |
| 59 | 60 | ||
| 61 | def get_cms_token(self): | ||
| 62 | return self.redis.get(self.cms_token_key) | ||
| 63 | |||
| 64 | def set_cms_token(self, token, expires=None): | ||
| 65 | return self.redis.set(self.cms_token_key, token, expires) | ||
| 66 | ... | ... |
src/common/tools/des.py
0 → 100644
| 1 | from Crypto.Cipher import DES3 | ||
| 2 | from Crypto.Hash import MD5 | ||
| 3 | import struct | ||
| 4 | import base64 | ||
| 5 | import codecs | ||
| 6 | |||
| 7 | |||
| 8 | def mds_hash(target_str): | ||
| 9 | h = MD5.new() | ||
| 10 | h.update(target_str.encode('utf-8')) | ||
| 11 | return h.digest() | ||
| 12 | |||
| 13 | |||
| 14 | def des_pad(data): | ||
| 15 | data = data.encode('utf-8') | ||
| 16 | e = len(data) | ||
| 17 | x = (e + 4) % 8 | ||
| 18 | y = 0 if x == 0 else 8 - x | ||
| 19 | size_byte = struct.pack('>I', e) | ||
| 20 | result_byte = list(range(len(size_byte) + e + y)) | ||
| 21 | result_byte[0:4] = size_byte | ||
| 22 | result_byte[4:4 + e] = data | ||
| 23 | for i in range(0, y): | ||
| 24 | result_byte[e + 4 + i] = 0 | ||
| 25 | result_str = bytearray(result_byte).decode('utf-8') | ||
| 26 | return result_str | ||
| 27 | |||
| 28 | |||
| 29 | # DES3加密数据 | ||
| 30 | def encode_des(to_encode_str, des_key): | ||
| 31 | """ | ||
| 32 | DES3加密数据 | ||
| 33 | Args: | ||
| 34 | to_encode_str(str): 要被加密的原字符串,这里的字符串需要被des_pad一下 | ||
| 35 | des_key(str): 加密的key | ||
| 36 | Returns: | ||
| 37 | |||
| 38 | """ | ||
| 39 | key = mds_hash(des_key) | ||
| 40 | des3 = DES3.new(key, DES3.MODE_ECB) | ||
| 41 | data = des3.encrypt(des_pad(to_encode_str)) | ||
| 42 | data = codecs.encode(data, 'hex') | ||
| 43 | return data | ||
| 44 | |||
| 45 | |||
| 46 | def un_des_pad(data): | ||
| 47 | result_byte = data[0:4] | ||
| 48 | e = struct.unpack('>I', result_byte)[0] | ||
| 49 | x = (e + 4) % 8 | ||
| 50 | y = 0 if x == 0 else 8 - x | ||
| 51 | return data[4:] if y == 0 else data[4:-y] | ||
| 52 | |||
| 53 | |||
| 54 | def decode_des(to_decode_str, des_key): | ||
| 55 | """ | ||
| 56 | 解密数据 | ||
| 57 | Args: | ||
| 58 | to_decode_str(str): 要解密的原字符串 | ||
| 59 | des_key(str): 解密的key | ||
| 60 | Returns: | ||
| 61 | |||
| 62 | """ | ||
| 63 | key = mds_hash(des_key) | ||
| 64 | des3 = DES3.new(key, DES3.MODE_ECB) | ||
| 65 | param = base64.b64decode(to_decode_str) | ||
| 66 | |||
| 67 | param = des3.decrypt(param) | ||
| 68 | param = un_des_pad(param).decode('utf-8') | ||
| 69 | return param |
src/common/tools/mssql_script9.py
0 → 100644
| 1 | import pyodbc | ||
| 2 | |||
| 3 | hil_sql = """ | ||
| 4 | create table afc_se_cms_info | ||
| 5 | ( | ||
| 6 | id bigint identity primary key, | ||
| 7 | application_id nvarchar(64) not null, | ||
| 8 | content nvarchar(max) not null, | ||
| 9 | update_time datetime not null, | ||
| 10 | create_time datetime not null | ||
| 11 | ); | ||
| 12 | |||
| 13 | create index afc_se_cms_info_application_id_index | ||
| 14 | on afc_se_cms_info (application_id); | ||
| 15 | |||
| 16 | create index afc_se_cms_info_create_time_index | ||
| 17 | on afc_se_cms_info (create_time); | ||
| 18 | """ | ||
| 19 | |||
| 20 | afc_sql = """ | ||
| 21 | create table hil_se_cms_info | ||
| 22 | ( | ||
| 23 | id bigint identity primary key, | ||
| 24 | application_id nvarchar(64) not null, | ||
| 25 | content nvarchar(max) not null, | ||
| 26 | update_time datetime not null, | ||
| 27 | create_time datetime not null | ||
| 28 | ); | ||
| 29 | |||
| 30 | create index hil_se_cms_info_application_id_index | ||
| 31 | on hil_se_cms_info (application_id); | ||
| 32 | |||
| 33 | create index hil_se_cms_info_create_time_index | ||
| 34 | on hil_se_cms_info (create_time); | ||
| 35 | """ | ||
| 36 | |||
| 37 | hil_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True) | ||
| 38 | |||
| 39 | hil_cursor = hil_cnxn.cursor() | ||
| 40 | hil_cursor.execute(hil_sql) | ||
| 41 | |||
| 42 | hil_cursor.close() | ||
| 43 | hil_cnxn.close() | ||
| 44 | |||
| 45 | afc_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True) | ||
| 46 | |||
| 47 | afc_cursor = afc_cnxn.cursor() | ||
| 48 | afc_cursor.execute(afc_sql) | ||
| 49 | |||
| 50 | afc_cursor.close() | ||
| 51 | afc_cnxn.close() |
-
Please register or sign in to post a comment