"""Presentation cleanup, preserving quality verification and inventory semantics.""" import sys,json,re from pathlib import Path from collections import defaultdict P=Path(__file__).parent sys.stdout.reconfigure(encoding='utf8') sys.path.insert(0,str(P.parent/'iqc-import-20261012/deps')) import pymysql assert not (P/'result.json').exists(),'Already applied; inspect before repeating.' demo='10月8日至14日业务链演示补充;非真实交易、投料、检验或物流凭证;沿用现有示意BOM及工艺主数据。' offset='九月历史销售流程补录;按用户要求等量补库存后出库,净库存不变;非真实采购或生产入库;汇总批次非真实生产批次;补录时间为本次执行时间。' batch='2026年9月库存台账期初汇总;按物料汇总跨原生产批次,非真实生产批次;不填生产日期、有效期和质检结果' def clean(t,text): if not text:return text s=text.replace(demo,'') s=s.replace('演示参数值;不是现场实测参数,原工艺限值未改动。','参数值待现场核验;工艺限值保持原要求。') s=s.replace('演示样例结果;不作为真实检测或放行依据。','检测结果待复核,不作为放行依据。') s=s.replace('按2026年9月产量表补充的工艺路线(示意BOM,实际配方以客户工艺文件为准)','实际配方以客户工艺文件为准。') s=s.replace(offset,'历史销售库存等量调整;补入后出库,净库存不变;使用库存汇总批次。') s=s.replace(batch,'期初汇总批次;跨生产批次汇总;生产日期、有效期及检验信息待补充') s=re.sub(r'^2026年9月台账Sheet1第\d+行,按结存覆盖;按原表库位分仓;INIT202609为期初汇总批次,不代表真实生产批次;+','期初结存;按库位分仓;期初汇总批次;',s) s=s.replace('按同编码包装成品/包材的计数单位1:1录入','同编码包装成品/包材按1:1计数') s=s.replace('同SKU完整销售包装计数按1:1补录','同SKU完整销售包装按1:1计数') s=s.replace('瓶/盒/个为原台账计数称谓','瓶/盒/个为同SKU销售包装计数') s=s.replace('不新增通用单位换算','仅适用于当前SKU包装') if t=='mes_qc_template_item': s=s.replace('来源:来料检验导入表;按物料编码/名称加规格及标准编号匹配。','物料与来料检验方案关联。') s=s.replace('来源:出货检验导入表;按检验单名称与方案名称模糊映射,多候选依用户要求随机选择并留档。','产品与出货检验方案关联。') if t=='mes_qc_template': s=s.replace('国标补充核对:','检验要求:').replace('暂缓检验单导入。','资料完善前暂缓检验。') s=s.replace('本仓默认库区,承接9月台账库存','本仓默认库区') if s==text:return text s=re.sub(r';{2,}',';',s).strip(' ;') return s or None c=pymysql.connect(host='36.213.150.237',port=10000,user='root',password=sys.stdin.readline().strip(),database='mom-hm',charset='utf8mb4',autocommit=False,cursorclass=pymysql.cursors.DictCursor) result={'counts':{},'changes':[]} try: with c.cursor() as q: q.execute("SET time_zone='+08:00'") q.execute('SELECT DATABASE() db,NOW() now,GET_LOCK(%s,10) locked',('operations-remarks-20261014',));state=q.fetchone();assert state['db']=='mom-hm' and state['locked']==1 q.execute("SELECT table_name FROM information_schema.columns WHERE table_schema=DATABASE() AND column_name='remark' AND (table_name LIKE 'mes_pro_%' OR table_name LIKE 'mes_qc_%' OR table_name LIKE 'mes_wm_%' OR table_name LIKE 'erp_stock_%' OR table_name IN ('erp_sale_out','erp_sale_out_items','erp_purchase_in','erp_purchase_in_items')) ORDER BY table_name");tabs=[x['TABLE_NAME'] for x in q.fetchall()] before={} for t in tabs: q.execute('SHOW COLUMNS FROM '+t);cols={x['Field'] for x in q.fetchall()} if not {'id','deleted','update_time','updater'}<=cols:continue q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id FOR UPDATE');before[t]=q.fetchall() q.execute('SELECT id,status FROM system_users WHERE id IN (244,289) AND deleted=0');actors={x['id']:x['status'] for x in q.fetchall()};assert actors=={244:0,289:0} backup=P/('locked-before-'+state['now'].strftime('%Y%m%d-%H%M%S')+'.json') backup.write_text(json.dumps({'state':state,'tables':before},ensure_ascii=False,default=str,indent=2),encoding='utf8') expected={} for t,rows in before.items(): grouped=defaultdict(list);actor='289' if t.startswith('mes_qc_') else '244' for old in rows: new=clean(t,old['remark']) if new==old['remark']:continue assert not any(w in (new or '') for w in ['非真实交易','业务链演示','示意BOM','演示参数值','演示样例结果','九月历史销售流程补录']) expected[(t,old['id'])]=new;result['changes'].append({'table':t,'id':old['id'],'old_remark':old['remark'],'remark':new});grouped[new].append(old['id']) result['counts'][t]=sum(len(ids) for ids in grouped.values()) for new,ids in grouped.items(): q.execute('UPDATE '+t+' SET remark=%s,updater=%s,update_time=update_time WHERE deleted=0 AND id IN ('+','.join(['%s']*len(ids))+')',[new,actor,*ids]);assert q.rowcount==len(ids) after={} for t,rows in before.items(): q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id');newrows=q.fetchall();after[t]=newrows;assert len(rows)==len(newrows) for old,new in zip(rows,newrows): assert old['id']==new['id'];key=(t,old['id']);diff={k for k in old if old[k]!=new[k]};assert diff<=({'remark','updater'} if key in expected else set()),(t,old['id'],diff) if key in expected:assert new['remark']==expected[key] assert '非真实交易' not in (new['remark'] or '') c.commit() for t,rows in after.items(): q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id');assert q.fetchall()==rows,('Post-commit mismatch',t) totals={'生产':sum(n for t,n in result['counts'].items() if t.startswith('mes_pro_')),'质量':sum(n for t,n in result['counts'].items() if t.startswith('mes_qc_')),'仓库':sum(n for t,n in result['counts'].items() if not t.startswith(('mes_pro_','mes_qc_')))} result.update(committed=True,verified=True,at=str(state['now']),module_totals=totals,total=len(result['changes']),backup=backup.name,quantities_results_states_relations_and_times_unchanged=True) (P/'result.json').write_text(json.dumps(result,ensure_ascii=False,indent=2),encoding='utf8') print(json.dumps({k:v for k,v in result.items() if k not in ['changes','counts']},ensure_ascii=False)) except Exception:c.rollback();raise finally: with c.cursor() as q:q.execute('SELECT RELEASE_LOCK(%s)',('operations-remarks-20261014',)) c.close()