from pathlib import Path
import json,re,math,unicodedata,html,csv,hashlib
import xlsxwriter,openpyxl
R=Path(__file__).resolve().parent
user=json.loads((R/'source/user-table.json').read_text())
products=json.loads((R/'source/vendor-products.json').read_text())
H=user['headers'];named=[x for x in user['rows'] if x['values'][0]]

STAGES=[
['S1','客户需求与项目条件采集','销售','售前＋客户业务负责人','客户需求、现场基础信息','填写原23列；确定三条业务线、规模与使用入口；空白/未勾选逐项解释','项目条件总览＋待确认清单','可出带假设的预算版；核心范围未定不能标正式报价'],
['S2','功能与设备配置','售前','产品＋硬件/采购＋客户','总览＋客户流程＋现场图','匹配标准功能；列设备型号、数量、配套、含软件和选配；差异转专项评估','功能设备清单＋标准/定制差异表','关键功能有满足依据；可选/替代项不累计；未知型号或数量列待确认'],
['S3','部署、支付与接口评估','技术负责人','售前＋客户IT/财务＋第三方','规模、部署方式、设备与业务范围','冻结服务器/数据库/网络；小程序、支付、接口各方提供与开发责任；评估数据导入','部署接口分工表＋工作量估算','关键网络/接口/许可/测试环境有负责人；风险未关闭仅条件报价'],
['S4','实施与服务范围确认','交付负责人','售前＋客户现场方＋采购','现场点位、设备、部署接口表','确定布线施工、运输楼层、安装培训、初始化、驻场跟餐、售后期限和排除项','实施服务清单＋客户配合条件','进场条件、服务次数/人天和验收方式明确；施工边界有确认依据'],
['S5','报价编制与内部审核','商务/销售','售前汇总；产品、技术、交付确认各自范围','已确认的配置、差异和服务表','按软件、硬件、开发对接、实施物流、年度/第三方五类报价；检查包内项防重复收费','报价明细＋范围附件，统一版本','价格、税费、付款、有效期按公司权限审核；技术不能代商务承诺'],
['S6','客户会签与交付交接','销售','售前＋客户决策/验收人＋交付负责人','报价与五表同版本','逐项确认包含/不包含、客户提供、未关闭条件及其影响；形成合同附件并交接','会签范围包＋交付交接记录','报价版本与附件一致；实际签署/批准前只称评审稿；变更经增补流程']
]
TABLES=[
['表1','项目条件总览','保留原23列，营养结算/食安/采购三条线分别填','增加项目编号、售前负责人、售前阶段、确认状态、报价版本、范围附件版本六个管理字段','销售采集，售前汇总','看项目卖什么、怎么部署、卡在哪里'],
['表2','功能与设备清单','按业务线→模块→设备/功能分层','型号/版本、品牌、数量单位、含软件、必选/可选/替代、能力证据、合同条目ID','产品与硬件确认，售前编制','把需要交付的东西逐项列清楚'],
['表3','部署及接口分工表','共用基础设施集中登记，三条线的独立要求单独列','提供方、实施方、费用承担方、前置材料、测试条件、确认人和完成标准','技术牵头，客户IT/财务及接口方确认','把系统跑起来所需条件和双方分工问清楚'],
['表4','报价与服务边界表','软件/硬件/开发对接/实施物流/年度及第三方五类','包内/另计、一次性/年度、服务地点次数、运输楼层、售后期、税费、排除项、报价条目ID','商务牵头，技术与交付确认范围','把实际金额与包含的服务对应起来'],
['表5','合同范围与验收表','逐项连接客户要求→配置→报价→交付→验收','交付物、验收场景与证据、客户配合、排除项、依赖、确认状态、变更版本','销售推进会签，交付和客户验收人确认','签约前说明做到什么程度、谁确认完成']
]
COMPARE=[
['营养结算','你的D–N列：规模、部署、域名、小程序、支付、对接','雄伟“智慧服务”按管理平台、卡务中心、自助称重/套餐、实施服务列项','保留你的条件采集；补标准软件模块、设备/餐盘/绑盘/结算配套、关键流程验收','智慧服务!C6:J35','表1＋表2＋表5'],
['智慧食安','你的O–R列：是否选购、视频网络、使用入口、设备/监管对接','雄伟按明厨亮灶、AI行为/客流、晨检、留样、检测、环境、数据大屏、机房配套展开','增加点位图、视频存储/带宽、算法授权、设备与平台对接、支撑设备与证据清单','智慧食安!C3:I34','表2＋表3'],
['智慧采购','你的S–V列：是否选购、供应商/餐厅端、对接、初始化','雄伟单列采购平台、收货秤、仓库看板、出库终端、打印机、盘点机和实施服务','补收货/出库/盘点/打印/仓库场景与设备数量，供应商端使用与菜品/库存初始化责任','智慧采购 !C3:J9','表2＋表3＋表4'],
['部署方式','你的H–J列及W备注覆盖本地、公有云、政务云和高可用','雄伟列本地服务器；另列“或：专业版阿里云服务”，按年计单位','配置备选方案应标互斥；按技术确认冻结环境、许可、性能和续费责任','智慧服务!C10:J11','表3＋表4'],
['软硬件绑定','你当前没有逐项设备型号/含软件的独立表','雄伟多台设备名称括号注明含专用软件','每台设备标软件、版本、授权期限及平台授权关系，报价检查重复收费','智慧服务!C18:C31；智慧采购 !C4:C8','表2＋表4'],
['实施与运输','你的表主要记录运行条件，尚未独立列服务范围','雄伟实施包含安装、调试、培训、跟餐、一年售后；不含强弱电施工；运送至指定楼层','借鉴包含/排除的表达，服务次数、驻场和期限由我方重新确认，不直接照搬一年','智慧服务!J33:J34；智慧采购 !J9','表4＋表5'],
['年度/第三方费用','你的M列写支付类型，但没有开通、授权及年度费用字段','雄伟聚合支付通道开通按年列项，说明含开通费和终端授权使用费','区分客户商户申请、支付接入、终端授权和持续费用，金额/承担方按实际确认','智慧服务!H35:J35','表3＋表4'],
['功能证据','你的表未单列技术参数、证书和功能满足证据','雄伟多处列CMA/CNAS评测、三级等保备案、CCC与节能证书要求','建立证据列；第三方要求不能当作我方持证或能力证明；不满足/待验证单独列','智慧服务!J7/J19/J25；智慧食安!I27/I29','表2＋表5'],
['报价完整性','你的表不承担金额计算，定位应保留','雄伟“智慧服务”“智慧采购”列有部分单价；“智慧食安”表头无单价，其他配套与服务价也存在空白','只能作为配置结构参考，不能推算整套总价；保留空白、备选与待确认关系','智慧服务!G6:G35；智慧采购 !G3:G9；智慧食安!G2:I2','表4']
]

