import sys,json
|
from pathlib import Path
|
from collections import defaultdict
|
sys.stdout.reconfigure(encoding='utf-8')
|
sys.path.insert(0,str(Path(__file__).parent/'iqc-import-20261012/deps'))
|
import pymysql
|
out=Path(__file__).parent/'schedule-diagnosis-20261015'
|
before=json.loads(sorted(out.glob('complete-route-before-*.json'))[-1].read_text(encoding='utf-8'))
|
data={}
|
with pymysql.connect(host='36.213.150.237',port=10000,user='root',password=sys.stdin.readline().strip(),database='mom-hm',charset='utf8mb4',connect_timeout=15,cursorclass=pymysql.cursors.DictCursor) as c:
|
with c.cursor() as q:
|
for t in before:
|
q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id');data[t]=q.fetchall()
|
q.execute('SELECT * FROM mes_pro_work_order_process WHERE deleted=0 ORDER BY id');data['mes_pro_work_order_process']=q.fetchall()
|
q.execute('SELECT id,status FROM mes_dv_machinery WHERE deleted=0');machines={m['id']:m['status'] for m in q.fetchall()}
|
q.execute('SELECT * FROM mes_pro_task WHERE deleted=0 AND status NOT IN (4,5)');active=q.fetchall()
|
q.execute('SELECT * FROM mes_md_workstation WHERE deleted=0 AND status=0');stations=q.fetchall()
|
q.execute('SELECT * FROM mes_md_workstation_machine WHERE deleted=0');links=q.fetchall()
|
normalize=lambda rows:json.loads(json.dumps(rows,default=str))
|
assert normalize(data['mes_pro_work_order'])==before['mes_pro_work_order'],'工单被改动'
|
for table,allowed in [('mes_pro_route',{'status','update_time'}),('mes_pro_route_process',{'output_item_id','update_time'})]:
|
now={r['id']:r for r in normalize(data[table])}
|
for row in before[table]:
|
unexpected={k:{'before':v,'after':now[row['id']].get(k)} for k,v in row.items() if k not in allowed and v!=now[row['id']].get(k)}
|
if unexpected:print(json.dumps({'concurrentChange':table,'id':row['id'],'fields':unexpected},ensure_ascii=False))
|
for table in ['mes_md_product_bom','mes_pro_route_product_bom']:
|
now={r['id']:r for r in normalize(data[table])}
|
assert all(now[r['id']]==r for r in before[table]),'原有BOM被改动'
|
assert all(r['status']==0 for r in data['mes_pro_route'])
|
alloc={(b['route_id'],b['product_id']) for b in data['mes_pro_route_product_bom']}
|
assert all((p['route_id'],p['item_id']) in alloc for p in data['mes_pro_route_product'])
|
station_machines=defaultdict(set)
|
for rel in links:station_machines[rel['workstation_id']].add(rel['machinery_id'])
|
occupied=set().union(*(station_machines[t['workstation_id']] for t in active)) if active else set()
|
station_available={s['id']:bool(station_machines[s['id']]) and all(machines.get(i)==1 or (machines.get(i)==2 and i in occupied) for i in station_machines[s['id']]) for s in stations}
|
order_checks=[]
|
for o in data['mes_pro_work_order']:
|
if o['status']!=1:continue
|
qps=[p for p in data['mes_pro_work_order_process'] if p['work_order_id']==o['id']]
|
blocked=[p['process_id'] for p in qps if not any(s['process_id']==p['process_id'] and station_available[s['id']] for s in stations)]
|
order_checks.append({'id':o['id'],'code':o['code'],'blockedEquipmentProcesses':blocked})
|
report={'allRoutesEnabled':len(data['mes_pro_route']),'boundProductsWithInput':len(data['mes_pro_route_product']),'explicitOutputProcesses':sum(bool(p['output_item_id']) for p in data['mes_pro_route_process']),'nativeDefaultOutputProcesses':sum(not p['output_item_id'] for p in data['mes_pro_route_process']),'existingBomAndWorkOrdersPreserved':True,'equipmentChecks':order_checks,'scope':'数据库读回及资源前置条件核验,未执行实际排产或线上HTTP预览'}
|
(out/'verification.json').write_text(json.dumps(report,ensure_ascii=False,indent=2),encoding='utf-8')
|
print(json.dumps(report,ensure_ascii=False))
|