import sys,json
|
from pathlib import Path
|
from read_links import P,connect,encode
|
def save(name,data):(P/name).write_text(encode(data),encoding='utf8')
|
def main():
|
assert not (P/'oqc-binding-result.json').exists(),'Already applied'
|
plan=json.loads((P/'oqc-binding-plan.json').read_text(encoding='utf8'))
|
c=connect(sys.stdin.readline().strip())
|
try:
|
with c.cursor() as q:
|
q.execute("SET time_zone='+08:00'");q.execute('SELECT DATABASE() db,NOW() now');state=q.fetchone();assert state['db']=='mom-hm'
|
q.execute("SELECT GET_LOCK('codex-customer-chain-repair-20261015',0) locked");assert q.fetchone()['locked']==1
|
q.execute('SELECT * FROM mes_qc_oqc WHERE deleted=0 ORDER BY id FOR UPDATE');before=q.fetchall()
|
backup='oqc-before-'+state['now'].strftime('%Y%m%d-%H%M%S')+'.json';save(backup,before)
|
current={r['id']:r for r in before};expected={id:dict(r) for id,r in current.items()}
|
q.execute('SELECT id,name FROM crm_customer WHERE deleted=0 FOR SHARE');customers={r['id']:r for r in q.fetchall()}
|
q.execute('SELECT id,no,customer_id,order_time FROM erp_sale_order WHERE deleted=0 FOR SHARE');orders={r['id']:r for r in q.fetchall()}
|
q.execute('SELECT id,order_id,product_id FROM erp_sale_order_items WHERE deleted=0 FOR SHARE');lines={r['id']:r for r in q.fetchall()}
|
for change in plan['changes']:
|
id=change['id'];assert encode(current[id])==encode(change['source_before']),f'QC changed: {id}'
|
assert change['after'] in customers and customers[change['after']]['name']==change['customer_name']
|
for e in change['evidence']:
|
if 'order_id' in e:
|
o=orders[e['order_id']];l=lines[e['line_id']]
|
assert o['customer_id']==change['after'] and o['no']==e['order_no'] and str(o['order_time'])==e['order_time']
|
assert l['order_id']==o['id'] and l['product_id']==e['product_id']
|
expected[id]['client_id']=change['after']
|
q.execute('UPDATE mes_qc_oqc SET client_id=%s,update_time=%s WHERE id=%s AND client_id IS NULL AND deleted=0',
|
(change['after'],current[id]['update_time'],id));assert q.rowcount==1
|
q.execute('SELECT * FROM mes_qc_oqc WHERE deleted=0 ORDER BY id');after={r['id']:r for r in q.fetchall()}
|
assert encode(after)==encode(expected),'Unexpected QC field change'
|
assert all(r['client_id'] in customers for r in after.values()),'Missing or invalid customer remains'
|
c.commit()
|
result=dict(plan['summary'],committed_at=str(state['now']),backup=str(P/backup),
|
changed_fields=['client_id'],unrelated_oqc_unchanged=len(before)-len(plan['changes']),
|
all_active_oqc_customer_valid=len(after),source_doc_links_unchanged=True,
|
qc_results_quantities_dates_statuses_unchanged=True)
|
save('oqc-binding-result.json',result);print(encode(result))
|
except BaseException:c.rollback();raise
|
finally:c.close()
|
|
def verify():
|
plan=json.loads((P/'oqc-binding-plan.json').read_text(encoding='utf8'))
|
result=json.loads((P/'oqc-binding-result.json').read_text(encoding='utf8'))
|
before=json.loads(Path(result['backup']).read_text(encoding='utf8'))
|
expected={r['id']:r for r in before}
|
for r in plan['changes']:expected[r['id']]['client_id']=r['after']
|
c=connect(sys.stdin.readline().strip())
|
try:
|
with c.cursor() as q:
|
q.execute("SET time_zone='+08:00'");q.execute('SELECT NOW() now');now=q.fetchone()['now']
|
q.execute('SELECT * FROM mes_qc_oqc WHERE deleted=0 ORDER BY id');after={r['id']:r for r in q.fetchall()}
|
assert encode(after)==encode(expected),'Unexpected field changes'
|
q.execute('SELECT id,name FROM crm_customer WHERE deleted=0');customers={r['id']:r for r in q.fetchall()}
|
assert all(r['client_id'] in customers for r in after.values())
|
for r in plan['changes']:assert after[r['id']]['client_id']==r['after'] and customers[r['after']]['name']==r['customer_name']
|
verified={'passed':True,'verified_at':str(now),'updated':len(plan['changes']),'all_active_oqc':len(after),
|
'missing_or_invalid_customers':0,'only_client_id_changed':True,'match_basis_retained':True}
|
save('oqc-binding-verification.json',verified);print(encode(verified))
|
finally:c.close()
|
if __name__=='__main__':verify() if '--verify' in sys.argv else main()
|