FIELDS=[]
for i,name in enumerate(H):
 group='基本信息' if i<3 else ('营养结算' if i<14 else ('智慧食安' if i<18 else ('智慧采购' if i<22 else '特殊条件')))
 target='表1；详细责任进表3' if i in [7,8,9,11,12,13,15,17,20,21] else ('表1；配置进表2' if i in [3,6,14,18] else '表1')
 question={0:'客户项目名称与同一项目编号',1:'客户主体、使用者与验收方',2:'进场地点及物流/施工条件',3:'确认包含、不包含、待确认；未勾选不等于已排除',4:'区分在册人数、日均实际就餐及峰值',5:'记录同时就餐人数与集中时间窗口',6:'按食堂/餐线/档口列设备型号、数量、功能和点位',7:'部署拓扑、资源、系统/数据库、提供方及维护方',8:'区分内网入口、公网入口、小程序/API/支付外部依赖',9:'端口清单、申请方、依赖与开通时间；不在公开表写敏感配置',10:'我方小程序、客户独立小程序、H5/PC；对应使用功能与角色',11:'区分独立小程序备案、域名备案与复用我方已有入口的适用性',12:'商户主体、支付方式、收款/充值/退款及对账责任',13:'逐个系统列字段、协议、提供方、开发方、测试和验收',14:'确认包含、不包含、待确认',15:'摄像头点位、协议、视频存储、网络与平台部署资源',16:'学校/监管/移动/大屏是否在交付范围及访问路径',17:'设备型号数量、授权、第三方配合和外部监管字段',18:'确认包含、不包含、待确认',19:'供应商、餐厅、管理员使用入口与账号、网络条件',20:'供应商/财务/ERP接口及主数据口径、分工、测试条件',21:'初始菜品/食材/供应商/库存由谁提供、谁整理、谁导入、谁核对',22:'备注仅留摘要；关键约束分解进对应明细并指定确认人'}[i]
 FIELDS.append([f'F{i+1:02}',name,group,'保留原字段',question,target,f'售前.xlsx!{openpyxl.utils.get_column_letter(i+1)}2'])
