feat: add assessment workbench and September reconciliation
Preserve August hydrogen revision and September audit evidence; calculate interrupted vehicle history across all prior months. Record remaining carry-policy and layout-baseline discrepancies.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
p=Path(__file__).parent/'build_september.mjs'
|
||||
s=p.read_text()
|
||||
if "applyAugustLayout" in s: raise SystemExit('Already patched')
|
||||
shutil.copy2(p,p.with_suffix('.before-layout.txt'))
|
||||
shutil.copy2(p.parent/'里程任务考核_2026年9月_含缺口核算.xlsx',p.parent/'before-layout.xlsx.bak')
|
||||
s=s.replace("import path from 'node:path';", "import path from 'node:path';\nimport {applyAugustLayout} from './august_layout.mjs';")
|
||||
s=s.replace("const w=Workbook.create(),previews=[];", "const w=Workbook.create(),previews=[];\nconst meta=JSON.parse(await fs.readFile(path.join(dir,'../hydrogen-history-20260916/july_style_metadata.json'),'utf8'));\nconst department=p=>[...new Set(d.groups.filter(g=>g.sales===p).map(g=>g.department))].join('、');\nconst personalName=p=>(department(p).includes('、')?'跨部门':department(p).replace('业务',''))+'-'+p;")
|
||||
s=s.replace("s.showGridLines=false;", "s.showGridLines=true;")
|
||||
s=s.replace("color:'#172D3D'},columnWidth:16,rowHeight:22", "color:'#000000'},columnWidth:14,rowHeight:19")
|
||||
s=s.replace("font:{bold:true},wrapText:true,horizontalAlignment:'center',rowHeight:38", "font:{name:'宋体',size:11,bold:true,color:'#000000'},wrapText:true,horizontalAlignment:'center',rowHeight:34,borders:{preset:'all',style:'thin',color:'#000000'}")
|
||||
s=s.replace("function table(s,h,rs,ws={},nums=[]){head(s,1,h);", "function table(s,h,rs,ws={},nums=[]){s.getRange(`A1:${col(h.length)}${rs.length+1}`).format={font:{name:'宋体',size:11,color:'#000000'},rowHeight:19,verticalAlignment:'center',borders:{preset:'all',style:'thin',color:'#000000'}};head(s,1,h);")
|
||||
start=s.index('const sumSheet=sh(');end=s.index('const dr=d.daily.length',start)
|
||||
s=s[:start]+"""const mainRules=sh('考核奖励规则',6,70),monthly=sh('里程明细9月',24,d.records.length+1),calc=sh('9月计算过程',29,d.groups.length+1),track=sh('车辆考核追踪',44,d.groups.length+1),ledger=sh('9月奖金发放记录',18,d.ledger.length+6),oldSum=sh('9月汇总',3,250),sumSheet=sh('9月汇总(新版界面)',14,38);
|
||||
const personal={};for(const p of d.people)personal[p]=sh(personalName(p),14,d.groups.filter(x=>x.sales===p).length*10+20);
|
||||
const detail=sh('业务考核视图',31,d.records.length+1),daily=sh('逐日取数依据',16,d.daily.length+1),gap=sh('里程缺口',10,d.gaps.length+1),rules=sh('规则与名单',9,205),history=sh('历史结算资格',9,d.historical_months.length+1),aug=sh('8月已发台账',10,d.august_ledger.length+3);
|
||||
"""+s[end:]
|
||||
s=s.replace("${L('D')},\"${cat}\"", "${L('E')},\"${cat}\"")
|
||||
# Remove superseded reader layouts; the source calculation tables remain unchanged.
|
||||
start=s.index('table(ledger,');end=s.index('table(gap,',start);s=s[:start]+s[end:]
|
||||
start=s.index('widths(sumSheet,');end=s.index('w.recalculate();',start)
|
||||
s=s[:start]+"const layout=applyAugustLayout({w,d,meta,mainRules,monthly,oldSum,sumSheet,ledger,calc,track,personal,detail,previews,put,head,table,widths,col,pay,L,money});\n"+s[end:]
|
||||
s=s.replace("sumSheet.getRange('C4')", "sumSheet.getRange('J2')")
|
||||
s=s.replace("range:'9月汇总!A2:D6'", "range:'9月汇总(新版界面)!J1:N3'")
|
||||
s=s.replace("const errors=await w.inspect", "if(Math.abs(oldSum.getRange(layout.oldTotal).values[0][0]-d.summary.amount)>1e-7)throw Error('Vertical summary mismatch');\nfor(const [p,info] of Object.entries(layout.personControls)){const expected=d.ledger.filter(l=>l.sales===p).reduce((a,l)=>a+l.amount,0);if(Math.abs(w.worksheets.getItem(info.sheet).getRange(info.total).values[0][0]-expected)>1e-7)throw Error('Personal mismatch '+p);}\nawait fs.writeFile(path.join(dir,'layout_controls.json'),JSON.stringify(layout,null,2));\nconst errors=await w.inspect")
|
||||
p.write_text(s)
|
||||
Reference in New Issue
Block a user