from audit import connect,dump,P
|
import json,sys,urllib.request
|
from decimal import Decimal as D
|
sys.stdout.reconfigure(encoding='utf-8')
|
r=json.loads((P/'result-applied.json').read_text(encoding='utf-8'));assert r['applied']
|
c=connect();checks=[]
|
try:
|
with c.cursor() as q:
|
for row in r['links']:
|
q.execute('select m.*,w.quantity wo_quantity,w.quantity_produced wo_produced,w.parent_id,w.status wo_status,w.quantity_scheduled,w.order_source_code,w.request_date wo_due,l.count sale_quantity,l.product_unit_id,l.mps_id from mes_pro_mps m join mes_pro_work_order w on w.id=m.work_order_id join erp_sale_order_items l on l.id=m.sale_order_item_id where m.id=%s and m.deleted=0',(row['mps_id'],));v=q.fetchone()
|
assert v['quantity']==v['wo_quantity']==v['sale_quantity']==D(str(row['quantity']))
|
assert v['quantity_produced']==v['wo_produced']==0 and v['parent_id']==0 and v['status']==v['wo_status']==1
|
assert v['mps_id']==v['id'] and v['sale_order_no']==v['order_source_code']==row['order_no']
|
assert v['unit_measure_id']==v['product_unit_id']==row['unit_id']
|
assert v['request_date']==v['wo_due'] and v['request_date'].weekday()<5
|
checks.append({'product':row['name'],'quantity':row['quantity'],'unit':row['unit'],'due':str(v['request_date']),'mps':row['mps_code'],'work_order':row['wo_code'],'scheduled_quantity':str(v['quantity_scheduled']),'bom_count':row['bom_count']})
|
total=D(0)
|
for g in r['groups'].values():
|
q.execute('select * from crm_contract where id=%s',(g['contract_id'],));contract=q.fetchone()
|
q.execute('select * from erp_sale_order where id=%s',(g['order_id'],));order=q.fetchone()
|
q.execute('select * from crm_sale_quotation where id=%s',(g['quotation_id'],));quote=q.fetchone()
|
q.execute('select * from crm_receivable_plan where id=%s',(g['receivable_plan_id'],));plan=q.fetchone()
|
amount=D(g['amount']);assert contract['total_price']==order['total_price']==quote['total_price']==plan['price']==amount
|
assert all(x['customer_id']==1613 for x in [contract,order,quote,plan])
|
assert quote['contract_id']==contract['id']==order['contract_id']==plan['contract_id']
|
assert contract['order_id']==order['id'] and order['out_count']==0 and order['production_status']==0
|
assert plan['return_time'].strftime('%Y-%m-%d')=='2026-11-30' and plan['receivable_id'] is None
|
for t,col in [('crm_sale_quotation_product','quotation_id'),('crm_contract_product','contract_id'),('erp_sale_order_items','order_id')]:
|
q.execute('select sum(total_price) amount from '+t+' where '+col+'=%s and deleted=0',({'quotation_id':quote['id'],'contract_id':contract['id'],'order_id':order['id']}[col],));assert q.fetchone()['amount']==amount
|
total+=amount
|
assert total==D('2062353.18')
|
for table,count in r['protected_counts'].items():q.execute('select count(*) n from `'+table+'`');assert q.fetchone()['n']==count
|
ids=r['counts']['mes_pro_task'];current=next(x for x in r['links'] if x.get('task_ids'))
|
q.execute('select * from mes_pro_task where work_order_id=%s and deleted=0 order by start_time',(current['wo_id'],));tasks=q.fetchall();assert len(tasks)==3
|
assert tasks[0]['status']==2 and tasks[0]['produced_quantity']==800 and all(x['produced_quantity']==0 for x in tasks[1:])
|
assert all(t['start_time'].weekday()<5 and t['end_time'].weekday()<5 for t in tasks)
|
assert all(tasks[i]['end_time']<=tasks[i+1]['start_time'] for i in range(len(tasks)-1))
|
q.execute('select sum(feedback_quantity) qty from mes_pro_feedback where work_order_id=%s and deleted=0',(current['wo_id'],));assert q.fetchone()['qty']==800
|
dump('verification.json',{'passed':True,'total':str(total),'plans':checks,'groups':4,'today_packaged':800,'finished_goods_produced':0,'no_actual_receipts_or_warehousing':True})
|
lines=['# 10月15日至月底生产及销售录入清单','','客户:总公司;合计:2,062,353.18元;4组销售单据,13项产品。','回款:11月30日一次月结,仅建立回款计划。','今天:蜜桃味营养素饮品包装部分完成800盒,尚未形成末道成品;其余12工单待排产,不提前报工。','','| 产品 | 数量 | 单位 | 计划开工 | 交期 | 工单 |','|---|---:|---|---|---|---|']
|
for row,check in zip(r['links'],checks):lines.append('|'+ '|'.join(map(str,[row['name'],row['quantity'],row['unit'],row['planned_start'][:10],check['due'][:10],row['wo_code']]))+'|')
|
lines+=['','以下产品现有BOM不完整,未套用其他规格或虚构投料:'+ '、'.join(row['name'] for row in r['links'] if not row['bom_count'])+'。','原表中的项目号、进度备注均保留在对应单据;168盒、90瓶、180瓶等小批量保持原数,没有为了凑数量上调。','价格按表列结算单价及金额执行,未额外假设税率或追加税款。','新增了表内原编码缺失的3款成品;规范了相关成品的包装单位和规格,历史单据数量金额未改动。','工作日校对参考:https://www.gov.cn/zhengce/content/202511/content_7047090.htm']
|
(P/'录入清单.md').write_text('\n'.join(lines)+'\n',encoding='utf-8')
|
finally:c.rollback();c.close()
|
api=[]
|
for path in ['/crm/contract/get?id='+str(g['contract_id']) for g in r['groups'].values()]+['/mes/pro/task/gantt-list?status=1&type=1']:
|
request=urllib.request.Request('http://127.0.0.1:48080/admin-api'+path,headers={'Authorization':'Bearer test1','tenant-id':'1'})
|
with urllib.request.urlopen(request,timeout=25) as response:result=json.load(response)
|
assert result['code']==0,(path,result)
|
if 'gantt-list' in path:
|
nodes=result['data'];all_ids={n['id'] for n in nodes};assert all(n.get('parent') in (None,'',0,'0') or n['parent'] in all_ids for n in nodes)
|
api.append({'path':path,'ok':True})
|
dump('api-verification.json',api)
|
print(json.dumps({'passed':True,'plans':13,'work_orders':13,'sales_chains':4,'amount':'2062353.18','today_partial_packaging':800,'api_checks':len(api)},ensure_ascii=False))
|