EXTRA=[
('业务线及模块版本','选购/交付范围','标准模块、版本和权限/入口边界，未定不标标准满足','表2','产品'),
('设备型号数量及配套','硬件范围','型号、数量、单位、软件、辅材及选配/替代项','表2','硬件/采购'),
('关键功能能力证据','满足性','标准满足/需配置/需开发/第三方提供/不支持/待确认；附证据','表2','产品/技术'),
('部署资源与许可','技术条件','操作系统、数据库版本、许可证、资源和备份方案','表3','技术＋客户IT'),
('支付与接口分工','技术责任','对接清单、字段、样例、SDK、测试环境和双方开发边界','表3','技术＋客户/厂家'),
('现场施工和利旧','交付条件','勘察、点位图、强弱电、岛台、旧设备兼容与费用责任','表3/4','交付＋客户'),
('数据初始化与迁移','服务范围','哪些数据、数量/质量、整理导入和核对责任','表3/4','交付/技术＋客户'),
('实施培训及现场保障','服务范围','安装调试、培训角色场次、跟餐天数时段、物料与资料','表4','交付'),
('第三方及年度费用','持续费用','云/许可/支付/测评等、费用承担方与续费期限','表4','商务/采购'),
('包含与排除项','交付边界','各模块服务是否包内、另计、客户提供或不交付','表4/5','售前＋商务＋交付'),
('验收及交付周期','确认标准','场景/功能/数据验收、证据、验收人、依赖及里程碑','表5','交付/测试＋客户'),
('范围编号和确认状态','版本一致','项目与条目ID、报价/范围附件版本、负责人、确认人与变更记录','全部五表','售前＋销售')
]
FIELDS += [[f'G{i+1:02}',name,group,'补充到明细，避免主表横向膨胀',q,target,'方案建议；非源表既有字段'] for i,(name,group,q,target,owner) in enumerate(EXTRA)]

ISSUES=[
['三全集团智慧餐厅','范围与资源','采购已勾选，食安未勾选；备注写Food01资源/访问/验收待锁','明确Food01具体业务归属和采购实施范围；不要从节点名推定食安已选购','售前＋技术＋产品＋客户','Sheet1!D3:W3'],
['三全集团智慧餐厅','高可用与容量','部署为客户双机热备/集群，规模与点位空白，备注列多个角色节点','补日均/峰值、点位；明确资源提供、共享存储/任务防重/故障演练的验收责任','技术＋客户IT＋交付','Sheet1!E3:J3/W3'],
['四方达超硬材料','部署口径','H4本地单机；W4备注应用服务器与独立数据库服务器两台','把单应用节点与单物理服务器区分，技术确认后统一架构名称与数量','技术＋客户IT','Sheet1!H4/W4'],
['四方达超硬材料','业务与接口','日均3000；峰值/点位及小程序、支付、对接字段仍空白','先补峰值和设备数量，再确认页面入口、资金规则、接口字段与上线窗口','销售＋售前＋产品/技术','Sheet1!E4:N4/W4'],
['城市副中心','客户环境适配','多系统对接；域名待确认；备注有客户现有数据库/平台与56台人脸设备','为数据库、人脸平台和设备分开出适配范围、证据与对接责任；网络依赖单列','技术＋客户IT/安全','Sheet1!G5:N5/W5'],
['滨州健康科技职业学院','两条业务线入口','营养与采购已勾选；独立小程序备案待提交；供应商端也使用小程序','分开确认就餐者与供应商两个入口的申请、备案、网络、账号、费用责任','售前＋客户IT/商务','Sheet1!D6:V6/W6'],
['滨州健康科技职业学院','支付与多系统对接','N6多系统；备注有一卡通与访客微信充值不同链路','逐个列一卡通、财务/中台、硬件接口；资金、账号、数据和测试责任分别冻结','产品＋技术＋客户财务/IT','Sheet1!M6:N6/W6'],
['国康医院','备案适用性','使用我方小程序，但备案栏为材料待提交','区分复用我方小程序与客户域名/商户手续，确认实际需要的备案事项，不直接改源值','售前＋技术＋客户商户主体','Sheet1!I8:N8'],
['张家港市农商行项目','信创与对接边界','仅H5/PC、多系统、麒麟系统；设备描述有类别但无具体数量','逐系统列接口，补设备型号数量、麒麟版本/数据库/授权及兼容验证条件','技术＋硬件＋客户IT','Sheet1!G9:N9/W9'],
['中央美术学院','营养端使用入口','K10待确认，L10不涉及备案；营养结算、食安均已选','先确认营养端实际入口，再判断备案适用性；食安“不需要移动端”不代替营养入口结论','售前＋产品＋客户','Sheet1!D10:R10'],
['中央美术学院','两系统实施与验收','营养与食安均勾选；食安含明厨亮灶、摄像头，点位字段仅“20台”','分别列餐厅设备和摄像头型号数量，视频网络/存储、各系统培训与验收范围','售前＋交付＋技术','Sheet1!G10/R10/P10'],
['哈尔滨膳质舍连锁餐饮营养结算','SaaS与对接','公有云SaaS、我方域名/小程序、客户微信商户；对接为多系统','明确租户/食堂数量、设备点位、体检等对接项、商户责任、年度费用及服务期限','售前＋商务＋产品/技术','Sheet1!G11:N11'],
['安庆某部队','选购范围','三个业务线均未勾选，但填写人数、点位、本地服务器与H5/PC','先明确本期采购哪套系统及版本；保留“□”原值，标范围待确认，不视为已排除','销售＋售前＋客户','Sheet1!D13:V13'],
['全表','确认与交付边界','9项目都有不同程度的空白/待确认，3行项目名空白为模板行','空白标待补，不默认无需；每项记录确认人、资料与报价版本，模板行不计项目','售前＋销售','Sheet1!A3:W14']
]

