gaoluyang
2 天以前 e71d71bf43c2307c89d3592adf08c1b32fcd0907
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
"""User-requested presentation cleanup of marketing remarks only.
Original source/provenance remains in the backup; no transaction is asserted real.
"""
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 the result before repeating.'
demo='10月8日至14日业务链演示补充;非真实交易、投料、检验或物流凭证;沿用现有示意BOM及工艺主数据。'
def clean(t,text):
 if not text:return text
 s=text.strip().replace(demo,'').strip()
 s=s.replace('约定回款日期与比例为演示计划;','')
 s=re.sub(r'^九月台账补录202609-L\d+,行\d+-\d+;原单[^。]+。含税合并金额[-\d.]+;净税额与合并金额尾差[-\d.]+元,按台账合并金额登记。','',s)
 s=re.sub(r'^九月台账202609-L\d+;','',s)
 if s.startswith('台账行') and t in ['crm_sale_quotation_product','erp_sale_order_items']:
  s=re.sub(r'^台账行\d+;原单[^;]+;原项目号[^;]+;原净额[-\d.]+,税[-\d.]+,含税[-\d.]+','',s)
 if t=='crm_customer':
  s=re.sub(r'^九月销售台账补录;来源客户号\d+;原备注:','',s)
  if s.startswith('由商机导入补建,来源:'):s=''
  if s=='来源:销售报价单_2026.8.1-10.11.xlsx;客户名称按明细表主体,不替换为门店':s=''
 if t=='crm_clue':s=re.sub(r'^来自销售收入台账渠道分类(([^)]+)),',r'渠道:\1;',s)
 s=s.replace('原票据未提供附件。','发票附件待补充。')
 s=s.replace('两张发票合并登记;只有合计金额,未分配单张金额,不代表单张发票。','两张发票合计登记,单张金额待核对。')
 s=s.replace('用户确认到账日期取开票日;无票电商取备注销售日。','')
 s=s.replace('暂无原票附件,按系统允许的未关联开票回款登记,合同已关联;到账方式保留原备注,未推断转账渠道。','已关联合同,暂未关联发票。')
 s=s.replace('原票号无需开票。','无需开票。').replace('原票号','发票号:')
 s=s.replace('日期按开票/销售日后30天补录测算,非约定账期;台账状态截至2026-09-29,实际到账另行核对。','计划日期待确认;实际到账情况待核对。')
 s=s.replace('只回了12600,剩余部分未回款','已回款12,600元,剩余5,400元待回款')
 s=s.replace('(青海南玻新能源科技有限公司0开','(青海南玻新能源科技有限公司)开')
 for old,new in [('开专票一张','开具增值税专用发票1张'),('开专票两张','开具增值税专用发票2张'),('开普票一张','开具普通发票1张'),('开普票两张','开具普通发票2张')]:s=s.replace(old,new)
 if s=='退货原单,负数量负金额保留':s='退货订单。'
 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',('marketing-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 'crm_%' OR table_name IN ('erp_sale_order','erp_sale_order_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','updater','update_time'}<=cols:continue
   q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id FOR UPDATE');before[t]=q.fetchall()
  q.execute('SELECT status FROM system_users WHERE id=291 AND deleted=0');assert q.fetchone()['status']==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)
   for old in rows:
    new=clean(t,old['remark'])
    if old['remark']==new:continue
    assert not any(w in (new or '') for w in ['非真实交易','业务链演示','示意BOM','九月台账','台账补录','由商机导入补建'])
    change={'table':t,'id':old['id'],'old_remark':old['remark'],'remark':new};result['changes'].append(change);expected[(t,old['id'])]=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,'291',*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)
  result.update(committed=True,verified=True,at=str(state['now']),total=len(result['changes']),backup=backup.name,amounts_relations_statuses_dates_and_nonremark_data_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!='changes'},ensure_ascii=False))
except Exception:c.rollback();raise
finally:
 with c.cursor() as q:q.execute('SELECT RELEASE_LOCK(%s)',('marketing-remarks-20261014',))
 c.close()