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