QUOTE=[
['软件平台','营养结算/食安/采购选购模块、管理端/移动端/大屏、版本和授权范围','单独软件与设备内嵌软件区分；平台套件父子项不重复计费','一次性/年度按实际许可确认','表2能力/版本＋表1业务线','产品确认能力，商务确认金额'],
['硬件与配套','型号品牌、数量单位、餐盘/读卡器/打印机/网络存储与辅材','必选、可选、替代；型号/数量未定不作为已锁定采购清单','采购/租赁按方案确认','表2设备与点位','硬件/采购确认供货与证据'],
['开发与第三方对接','现有能力差异、支付/一卡通/监管/ERP/体检等接口','标准配置、我方定制、第三方提供、许可分别列；先确认合同内责任','专项开发/第三方授权','表2差异＋表3接口分工','技术评估，产品确认边界'],
['实施、物流与服务','安装调试、初始化、运输楼层、培训、跟餐、现场保障','写服务地点、次数/人天、交付资料、售后期和强弱电等排除项','一次性或明确服务周期','表3现场条件＋表4服务明细','交付评估投入，商务核价'],
['年度及持续费用','云资源、域名/证书、支付/算法/终端授权、维保等适用项','明确包内/另计、期限、续费方、停服条件；按实际范围确认','年度/周期；不混入一次性总价','表3提供方＋表4持续费用','商务/采购＋客户确认']
]

CONTRACT=[
['范围总表','哪三条业务线、哪些模块、入口/角色、数量与版本','表1/2/4一致；包含、不包含和可选项明确','销售推进；产品与客户会签'],
['配置与功能附件','设备型号、软件授权、功能满足依据和选配/替代项','客户要求→配置ID→报价ID→验收ID可逐项对应','产品/硬件确认'],
['部署接口与客户配合','资源、网络、域名、账号、接口资料、第三方配合、数据样本','谁提供、谁实施、何时到位；缺项及其工期/费用影响写清','技术＋客户IT/财务'],
['服务与排除项','安装、培训、初始化、跟餐、物流、施工、维保、续费','约定次数、地点、服务期；强弱电/岛台等是否包含逐项确认','交付＋商务＋客户'],
['验收与里程碑','每项交付物、验收场景、证据、责任人、时间与恢复要求','不能用设备到货替代全流程验收；依赖未完的项目列条件','交付/测试＋客户验收人'],
['变更与交接','新增要求、客户环境变更、额外服务、版本和批准记录','原范围明确后再判定包内/新增；合同内故障和保修不自动另收费','商务＋产品/技术＋交付']
]

