import json,collections,xml.etree.ElementTree as ET,sys
|
from pathlib import Path
|
from decimal import Decimal
|
P=Path('scripts/quotation-import')
|
target=sys.argv[1] if len(sys.argv)>1 else 'local'
|
assert target in ['local','remote']
|
plan=json.loads((P/f'{target}-plan.json').read_text(encoding='utf-8'))
|
source=json.loads((P/'source.json').read_text(encoding='utf-8'))
|
r=ET.parse(P/f'{target}-post-snapshot.xml')
|
def records(tag):return [{e.tag:e.text or '' for e in x} for x in r.findall('./'+tag+'/row')]
|
customers={x['id']:x for x in records('customers')}
|
materials={x['id']:x for x in records('materials')}
|
units={x['id']:x for x in records('units')}
|
users={x['username']:x for x in records('users')}
|
owner=users['zhuli'];assert owner['nickname'].strip()=='朱莉' and owner['status']=='0'
|
headers={x['no']:x for x in records('quotations') if x['deleted']=='0'}
|
lines=collections.defaultdict(list)
|
for x in records('lines'):
|
if x['deleted']=='0':lines[x['quotation_id']].append(x)
|
permissions={(x['biz_type'],x['biz_id'],x['user_id'],x['level']) for x in records('permissions') if x['deleted']=='0'}
|
assert len(headers)==345 and sum(len(v) for v in lines.values())==1702
|
assert len({h['customer_id'] for h in headers.values()})==344
|
original={q['no']:q for q in source['quotes']}
|
total=Decimal(0)
|
for q in plan['quotes']:
|
h=headers[q['no']];s=original[q['no']]
|
assert h['owner_user_id']==owner['id'] and h['status']=='0'
|
assert customers[h['customer_id']]['name']==q['customer']
|
assert customers[h['customer_id']]['owner_user_id']==owner['id']
|
assert h['quotation_time']==q['quotation_time'] and h['valid_until']==q['valid_until']
|
assert Decimal(h['total_product_price'])==Decimal(q['total'])==Decimal(h['total_price'])
|
assert h['tax_rate']==h['tax_price']==''
|
assert Decimal(h['discount_percent'])==Decimal(h['discount_price'])==0
|
assert h['business_id']==h['contact_id']==''
|
assert h['remark']==q['remark']
|
assert ('9',h['id'],owner['id'],'1') in permissions
|
assert ('2',h['customer_id'],owner['id'],'1') in permissions
|
items={materials[x['item_id']]['code']:x for x in lines[h['id']]}
|
assert len(items)==len(q['items'])==len(s['items'])
|
for x,sx in zip(q['items'],s['items']):
|
d=items[x['item_code']]
|
assert d['item_unit_id']==str(x['item_unit_id'])
|
assert units[d['item_unit_id']]['name'].strip()==sx['unit']
|
assert d['remark']==x['remark'] and d['tax_percent']==d['tax_price']==''
|
for stored,field in [('item_price','original_price'),('quotation_price','price'),('count','count'),('total_price','total')]:
|
assert Decimal(d[stored])==Decimal(sx[field]),(q['no'],x['line'],stored)
|
total+=Decimal(h['total_price'])
|
assert total==Decimal('15392805.71')
|
for product in plan['new_products']:
|
matches=[m for m in materials.values() if m['code']==product['code']]
|
assert len(matches)==1 and matches[0]['specification']==product['specification'] and matches[0]['item_type']=='2'
|
assert source['excluded_sheets']==['报价单汇总总表','编制说明']
|
result=f'PASS {target}: 345 quotations, 1702 lines, 344 customers, total {total}; exact source prices/quantities/amounts, dates, units, owner zhuli, draft status and scoped ownership permissions verified. Summary excluded.\n'
|
(P/f'{target}-verification-result.txt').write_text(result,encoding='utf-8');print(result)
|