gaoluyang
2 天以前 e40a608ef9bf51db294d8eefada6a8e2e80cebca
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
"""Independent read-only validation of posted documents and inventory conservation."""
import sys,json,csv
from pathlib import Path
from decimal import Decimal
P=Path(__file__).parent
sys.path.insert(0,str(P.parent/'iqc-import-20261012/deps'))
import pymysql
D=Decimal
canon=lambda x:json.loads(json.dumps(x,default=str))
r=json.loads((P/'shipping-complete-result.json').read_text(encoding='utf8'))
b=json.loads((P/'shipping-complete-locked-before.json').read_text(encoding='utf8'))
name_fix_path=P/'contract-name-prefix-result.json'
name_fixes={x['id']:x for x in json.loads(name_fix_path.read_text(encoding='utf8'))['changes']} if name_fix_path.exists() else {}
quote_fix_path=P/'quotation-name-sync-result.json'
quote_name_fixes={x['id']:x for x in json.loads(quote_fix_path.read_text(encoding='utf8'))['changes']} if quote_fix_path.exists() else {}
date_fix_path=P/'business-create-times-result.json'
date_fixes={(x['table'],x['id']):x for x in json.loads(date_fix_path.read_text(encoding='utf8'))['changes']} if date_fix_path.exists() else {}
remark_fix_path=P/'contract-order-remarks-cleaned-result.json'
remark_fixes={(x['table'],x['id']):x for x in json.loads(remark_fix_path.read_text(encoding='utf8'))['changes']} if remark_fix_path.exists() else {}
if date_fix_path.exists():
 date_result=json.loads(date_fix_path.read_text(encoding='utf8'))
 latest_backup=json.loads((P/date_result['backup']).read_text(encoding='utf8'))
 # Verify against customer state immediately before this authorized adjustment.
 b['tables']['crm_customer']=latest_backup['tables']['crm_customer']