md='''# 售前工作划分与合同范围方案 v0.1（评审稿）

建议采用“一份项目总览，四张明细，共同组成一套合同范围包”。保留你已有的23个字段和营养结算、智慧食安、智慧采购三条主线，补上配置、分工、服务、验收和确认状态，让信息采集、报价与交付使用同一套范围。

依据：本地《售前.xlsx》有23个字段、9个具名项目和3行空白项目模板。雄伟文件有6个子表，实际文本配置集中在智慧服务、智慧采购、智慧食安；抽取55个配置/服务行作为对照。它是配置方案样例，不能当作完整最终报价或我方能力证明。

## 保留什么，补什么

你的表已经把客户规模、部署、域名、网络和三条业务线的入口与对接分开，这是方案主线。主表保留23列，建议追加项目编号、负责人、阶段、确认状态、报价版本、范围附件版本6个管理字段；详细设备、接口和服务放子表。所有明细都带项目编号和名称；W列保留特殊情况摘要，关键约束拆成有负责人、有依据、有验收方式的明细。

雄伟可借鉴的是：按业务场景组织平台、设备和配套；设备名称注明包含软件；参数旁列证明要求；实施、运输、支付开通单列；把服务包含与排除项写出来。其实施说明包含安装、调试、培训、跟餐和一年售后，排除强弱电施工；本地服务器与云服务呈现备选关系，支付通道按年列项。

我方的型号、证书、服务期、价格和适配能力要另行确认。雄伟食安表没有单价列，其他表也有空价、父项/子项与备选关系，因此本方案不推算雄伟整套总价、不直接使用其单价。

## 五张工作表
'''
for t in TABLES:md+=f"\n### {t[0]}：{t[1]}\n\n{t[2]}。补齐：{t[3]}。{t[4]}。用途：{t[5]}。\n"
md+='\n## 六步工作分工\n\n|步骤|工作|主责角色|配合角色|必须交付|进入下一步的条件|\n|---|---|---|---|---|---|\n'
for s in STAGES:md+='|'+'|'.join([s[0],s[1],s[2],s[3],s[6],s[7]])+'|\n'
md+='''
销售对客户需求与商务推进负责；售前对资料齐套、版本一致、内部协作与方案汇总负责；产品确认功能和标准/定制边界；技术确认部署接口与兼容；交付确认现场、服务投入和验收；商务/采购确认价格、第三方费用及供货。每个项目由一个售前负责人汇总，不代表该角色替所有专业方做承诺。

## 报价五类与防重规则
'''
for q in QUOTE:md+=f"\n- **{q[0]}**：{q[1]}。{q[2]}；{q[3]}。\n"
md+='''
设备包含的软件不能又作为同一能力重复收取；平台与设备软件可以分别报价，但必须说明授权层级差异。单服务器/云、不同型号/不同套餐等替代关系先确认选型，不能全部加在一起。材料准备、网络开通和客户提供的资源应写成前置条件，不因列入售前清单就自动收款。合同内缺陷与保修不自动转为新增开发报价。

## 当前项目先处理哪些问题

'''
for x in ISSUES:md+=f"- **{x[0]}｜{x[1]}**：{x[2]}。建议：{x[3]}（来源：售前.xlsx {x[5]}）。\n"
md+='''
## 合同附件的建议组成

'''
for x in CONTRACT:md+=f"- **{x[0]}**：{x[1]}。确认标准：{x[2]}。\n"
md+='''
## 确认状态与报价门槛

原表勾选原样保留；后续建议为每条业务线增加“包含/不包含/待确认”状态，只有客户确认后的不包含才是排除。字段状态用“待客户提供/待我方评估/待第三方/已确认/不适用”，不适用要写原因。先做有条件预算时明确假设；正式报价前锁定范围、资源/接口责任、设备数量和服务边界；签约前再把客户配合、验收和排除项会签收口。价格与合同措辞由公司的商务/法务及客户审批，本方案未代替签约。

## 试行顺序（建议，未实施）

先选四方达（应用与数据库口径）、张家港（本地/信创/多系统）和滨州（双业务线/小程序/资金接口）三个项目各试填一次五表，再让专业负责人确认增补字段是否必要。其他六个具名项目按相同结构回填；3行空白模板不作为项目。试行看资料缺项、报价范围差异、售前到交付的补问事项，尚无节省工时或返工下降的实测结论。

## UC-PRESALES-001：采集到合同范围包

角色：销售发起、售前汇总、产品/技术/交付/商务确认、客户确认；触发为新报价或范围变更。主流程为6步分工。分支为标准配置、定制开发或第三方配合；资料缺失/语义冲突保留原值、列待确认，只能出显式假设的预算草案。验收为23源字段及9项目完整可追溯、所有报价与交付条目有范围和确认责任、未关闭项显式标注。测试为源文件哈希、源表逐字段回读、55对照项坐标验证、九项目覆盖与网页检查。页面/API/数据库及生产性能：[不适用：本次只交付管理方案，不开发或部署系统]。云效：[不适用：本次未要求创建开发需求/任务]。本次DoR：方案评审READY；正式制度/客户承诺待Jack及对应责任人审核。
'''
(R/'proposal.md').write_text(md)

P=R/'售前工作划分与合同范围方案_20261008_v01.xlsx'
w=xlsxwriter.Workbook(P,{'strings_to_formulas':False,'strings_to_urls':False})
f=w.add_format({'font_name':'微软雅黑','font_size':12,'valign':'top','text_wrap':True});hf=w.add_format({'font_name':'微软雅黑','font_size':12,'bold':True,'font_color':'FFFFFF','bg_color':'163B56','text_wrap':True,'valign':'vcenter'})
warn=w.add_format({'font_name':'微软雅黑','font_size':12,'bg_color':'FFF1CE','text_wrap':True});nf=w.add_format({'font_name':'微软雅黑','font_size':12,'num_format':'#,##0.00','valign':'top'})

def tab(name,headers,rows,widths={}):
 s=w.add_worksheet(name);s.hide_gridlines(2);s.freeze_panes(1,min(3,len(headers)));s.set_column(0,len(headers)-1,25,f);s.set_row(0,52)
 for c,width in widths.items():s.set_column(c,c,width,f)
 s.write_row(0,0,headers,hf)
 for i,row in enumerate(rows,1):
  for j,v in enumerate(row):
   if v is None:s.write_blank(i,j,None,f)
   elif isinstance(v,(int,float)):s.write_number(i,j,v,nf)
   else:s.write_string(i,j,str(v),f)
  lines=max(sum(max(1,math.ceil(sum(2 if unicodedata.east_asian_width(c) in 'WF' else 1 for c in line)/max(12,widths.get(j,25)-2))) for line in str(v or '').split('\n')) for j,v in enumerate(row))
  s.set_row(i,min(150,max(45,18*lines+8)))
 if rows:s.add_table(0,0,len(rows),len(headers)-1,{'columns':[{'header':t} for t in headers],'style':'Table Style Medium 2'})
 s.set_landscape();s.fit_to_pages(1,0);return s

