369697a8 by 周伟奇

fix merge

2 parents db2ce2cf ec8b39ff
......@@ -1649,3 +1649,69 @@ CA_COMPARE_FIELD = {
}
CONTRACT_SHEET_NAME = '合同'
# ------------------CMS--------------------------------------
BANK_INFO_MAP = (
('accountNo', 'bankAccountDetails.accountNo'),
('bankName', 'bankAccountDetails.bankName'),
('accountHolderName', 'bankAccountDetails.accountHolderName'),
)
VEHICLE_INFO_MAP = (
('vehicleStatus', 'vehicleStatus'),
('vinNo', 'vehicleInformation.vinNo'),
('dealer', 'dealerName'),
('vehicleTransactionAmount', 'totalFinanceAmount'),
)
CORPORATE_INFO_MAP = (
('firstIdType', ),
('firstIdNo', ),
('companyName', ),
('legalRepName', ),
('businessLicenseNo', ),
('organizationCreditCode', ),
('taxRegistrationCertificateNo', ),
('establishmentDate', ),
('businessLicenseDueDate', ),
)
INDIVIDUAL_INFO_MAP = (
('applicantType', 'applicantInformation.applicantType'),
('customerType', 'applicantInformation.customersubType'),
('idType', 'applicantInformation.IDInformation.idType'),
('customerName', 'applicantInformation.name'),
('idNum', 'applicantInformation.IDInformation.idNum'),
('dateOfBirth', 'applicantInformation.dateOfBirth'),
('idExpiryDate', 'applicantInformation.IDInformation.idExpiryDate'),
('hukouProvince', ),
('hukouCity', ),
('secondIdType', 'applicantInformation.IDInformation.idType'),
('secondIdNum', 'applicantInformation.IDInformation.idNum'),
('companyName', ),
('registeredCapital', ),
('selfEmployedSubType', ),
)
CMS_TO_POS = [
('bank_info', BANK_INFO_MAP),
('vehicle_info', VEHICLE_INFO_MAP),
('corporate_cus_info', CORPORATE_INFO_MAP),
('individual_cus_info', INDIVIDUAL_INFO_MAP),
]
TENANT_MAP = {
AFC_PREFIX: 1,
HIL_PREFIX: 2,
}
APPLICANT_TYPE_MAP = {
'Borrower': 'CUSTR',
'Co Borrower': 'COAPP',
'Guarantor': 'GAUTR1',
'Mortgager': 'GAUTR2'
}
......
......@@ -13,9 +13,14 @@ class OCR2Exception(Exception):
class OCR4Exception(Exception):
pass
class LTGTException(Exception):
pass
class GCAPException(Exception):
pass
class CMSException(Exception):
pass
......
......@@ -244,6 +244,33 @@ class HILSEComparisonInfo(models.Model):
# 比对信息表
class AFCSECMSInfo(models.Model):
id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键
application_id = models.CharField(max_length=64, verbose_name="申请id") # 索引
content = models.TextField(verbose_name="CMS信息")
update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 索引
class Meta:
managed = False
db_table = 'afc_se_cms_info'
situ_db_label = 'afc'
# 比对信息表
class HILSECMSInfo(models.Model):
id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键
application_id = models.CharField(max_length=64, verbose_name="申请id") # 索引
content = models.TextField(verbose_name="CMS信息")
update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') # 索引
class Meta:
managed = False
db_table = 'hil_se_cms_info'
# 比对信息表
class HILComparisonInfo(models.Model):
id = models.BigAutoField(primary_key=True, verbose_name="id") # 主键
uniq_seq = models.CharField(max_length=128, verbose_name="唯一序列号") # 索引?
......
import requests
from settings import conf
from common.redis_cache import redis_handler as rh
from apps.doc.exceptions import CMSException
class CMS:
def __init__(self):
self.oauth_url = conf.CMS_OAUTH_URL
self.url = conf.CMS_URL
self.oauth_payload = {
'grant_type': 'client_credentials',
'client_id': conf.CMS_OAUTH_ID,
'client_secret': conf.CMS_OAUTH_SECRET,
'scope': conf.CMS_OAUTH_SCOPE
}
self.token_type = 'bearer'
self.token = None
self.token_key = 'access_token'
self.expires_key = 'expires_in'
self.token_type_key = 'token_type'
def update_token(self):
response = requests.post(self.oauth_url, data=self.oauth_payload, files=[])
if response.status_code != 200:
raise CMSException('CMS Oauth response with code: {0}'.format(response.status_code))
token = response.json().get(self.token_key)
if not isinstance(token, str):
raise CMSException('CMS Oauth can not get token: {0}'.format(response.json()))
self.token = token
self.token_type = response.json().get(self.token_type_key, self.token_type)
expires = response.json().get(self.expires_key, 3600)
rh.set_cms_token(self.token, expires)
def get_token(self):
if self.token is None:
self.token = rh.get_cms_token()
if self.token is None:
self.update_token()
return self.token
def send(self, payload):
token = self.get_token()
headers = {
'Authorization': '{0} {1}'.format(self.token_type.capitalize(), token),
'Content-Type': 'application/json',
}
response = requests.post(self.url, headers=headers, json=payload)
if response.status_code != 200:
raise CMSException('CMS Oauth response with code: {0}'.format(response.status_code))
return response.json()
cms = CMS()
......@@ -22,8 +22,10 @@ from .models import (
GCAPRecords,
AFCComparisonInfo,
AFCSEComparisonInfo,
AFCSECMSInfo,
HILComparisonInfo,
HILSEComparisonInfo,
HILSECMSInfo,
AFCCompareOfflineReport,
HILCompareOfflineReport,
AFCCACompareResult,
......@@ -327,7 +329,7 @@ info_args = {
'customersubType': fields.Str(required=True, validate=validate.Length(max=32)),
'selfEmployedSubType': fields.Str(required=False, validate=validate.Length(max=32)),
'name': fields.Str(required=True, validate=validate.Length(max=64)),
'legalRepName': fields.Str(required=True, validate=validate.Length(max=64)),
'legalRepName': fields.Str(required=False, validate=validate.Length(max=64)),
'dateOfBirth': CustomDate(required=False),
'nationality': fields.Str(required=False, validate=validate.Length(max=64)),
'establishmentDate': CustomDate(required=False),
......@@ -358,10 +360,10 @@ payment_schedule = {
}
associated_services = {
'associatedServices': fields.Str(required=True, validate=validate.Length(max=64)),
'price': CustomDecimal(required=True),
'financed': CustomDecimal(required=True),
'total': CustomDecimal(required=True),
'associatedServices': fields.Str(required=False, validate=validate.Length(max=64)),
'price': CustomDecimal(required=False),
'financed': CustomDecimal(required=False),
'total': CustomDecimal(required=False),
}
vehicle_info = {
......@@ -382,13 +384,13 @@ insurance_details = {
}
corporate_info = {
'hashCode': fields.Str(required=True, validate=validate.Length(max=64)),
'borrowerName': fields.Str(required=True, validate=validate.Length(max=64)),
'fiscalYear': fields.Int(required=True),
'totaAssets': CustomDecimal(required=True),
'totalLiabilitiesAndOwnersEquity': CustomDecimal(required=True),
'cashAndCashEquivalentAtEndOfPeriod': CustomDecimal(required=True),
'netProfit': CustomDecimal(required=True),
'hashCode': fields.Str(required=False, validate=validate.Length(max=64)),
'borrowerName': fields.Str(required=False, validate=validate.Length(max=64)),
'fiscalYear': fields.Int(required=False),
'totaAssets': CustomDecimal(required=False),
'totalLiabilitiesAndOwnersEquity': CustomDecimal(required=False),
'cashAndCashEquivalentAtEndOfPeriod': CustomDecimal(required=False),
'netProfit': CustomDecimal(required=False),
}
se_verification = {
......@@ -411,13 +413,13 @@ se_cms_content = {
'dealerName': fields.Str(required=True, validate=validate.Length(max=512)),
'tier': fields.Str(required=True, validate=validate.Length(max=64)),
'province': fields.Str(required=True, validate=validate.Length(max=64)),
'fapiaoIssuerDealer': fields.Str(required=True, validate=validate.Length(max=512)),
'fapiaoIssuerDealer': fields.Str(required=False, validate=validate.Length(max=512)),
'customerName': fields.Str(required=True, validate=validate.Length(max=64)),
'customerIdNo': fields.Str(required=True, validate=validate.Length(max=64)),
'vehicleStatus': fields.Str(required=True, validate=validate.Length(max=64)),
'applicationSource': fields.Str(required=True, validate=validate.Length(max=64)),
'contractSource': fields.Str(required=True, validate=validate.Length(max=64)),
'applicationRating': fields.Int(required=True),
'applicationRating': fields.Int(required=False),
'applicantInformation': fields.List(fields.Nested(info_args),
required=True, validate=validate.Length(min=1, max=4)),
......@@ -647,7 +649,7 @@ class CompareView(GenericView):
corporate_cus_info=corporate_cus_info,
)
# 触发比对
compare.apply_async((application_id, business_type, uniq_seq, None, True),
compare.apply_async((application_id, business_type, uniq_seq, None, True, False),
queue='queue_compare')
return response.ok()
......@@ -708,7 +710,7 @@ class SECompareView(GenericView):
quotationt_info=quotationt_info
)
# 触发比对
compare.apply_async((application_id, business_type, uniq_seq, None, False),
compare.apply_async((application_id, business_type, uniq_seq, None, False, False),
queue='queue_compare')
return response.ok()
......@@ -1091,7 +1093,21 @@ class SECMSView(GenericView):
# pos上传比对信息接口 SE
@use_args(se_cms_args, location='data')
def post(self, request, args):
self.running_log.info('cms in')
cms_info = args.get('content', {})
business_type = consts.AFC_PREFIX if cms_info.get('financeCompany', '').startswith('宝马') else consts.HIL_PREFIX
src_application_id = cms_info.get('settlemnetVerification', {}).get('applicationNo', '')
application_id = src_application_id[:src_application_id.rfind('-')]
content_str = json.dumps(cms_info)
comparison_class = HILSECMSInfo if business_type in consts.HIL_SET else AFCSECMSInfo
comparison_class.objects.create(
application_id=application_id,
content=content_str,
)
# 触发比对
compare.apply_async((application_id, business_type, None, None, False, True),
queue='queue_compare')
return response.ok()
post.openapi_doc = '''
......
......@@ -13,8 +13,10 @@ from apps.doc.models import (
HILSEOCRResult,
AFCComparisonInfo,
AFCSEComparisonInfo,
AFCSECMSInfo,
HILComparisonInfo,
HILSEComparisonInfo,
HILSECMSInfo,
Configs,
HILCompareReport,
AFCCompareReport,
......@@ -25,14 +27,30 @@ from apps.doc.models import (
)
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]'
empty_str = ''
empty_error_type = 1000
des_key = conf.CMS_DES_KEY
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):
......@@ -882,6 +900,173 @@ 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]
......@@ -1099,12 +1284,14 @@ def se_result_detect(ocr_res_dict):
return detect_list
def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict):
def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms):
try:
# 比对逻辑
start_time = datetime.now()
detect_list = se_result_detect(ocr_res_dict)
compare_info = get_se_compare_info(last_obj, application_entity, detect_list)
if is_cms:
last_obj = rebuild_compare_info(last_obj, application_id)
compare_info, is_gsyh = get_se_compare_info(last_obj, application_entity, detect_list)
compare_result, total_fields, failed_count, successful_at_this_level, failure_reason_str = se_compare_process(
compare_info, ocr_res_dict)
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
'[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",
"Failure_Reason": failure_reason_str,
"Application_Number": application_id,
"Bank_Statement": "",
"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}] [response={4}]'.format(
log_base, application_entity, application_id, ocr_res_id, response))
@app.task
def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True):
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}]'.format(
log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca))
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:
comparison_class = HILSEComparisonInfo if application_entity == consts.HIL_PREFIX else AFCSEComparisonInfo
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}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca))
'[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字段,如果没有,结束
......@@ -1191,13 +1408,14 @@ def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True
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}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id, is_ca))
'[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:
se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict)
se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res_dict, is_cms)
......
......@@ -36,6 +36,7 @@ class RedisHandler:
self.common_queue_key = '{0}:common_queue'.format(self.prefix)
self.priority_queue_key = '{0}:priority_queue'.format(self.prefix)
self.session_id_key = '{0}:session_id'.format(self.prefix)
self.cms_token_key = '{0}:cms_token'.format(self.prefix)
def enqueue(self, tasks, is_priority=False):
# 1
......@@ -57,3 +58,9 @@ class RedisHandler:
def get_session_id(self):
return self.redis.get(self.session_id_key)
def get_cms_token(self):
return self.redis.get(self.cms_token_key)
def set_cms_token(self, token, expires=None):
return self.redis.set(self.cms_token_key, token, expires)
......
from Crypto.Cipher import DES3
from Crypto.Hash import MD5
import struct
import base64
import codecs
def mds_hash(target_str):
h = MD5.new()
h.update(target_str.encode('utf-8'))
return h.digest()
def des_pad(data):
data = data.encode('utf-8')
e = len(data)
x = (e + 4) % 8
y = 0 if x == 0 else 8 - x
size_byte = struct.pack('>I', e)
result_byte = list(range(len(size_byte) + e + y))
result_byte[0:4] = size_byte
result_byte[4:4 + e] = data
for i in range(0, y):
result_byte[e + 4 + i] = 0
result_str = bytearray(result_byte).decode('utf-8')
return result_str
# DES3加密数据
def encode_des(to_encode_str, des_key):
"""
DES3加密数据
Args:
to_encode_str(str): 要被加密的原字符串,这里的字符串需要被des_pad一下
des_key(str): 加密的key
Returns:
"""
key = mds_hash(des_key)
des3 = DES3.new(key, DES3.MODE_ECB)
data = des3.encrypt(des_pad(to_encode_str))
data = codecs.encode(data, 'hex')
return data
def un_des_pad(data):
result_byte = data[0:4]
e = struct.unpack('>I', result_byte)[0]
x = (e + 4) % 8
y = 0 if x == 0 else 8 - x
return data[4:] if y == 0 else data[4:-y]
def decode_des(to_decode_str, des_key):
"""
解密数据
Args:
to_decode_str(str): 要解密的原字符串
des_key(str): 解密的key
Returns:
"""
key = mds_hash(des_key)
des3 = DES3.new(key, DES3.MODE_ECB)
param = base64.b64decode(to_decode_str)
param = des3.decrypt(param)
param = un_des_pad(param).decode('utf-8')
return param
import pyodbc
hil_sql = """
create table afc_se_cms_info
(
id bigint identity primary key,
application_id nvarchar(64) not null,
content nvarchar(max) not null,
update_time datetime not null,
create_time datetime not null
);
create index afc_se_cms_info_application_id_index
on afc_se_cms_info (application_id);
create index afc_se_cms_info_create_time_index
on afc_se_cms_info (create_time);
"""
afc_sql = """
create table hil_se_cms_info
(
id bigint identity primary key,
application_id nvarchar(64) not null,
content nvarchar(max) not null,
update_time datetime not null,
create_time datetime not null
);
create index hil_se_cms_info_application_id_index
on hil_se_cms_info (application_id);
create index hil_se_cms_info_create_time_index
on hil_se_cms_info (create_time);
"""
hil_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True)
hil_cursor = hil_cnxn.cursor()
hil_cursor.execute(hil_sql)
hil_cursor.close()
hil_cnxn.close()
afc_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True)
afc_cursor = afc_cnxn.cursor()
afc_cursor.execute(afc_sql)
afc_cursor.close()
afc_cnxn.close()
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!