import json,xml.etree.ElementTree as ET,collections,re
|
from pathlib import Path
|
from decimal import Decimal,ROUND_HALF_UP
|
root=Path('scripts/stock-import-202609')
|
before=ET.parse(root/'remote-snapshot.xml').getroot()
|
after=ET.parse(root/'remote-post-snapshot.xml').getroot()
|
def rows(db,key):return [{c.tag:c.text or '' for c in r} for r in db.find(key)]
|
source=json.loads((root/'source.json').read_text(encoding='utf-8'),parse_float=Decimal)
|
ledger=next(s for s in source if s['sheet']=='Sheet1')['rows']
|
original={str(r[4]).strip():r for r in ledger if len(r)>20 and isinstance(r[4],(str,int)) and re.fullmatch('[A-Za-z0-9]+',str(r[4]).strip())}
|
assert len(original)==843
|
units={r['id']:r['name'].strip() for r in rows(after,'units')}
|
materials=collections.defaultdict(list)
|
for m in rows(after,'materials'):materials[m['code']].append(m)
|
warehouses={w['id']:w for w in rows(after,'warehouses')}
|
batches={b['id']:b for b in rows(after,'batches')}
|
stock=[s for s in rows(after,'stock') if s['creator']=='stock-import-202609']
|
assert len(stock)==855
|
assert len(rows(after,'warehouses'))==len(rows(before,'warehouses'))+9
|
oldmdm={m['id']:m for m in rows(before,'materials')}
|
newmdm={m['id']:m for m in rows(after,'materials')}
|
assert all(newmdm[k]==m for k,m in oldmdm.items()),'Existing material was modified'
|
assert len(newmdm)-len(oldmdm)==582
|
assert rows(before,'deletedMaterials')==rows(after,'deletedMaterials')
|
actual=collections.defaultdict(Decimal)
|
distribution=collections.Counter()
|
stockids=set()
|
for s in stock:
|
assert s['id'] not in stockids;stockids.add(s['id'])
|
m=newmdm[s['item_id']]
|
assert m['code'] in original
|
b=batches[s['batch_id']]
|
assert b['item_id']==s['item_id'] and b['code']=='INIT202609-'+m['code']==s['batch_code']
|
assert b['produce_date']==b['expire_date']==''
|
assert s['frozen']=='0' and Decimal(s['frozen_quantity'])==Decimal(s['reserved_quantity'])==Decimal(s['in_transit_quantity'])==0
|
assert Decimal(s['quantity'])>=0
|
actual[m['code']]+=Decimal(s['quantity'])
|
distribution[warehouses[s['warehouse_id']]['name']]+=1
|
assert s['location_id']==s['area_id']==s['vendor_id']==''
|
assert s['receipt_time']=='2026-09-30 23:59:59'
|
assert set(actual)==set(original)
|
for code,r in original.items():
|
assert len(materials[code])==1
|
m=materials[code][0];sourceunit=r[5];unit=units[m['unit_measure_id']]
|
if code=='81013938':sourceunit='克'
|
quantity=Decimal(r[20])
|
if sourceunit=='公斤' and unit=='克':quantity*=1000
|
elif sourceunit=='克' and unit=='公斤':quantity/=1000
|
elif sourceunit!=unit:assert sourceunit in ('盒','罐','袋','套','个') and unit in ('个','张')
|
assert actual[code]==quantity.quantize(Decimal('.000001'),rounding=ROUND_HALF_UP),(code,quantity,actual[code])
|
transactions=[t for t in rows(after,'transactions') if t['creator']=='stock-import-202609']
|
positive={s['id']:s for s in stock if Decimal(s['quantity'])>0}
|
assert len(transactions)==len(positive)==755
|
seen=set()
|
for t in transactions:
|
sid=t['material_stock_id'];assert sid not in seen;seen.add(sid)
|
s=positive[sid]
|
assert t['item_id']==s['item_id'] and t['batch_id']==s['batch_id'] and t['warehouse_id']==s['warehouse_id']
|
assert Decimal(t['quantity'])==Decimal(s['quantity']) and t['type']=='1' and t['biz_type']=='126'
|
assert seen==set(positive)
|
assert len(rows(after,'batches'))==843
|
text='线上36 mom-hm独立回读校验通过:843个台账物料、855条分仓库存、582个新物料、9个仓库、843个期初汇总批次、755条库存流水;100条零结存;原有物料和已删除记录未改动。\n'+json.dumps(dict(distribution),ensure_ascii=False)+'\n'
|
(root/'verification-result.txt').write_text(text,encoding='utf-8')
|
print(text)
|