over=w.add_worksheet('方案先看这里');over.hide_gridlines(2);over.set_column('A:A',4);over.set_column('B:H',20,f)
for rng,t,style in [
('B2:H3','售前工作划分与合同范围方案 v0.1',hf),
('B5:H7','主张：保留你的营养结算、智慧食安、智慧采购三条主线。原23列做项目总览，配四张明细，组成同版本合同范围包。',f),
('B9:H12','五表：项目条件总览 → 功能设备清单 → 部署接口分工 → 报价服务边界 → 合同范围验收。销售采集、售前汇总、专业负责人确认，最终由客户会签。',f),
('B14:H17','雄伟值得借鉴：按场景分层、设备注明含软件、配套与实施/运输/支付授权单列、包含与排除写清。原文件55个配置/服务行已对照。',f),
('B19:H22','本次是评审方案：原表9个具名项目、3行空白模板全部保留；各行原值不改。雄伟价格仅作源文件参考；食安表无单价，空价与备选关系不合计。',warn),
('B24:H27','优先看“售前工作分工”和“九项目待确认”。注意四方达单机/双服务器口径、安庆未勾选业务线、三全采购资源及边界、央美和国康入口/备案适用性。',warn),
('B29:H33','模板用于后续填写，不代表已获客户确认：设备数量/配置、价格、服务期限、技术适配、证书与合同承诺须对应负责人确认。不把客户配合条件或合同内故障自动作为新增收费。',f)]:over.merge_range(rng,t,style)
for i,name in enumerate(['原售前表23字段','售前工作分工','五表设计','字段保留与增强','雄伟结构对照','雄伟55配置行','九项目待确认','合同附件与验收','报价五类'],35):over.write_url(i,1,f"internal:'{name}'!A1",f,name)
original=tab('原售前表23字段',H,[x['values'] for x in user['rows']],{0:34,6:45,7:35,9:40,13:40,22:95})
original.write_comment(0,0,'原表A1说明：'+user['instruction'])
for issue in ISSUES:
 if issue[0]=='全表':continue
 idx=next((i for i,x in enumerate(user['rows'],1) if x['values'][0]==issue[0]),None)
 if idx:original.write_comment(idx,22,issue[3])
tab('售前工作分工',['阶段ID','工作阶段','主责角色','配合角色','输入','具体工作','必须产出','进入下一步条件'],STAGES,{1:34,3:50,5:85,6:65,7:85})
tab('五表设计',['表号','表名','保留/分层方式','明细要求','谁维护确认','用普通话说用途'],TABLES,{2:75,3:100,4:55,5:65})
tab('字段保留与增强',['字段ID','字段名','类别','处理建议','需要问清/冻结什么','落到哪张表','来源或建议属性'],FIELDS,{1:45,3:55,4:105,5:43,6:65})
tab('雄伟结构对照',['主题','你的表已覆盖','雄伟文件怎么组织','我方方案建议','来源坐标','建议落位'],COMPARE,{1:70,2:85,3:95,4:65})
vr=[]
for i,x in enumerate(products,1):
 state='原价空白/该表未列单价'
 if x['price'] is not None:state='原文件单价，仅参考，不作为我方报价'
 if x['row']==6 and x['sheet']=='智慧服务':state='父项价格；子项关系待确认，不能重复合计'
 option='配套可选' if '可选' in x['name'] else ('备选云服务，不与本地自动相加' if x['name'].startswith('或') else ('型号/数量/选择关系待项目确认'))
 vr.append([f'VX-{i:03}',x['sheet'],x['row'],x['name'],x['model'],x['brand'],x['price'],x['unit'],x['qty'],state,option,x['spec'],'含软件' if '含' in x['name'] else '包含关系需确认','对照文件描述，非我方已具备/认证'])
tab('雄伟55配置行',['参考ID','源子表','源行','设备/软件/服务名称','原型号','原品牌','原单价（元，仅参考）','原单位','原数量','价格边界','选择/配套关系','原功能参数/服务说明','软硬件关系','证据边界'],vr,{3:70,4:38,9:75,10:65,11:110,13:55})
tab('九项目待确认',['项目','主题','源表事实（摘要）','建议提前确认什么','建议确认角色','原表坐标'],ISSUES,{0:42,2:90,3:105,4:60,5:55})
tab('报价五类',['报价类别','应列内容','包含/排除及防重规则','计费周期判断','输入依据','专业与商务分工'],QUOTE,{1:95,2:100,3:60,4:60,5:65})
tab('合同附件与验收',['附件内容','写清什么','确认/验收标准','确认责任'],CONTRACT,{1:100,2:110,3:65})

