云
12 小时以前 1f6a660180d4e6fccd1ec83a27b79ea93a121817
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
import sys,json,collections,copy
from pathlib import Path
from decimal import Decimal as D
sys.stdout.reconfigure(encoding='utf-8')
P=Path(__file__).parent;db=json.loads((P/'audit.json').read_text(encoding='utf8'));plan=json.loads((P/'plan.json').read_text(encoding='utf8'))
def active(t):return [x for x in db[t]['rows'] if x.get('deleted') not in (1,"b'\\x01'")]
inds={x['id']:x for x in plan['indicators']};details=collections.defaultdict(list)
for x in plan['details']:details[x['result_id']].append(x)
versions={(x['template_id'],x['version']):json.loads(x['schema_json']) for x in active('qc_report_template_version')}
new_schema=json.loads(json.dumps(versions[(14,'v1.1')],ensure_ascii=False).replace('item.standardValue','item.requirement').replace('标准值','标准要求'))
# Keep inspection names readable and reserve sufficient width for long SOP requirements on A4.
new_schema['grapes']['styles'].extend([
 {'selectors':['#ipnmhk'],'style':{'table-layout':'fixed','width':'100%'}},
 *[{'selectors':['#'+iid],'style':{'width':width}} for iid,width in zip(['iea1ya','iy2rxi','iqwrcq','itsffd','iwpsmz','i0sop1'],['6%','19%','40%','13%','11%','11%'])]
])
versions[(14,'v1.2')]=new_schema
(P/'report-template-upgrade.json').write_text(json.dumps({'template_id':14,'version':'v1.2','schema':new_schema,'source_version':'v1.1'},ensure_ascii=False,indent=2),encoding='utf8')
users=json.loads(Path('scripts/qc-complete-20261014/audit.json').read_text(encoding='utf8'))['users'];usernames={x['id']:x['nickname'].strip() for x in users}
unitnames={x['id']:x['name'] for x in active('mes_md_unit_measure')}
heads={k:{x['id']:x for x in active('mes_qc_'+k)} for k in ['iqc','ipqc','oqc','rqc']}
def plain(v):return format(D(v).normalize(),'f') if v is not None else ''
def requirement(line):
 low,high=line.get('min_threshold'),line.get('max_threshold')
 unit=line.get('_unit_name') or unitnames.get(line.get('unit_measure_id')) or inds[line['indicator_id']].get('unit_text') or ''
 if low is not None and high is not None:text='='+plain(low) if D(low)==D(high) else plain(low)+'~'+plain(high)
 elif low is not None:text='≥'+plain(low)
 elif high is not None:text='≤'+plain(high)
 else:
  m=line.get('check_method') or '';remark=line.get('remark') or ''
  return m[3:].split(';方法:')[0] if m.startswith('要求:') else remark if not remark.startswith('10月8日至14日业务链') else ''
 return text+(' '+unit if unit else '')
jobs=[];preserved=[]
for instance in active('qc_report_instance'):
 kind=instance['business_type'].replace('mes_qc_','');qid=int(instance['business_id']);head=heads[kind].get(qid)
 if not head:
  preserved.append({'id':instance['id'],'report_no':instance['report_no'],'reason':'来源单据已删除,保留原冻结报告,避免改写历史依据'});continue
 qc_type={'iqc':1,'ipqc':2,'oqc':3,'rqc':4}[kind]
 samples=[x for x in active('mes_qc_indicator_result') if x['qc_type']==qc_type and x['qc_id']==qid]
 lines=[x for x in plan['line_state'][kind] if x[kind+'_id']==qid]
 child=collections.defaultdict(list);own=collections.defaultdict(list)
 for line in lines:
  ind=inds[line['indicator_id']];parent=inds.get(ind['parent_id'])
  if parent and parent['item_type']==2:child[parent['id']].append(line)
  else:own[ind['id']].append(line)
 entries=[]
 for iid,ll in child.items():entries.append((inds[iid],own.pop(iid,[]),sorted(ll,key=lambda x:inds[x['indicator_id']]['sort_order'] or 999999)))
 for iid,ll in own.items():entries.append((inds[iid],ll,[]))
 entries.sort(key=lambda x:(x[0].get('sort_order') or 999999,x[0]['id']))
 items=[]
 def expand(ind,line):
  values=[d for sample in samples for d in details[sample['id']] if d['indicator_id']==ind['id']]
  if not values:values=[{'value':None,'remark':None}]
  output=[]
  for value in values:
   unit='' if ind['item_type']==2 else line.get('_unit_name') or unitnames.get(line.get('unit_measure_id')) or ind.get('unit_text') or ''
   remark=';'.join(x for x in [line.get('remark'),value.get('remark')] if x)
   output.append({'index':0,'itemCode':ind['code'],'itemName':ind['name'],'standardValue':plain(line.get('standard_value')),'actualValue':value['value'] or '','unit':unit,'requirement':requirement(line),'checkMethod':line.get('check_method') or '', 'group':{'childName':'','span':1,'hidden':''},'upperLimit':float(line['max_threshold']) if line.get('max_threshold') is not None else None,'lowerLimit':float(line['min_threshold']) if line.get('min_threshold') is not None else None,'result':'','resultText':'待判定','remark':remark})
  return output
 for ind,ownlines,children in entries:
  entry=[]
  for line in ownlines:entry.extend(expand(ind,line))
  if children and not entry:entry=expand(ind,{'indicator_id':ind['id']})
  anchors=len(entry)
  for line in children:
   leaf=inds[line['indicator_id']];rr=expand(leaf,line)
   for row in rr:row['group']['childName']=leaf['name']
   entry.extend(rr)
  for index,row in enumerate(entry):
   row['index']=len(items)+1;row['group']['span']=len(entry) if children and index==0 else 1;row['group']['hidden']='hidden' if children and index>0 else ''
   if index<anchors and ind.get('formula_text'):row['requirement']=ind['formula_text']
   items.append(row)
 snapshot=json.loads(instance['data_snapshot']);report=copy.deepcopy(snapshot['report']);report.update(reportNo=instance['report_no'],inspectDate=head['inspect_date'],inspector=usernames.get(head['inspector_user_id'],report.get('inspector','')),qcResult=str(head['check_result']),result='',resultText='待判定',conclusion='待判定',passRate='',total=len(items),passCount=0,failCount=0)
 version='v1.2' if instance['template_id']==14 and instance['template_version']=='v1.1' else instance['template_version']
 jobs.append({'id':instance['id'],'report_no':instance['report_no'],'template_version':version,'schema':versions[(instance['template_id'],version)],'snapshot':{'report':report,'inspectionItems':items}})
(P/'report-input.json').write_text(json.dumps(jobs,ensure_ascii=False,indent=2),encoding='utf8')
(P/'preserved-reports.json').write_text(json.dumps(preserved,ensure_ascii=False,indent=2),encoding='utf8')
print(json.dumps({'reports':len(jobs),'report_items':sum(len(x['snapshot']['inspectionItems']) for x in jobs)},ensure_ascii=False))