gaoluyang
14 小时以前 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
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))