# Ready-to-fill operational tables. Examples are not customer confirmations.
projectrows=[x['values']+['待指定','待指定','信息补齐','待确认','待生成','待生成'] for x in named]
tab('表1项目总览模板',H+['项目编号','售前负责人','售前阶段','确认状态','报价版本','范围附件版本'],projectrows,{0:36,6:45,7:35,22:95})
scopes=['营养结算','智慧食安','智慧采购']
rows2=[[f'CFG-{i+1:03}',line,'待客户确认','待匹配','待选型','待确认',None,'待确认','待确认','待确认','待确认','待验证','待关联'] for i,line in enumerate(scopes)]
s=tab('表2功能设备模板',['项目编号','项目名称','配置ID','业务线','客户要求','标准功能/软件版本','型号/品牌','设备/功能分类','数量','单位','含软件与授权期限','必选/可选/替代','能力状态','满足证据','合同/报价条目ID'],[['待指定','待填写']+x for x in rows2],{4:65,5:50,10:60,13:65})
s.data_validation(1,12,len(rows2),12,{'validate':'list','source':['标准满足','需配置','需开发','第三方提供','不支持','待确认']})
rows3=[[f'DEP-{i+1:03}',line,t,'待确认','待确认','待确认','待补','待确认','待确认','待确认','待关联'] for i,(line,t) in enumerate([('共用基础','服务器/操作系统/数据库/许可'),('共用基础','域名/证书/网络/端口'),('营养结算','小程序/商户/支付'),('营养结算','一卡通/其他系统对接'),('智慧食安','摄像头/视频/监管/设备接入'),('智慧采购','供应商端/ERP/基础数据初始化')])]
tab('表3部署接口模板',['项目编号','项目名称','依赖ID','业务线','事项','提供方','实施方','费用承担方','需提供的资料','前置时间/条件','测试/验收方式','确认状态与确认人','对应条目ID'],[['待指定','待填写']+x for x in rows3],{4:70,8:65,9:65,10:75})
rows4=[[f'Q-{i+1:03}',q[0],'待选条目','待确认',None,'待确认','待确认','待确认','待补','待补','待关联'] for i,q in enumerate(QUOTE)]
tab('表4报价服务模板',['项目编号','项目名称','报价ID','类别','报价项','配置/依赖ID','金额（元，待正式报价）','计费单位与周期','包含/另计/客户提供','服务次数/地点/期限','包含内容','排除与客户配合条件','合同/验收ID'],[['待指定','待填写']+x for x in rows4],{4:55,5:50,8:55,9:65,10:70,11:85})
rows5=[[f'AC-{i+1:03}',line,'待客户确认','待关联','待确定','待约定','待指定','待补','待明确','待明确','待确认','v0.1评审草案'] for i,line in enumerate(scopes)]
tab('表5合同验收模板',['项目编号','项目名称','验收ID','业务线','客户要求/范围项','配置/报价/依赖ID','交付物','验收场景与证据','客户验收人','客户配合条件','排除项','节点及未关闭依赖','确认状态','范围附件版本'],[['待指定','待填写']+x for x in rows5],{4:70,6:65,7:80,9:70,10:65,11:80})
w.close()

