云
昨天 74b0d9c5ab1dc316b29f8525dcffe45225d4c43c
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
81
82
83
84
85
86
87
88
89
90
91
92
93
"""Production department schedule: 09:00-18:00, fixed weekends off, no holidays."""
import sys,json
from pathlib import Path
from datetime import date,datetime,time,timedelta
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 filled; verify rather than repeat.'
START=date(2026,9,1);END=date(2026,10,14)
holidays={date(2026,9,d):'中秋节' for d in range(25,28)}|{date(2026,10,d):'国庆节' for d in range(1,8)}
days=[START+timedelta(days=i) for i in range((END-START).days+1)]
workdays=[d for d in days if d.weekday()<5 and d not in holidays]
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={'plans':[],'members':[],'holiday_ids':[],'schedule_ids':[],'source':'https://www.beijing.gov.cn/cs/gncs/zcwj/202603/t20260327_4568275.html','fixed_weekends_off':True,'start':'2026-09-01','end':'2026-10-14','shift':'09:00–18:00'}
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',('production-schedule-20261014',));state=q.fetchone();assert state['db']=='mom-hm' and state['locked']==1;now=state['now'];assert now.date()>=END
  tabs=['mes_cal_plan','mes_cal_plan_shift','mes_cal_plan_team','mes_cal_team','mes_cal_team_member','mes_cal_team_shift','mes_cal_holiday','system_dept','system_users']
  before={};schema={}
  for t in tabs:
   q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id'+(' FOR UPDATE' if t.startswith('mes_cal_') else ''));before[t]=q.fetchall()
   q.execute('SHOW COLUMNS FROM '+t);schema[t]={x['Field'] for x in q.fetchall()}
  q.execute("SELECT * FROM system_dict_data WHERE dict_type='mes_cal_calendar_type' ORDER BY id FOR UPDATE");dicts=q.fetchall()
  backup={'state':state,'tables':before,'dicts':dicts}
  (P/'locked-before.json').write_text(json.dumps(backup,ensure_ascii=False,default=str,indent=2),encoding='utf8')
  production={d['id'] for d in before['system_dept'] if d['status']==0 and d['name'] in ['生产部','生产部门']};assert production
  while True:
   extended=production|{d['id'] for d in before['system_dept'] if d['status']==0 and d['parent_id'] in production}
   if extended==production:break
   production=extended
  users=[u for u in before['system_users'] if u['status']==0 and u['dept_id'] in production];assert users
  actor=next(u for u in users if u['id']==244)
  q.execute('SELECT COUNT(*) n FROM system_user_role WHERE user_id=244 AND role_id=166 AND deleted=0');assert q.fetchone()['n']>0
  def insert(t,v):
   v={**v,'creator':'244','updater':'244','create_time':now,'update_time':now,'deleted':0};assert set(v)<=schema[t],(t,set(v)-schema[t])
   q.execute('INSERT INTO '+t+' ('+','.join('`'+k+'`' for k in v)+') VALUES ('+','.join(['%s']*len(v))+')',list(v.values()));return q.lastrowid
  active=[d for d in dicts if d['deleted'] in (0,b'\x00') and d['status']==0]
  candidates=[d for d in active if d['label']=='生产']
  if candidates:calendar_type=int(candidates[0]['value']);result['new_calendar_type']=None
  else:
   calendar_type=max([int(d['value']) for d in dicts if str(d['value']).isdigit()] or [0])+1
   q.execute('INSERT INTO system_dict_data (sort,label,value,dict_type,status,color_type,remark,creator,updater,create_time,update_time,deleted) VALUES (%s,%s,%s,%s,0,%s,%s,%s,%s,%s,%s,0)',(calendar_type,'生产',str(calendar_type),'mes_cal_calendar_type','primary','生产部门白班排班','244','244',now,now));result['new_calendar_type']=q.lastrowid
  result['calendar_type']=calendar_type
  assert not any(t['code']=='SCBB-2026' for t in before['mes_cal_team']), 'Production team already exists; inspect before appending.'
  team=insert('mes_cal_team',{'code':'SCBB-2026','name':'生产白班组','calendar_type':calendar_type,'remark':'生产部门人员;09:00–18:00;固定双休,节假日休息'})
  result['team_id']=team;result['department_ids']=sorted(production)
  for u in users:
   id=insert('mes_cal_team_member',{'team_id':team,'user_id':u['id']});result['members'].append({'id':id,'user_id':u['id'],'name':u['nickname'],'dept_id':u['dept_id']})
  # Explicit holiday overrides ensure native confirm/generate also excludes them.
  holiday_dates={x['day'].date():x for x in before['mes_cal_holiday']}
  assert len(holiday_dates)==len(before['mes_cal_holiday']),'Duplicate existing holiday dates'
  for day,label in holidays.items():
   if day in holiday_dates:
    assert holiday_dates[day]['type']==2,('Conflicting holiday',str(day));id=holiday_dates[day]['id']
   else:id=insert('mes_cal_holiday',{'day':datetime.combine(day,time.min),'type':2,'remark':label})
   result['holiday_ids'].append(id)
  # Fixed weekends remain off even for the national adjusted working weekends.
  assert not any(h['type']==1 and START<=h['day'].date()<=END and h['day'].weekday()>=5 for h in before['mes_cal_holiday']), 'Existing weekend working overrides conflict with fixed weekends.'
  for month,start,end in [('202609',START,date(2026,9,30)),('202610',date(2026,10,1),END)]:
   code='SC-'+month
   assert not any(x['code']==code for x in before['mes_cal_plan']),('Plan already exists',code)
   pid=insert('mes_cal_plan',{'code':code,'name':'生产部门'+('9月' if month=='202609' else '10月1日至14日')+'排班','calendar_type':calendar_type,'start_date':datetime.combine(start,time.min),'end_date':datetime.combine(end,time.min),'shift_type':1,'shift_method':2,'shift_count':1,'status':0,'exclude_weekend':1,'remark':'09:00–18:00;固定双休,法定节假日不排班'})
   sid=insert('mes_cal_plan_shift',{'plan_id':pid,'sort':1,'name':'白班','start_time':'09:00','end_time':'18:00'})
   link=insert('mes_cal_plan_team',{'plan_id':pid,'team_id':team})
   dates=[d for d in workdays if start<=d<=end]
   for day in dates:
    id=insert('mes_cal_team_shift',{'plan_id':pid,'team_id':team,'shift_id':sid,'day':datetime.combine(day,time.min),'sort':1});result['schedule_ids'].append(id)
   q.execute('UPDATE mes_cal_plan SET status=1,updater=%s,update_time=%s WHERE id=%s',('244',now,pid));assert q.rowcount==1
   result['plans'].append({'id':pid,'code':code,'shift_id':sid,'plan_team_id':link,'days':[str(d) for d in dates]})
  # Check no prior business records or staff have been modified.
  for t,rows in before.items():
   q.execute('SELECT * FROM '+t+' WHERE deleted=0 ORDER BY id');after={x['id']:x for x in q.fetchall()}
   for old in rows:assert after[old['id']]==old,('Existing data changed',t,old['id'])
   if not t.startswith('mes_cal_'):assert len(after)==len(rows)
  assert len(workdays)==26 and len(result['schedule_ids'])==26 and len(users)==45
  c.commit()
  # Post-commit independent read of the generated relationships and all dates.
  q.execute('SELECT * FROM mes_cal_team_shift WHERE team_id=%s AND deleted=0 ORDER BY day',(team,));shifts=q.fetchall()
  assert [s['day'].date() for s in shifts]==workdays and len({s['day'] for s in shifts})==len(workdays)
  q.execute('SELECT * FROM mes_cal_team_member WHERE team_id=%s AND deleted=0',(team,));members=q.fetchall();assert {m['user_id'] for m in members}=={u['id'] for u in users} and len(members)==len(users)
  for p in result['plans']:
   q.execute('SELECT * FROM mes_cal_plan WHERE id=%s',(p['id'],));p_row=q.fetchone();assert p_row['status']==1 and p_row['exclude_weekend']==1
   q.execute('SELECT * FROM mes_cal_plan_shift WHERE id=%s',(p['shift_id'],));s_row=q.fetchone();assert s_row['start_time']=='09:00' and s_row['end_time']=='18:00'
   assert all(s['shift_id']==p['shift_id'] for s in shifts if s['plan_id']==p['id'])
  result.update(committed=True,verified=True,at=str(now),workdays=26,users=45,person_days=26*45,excluded_days=[str(d) for d in days if d not in workdays])
  (P/'result.json').write_text(json.dumps(result,ensure_ascii=False,default=str,indent=2),encoding='utf8')
  print(json.dumps({k:result[k] for k in ['committed','verified','at','start','end','shift','team_id','users','workdays','person_days','calendar_type']},ensure_ascii=False))
except Exception:c.rollback();raise
finally:
 with c.cursor() as q:q.execute('SELECT RELEASE_LOCK(%s)',('production-schedule-20261014',))
 c.close()