c=pymysql.connect(host='36.213.150.237',port=10000,user='root',password=sys.stdin.readline().strip(),database='mom-hm',charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor)
with c.cursor() as q:
 data={}
 for t in b['tables']:
  q.execute('SELECT * FROM `'+t+'` WHERE deleted=0 ORDER BY id');data[t]={x['id']:x for x in q.fetchall()}
 receipt=data['mes_wm_misc_receipt'][r['receipt_id']];assert receipt['status']==4 and receipt['code']==r['receipt_code']
 expected_new={'mes_wm_misc_receipt':{r['receipt_id']},'mes_wm_misc_receipt_line':{a['receipt_line_id'] for a in r['allocations']},'mes_wm_product_sales_detail':{a['detail_id'] for a in r['allocations']},'mes_wm_stock_reserve':{a['reserve_id'] for a in r['allocations']},'mes_wm_transaction':{a[k] for a in r['allocations'] for k in ['in_transaction_id','out_transaction_id']},'mes_wm_material_stock':set(r['new_stock_ids']),'mes_wm_batch':set(r['new_batch_ids'])}
 for t,ids in expected_new.items():assert set(data[t])-{x['id'] for x in b['tables'][t]}==ids,(t,'Unexpected added rows')
 for old in b['tables']['mes_wm_material_stock']:
  actual=canon(data['mes_wm_material_stock'][old['id']]);diff={k for k in old if old[k]!=actual[k]};assert diff<={'updater','update_time'},(old['id'],diff)
 for id in r['new_stock_ids']:
  s=data['mes_wm_material_stock'][id];assert all(s[k]==0 for k in ['quantity','frozen_quantity','reserved_quantity','in_transit_quantity'])
 for a in r['allocations']:
  qty=D(a['quantity']);inc=data['mes_wm_transaction'][a['in_transaction_id']];out=data['mes_wm_transaction'][a['out_transaction_id']]
  assert inc['quantity']==qty and out['quantity']==-qty and inc['type']==1 and out['type']==2 and inc['biz_type']==115 and out['biz_type']==119
  for k in ['item_id','material_stock_id','batch_id','batch_code','warehouse_id','location_id','area_id']:assert inc[k]==out[k],(a['no'],k)
  assert inc['material_stock_id']==a['stock_id'] and inc['biz_id']==r['receipt_id'] and inc['biz_line_id']==a['receipt_line_id'] and out['biz_id']==a['sales_id'] and out['biz_line_id']==a['sales_line_id']
  reserve=data['mes_wm_stock_reserve'][a['reserve_id']];assert reserve['status']==3 and reserve['quantity']==qty and reserve['material_stock_id']==a['stock_id']
  detail=data['mes_wm_product_sales_detail'][a['detail_id']];assert detail['quantity']==qty and detail['material_stock_id']==a['stock_id']
  sl=data['mes_wm_product_sales_line'][a['sales_line_id']];nl=data['mes_wm_sales_notice_line'][a['notice_line_id']];ol=data['erp_sale_order_items'][a['order_item_id']]
  assert sl['quantity']==nl['out_count']==ol['out_count']==ol['count']==qty and sl['batch_id']==nl['batch_id']==a['batch_id']
  assert sl['material_stock_id']==a['stock_id'] and sl['quality_status'] is None and sl['oqc_id'] is None
 for o in r['orders']:
  erp=data['erp_sale_order'][o['order_id']];notice=data['mes_wm_sales_notice'][o['notice_id']];sales=data['mes_wm_product_sales'][o['sales_id']]
  assert erp['out_count']==erp['total_count'] and erp['out_status']==3 and notice['status']==4 and notice['out_status']==2 and sales['status']==4
  assert sales['carrier']==o['carrier'] and sales['shipping_number']==o['shipping_number'] and sales['client_id']==erp['customer_id']==o['customer_id']
  if (P/'shipping-remarks-cleared-result.json').exists():assert sales['remark'] is None and notice['remark'] is None
  else:assert ('模拟生成' in sales['remark']) if o['jd'] else ('青H' in sales['carrier'])
 assert len({o['shipping_number'] for o in r['orders']})==23
 affected_orders={o['order_id'] for o in r['orders']};affected_lines={a['order_item_id'] for a in r['allocations']}
 for t,rows in b['tables'].items():
  if t in ['erp_sale_order','erp_sale_order_items']:
   ids=affected_orders if t=='erp_sale_order' else affected_lines
   allowed={'out_count','updater','update_time'}|({'out_status'} if t=='erp_sale_order' else set())
   for old in rows:
    new=canon(data[t][old['id']]);diff={k for k in old if old[k]!=new[k]};allowed_row=allowed if old['id'] in ids else set()
    if (t,old['id']) in date_fixes:
     allowed_row=allowed_row|{'create_time','updater','update_time'}
     assert new['create_time']==date_fixes[(t,old['id'])]['create_time']
    if (t,old['id']) in remark_fixes:
     allowed_row|={'remark','updater'}
     assert new['remark']==remark_fixes[(t,old['id'])]['remark']
    assert diff<=allowed_row,(t,old['id'],diff)
  elif t.startswith('crm_') or t in ['mdm_item','mes_qc_oqc','mes_wm_warehouse','mes_wm_warehouse_location','mes_wm_warehouse_area']:
   fixes=name_fixes if t=='crm_contract' else quote_name_fixes if t=='crm_sale_quotation' else {}
   if fixes or any(k[0]==t for k in date_fixes) or any(k[0]==t for k in remark_fixes):
    for old in rows:
     new=canon(data[t][old['id']]);diff={k for k in old if old[k]!=new[k]}
     allowed_row={'name','updater','update_time'} if old['id'] in fixes else set()
     if (t,old['id']) in date_fixes:
      allowed_row|={'create_time','updater','update_time'}
      assert new['create_time']==date_fixes[(t,old['id'])]['create_time']
     if (t,old['id']) in remark_fixes:
      allowed_row|={'remark','updater'}
      assert new['remark']==remark_fixes[(t,old['id'])]['remark']
     assert diff<=allowed_row
     if old['id'] in fixes:assert new['name']==fixes[old['id']]['new_name']
   else:assert rows==canon(list(data[t].values())),('Protected table changed',t)
 for t in ['mes_wm_transaction','mes_wm_stock_reserve','mes_wm_product_sales_detail','mes_wm_batch','mes_wm_misc_receipt','mes_wm_misc_receipt_line','mes_wm_misc_receipt_detail']:
  for old in b['tables'][t]:assert old==canon(data[t][old['id']]),('Existing row changed',t,old['id'])
 negative=next(x for x in data['erp_sale_order'].values() if x['no']=='26000369');assert negative['out_count']==0
 summary={'passed':True,**r['counts'],'original_stock_rows_unchanged':len(b['tables']['mes_wm_material_stock']),'new_zero_stock_rows':len(r['new_stock_ids']),'stock_net_change':'0','financial_data_unchanged':True,'negative_order_not_shipped':'26000369','tracking_numbers':'模拟生成;自送保留青H前缀'}
 (P/'shipping-complete-verification.json').write_text(json.dumps(summary,ensure_ascii=False,indent=2),encoding='utf8')
 with (P/'九月销售出库发货核对清单.csv').open('w',encoding='utf-8-sig',newline='') as f:
  w=csv.writer(f);w.writerow(['销售订单号','客户','发货通知单号','出库单号','状态','承运商','运单或内部配送号','说明'])
  for o in r['orders']:w.writerow([o['no'],o['customer'],o['notice_code'],o['sales_code'],'已完成',o['carrier'],o['shipping_number'],'模拟运单,非真实物流凭证' if o['jd'] else '自有车辆;车牌前缀青H;编号为内部配送号'])
 print(json.dumps(summary,ensure_ascii=False))
c.close()