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()
|