import sys,json,csv
|
from collections import defaultdict
|
from read_links import P,connect,encode
|
from plan_links import build
|
BASE=['crm_customer','erp_sale_order','mes_pro_mps','mes_pro_work_order','mes_pro_task','mes_wm_batch']
|
def save(path,obj):path.write_text(encode(obj),encoding='utf8')
|
def main():
|
assert not (P/'result.json').exists(),'Already applied'
|
plan=json.loads((P/'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
|
before={}
|
targets={x['table'] for x in plan['changes']}
|
for table in BASE:
|
q.execute('SELECT * FROM `'+table+'` WHERE deleted=0 ORDER BY id'+(' FOR UPDATE' if table in targets else ' FOR SHARE'))
|
before[table]=q.fetchall()
|
backup=P/('locked-before-'+state['now'].strftime('%Y%m%d-%H%M%S')+'.json');save(backup,before)
|
original={t:{r['id']:r for r in rows} for t,rows in before.items()}
|
expected={t:{id:dict(r) for id,r in rows.items()} for t,rows in original.items()}
|
for change in plan['changes']:
|
table,id,field=change['table'],change['id'],change['field']
|
assert encode(original[table][id])==encode(change['source_before']),f'Source changed {table}/{id}'
|
assert change['after'] in original['crm_customer'] and change['before'] not in original['crm_customer']
|
expected[table][id][field]=change['after']
|
for change in plan['changes']:
|
for ev in change['evidence']:
|
assert expected[ev['table']][ev['id']][ev['field']]==change['after'],'Upstream customer changed'
|
for change in plan['changes']:
|
r=original[change['table']][change['id']]
|
q.execute('UPDATE `'+change['table']+'` SET `'+change['field']+'`=%s,update_time=%s WHERE id=%s AND deleted=0 AND `'+change['field']+'` <=> %s',
|
(change['after'],r['update_time'],change['id'],change['before']))
|
assert q.rowcount==1
|
for table in BASE:
|
q.execute('SELECT * FROM `'+table+'` WHERE deleted=0 ORDER BY id');after={r['id']:r for r in q.fetchall()}
|
assert encode(after)==encode(expected[table]),'Unexpected table/field change: '+table
|
c.commit()
|
result=dict(plan['summary'],committed_at=str(state['now']),backup=str(backup),changed_fields=['client_id'],
|
business_dates_status_quantities_amounts_preserved=True,customers_unchanged=True)
|
save(P/'result.json',result)
|
with (P/'客户关联修复清单.csv').open('w',encoding='utf-8-sig',newline='') as f:
|
w=csv.writer(f);w.writerow(['业务表','业务ID','客户ID','客户名称','关联依据'])
|
for r in plan['changes']:w.writerow([r['table'],r['id'],r['after'],r['customer_name'],encode(r['evidence'])])
|
save(P/'待确认出货检验单.json',plan['unresolved']);print(encode(result))
|
except BaseException:c.rollback();raise
|
finally:c.close()
|
if __name__=='__main__':main()
|