import sys,json from pathlib import Path from collections import Counter P=Path(__file__).parent sys.path.insert(0,str(P.parent/'iqc-import-20261012/deps')) import pymysql encode=lambda r:json.dumps(r,ensure_ascii=False,default=str,sort_keys=True) snapshot=json.loads((P/'before-mdm-material-logs.json').read_text(encoding='utf8')) c=pymysql.connect(host='36.213.150.237',port=10000,user='root',password=sys.stdin.readline().strip(),database='mom-hm',charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor,autocommit=False) changes=[] try: with c.cursor() as q: q.execute("SELECT GET_LOCK('codex-business-metadata-log-v1',0) locked");assert q.fetchone()['locked']==1 q.execute('SELECT NOW() now');now=q.fetchone()['now'] q.execute('SELECT u.id,u.nickname,r.id role_id FROM system_users u JOIN system_user_role ur ON ur.user_id=u.id JOIN system_role r ON r.id=ur.role_id WHERE u.id=244 AND u.deleted=0 AND u.status=0 AND ur.deleted=0 AND r.deleted=0 AND r.status=0 AND r.name=%s AND u.tenant_id=0 AND r.tenant_id=0 FOR SHARE',('生产管理员',)) member=q.fetchone();assert member is not None q.execute('SELECT id,nickname FROM system_users WHERE deleted=0');users={r['id']:r['nickname'].strip() for r in q.fetchall()} q.execute('SELECT * FROM system_operate_log ORDER BY id');before=q.fetchall() (P/'before-mdm-log-role-assignment-full.json').write_text(encode(before),encoding='utf8') q.execute('SELECT * FROM system_operate_log WHERE deleted=0 AND type=%s FOR UPDATE',('MDM 物料',)) targets=q.fetchall();expected={r['id']:r for r in snapshot['mdm_material_logs']} assert len(targets)==len(expected)==17 assert all(encode(r)==encode(expected[r['id']]) for r in targets) for log in targets: if log['user_id']==member['id']:continue assert log['tenant_id']==0 # Preserve the original request attribution explicitly, not merely in a local backup. evidence={'record_kind':'original_request_log_with_display_role_assignment', 'original_request_user_id':log['user_id'],'original_request_user_name':users.get(log['user_id'],str(log['user_id'])), 'original_action':log['action'],'original_extra':log['extra'], 'original_create_time':str(log['create_time']),'original_updater':log['updater'],'original_update_time':str(log['update_time']), 'role_assignment':{'role_id':member['role_id'],'role_name':'生产管理员','assigned_user_id':member['id'], 'assigned_user_name':member['nickname'].strip(),'assigned_at':str(now), 'basis':'用户指定日志显示归属;不替代原始请求账号证据'}} action=(f'【日志归属调整】按用户要求归属生产管理员:{member["nickname"].strip()}({member["id"]});' f'原始请求账号:{evidence["original_request_user_name"]}({log["user_id"]})。' f'归属调整时间:{now};原操作时间保留。原操作内容:{log["action"]}') assert len(action)<=2000 and len(encode(evidence))<=2000 q.execute('UPDATE system_operate_log SET user_id=%s,action=%s,extra=%s,updater=%s,update_time=%s WHERE id=%s AND type=%s', (member['id'],action,encode(evidence),'1',now,log['id'],'MDM 物料')) assert q.rowcount==1 changes.append({'id':log['id'],'before_user_id':log['user_id'],'after_user_id':member['id'], 'create_time':str(log['create_time']),'action':action,'extra':encode(evidence),'update_time':str(now)}) q.execute('SELECT * FROM system_operate_log ORDER BY id');after={r['id']:r for r in q.fetchall()} changed_ids={r['id'] for r in changes} assert all(encode(r)==encode(after[r['id']]) for r in before if r['id'] not in changed_ids) for old in targets: new=after[old['id']] assert new['user_id']==244 for field in ['create_time','request_method','request_url','user_ip','user_agent','success','sub_type','biz_id','creator','tenant_id']: assert new[field]==old[field] if old['id'] in changed_ids: evidence=json.loads(new['extra']);assert evidence['original_request_user_id']==old['user_id'] and evidence['original_action']==old['action'] c.commit() result={'matched_logs':len(targets),'updated_logs':len(changes),'already_assigned':len(targets)-len(changes), 'assigned_user_id':244,'assigned_user_name':member['nickname'].strip(),'role_id':member['role_id'], 'original_request_evidence_preserved':True,'original_operation_times_preserved':True, 'other_logs_unchanged':len(before)-len(changes),'assigned_at':str(now)} (P/'mdm-material-log-role-assignment-result.json').write_text(encode(result),encoding='utf8') (P/'mdm-material-log-role-assignment-changes.json').write_text(encode(changes),encoding='utf8') print(encode(result)) finally:c.close()