9f4b3645 by 周伟奇

Merge branch 'feature/uat-tmp' into 'master'

Feature/uat tmp

See merge request !18
2 parents 284b3e1d 66e1870b
...@@ -10,8 +10,8 @@ PAGE_SIZE_DEFAULT = 10 ...@@ -10,8 +10,8 @@ PAGE_SIZE_DEFAULT = 10
10 10
11 FIXED_APPLICATION_ID_PREFIX = 'CH-S' 11 FIXED_APPLICATION_ID_PREFIX = 'CH-S'
12 12
13 DOC_SCHEME_LIST = ['ACCEPTANCE', 'SETTLEMENT', 'CONTRACTMANAGEMENT'] 13 DOC_SCHEME_LIST = ['ACCEPTANCE', 'SETTLEMENT', 'CONTRACTMANAGEMENT', 'INSURANCE']
14 DATA_SOURCE_LIST = ['POS', 'EAPP', 'ECONTRACT'] 14 DATA_SOURCE_LIST = ['POS', 'EAPP', 'ECONTRACT', 'OVP']
15 COMPARE_DOC_SCHEME_LIST = ['CA', 'SE'] 15 COMPARE_DOC_SCHEME_LIST = ['CA', 'SE']
16 16
17 HIL_PREFIX = 'HIL' 17 HIL_PREFIX = 'HIL'
...@@ -1057,7 +1057,25 @@ HIL_CONTRACT_2_CLASSIFY = 44 ...@@ -1057,7 +1057,25 @@ HIL_CONTRACT_2_CLASSIFY = 44
1057 HIL_CONTRACT_3_CN_NAME = '车辆处置协议' 1057 HIL_CONTRACT_3_CN_NAME = '车辆处置协议'
1058 HIL_CONTRACT_3_CLASSIFY = 45 1058 HIL_CONTRACT_3_CLASSIFY = 45
1059 1059
1060 CONTRACT_SET = {CONTRACT_QRS_CLASSIFY, CONTRACT_CLASSIFY, HIL_CONTRACT_1_CLASSIFY, HIL_CONTRACT_2_CLASSIFY, HIL_CONTRACT_3_CLASSIFY} 1060 FSM_CONTRACT_WEP_CN_NAME = '延长保修合同'
1061 FSM_CONTRACT_WEP_CLASSIFY = 51
1062
1063 FSM_CONTRACT_MSI_CN_NAME = '长悦保养合同'
1064 FSM_CONTRACT_MSI_CLASSIFY = 52
1065
1066 FSM_CONTRACT_SC_CN_NAME = '汽车销售合同'
1067 FSM_CONTRACT_SC_CLASSIFY = 53
1068
1069 CONTRACT_SET = {
1070 CONTRACT_QRS_CLASSIFY,
1071 CONTRACT_CLASSIFY,
1072 HIL_CONTRACT_1_CLASSIFY,
1073 HIL_CONTRACT_2_CLASSIFY,
1074 HIL_CONTRACT_3_CLASSIFY,
1075 FSM_CONTRACT_WEP_CLASSIFY,
1076 FSM_CONTRACT_MSI_CLASSIFY,
1077 FSM_CONTRACT_SC_CLASSIFY,
1078 }
1061 1079
1062 CONTRACT_MAP = { 1080 CONTRACT_MAP = {
1063 HIL_CONTRACT_1_CLASSIFY: HIL_CONTRACT_1_CN_NAME, 1081 HIL_CONTRACT_1_CLASSIFY: HIL_CONTRACT_1_CN_NAME,
...@@ -1065,8 +1083,13 @@ CONTRACT_MAP = { ...@@ -1065,8 +1083,13 @@ CONTRACT_MAP = {
1065 HIL_CONTRACT_3_CLASSIFY: HIL_CONTRACT_3_CN_NAME, 1083 HIL_CONTRACT_3_CLASSIFY: HIL_CONTRACT_3_CN_NAME,
1066 CONTRACT_CLASSIFY: CONTRACT_CN_NAME, 1084 CONTRACT_CLASSIFY: CONTRACT_CN_NAME,
1067 CONTRACT_QRS_CLASSIFY: CONTRACT_QRS_CN_NAME, 1085 CONTRACT_QRS_CLASSIFY: CONTRACT_QRS_CN_NAME,
1086 FSM_CONTRACT_WEP_CLASSIFY: FSM_CONTRACT_WEP_CN_NAME,
1087 FSM_CONTRACT_MSI_CLASSIFY: FSM_CONTRACT_MSI_CN_NAME,
1088 FSM_CONTRACT_SC_CLASSIFY: FSM_CONTRACT_SC_CN_NAME,
1068 } 1089 }
1069 1090
1091 FSM_CONTRACT_CLASSIFY_SET = {FSM_CONTRACT_WEP_CLASSIFY, FSM_CONTRACT_MSI_CLASSIFY, FSM_CONTRACT_SC_CLASSIFY}
1092
1070 # 保单 1093 # 保单
1071 INSURANCE_CN_NAME = '保单' 1094 INSURANCE_CN_NAME = '保单'
1072 INSURANCE_CLASSIFY = 42 1095 INSURANCE_CLASSIFY = 42
...@@ -1215,6 +1238,11 @@ BS_FIELD = 'bss_ocr' ...@@ -1215,6 +1238,11 @@ BS_FIELD = 'bss_ocr'
1215 HIL_CONTRACT_1_FIELD = 'hil_contract_1_ocr' 1238 HIL_CONTRACT_1_FIELD = 'hil_contract_1_ocr'
1216 HIL_CONTRACT_2_FIELD = 'hil_contract_2_ocr' 1239 HIL_CONTRACT_2_FIELD = 'hil_contract_2_ocr'
1217 HIL_CONTRACT_3_FIELD = 'hil_contract_3_ocr' 1240 HIL_CONTRACT_3_FIELD = 'hil_contract_3_ocr'
1241 FSM_CONTRACT_WEP_FIELD = 'fsm_wep_ocr'
1242 FSM_CONTRACT_MSI_FIELD = 'fsm_msi_ocr'
1243 FSM_CONTRACT_SC_FIELD = 'fsm_sc_ocr'
1244
1245
1218 BS_CLASSIFY = 10089 1246 BS_CLASSIFY = 10089
1219 1247
1220 RESULT_MAPPING = { 1248 RESULT_MAPPING = {
...@@ -1239,6 +1267,9 @@ RESULT_MAPPING = { ...@@ -1239,6 +1267,9 @@ RESULT_MAPPING = {
1239 HIL_CONTRACT_1_CLASSIFY: HIL_CONTRACT_1_FIELD, 1267 HIL_CONTRACT_1_CLASSIFY: HIL_CONTRACT_1_FIELD,
1240 HIL_CONTRACT_2_CLASSIFY: HIL_CONTRACT_2_FIELD, 1268 HIL_CONTRACT_2_CLASSIFY: HIL_CONTRACT_2_FIELD,
1241 HIL_CONTRACT_3_CLASSIFY: HIL_CONTRACT_3_FIELD, 1269 HIL_CONTRACT_3_CLASSIFY: HIL_CONTRACT_3_FIELD,
1270 FSM_CONTRACT_WEP_CLASSIFY: FSM_CONTRACT_WEP_FIELD,
1271 FSM_CONTRACT_MSI_CLASSIFY: FSM_CONTRACT_MSI_FIELD,
1272 FSM_CONTRACT_SC_CLASSIFY: FSM_CONTRACT_SC_FIELD,
1242 } 1273 }
1243 1274
1244 CA_ADD_COMPARE_FIELDS = (IC_OCR_FIELD, BL_OCR_FIELD, BS_FIELD) 1275 CA_ADD_COMPARE_FIELDS = (IC_OCR_FIELD, BL_OCR_FIELD, BS_FIELD)
...@@ -1511,6 +1542,9 @@ SE_AFC_CON_MAP = { ...@@ -1511,6 +1542,9 @@ SE_AFC_CON_MAP = {
1511 '还款账号': (2, 2, '还款账户', '账号'), 1542 '还款账号': (2, 2, '还款账户', '账号'),
1512 '户名': (2, 2, '还款账户', '户名'), 1543 '户名': (2, 2, '还款账户', '户名'),
1513 '开户行': (2, 2, '还款账户', '开户行'), 1544 '开户行': (2, 2, '还款账户', '开户行'),
1545 '收款账号': (2, 2, '借款人收款账户', '账号'),
1546 '收款户名': (2, 2, '借款人收款账户', '户名'),
1547 '收款开户行': (2, 2, '借款人收款账户', '开户行'),
1514 1548
1515 '借款人签字及时间': (1, 1, '借款人签字及时间', None), 1549 '借款人签字及时间': (1, 1, '借款人签字及时间', None),
1516 1550
...@@ -1550,9 +1584,12 @@ SE_HIL_CON_1_MAP = { ...@@ -1550,9 +1584,12 @@ SE_HIL_CON_1_MAP = {
1550 '融资成本总额': (5, 4, 7, '融资成本总额', None), 1584 '融资成本总额': (5, 4, 7, '融资成本总额', None),
1551 '租期': (5, 4, 7, '租期', None), 1585 '租期': (5, 4, 7, '租期', None),
1552 '还款计划表': (5, 5, 7, '付款计划表', None), 1586 '还款计划表': (5, 5, 7, '付款计划表', None),
1553 '还款账号': (5, 5, 7, '银行账户-银行账号', None), 1587 '还款账号': (5, 6, 7, '银行账户-银行账号', None),
1554 '户名': (5, 5, 7, '银行账户-户名', None), 1588 '户名': (5, 6, 7, '银行账户-户名', None),
1555 '开户行': (5, 5, 7, '银行账户-开户行', None), 1589 '开户行': (5, 6, 7, '银行账户-开户行', None),
1590 '收款账号': (5, 5, 7, '收款银行账户-银行账号', None),
1591 '收款户名': (5, 5, 7, '收款银行账户-户名', None),
1592 '收款开户行': (5, 5, 7, '收款银行账户-开户行', None),
1556 'ASP项目详情': (5, 4, 7, '车辆附加产品明细表', None), 1593 'ASP项目详情': (5, 4, 7, '车辆附加产品明细表', None),
1557 '承租人法定代表人或授权代表': (1, 1, 7, '承租人-法定代表人或授权代表', None), 1594 '承租人法定代表人或授权代表': (1, 1, 7, '承租人-法定代表人或授权代表', None),
1558 '共同承租人法定代表人或授权代表': (1, 1, 7, '共同承租人-法定代表人或授权代表', None), 1595 '共同承租人法定代表人或授权代表': (1, 1, 7, '共同承租人-法定代表人或授权代表', None),
...@@ -1608,6 +1645,39 @@ SE_HIL_CON_MAP = { ...@@ -1608,6 +1645,39 @@ SE_HIL_CON_MAP = {
1608 HIL_CONTRACT_3_CLASSIFY: SE_HIL_CON_3_MAP, 1645 HIL_CONTRACT_3_CLASSIFY: SE_HIL_CON_3_MAP,
1609 } 1646 }
1610 1647
1648 SE_FSM_WEP_MAP = {
1649 '客户姓名': (1, '客户姓名'),
1650 '证件类型': (1, '证件类型'),
1651 '证件号码': (1, '证件号码'),
1652 '合同价格(小写)': (1, '合同价格(小写)'),
1653 '客户签名': (1, '客户签名'),
1654 '签单日期': (1, '签单日期'),
1655 }
1656
1657 SE_FSM_MSI_MAP = {
1658 '客户姓名': (1, '客户姓名'),
1659 '证件类型': (1, '证件类型'),
1660 '证件号码': (1, '证件号码'),
1661 '合同价格(小写)': (1, '合同价格(小写)'),
1662 '客户签名': (2, '客户签名'),
1663 '签单日期': (2, '签单日期'),
1664 }
1665
1666 SE_FSM_SC_MAP = {
1667 '姓名': (1, '姓名'),
1668 '证件类型': (1, '证件类型'),
1669 '证件号码': (1, '证件号码'),
1670 '总价': (1, '总价'),
1671 '客户签名': (12, '客户签名'),
1672 '签单日期': (12, '签单日期'),
1673 }
1674
1675 SE_FSM_CON_MAP = {
1676 FSM_CONTRACT_WEP_CLASSIFY: SE_FSM_WEP_MAP,
1677 FSM_CONTRACT_MSI_CLASSIFY: SE_FSM_MSI_MAP,
1678 FSM_CONTRACT_SC_CLASSIFY: SE_FSM_SC_MAP,
1679 }
1680
1611 SE_AFC_CON_QRS_FIELD = ['合同编号'] 1681 SE_AFC_CON_QRS_FIELD = ['合同编号']
1612 SE_AFC_CON_FIELD = ['合同编号-每页', '所购车辆价格-小写-重要条款', '车架号-重要条款', '贷款本金金额-重要条款', '贷款期限-重要条款', 1682 SE_AFC_CON_FIELD = ['合同编号-每页', '所购车辆价格-小写-重要条款', '车架号-重要条款', '贷款本金金额-重要条款', '贷款期限-重要条款',
1613 '车辆贷款本金金额-重要条款', '附加产品融资贷款本金总额-重要条款', '所购车辆价格', '车架号', '经销商', 1683 '车辆贷款本金金额-重要条款', '附加产品融资贷款本金总额-重要条款', '所购车辆价格', '车架号', '经销商',
...@@ -2314,29 +2384,42 @@ APPLICANT_TYPE_MAP = { ...@@ -2314,29 +2384,42 @@ APPLICANT_TYPE_MAP = {
2314 2384
2315 APPLICANT_TYPE_ORDER = ['Borrower', 'Co-Borrower', 'Guarantor', 'Mortgager'] 2385 APPLICANT_TYPE_ORDER = ['Borrower', 'Co-Borrower', 'Guarantor', 'Mortgager']
2316 2386
2317 FILE_NAME_PREFIX_MAP = { 2387 # FILE_NAME_PREFIX_MAP = {
2318 AFC_PREFIX: [ 2388 # AFC_PREFIX: [
2319 ((CONTRACT_CLASSIFY, 0), '{0}_电子签署-汽车抵押贷款合同'), 2389 # ((CONTRACT_CLASSIFY, 0), '{0}_电子签署-汽车抵押贷款合同'),
2320 ((HMH_CLASSIFY, 0), '{0}_电子签署-抵押登记豁免函'), 2390 # ((HMH_CLASSIFY, 0), '{0}_电子签署-抵押登记豁免函'),
2321 ], 2391 # ],
2322 HIL_PREFIX: [ 2392 # HIL_PREFIX: [
2323 ((HIL_CONTRACT_1_CLASSIFY, HIL_CONTRACT_3_CLASSIFY), '{0}_电子签署-售后回租合同'), 2393 # ((HIL_CONTRACT_1_CLASSIFY, HIL_CONTRACT_3_CLASSIFY), '{0}_电子签署-售后回租合同'),
2324 ((HIL_CONTRACT_2_CLASSIFY, 0), '{0}_电子签署-汽车租赁抵押合同'), 2394 # ((HIL_CONTRACT_2_CLASSIFY, 0), '{0}_电子签署-汽车租赁抵押合同'),
2325 ((HMH_CLASSIFY, 0), '{0}_电子签署-抵押登记豁免函'), 2395 # ((HMH_CLASSIFY, 0), '{0}_电子签署-抵押登记豁免函'),
2326 ] 2396 # ]
2327 } 2397 # }
2328 2398
2329 ECONTRACT_KEYWORDS_MAP = { 2399 ECONTRACT_KEYWORDS_MAP = {
2330 AFC_PREFIX: [ 2400 AFC_PREFIX: [
2331 ('抵押贷款合同', CONTRACT_CLASSIFY), 2401 ('抵押贷款合同', CONTRACT_CLASSIFY),
2332 ('送达地址确认书', CONTRACT_QRS_CLASSIFY), 2402 ('送达地址确认书', CONTRACT_QRS_CLASSIFY),
2333 # ('电子签署-抵押登记豁免函', HMH_CLASSIFY, 0), 2403 ('抵押登记豁免函', HMH_CLASSIFY),
2334 ], 2404 ],
2335 HIL_PREFIX: [ 2405 HIL_PREFIX: [
2336 ('售后回租合同', HIL_CONTRACT_1_CLASSIFY), 2406 ('售后回租合同', HIL_CONTRACT_1_CLASSIFY),
2337 ('租赁抵押合同', HIL_CONTRACT_2_CLASSIFY), 2407 ('租赁抵押合同', HIL_CONTRACT_2_CLASSIFY),
2338 ('车辆处置协议', HIL_CONTRACT_3_CLASSIFY), 2408 ('车辆处置协议', HIL_CONTRACT_3_CLASSIFY),
2339 # ('电子签署-抵押登记豁免函', HMH_CLASSIFY, 0), 2409 ('抵押登记豁免函', HMH_CLASSIFY),
2410 ]
2411 }
2412
2413 FSM_ECONTRACT_KEYWORDS_MAP = {
2414 AFC_PREFIX: [
2415 ('延长保修条款与条件', FSM_CONTRACT_WEP_CLASSIFY),
2416 ('长悦保养套餐服务合约', FSM_CONTRACT_MSI_CLASSIFY),
2417 ('汽车销售合同', FSM_CONTRACT_SC_CLASSIFY),
2418 ],
2419 HIL_PREFIX: [
2420 ('延长保修条款与条件', FSM_CONTRACT_WEP_CLASSIFY),
2421 ('长悦保养套餐服务合同', FSM_CONTRACT_MSI_CLASSIFY),
2422 ('汽车销售合同', FSM_CONTRACT_SC_CLASSIFY),
2340 ] 2423 ]
2341 } 2424 }
2342 2425
...@@ -2346,6 +2429,12 @@ HIL_CONTRACT_TYPE_MAP = { ...@@ -2346,6 +2429,12 @@ HIL_CONTRACT_TYPE_MAP = {
2346 str(HIL_CONTRACT_3_CLASSIFY): 1, 2429 str(HIL_CONTRACT_3_CLASSIFY): 1,
2347 } 2430 }
2348 2431
2432 FSM_CONTRACT_TYPE_MAP = {
2433 str(FSM_CONTRACT_WEP_CLASSIFY): 0,
2434 str(FSM_CONTRACT_MSI_CLASSIFY): 1,
2435 str(FSM_CONTRACT_SC_CLASSIFY): 2,
2436 }
2437
2349 RESULT_MAP = { 2438 RESULT_MAP = {
2350 0: None, 2439 0: None,
2351 1: True, 2440 1: True,
...@@ -2379,3 +2468,26 @@ MPOS_MAP = { ...@@ -2379,3 +2468,26 @@ MPOS_MAP = {
2379 } 2468 }
2380 2469
2381 FOLDER_WSC_CLASSIFY = 199 2470 FOLDER_WSC_CLASSIFY = 199
2471
2472
2473 FSM_BEFORE_ACTIVITED_STATUS = {
2474 "APSVD": "Saved",
2475 "APEAE": "E-app Editing",
2476 "APADA": "Awaiting Dealer Action",
2477 "APAPR": "Acceptance Processing",
2478 "APPSB": "Pre-submit Processed",
2479 "APSBT": "Submitted",
2480 "APAPP": "Approved",
2481 "APHOC": "Held Offer-Docs",
2482 "APHOD": "Held Offer-Data",
2483 "APINI": "Initiated",
2484 "APSEP": "Settlement Processing"
2485 }
2486
2487 FSM_ACTIVITED_STATUS = {
2488 "APADF": "Activated-Document Follow up",
2489 "APASC": "Activated-Awaiting Settlement Check",
2490 "APIPN": "Activated-Invoice Passed-Non PT",
2491 "APIPP": "Activated-Invoice Passed-PT Doc Required",
2492 "APARD": "Activated-Review done",
2493 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -329,6 +329,11 @@ class AFCOCRResult(models.Model): ...@@ -329,6 +329,11 @@ class AFCOCRResult(models.Model):
329 hil_contract_2_ocr = models.TextField(null=True, verbose_name="HIL合同2") 329 hil_contract_2_ocr = models.TextField(null=True, verbose_name="HIL合同2")
330 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3") 330 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3")
331 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书") 331 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书")
332 fsm_wep_ocr = models.TextField(null=True, verbose_name="延长保修合同")
333 fsm_msi_ocr = models.TextField(null=True, verbose_name="长悦保养合同")
334 fsm_sc_ocr = models.TextField(null=True, verbose_name="汽车销售合同")
335 fsm_activited = models.IntegerField(null=False, default=0, verbose_name="fsm激活状态 1:激活")
336
332 337
333 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') 338 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
334 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') 339 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
...@@ -366,6 +371,11 @@ class HILOCRResult(models.Model): ...@@ -366,6 +371,11 @@ class HILOCRResult(models.Model):
366 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3") 371 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3")
367 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书") 372 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书")
368 373
374 fsm_wep_ocr = models.TextField(null=True, verbose_name="延长保修合同")
375 fsm_msi_ocr = models.TextField(null=True, verbose_name="长悦保养合同")
376 fsm_sc_ocr = models.TextField(null=True, verbose_name="汽车销售合同")
377 fsm_activited = models.IntegerField(null=False, default=0, verbose_name="fsm激活状态 1:激活")
378
369 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') 379 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
370 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') 380 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
371 381
...@@ -401,6 +411,11 @@ class AFCSEOCRResult(models.Model): ...@@ -401,6 +411,11 @@ class AFCSEOCRResult(models.Model):
401 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3") 411 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3")
402 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书") 412 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书")
403 413
414 fsm_wep_ocr = models.TextField(null=True, verbose_name="延长保修合同")
415 fsm_msi_ocr = models.TextField(null=True, verbose_name="长悦保养合同")
416 fsm_sc_ocr = models.TextField(null=True, verbose_name="汽车销售合同")
417 fsm_activited = models.IntegerField(null=False, default=0, verbose_name="fsm激活状态 1:激活")
418
404 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') 419 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
405 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') 420 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
406 421
...@@ -436,6 +451,10 @@ class HILSEOCRResult(models.Model): ...@@ -436,6 +451,10 @@ class HILSEOCRResult(models.Model):
436 hil_contract_2_ocr = models.TextField(null=True, verbose_name="HIL合同2") 451 hil_contract_2_ocr = models.TextField(null=True, verbose_name="HIL合同2")
437 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3") 452 hil_contract_3_ocr = models.TextField(null=True, verbose_name="HIL合同3")
438 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书") 453 qrs_ocr = models.TextField(null=True, verbose_name="AFC合同确认书")
454 fsm_wep_ocr = models.TextField(null=True, verbose_name="延长保修合同")
455 fsm_msi_ocr = models.TextField(null=True, verbose_name="长悦保养合同")
456 fsm_sc_ocr = models.TextField(null=True, verbose_name="汽车销售合同")
457 fsm_activited = models.IntegerField(null=False, default=0, verbose_name="fsm激活状态 1:激活")
439 458
440 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间') 459 update_time = models.DateTimeField(auto_now=True, verbose_name='修改时间')
441 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') 460 create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
...@@ -1042,3 +1061,41 @@ class AFCCompareReportNew(models.Model): ...@@ -1042,3 +1061,41 @@ class AFCCompareReportNew(models.Model):
1042 managed = False 1061 managed = False
1043 db_table = 'afc_compare_report_new' 1062 db_table = 'afc_compare_report_new'
1044 situ_db_label = 'afc' 1063 situ_db_label = 'afc'
1064
1065
1066 class NscInvoice(models.Model):
1067 id = models.AutoField(primary_key=True, verbose_name="id") # 主键
1068 vin = models.CharField(max_length=64, verbose_name="车架号") # 索引
1069 content = models.TextField(null=True, verbose_name="nsc发票信息")
1070 create_time = models.DateTimeField(verbose_name='创建时间')
1071
1072 class Meta:
1073 managed = False
1074 db_table = 'nsc_invoice'
1075
1076
1077 class AFCCmsStatusInfo(models.Model):
1078 id = models.AutoField(primary_key=True, verbose_name="id") # 主键
1079 application_id = models.CharField(max_length=64, verbose_name="订单id") # 索引
1080 business_type = models.CharField(max_length=64, verbose_name="业务类型")
1081 is_fsm = models.SmallIntegerField(null=False, default=0, verbose_name="是否fsm流程 1:是")
1082 update_time = models.DateTimeField(verbose_name='更新时间')
1083 create_time = models.DateTimeField(verbose_name='创建时间')
1084
1085 class Meta:
1086 managed = False
1087 db_table = 'afc_cms_status_info'
1088 situ_db_label = 'afc'
1089
1090
1091 class HILCmsStatusInfo(models.Model):
1092 id = models.AutoField(primary_key=True, verbose_name="id") # 主键
1093 application_id = models.CharField(max_length=64, verbose_name="订单id") # 索引
1094 business_type = models.CharField(max_length=64, verbose_name="业务类型")
1095 is_fsm = models.SmallIntegerField(null=False, default=0, verbose_name="是否fsm流程 1:是")
1096 update_time = models.DateTimeField(verbose_name='更新时间')
1097 create_time = models.DateTimeField(verbose_name='创建时间')
1098
1099 class Meta:
1100 managed = False
1101 db_table = 'hil_cms_status_info'
......
...@@ -27,6 +27,7 @@ class RequestTeam(NamedEnum): ...@@ -27,6 +27,7 @@ class RequestTeam(NamedEnum):
27 SETTLEMENT = (1, 'SETTLEMENT') 27 SETTLEMENT = (1, 'SETTLEMENT')
28 CONTRACTMANAGEMENT = (2, 'CONTRACTMANAGEMENT') 28 CONTRACTMANAGEMENT = (2, 'CONTRACTMANAGEMENT')
29 CONTROLLING = (3, 'CONTROLLING') 29 CONTROLLING = (3, 'CONTROLLING')
30 INSURANCE = (4, 'INSURANCE')
30 31
31 32
32 class RequestTrigger(NamedEnum): 33 class RequestTrigger(NamedEnum):
...@@ -36,6 +37,7 @@ class RequestTrigger(NamedEnum): ...@@ -36,6 +37,7 @@ class RequestTrigger(NamedEnum):
36 DOCUPLOAD = (3, 'Document Upload') 37 DOCUPLOAD = (3, 'Document Upload')
37 SUBMITING = (4, 'Submiting') 38 SUBMITING = (4, 'Submiting')
38 UPLOADING = (5, 'Uploading') 39 UPLOADING = (5, 'Uploading')
40 OVP = (6, 'OVP')
39 41
40 42
41 class FailureReason(NamedEnum): 43 class FailureReason(NamedEnum):
......
...@@ -34,6 +34,7 @@ class ECM: ...@@ -34,6 +34,7 @@ class ECM:
34 'ACCEPTANCE': ('acceptance', conf.ECM_FOLDER_CA, conf.ECM_FOLDER_CA_HIL), 34 'ACCEPTANCE': ('acceptance', conf.ECM_FOLDER_CA, conf.ECM_FOLDER_CA_HIL),
35 'SETTLEMENT': (self.settlement_type, conf.ECM_FOLDER_SE, conf.ECM_FOLDER_SE_HIL), 35 'SETTLEMENT': (self.settlement_type, conf.ECM_FOLDER_SE, conf.ECM_FOLDER_SE_HIL),
36 'CONTRACTMANAGEMENT': ('contract_management', conf.ECM_FOLDER_CA, conf.ECM_FOLDER_CA_HIL), 36 'CONTRACTMANAGEMENT': ('contract_management', conf.ECM_FOLDER_CA, conf.ECM_FOLDER_CA_HIL),
37 'INSURANCE': ('insurance', conf.ECM_FOLDER_SE, conf.ECM_FOLDER_SE_HIL),
37 } 38 }
38 self.doc_base_map = { 39 self.doc_base_map = {
39 'AFC': 'SF5_CN', 40 'AFC': 'SF5_CN',
......
...@@ -808,10 +808,12 @@ class BSWorkbook(Workbook): ...@@ -808,10 +808,12 @@ class BSWorkbook(Workbook):
808 if field_str is not None: 808 if field_str is not None:
809 count_list.append((field_str, count)) 809 count_list.append((field_str, count))
810 810
811 def contract_rebuild(self, contract_result_dict): 811 def contract_rebuild(self, contract_result_dict, is_ca=False):
812 for classify, contract_result in contract_result_dict.items(): 812 for classify, contract_result in contract_result_dict.items():
813 if len(contract_result) == 0: 813 if len(contract_result) == 0:
814 continue 814 continue
815 if is_ca and classify not in consts.FSM_CONTRACT_CLASSIFY_SET:
816 continue
815 ws = self.create_sheet(consts.CONTRACT_MAP.get(classify)) 817 ws = self.create_sheet(consts.CONTRACT_MAP.get(classify))
816 for i in range(30): 818 for i in range(30):
817 if str(i) in contract_result: 819 if str(i) in contract_result:
...@@ -934,6 +936,7 @@ class BSWorkbook(Workbook): ...@@ -934,6 +936,7 @@ class BSWorkbook(Workbook):
934 else: 936 else:
935 self.bs_rebuild(bs_summary, res_count_tuple, metadata) 937 self.bs_rebuild(bs_summary, res_count_tuple, metadata)
936 self.license_rebuild(license_summary, document_scheme, count_list) 938 self.license_rebuild(license_summary, document_scheme, count_list)
939 self.contract_rebuild(contract_result, True)
937 self.move_res_sheet() 940 self.move_res_sheet()
938 self.remove_base_sheet() 941 self.remove_base_sheet()
939 return count_list, self.need_follow 942 return count_list, self.need_follow
......
...@@ -7,6 +7,9 @@ import traceback ...@@ -7,6 +7,9 @@ import traceback
7 import numpy as np 7 import numpy as np
8 from datetime import datetime, timedelta 8 from datetime import datetime, timedelta
9 from collections import OrderedDict 9 from collections import OrderedDict
10
11 import requests
12
10 from . import app 13 from . import app
11 from settings import conf 14 from settings import conf
12 from apps.doc.models import ( 15 from apps.doc.models import (
...@@ -3266,6 +3269,33 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res ...@@ -3266,6 +3269,33 @@ def se_compare(application_id, application_entity, ocr_res_id, last_obj, ocr_res
3266 3269
3267 3270
3268 @app.task 3271 @app.task
3272 def fsm_compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False):
3273 compare_log.info('{0} [receive fsm task] [entity={1}] [id={2}] [uniq_seq={3}] [ocr_res_id={4}] [is_ca={5}] '
3274 '[is_cms={6}]'.format(log_base, application_entity, application_id, uniq_seq, ocr_res_id,
3275 is_ca, is_cms))
3276 # 调用java fsm 比对流程接口(http)
3277 # 调用Java fsm 比对流程接口, fsm 是se流程, ca可以暂时忽略
3278 url = conf.FSM_URL
3279 body = {
3280 'applicationId': application_id,
3281 'businessType': application_entity,
3282 'ocrResId': ocr_res_id,
3283 'isCa': is_ca,
3284 'isCms': is_cms
3285 }
3286 try:
3287 compare_log.info("request java fsm api, url:{0}, body:{1}".format(url, json.dumps(body)))
3288 headers = {
3289 'Content-Type': 'application/json'
3290 }
3291 resp = requests.post(url, headers=headers, json=body)
3292 compare_log.info("response from fsm api, resp:{0}".format(resp.text))
3293 except Exception as e:
3294 compare_log.error("fsm full request to java error, url:{0}, param:{1}, errorMsg:{2}".format(
3295 url, json.dumps(body), traceback.format_exc()))
3296
3297
3298 @app.task
3269 def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False): 3299 def compare(application_id, application_entity, uniq_seq, ocr_res_id, is_ca=True, is_cms=False):
3270 # POS: application_id, application_entity, uniq_seq, None 3300 # POS: application_id, application_entity, uniq_seq, None
3271 # OCR: application_id, business_type(application_entity), None, ocr_res_id 3301 # OCR: application_id, business_type(application_entity), None, ocr_res_id
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
6 # @Description : 6 # @Description :
7 7
8 from .get_char import Finder 8 from .get_char import Finder
9 from .get_char_fsm import Finder as FSMFinder
9 import numpy as np 10 import numpy as np
10 11
11 12
...@@ -23,7 +24,7 @@ def extract_info(ocr_results): ...@@ -23,7 +24,7 @@ def extract_info(ocr_results):
23 return {'page_1': {'合同编号': contract_no}} 24 return {'page_1': {'合同编号': contract_no}}
24 25
25 26
26 def predict(pdf_info, is_qrs=False): 27 def predict(pdf_info, is_qrs=False, is_fsm=False):
27 ocr_results = {} 28 ocr_results = {}
28 for pno in pdf_info: 29 for pno in pdf_info:
29 ocr_results[pno] = {} 30 ocr_results[pno] = {}
...@@ -50,7 +51,10 @@ def predict(pdf_info, is_qrs=False): ...@@ -50,7 +51,10 @@ def predict(pdf_info, is_qrs=False):
50 results = extract_info(ocr_results) 51 results = extract_info(ocr_results)
51 else: 52 else:
52 # 输入是整个 PDF 中的信息 53 # 输入是整个 PDF 中的信息
53 f = Finder(pdf_info, ocr_results=ocr_results) 54 if is_fsm:
55 f = FSMFinder(pdf_info, ocr_results=ocr_results)
56 else:
57 f = Finder(pdf_info, ocr_results=ocr_results)
54 results = f.get_info() 58 results = f.get_info()
55 return results 59 return results
56 60
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
6 # @Description : 6 # @Description :
7 7
8 from .get_char import Finder 8 from .get_char import Finder
9 from .get_char_fsm import Finder as FSMFinder
9 10
10 11
11 def predict(pdf_info, file_cls): 12 def predict(pdf_info, file_cls, is_fsm=False):
12 """Summary 13 """Summary
13 14
14 Args: 15 Args:
...@@ -58,7 +59,11 @@ def predict(pdf_info, file_cls): ...@@ -58,7 +59,11 @@ def predict(pdf_info, file_cls):
58 pdf_info = dict() 59 pdf_info = dict()
59 for pno, page_info in enumerate(pdf_info_1): 60 for pno, page_info in enumerate(pdf_info_1):
60 pdf_info[str(pno)] = page_info 61 pdf_info[str(pno)] = page_info
61 f = Finder(pdf_info) 62
63 if is_fsm:
64 f = FSMFinder(pdf_info)
65 else:
66 f = Finder(pdf_info)
62 if file_cls == 0: 67 if file_cls == 0:
63 results = f.get_info() 68 results = f.get_info()
64 if file_cls == 1: 69 if file_cls == 1:
......
1 WEP_FIELD = {
2 "0": {
3 'keys': {
4 '客户姓名': [('客户姓名', (r'^姓名.?$', r'^企业名称.?$'), 'top1', {})],
5 '证件类型': [('证件类型', (r'^证件类型.?$', ), 'top1', {})],
6 '证件号码': [('证件号码', (r'^证件号码.?$', r'^统一社会信用代码.?$'), 'top1', {})],
7 '合同价格(小写)': [('人民币', (r'^人民币¥.?$', ), 'top1', {})],
8 '客户签名': [('客户签名/盖章', (r'^客户签名/盖章.*$', ), 'top1', {})],
9 '签单日期': [('签单日期', (r'^签单日期.*签单日期.?$', ), 'top1', {})],
10 },
11 'value': {
12 '客户姓名': ('text', 'right', {'offset_tuple': (-1.1, 1, 0.3, 0)}, ''),
13 '证件类型': ('text', 'right', {'offset_tuple': (-1, 1, 0, 0)}, ''),
14 '证件号码': ('text', 'right', {'offset_tuple': (-1, 2, 0.3, 0)}, ''),
15 '合同价格(小写)': ('text', 'right', {'offset_tuple': (-1, 1, 0.3, 0)}, ''),
16 '客户签名': ('img', 'under', {'offset_tuple': (0, 0, 0, 4), 'rigorous': True}, '无'),
17 '签单日期': ('img', 'right', {'offset_tuple': (0, 0, 1.1, 0), 'rigorous': True}, '无'),
18 },
19 }
20
21 }
22
23 MSI_FIELD = {
24 "0": {
25 'keys': {
26 '客户姓名': [('客户姓名', (r'^客户姓名.?$', r'^企业名称.?$'), 'top1', {})],
27 '证件类型': [('证件类型', (r'^证件类型.?$', ), 'top1', {})],
28 '证件号码': [('证件号码', (r'^证件号码.?$', r'^统一社会信用代码.?$'), 'top1', {})],
29 '合同价格(小写)': [('人民币', (r'^人民币¥.?$', ), 'top1', {})],
30 },
31 'value': {
32 '客户姓名': ('text', 'right', {'offset_tuple': (-1.2, 1, 0.3, 0)}, ''),
33 '证件类型': ('text', 'right', {'offset_tuple': (-1, 1, 0, 0)}, ''),
34 '证件号码': ('text', 'right', {'offset_tuple': (-1, 2, 0.3, 0)}, ''),
35 '合同价格(小写)': ('text', 'right', {'offset_tuple': (-1, 1, 0.3, 0)}, ''),
36 },
37 },
38 "1": {
39 'keys': {
40 '客户签名': [('客户签名/盖章', (r'^客户签名/盖章.*$', ), 'top1', {})],
41 '签单日期': [('签单日期', (r'^签单日期.*签单日期.?$', ), 'top1', {})],
42 },
43 'value': {
44 '客户签名': ('img', 'under', {'offset_tuple': (0, 0, 0, 4), 'rigorous': True}, '无'),
45 '签单日期': ('img', 'right', {'offset_tuple': (0, 0, 1.1, 0), 'rigorous': True}, '无'),
46 },
47 }
48 }
49
50 SC_FIELD = {
51 "0": {
52 'keys': {
53 '姓名': [('姓名', (r'^姓名.?$', r'^企业名称.?$'), 'top1', {})],
54 '证件类型': [('证件类型', (r'^证件类型.?$', ), 'top1', {})],
55 '证件号码': [('证件号码', (r'^证件号码.?$', r'^统一社会信用代码.?$'), 'top1', {})],
56 '总价': [('总价', (r'^总价.?$', ), 'top1', {})],
57 },
58 'value': {
59 '姓名': ('text', 'right', {'offset_tuple': (-2, 8, 0.5, 0)}, ''),
60 '证件类型': ('text', 'right', {'offset_tuple': (-2, 6, 0.5, 0)}, ''),
61 '证件号码': ('text', 'right', {'offset_tuple': (-2, 6, 0.5, 0)}, ''),
62 '总价': ('text', 'right', {'offset_tuple': (-2, 12, 0.5, 0)}, ''),
63 },
64 },
65 "-1": {
66 'keys': {
67 '客户签名': [('客户签名/盖章', (r'^客户签名/盖章.*$', r'^客户签名/盖章.*$'), 'top1', {})],
68 '签单日期': [('签单日期', (r'^签单日期.*签单日期.?$', ), 'top1', {})],
69 },
70 'value': {
71 '客户签名': ('img', 'under', {'offset_tuple': (1.5, 1, 0, 4), 'rigorous': True}, '无'),
72 '签单日期': ('img', 'right', {'offset_tuple': (0, 0, 1.1, 0), 'rigorous': True}, '无'),
73 },
74 }
75 }
1 from .retriever import Retriever
2 from .const import WEP_FIELD, MSI_FIELD, SC_FIELD
3 from .tools import pdf_info_rebuild
4
5 retriever_list = [Retriever(WEP_FIELD), Retriever(MSI_FIELD), Retriever(SC_FIELD)]
6
7 def predict(pdf_info, file_type=0):
8 retriever = retriever_list[file_type]
9 pdf_text_list, pdf_img_list = pdf_info_rebuild(pdf_info)
10 return retriever.get_target_fields(pdf_text_list, pdf_img_list)
11
12
1 from .retriever import HMHRetriever
2 from .tools import pdf_info_rebuild
3
4 hmh_retriever = HMHRetriever()
5
6 def predict(pdf_info):
7 pdf_text_list, _ = pdf_info_rebuild(pdf_info, fix_bbox=False)
8 return hmh_retriever.get_target_fields(pdf_text_list)
9
10
1 def pdf_info_rebuild(pdf_info, fix_bbox=True):
2 pdf_text_info = dict()
3 pdf_img_info = dict()
4 for pno_str, page_info in pdf_info.items():
5 text_set = set()
6 for block in page_info['blocks']:
7 if block['type'] == 0:
8 # text有重复的现象
9 text_set.clear()
10 for line in block['lines']:
11 for span in line['spans']:
12 bbox, text = span['bbox'], span['text'].strip()
13 if len(text) != 0 and text not in text_set:
14 text_set.add(text)
15 # bbox的高,不准
16 if fix_bbox and bbox[-1] - bbox[1] < span['size']:
17 bbox[-1] = bbox[-1] + span['size']
18 pdf_text_info.setdefault(pno_str, list()).append([bbox, text])
19 elif block['type'] == 1:
20 pdf_img_info.setdefault(pno_str, list()).append((block['bbox'], '有'))
21
22 return pdf_text_info, pdf_img_info
...\ No newline at end of file ...\ No newline at end of file
1 import pyodbc
2
3 hil_sql = """
4 ALTER TABLE hil_ocr_result ADD fsm_wep_ocr nvarchar(max);
5 ALTER TABLE hil_ocr_result ADD fsm_msi_ocr nvarchar(max);
6 ALTER TABLE hil_ocr_result ADD fsm_sc_ocr nvarchar(max);
7 ALTER TABLE hil_se_ocr_result ADD fsm_wep_ocr nvarchar(max);
8 ALTER TABLE hil_se_ocr_result ADD fsm_msi_ocr nvarchar(max);
9 ALTER TABLE hil_se_ocr_result ADD fsm_sc_ocr nvarchar(max);
10 """
11
12 afc_sql = """
13 ALTER TABLE afc_ocr_result ADD fsm_wep_ocr nvarchar(max);
14 ALTER TABLE afc_ocr_result ADD fsm_msi_ocr nvarchar(max);
15 ALTER TABLE afc_ocr_result ADD fsm_sc_ocr nvarchar(max);
16 ALTER TABLE afc_se_ocr_result ADD fsm_wep_ocr nvarchar(max);
17 ALTER TABLE afc_se_ocr_result ADD fsm_msi_ocr nvarchar(max);
18 ALTER TABLE afc_se_ocr_result ADD fsm_sc_ocr nvarchar(max);
19 """
20
21 hil_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True)
22
23 hil_cursor = hil_cnxn.cursor()
24 hil_cursor.execute(hil_sql)
25
26 hil_cursor.close()
27 hil_cnxn.close()
28
29 afc_cnxn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};', autocommit=True)
30
31 afc_cursor = afc_cnxn.cursor()
32 afc_cursor.execute(afc_sql)
33
34 afc_cursor.close()
35 afc_cnxn.close()
...@@ -8,13 +8,16 @@ from common.tools.comparison import cp ...@@ -8,13 +8,16 @@ from common.tools.comparison import cp
8 from common.mixins import LoggerMixin 8 from common.mixins import LoggerMixin
9 from rest_framework.permissions import IsAuthenticated 9 from rest_framework.permissions import IsAuthenticated
10 from apps.account.authentication import OAuth2AuthenticationWithUser 10 from apps.account.authentication import OAuth2AuthenticationWithUser
11 from apps.doc.models import NscInvoice
12 import json
13 from datetime import datetime
11 14
12 params = { 15 params = {
13 'invoiceCode': fields.Str(required=True, validate=validate.Length(max=128)), 16 'invoiceCode': fields.Str(required=True, validate=validate.Length(max=128)),
14 'invoiceNumber': fields.Str(required=True, validate=validate.Length(max=64)), 17 'invoiceNumber': fields.Str(required=True, validate=validate.Length(max=64)),
15 'issueDate': CustomDate(required=True), 18 'issueDate': CustomDate(required=True),
16 'buyerName': fields.Str(required=True, validate=validate.Length(max=64)), 19 'buyerName': fields.Str(required=True, validate=validate.Length(max=64)),
17 "buyerId": fields.Int(required=True), 20 "buyerId": fields.Str(required=True, validate=validate.Length(max=64)),
18 'vin': fields.Str(required=True, validate=validate.Length(max=128)), 21 'vin': fields.Str(required=True, validate=validate.Length(max=128)),
19 'dealer': fields.Str(required=False, validate=validate.Length(max=64)), 22 'dealer': fields.Str(required=False, validate=validate.Length(max=64)),
20 'priceWithVat': CustomDecimal(required=True), 23 'priceWithVat': CustomDecimal(required=True),
...@@ -29,7 +32,7 @@ input_args = { ...@@ -29,7 +32,7 @@ input_args = {
29 } 32 }
30 33
31 34
32 # poss 接口接收NSC 发票信息 35 # pos 接口接收NSC 发票信息
33 class NSCInvoiceView(GenericView): 36 class NSCInvoiceView(GenericView):
34 permission_classes = [IsAuthenticated] 37 permission_classes = [IsAuthenticated]
35 authentication_classes = [OAuth2AuthenticationWithUser] 38 authentication_classes = [OAuth2AuthenticationWithUser]
...@@ -50,6 +53,7 @@ class NSCInvoiceView(GenericView): ...@@ -50,6 +53,7 @@ class NSCInvoiceView(GenericView):
50 vat = content.get('vat', 0.0) 53 vat = content.get('vat', 0.0)
51 vat_rate = content.get('vatRate', 0.0) 54 vat_rate = content.get('vatRate', 0.0)
52 55
56 NscInvoice.objects.create(vin=vin, content=json.dumps(content), create_time=datetime.now())
53 return response.ok() 57 return response.ok()
54 58
55 59
...@@ -90,11 +94,17 @@ class DeMortgageView(GenericView): ...@@ -90,11 +94,17 @@ class DeMortgageView(GenericView):
90 'applicationName': application_name, 94 'applicationName': application_name,
91 'deMortgageDate': de_mortgage_date 95 'deMortgageDate': de_mortgage_date
92 } 96 }
93 de_mortgage_info = {} 97 de_mortgage_info = {'customer_name':'','applicationName':'','deMortgageDate':''}
94 # 绿本必须分开ocr 98 # 绿本必须分开ocr
95 for file_obj in files: 99 for file_obj in files:
96 info = PosHandler.de_mortgage_ocr_process1(file_obj) 100 info = PosHandler.de_mortgage_ocr_process1(file_obj)
97 de_mortgage_info.update(info) 101 if info.get('customerName') is not '':
102 de_mortgage_info['customerName'] = info.get('customerName')
103 if info.get('applicationName') is not '':
104 de_mortgage_info['applicationName'] = info.get('applicationName')
105 if info.get('deMortgageDate') is not '':
106 de_mortgage_info['deMortgageDate'] = info.get('deMortgageDate')
107 #de_mortgage_info.update(info)
98 108
99 request_pass = True 109 request_pass = True
100 fields_result = [] 110 fields_result = []
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!