# pakco webpage scaffold and its token system; no remote fonts or runtime.
pak=Path('/Users/jack/code/099-github/pakco-html')
base=(pak/'assets/base.css').read_text();theme=(pak/'assets/themes/minimal-white.css').read_text()
css=base+'\n'+theme+'''\n:root{--accent:#ef7626;--text-1:#233342;--text-2:#536271;--bg:#f6f8fa;--surface:#fff;--border:#dde3e8}body{font-family:"PingFang SC","Microsoft YaHei",sans-serif}.page{max-width:1120px!important}.hero .h1{font-size:clamp(30px,4vw,48px)}.lede{font-size:18px}.card p{line-height:1.7}section{scroll-margin-top:30px}.scroll-table{overflow-x:auto;max-width:100%}table{border-collapse:collapse;min-width:650px;width:100%;font-size:14px}th,td{border-bottom:1px solid var(--border);padding:14px;text-align:left;vertical-align:top;line-height:1.65}th{background:#edf2f5}a{color:#b44e16}.warning{border-left:4px solid var(--accent);padding:20px;background:#fff5ec;margin:25px 0}details{border-bottom:1px solid var(--border);padding:18px 0}summary{cursor:pointer;font-weight:700}.nav{display:flex;gap:14px;flex-wrap:wrap;margin:25px 0}.pill{white-space:normal}.grid{min-width:0}@media(max-width:600px){.page{padding:24px 18px!important}.grid.g3{grid-template-columns:1fr!important}th,td{padding:10px}.lede{font-size:16px}}'''
def esc(s):return html.escape(str(s))
body='''<section class="hero"><p class="kicker">康比特数字体育科技 · 售前工作方案 · v0.1评审</p><h1 class="h1">把售前采集，变成<br>明确的合同交付范围</h1><p class="lede">保留23字段、三条业务线。用一份总览和四张明细，让销售、售前、产品、技术、交付、商务各自确认负责的范围。</p><nav class="nav"><a href="#tables">五张工作表</a><a href="#roles">六步分工</a><a href="#vendor">雄伟借鉴</a><a href="#projects">项目待确认</a><a href="#quote">报价与验收</a></nav><div class="warning">这是根据两份本地Excel形成的评审方案。价格、设备参数、资质和服务期须对应负责人确认；源表原值完整保留。</div></section>'''
body+='<section id="tables"><h2 class="h2">原表做总览，细节放明细</h2><div class="grid g3 mt-l">'
for t in TABLES:body+=f'<article class="card"><p class="kicker">{t[0]}</p><h3>{esc(t[1])}</h3><p>{esc(t[5])}</p><p class="dim">{esc(t[3])}</p><p>{esc(t[4])}</p></article>'
body+='</div></section><div class="section-break"></div><section id="roles"><h2 class="h2">六步分工：每一步都有明确产出</h2>'
for s in STAGES:body+=f'<details><summary>{s[0]} {esc(s[1])} · 主责：{esc(s[2])}</summary><p>配合：{esc(s[3])}</p><p>{esc(s[5])}</p><p><b>产出：</b>{esc(s[6])}</p><p><b>确认条件：</b>{esc(s[7])}</p></details>'
body+='</section><div class="section-break"></div><section id="vendor"><h2 class="h2">从雄伟文件借鉴什么</h2><div class="scroll-table"><table><thead><tr><th>主题</th><th>文件内容</th><th>我方方案建议</th></tr></thead><tbody>'
for c in COMPARE:body+=f'<tr><td>{esc(c[0])}</td><td>{esc(c[2])}<br><small>{esc(c[4])}</small></td><td>{esc(c[3])}</td></tr>'
body+='</tbody></table></div><div class="warning">实施服务包含/排除的写法值得采用；“一年售后”是雄伟文件描述，不能直接替我方承诺。食安表无单价，其他表有空价与备选关系，不合计整套价格。</div></section><div class="section-break"></div><section id="projects"><h2 class="h2">九个项目，先核对这些事项</h2>'
for x in ISSUES:body+=f'<details><summary>{esc(x[0])} · {esc(x[1])}</summary><p><b>源表：</b>{esc(x[2])}</p><p><b>建议确认：</b>{esc(x[3])}</p><p>确认角色：{esc(x[4])}。来源：{esc(x[5])}</p></details>'
body+='</section><div class="section-break"></div><section id="quote"><h2 class="h2">报价五类，合同六项</h2><div class="grid g3 mt-l">'
for q in QUOTE:body+=f'<article class="card"><h3>{esc(q[0])}</h3><p>{esc(q[1])}</p><p class="dim">{esc(q[2])}</p></article>'
body+='</div><h3 class="h3 mt-l">签约前的范围包</h3>'
for c in CONTRACT:body+=f'<p><b>{esc(c[0])}：</b>{esc(c[1])}。{esc(c[2])}。</p>'
body+='''<div class="warning">合同内缺陷与保修不自动另收费。客户应提供的网络、账号、接口等要列前置条件；新增要求先确认原范围，再评估价格和工期。</div><h3 class="h3">建议先试三个项目</h3><p>四方达校准服务器口径；张家港确认信创/设备/接口；滨州分清两条业务线的小程序、资金和对接。试填后再推广到其他项目，尚未实施或证明节省工时。</p></section><div class="page-footer"><p>2026-10-08 · 本地评审稿 · 来源：售前.xlsx、科技园智慧食堂（雄伟科技）.xlsx</p></div>'''
page=(pak/'templates/webpage.html').read_text()
page=re.sub(r'<title>.*?</title>','<title>售前工作划分与合同范围方案</title>',page,flags=re.S)
page=re.sub(r'<link[^>]*stylesheet[^>]*>','',page)
page=page.replace('</head>',f'<style>{css}</style></head>')
page=re.sub(r'<div class="page">[\s\S]*?</div>\s*</body>',f'<div class="page">{body}</div></body>',page)
(R/'proposal-review.html').write_text(page)
with (R/'source-index.csv').open('w',newline='') as f:
 out=csv.writer(f);out.writerow(['source','role','evidence_level','snapshot','boundary'])
 out.writerows([['售前.xlsx','主线及项目字段','A：用户本地文件','source/售前.xlsx','源值保留，客户确认状态需回读'],['科技园智慧食堂（雄伟科技）.xlsx','配置和服务表达参照','B：第三方文件描述','source/科技园智慧食堂（雄伟科技）.xlsx','价格不套用，能力/证书未经我方验证'],['前述工作日志','售前前置问题的背景参考','B：人员自述','原日志任务目录','本轮项目事实以售前表为准']])
(R/'README.md').write_text('# 售前工作划分与合同范围方案（评审稿）\n\n主方案：[proposal.md](proposal.md)；人审：[proposal-review.html](proposal-review.html)；可编辑Excel：售前工作划分与合同范围方案_20261008_v01.xlsx。\n\n原23字段、9项目和3空白模板行完整保留；四张明细补配置、责任、费用服务和验收。来源与边界见source-index.csv。原文件快照仅本地保留，source与Excel不进Git；未修改原件、在线表或客户承诺。\n')
print(json.dumps({'file':str(P),'user_fields':len(H),'named_projects':len(named),'vendor_items':len(products),'sheets':len(w.worksheets()),'stages':len(STAGES),'tables':len(TABLES),'project_review_rows':len(ISSUES)},ensure_ascii=False))
