generate_s3_req_docx.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /**
  2. * Generate S3 供应协同业务需求描述.docx
  3. * 严格按照 S1 产销协同业务需求描述.docx 的格式:
  4. * 标题 → 文档信息 → 目录 → (一)模块功能说明+业务描述 → ...
  5. */
  6. const fs = require('fs');
  7. const {
  8. Document, Packer, Paragraph, TextRun, HeadingLevel,
  9. AlignmentType, PageBreak, TableOfContents, convertInchesToTwip,
  10. } = require('docx');
  11. const FONT = '微软雅黑';
  12. // ── 辅助函数 ──
  13. function empty() { return new Paragraph({ spacing: { after: 80 }, children: [] }); }
  14. function pageBreak() { return new Paragraph({ children: [new PageBreak()] }); }
  15. function normalPara(text, opts = {}) {
  16. return new Paragraph({
  17. children: [new TextRun({ text, size: 21, font: FONT, ...opts })],
  18. spacing: { after: 100, line: 360 },
  19. indent: opts.indent ? { left: convertInchesToTwip(opts.indent) } : undefined,
  20. });
  21. }
  22. // H2: (一) 物料需求计划
  23. function sectionHeading(text) {
  24. return new Paragraph({
  25. children: [new TextRun({ text, bold: true, size: 28, font: FONT })],
  26. heading: HeadingLevel.HEADING_2,
  27. spacing: { before: 400, after: 200 },
  28. });
  29. }
  30. // H3: 功能说明 / 业务描述
  31. function subHeading(text) {
  32. return new Paragraph({
  33. children: [new TextRun({ text, bold: true, size: 22, font: FONT })],
  34. heading: HeadingLevel.HEADING_3,
  35. spacing: { before: 200, after: 100 },
  36. });
  37. }
  38. // Title paragraph
  39. function titlePara(text) {
  40. return new Paragraph({
  41. children: [new TextRun({ text, bold: true, size: 36, font: FONT, color: '1F4E79' })],
  42. alignment: AlignmentType.CENTER,
  43. spacing: { after: 300 },
  44. });
  45. }
  46. function docInfoPara(text) {
  47. return new Paragraph({
  48. children: [new TextRun({ text, size: 21, font: FONT })],
  49. spacing: { after: 40 },
  50. bullet: { level: 0 },
  51. });
  52. }
  53. // ═══════════════════════════════════════════════════
  54. // 各模块业务需求描述数据
  55. // ═══════════════════════════════════════════════════
  56. const CN_NUM = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三'];
  57. const modules = [
  58. {
  59. title: '物料需求计划',
  60. funcDesc: [
  61. '物料需求计划模块实现物料需求的在线管理,通过MDP同步外部系统工单需求、库存和采购在途数据。',
  62. '利用MRP逻辑自动计算物料净需求(To-be-Scheduled Qty = MES Qty - Loc Qty - Scheduled Qty),生成可供发布的物料需求计划。',
  63. '支持勾选发布和全部发布两种模式,发布后数据驱动下游物料交货计划和物料采购申请。',
  64. '支持手动新增、编辑和删除物料需求记录,满足特殊场景下的灵活调整需求。',
  65. '数据通过MDP作业(S3_MDP_SYNC_TRANSFORM)从ERP定时同步,计算结果存入DWD宽表层供看板消费。',
  66. ],
  67. bizDesc: [
  68. '物料计划员登录DOP系统,进入"S3供应协同→物料需求计划"菜单,查看物料需求列表。',
  69. '系统自动展示MRP净需求计算结果:物料编码、物料名称、MES需求量、库存量、在途量和待排产净需求。',
  70. '通过物料编码、物料名称、需求日期等维度进行过滤查询,支持分页和列设置自定义显示字段。',
  71. '点击工具栏"勾选发布"按钮,将选中的物料需求计划行发布为"已发布"状态;也可点击"全部发布"一键发布所有未发布记录。',
  72. '已发布的计划可点击"取消发布"回退为未发布状态,重新参与后续计算和发布。',
  73. '对于特殊场景,可手动新增物料需求记录、编辑已有记录或删除记录(删除操作需二次确认)。',
  74. ],
  75. },
  76. {
  77. title: '物料交货计划',
  78. funcDesc: [
  79. '物料交货计划模块基于已发布的物料需求计划自动生成交货计划,并驱动供应商端交货计划同步。',
  80. '交货计划包含物料编码、供应商、计划交期等核心信息,作为供应商生产和交货的依据。',
  81. '供应商交货状态变更后自动回传至计划端,实现供应商与计划端的双向信息同步。',
  82. '每个交货计划行对应唯一的交货单号(dsnum),用于与供应商端交货单关联匹配。',
  83. ],
  84. bizDesc: [
  85. '物料计划员进入"S3供应协同→物料交货计划"菜单,查看基于已发布物料需求计划自动生成的交货计划列表。',
  86. '在列表中按物料编码、供应商、计划交期等条件筛选查询,查看各交货计划的执行情况。',
  87. '交货计划生成后自动同步至供应商端,驱动供应商按计划安排生产和交货。',
  88. '供应商交货状态变更时自动回传至计划端,交货计划列表实时反映最新的交货状态。',
  89. '物料计划员可根据交货状态跟踪结果,对未完成的交货计划进行催办和协调。',
  90. ],
  91. },
  92. {
  93. title: '交货单异常记录',
  94. funcDesc: [
  95. '交货单异常记录模块提供交货过程中产生的异常记录的只读查询视图,帮助物料计划员和质量管理人员快速掌握交货异常情况。',
  96. '系统自动比对交货计划与实际交货数据,逾期超过3个工作日或实收数量低于计划数量80%时自动标记为异常记录。',
  97. '异常数据来源于MDP同步的交货计划和实际交货数据自动比对结果,支持按交货单号、供应商、异常类型、日期范围等多维筛选。',
  98. '该页面为只读查询视图,不支持手动增删改操作,确保异常数据的客观性和可追溯性。',
  99. ],
  100. bizDesc: [
  101. '物料计划员进入"S3供应协同→交货单异常记录"菜单,查看系统自动识别的交货异常记录列表。',
  102. '通过交货单号、供应商名称、异常类型(逾期/短缺/质量)、计划日期范围等条件筛选查询。',
  103. '在列表中查看每条异常记录的基本信息:关联交货单、物料编码、计划数量、实际数量、异常原因。',
  104. '点击异常记录行查看明细信息,追溯异常来源和对生产计划的影响范围。',
  105. '支持将当前查询结果导出为CSV/Excel文件,用于离线分析和供应商绩效评估。',
  106. '质量管理员可通过该页面查看与质量相关的交货异常记录,进行质量追溯分析。',
  107. ],
  108. },
  109. {
  110. title: '要货令',
  111. funcDesc: [
  112. '要货令模块承接已批准物料采购申请驱动的要货指令(Demand Order)在线管理,作为采购执行的具体载体。',
  113. '业务流程为:物料采购申请驱动 → 要货令创建 → 供应选择 → 物料选择 → 订单保存。',
  114. '供应选择环节从货源清单动态加载下拉选择供应商和采购组,确保供应商资质合规。',
  115. '保存后生成DO类型采购订单记录(PurOrdMaster/DO),数据同步至ERP系统。',
  116. ],
  117. bizDesc: [
  118. '采购员进入"S3供应协同→要货令"菜单,接收已批准物料采购申请的驱动信号,启动要货令创建流程。',
  119. '在要货令表单中填写核心信息:单号、采购组、部门、日期、合同编号等。',
  120. '从货源清单动态加载下拉选择供应商和采购组,确保数据实时性和货源合规。',
  121. '选择要货物料,填写需求数量、交货日期等明细信息。',
  122. '确认无误后保存要货令,系统自动生成DO类型采购订单记录,数据同步至ERP。',
  123. '已保存的要货令可在列表中查看、编辑和删除;删除操作需二次确认。',
  124. ],
  125. },
  126. {
  127. title: '物料采购申请',
  128. funcDesc: [
  129. '物料采购申请模块承接物料交货计划和MRP检查输出的采购需求,通过规范的申请-审批流程确保采购需求的合理性和合规性。',
  130. '申请单提交后进入审批流,经指定审批人审核后状态更新为"已批准",审批过程可追溯、可审计。',
  131. '批准后系统根据物料类型自动合并生成对应订单:DO物料→要货令,PO物料→采购订单,PW物料→委外加工订单。',
  132. '已批准申请单不可编辑或删除,仅可查看,保护审批结果严肃性。',
  133. ],
  134. bizDesc: [
  135. '采购员进入"S3供应协同→物料采购申请"菜单,查看采购申请列表,支持按申请单号、物料、供应商、状态多维度筛选。',
  136. '基于物料交货计划或MRP检查结果点击"新增"按钮,填写申请单号、物料编码、供应商、需求数量、需求日期等必填字段。',
  137. '申请单保存后可提交审批,提交后进入审批流,状态变为"审核中"。',
  138. '审批人在审批列表中查看待审申请,执行"批准"或"驳回"操作;批准后状态更新为"已批准"。',
  139. '已批准的申请单由系统自动按物料类型合并生成对应订单:DO物料→要货令,PO物料→采购订单,PW物料→委外加工订单。',
  140. '已批准的申请单不可编辑或删除,仅可查看;未提交的申请可编辑或删除。',
  141. ],
  142. },
  143. {
  144. title: '物料采购订单',
  145. funcDesc: [
  146. '物料采购订单模块管理已下达至供应商的正式采购订单,跟踪订单从下达到收货完成的全生命周期。',
  147. '业务流程为:采购订单生成 → 供应商确认/交期回复 → 发货关联 → 订单状态跟踪 → 收货完成/订单关闭。',
  148. '供应商在线确认订单并回复预计交期,发货关联展示发货数量、日期与订单的对应关系。',
  149. '收货数据累计达订单数量时状态自动更新为"已完成",已完成订单可手动关闭。',
  150. ],
  151. bizDesc: [
  152. '采购员进入"S3供应协同→物料采购订单"菜单,查看采购订单列表,支持按订单号、供应商、物料、状态等条件筛选。',
  153. '基于已批准采购申请自动或手动生成采购订单,填写供应商、物料、数量、交期等核心信息。',
  154. '供应商在线确认订单并回复预计交期,确认信息回写至订单,采购员可在列表中查看交期回复状态。',
  155. '关联发货单数据,在发货关联视图中展示发货数量、日期与订单的对应关系。',
  156. '跟踪订单从"已下达→部分收货→已完成→已关闭"的完整生命周期状态。',
  157. '收货数据累计达订单数量时系统自动更新为"已完成";已完成或已取消的订单可手动关闭,关闭后不可再收货。',
  158. ],
  159. },
  160. {
  161. title: '委外加工订单',
  162. funcDesc: [
  163. '委外加工订单模块管理委托外部供应商进行物料加工的采购订单(PurOrdMaster/PW类型)。',
  164. '业务流程为:委外加工订单创建 → 委外商选择 → 货源清单物料选择 → 明细行管理 → 订单保存。',
  165. '委外商和物料选择均需校验货源清单有效性,确保委外业务物料选择合规。',
  166. '每个委外加工订单至少需包含一个明细行,不允许空订单;明细行支持增删改查操作。',
  167. ],
  168. bizDesc: [
  169. '外协管理员进入"S3供应协同→委外加工订单"菜单,查看委外加工订单列表。',
  170. '点击"新增"按钮创建委外加工订单,填写订单基本信息(订单号、委外商等)。',
  171. '从货源清单选择委外加工供应商,系统校验供应商在货源清单中存在且状态有效。',
  172. '从货源清单选择委外加工物料,管理每个明细行的物料、数量、单价、交货日期等。',
  173. '确认无误后保存订单,生成PW类型采购订单记录,数据同步至ERP并与生产工单关联。',
  174. '已保存的订单可在列表中查看、编辑和删除;支持通过子页面管理明细行的增删改查。',
  175. ],
  176. },
  177. {
  178. title: '工序外协订单',
  179. funcDesc: [
  180. '工序外协订单模块管理生产过程中特定工序委托外部供应商完成的采购订单。',
  181. '业务流程为:选择生产工单 → 选择外协工序 → 创建外协订单 → 供应商/数量校验 → 订单保存/工单工序关联。',
  182. '支持工单-工序-外协订单三级关联,同一工单同一工序不可重复创建外协订单,防止重复委外。',
  183. '外协数量不可超过工单该工序的计划生产数量,外协商必须在货源清单中有效。',
  184. ],
  185. bizDesc: [
  186. '外协管理员进入"S3供应协同→工序外协订单"菜单,查看工序外协订单列表。',
  187. '从生产工单列表选择需要外协的生产工单,系统展示该工单的基本信息。',
  188. '通过组件从工单中选择需要外协的工序,系统校验工序属于有效工单(状态不为已关闭或已取消)。',
  189. '基于选中的工单和工序创建外协订单,填写供应商、数量、交期等信息。',
  190. '系统校验外协商在货源清单中有效、外协数量不超过工序计划生产数量,同一工单同一工序不可重复创建。',
  191. '保存订单后自动与生产工单工序建立关联,工单状态联动更新。',
  192. ],
  193. },
  194. {
  195. title: '供应协同看板',
  196. funcDesc: [
  197. '供应协同看板为管理层和业务人员提供S3模块的核心KPI可视化监控面板。',
  198. '通过4个KPI卡片展示核心指标:物料计划周期、物料计划满足率、物料计划人效、物料库存周转天数。',
  199. '采用DynamicModuleDashboard动态看板组件(module-code="S3"),支持多维筛选联动和分支看板视图切换。',
  200. '分支一为MRP维度(BOM需求满足趋势+统计表),分支二为MDP维度(交货执行进度+满足率)。',
  201. '支持策略模拟What-If分析和运营指标建模配置,KPI数据通过MDP定时或手动刷新。',
  202. ],
  203. bizDesc: [
  204. '供应链经理进入"S3供应协同→供应协同看板"菜单,系统自动加载4个KPI指标卡片,直观展示当前供应协同健康度。',
  205. '通过基础查询条件(日期、产品、订单号、产线、物料、供应商)筛选,看板所有指标数据自动联动刷新。',
  206. '查看趋势箭头(上升绿色/下降红色),基于同比/环比计算,辅助管理层快速识别改善或恶化趋势。',
  207. '切换至分支一MRP维度看板,查看BOM需求满足趋势和统计表;切换至分支二维MDP看板,查看交货执行进度和满足率。',
  208. '点击"策略模拟"按钮进行What-If分析,模拟调整参数查看对KPI的影响;点击"导出"生成分析报告。',
  209. '点击"运营指标建模"链接跳转至指标配置页面,自定义KPI口径和计算规则。',
  210. ],
  211. },
  212. {
  213. title: '工单物料齐套上线看板',
  214. funcDesc: [
  215. '工单物料齐套上线看板以工单为维度,展示每个工单所需物料的齐套状态(需求、发料、欠料、备料、在检、在途、承诺数量)。',
  216. '数据来源于WorkOrdDetailTotalKB宽表,通过MRP计算工单物料齐套情况,展示30+字段完整齐套信息。',
  217. '帮助生产计划和物料计划人员精准识别缺料工单和责任供应商(供应商编码/名称/采购组/采购员)。',
  218. '支持列设置自定义显示/隐藏列、多字段排序和分页(10/20/50条每页),优化大数据量页面性能。',
  219. ],
  220. bizDesc: [
  221. '物料计划员进入"S3供应协同→工单物料齐套上线看板"菜单,查看工单物料齐套数据列表。',
  222. '通过订单号、工单号、产品编码、物料编码、供应商名称等条件筛选查询。',
  223. '在列表中查看30+字段的齐套信息:序号、订单/工单号、BOM版本、物料描述、需求数量、发料数量、欠料数量、备料数量、在检数量、在途数量等。',
  224. '欠料数量>0的物料行自动标记为"未齐套",通过供应商编码/名称/采购组/采购员快速定位责任供应商。',
  225. '点击"刷新"按钮调用refreshWorkOrderMaterialReadiness接口重新执行MRP齐套计算,获取最新数据。',
  226. '自定义显示/隐藏列配置和多字段升序/降序排序,满足不同角色的个性化视图需求。',
  227. ],
  228. },
  229. {
  230. title: 'MDP 运行监控',
  231. funcDesc: [
  232. 'MDP运行监控模块提供S3相关MDP数据同步与转换任务的运行状态可视化。',
  233. '展示S3模块相关的MDP同步任务列表:任务名称、运行状态(成功/失败/运行中)、开始/结束时间、处理记录数和错误信息。',
  234. '失败任务红色高亮标识和告警提示,帮助IT运维人员及时发现和定位数据同步失败、转换异常等问题。',
  235. '与平台级MDP监控形成"总-分"监控体系:S3页面聚焦本模块任务实例,平台级监控覆盖所有模块。',
  236. ],
  237. bizDesc: [
  238. 'IT运维人员进入"S3供应协同→MDP运行监控"菜单,查看S3模块相关的MDP同步任务列表。',
  239. '在列表中查看每个任务的运行状态:任务名称、最近一次执行状态(成功/失败/运行中)、开始时间、结束时间、处理记录数。',
  240. '按任务状态(全部/成功/失败/运行中)过滤查看,快速定位异常任务。',
  241. '失败任务以红色高亮标识,点击可查看错误信息详情,便于及时响应和修复。',
  242. '供应链经理和物料计划员也可通过该页面了解数据同步状态,确认数据时效性。',
  243. ],
  244. },
  245. {
  246. title: '数据中台架构',
  247. funcDesc: [
  248. 'S3供应协同模块采用Ai-DOP统一数据中台分层架构(STG→STD→DWD→KPI),确保前端页面、看板展示和KPI考核的数据口径一致。',
  249. '贴源层(STG/mdp_stg_*)保留源系统原始数据;标准层(STD/mdp_std_*)统一字段口径并清洗脏数据;宽表层(DWD/dwd_*)构建面向页面和KPI的主题事实表;指标层(KPI/ado_s9_kpi_value_*)按天存储L1-L4指标值。',
  250. 'MDP作业(S3_MDP_SYNC_TRANSFORM)负责全链路同步转换,支持手动触发和定时调度,作业日志可观测、异常可追溯。',
  251. '核心数据链路包括:物料需求/计划链路、采购订单/交货链路、齐套/看板链路。',
  252. ],
  253. bizDesc: [
  254. 'S3模块的业务数据通过MDP作业自动同步至数据中台各层,各页面统一消费DWD/KPI层数据。',
  255. '物料需求/计划链路:work_order_demand/inventory_snapshot/srm_in_transit → mdp_stg_demand贴源 → mdp_std_demand标准 → dwd_demand_schedule宽表 → KPI计算。',
  256. '采购订单/交货链路:PurOrdMaster/srm_polist_ds/vscm_jhjh → mdp_stg_po贴源 → mdp_std_po标准 → dwd_po_delivery宽表 → KPI计算。',
  257. '齐套/看板链路:WorkOrdDetailTotalKB/homeS3 → DWD直接消费 → 前端看板和KPI卡片 → ado_s9_kpi_value_*。',
  258. '各页面刷新按钮和计划联动手动触发可即时获取最新同步数据;系统管理员通过MDP监控页面查看作业执行状态和处理日志。',
  259. ],
  260. },
  261. {
  262. title: '权限管理汇总',
  263. funcDesc: [
  264. 'S3供应协同模块涉及以下核心角色和权限:',
  265. '物料计划员:查看和操作物料需求计划、交货计划;发布/取消发布;查看交货异常记录;刷新齐套看板。',
  266. '采购员:增删改查要货令、采购申请、采购订单;查看交货计划和交货异常记录。',
  267. '外协管理员:增删改查委外加工订单和工序外协订单。',
  268. '供应链经理:查看所有模块;查看供应协同看板和管理KPI;导出报表;策略模拟。',
  269. '审批人(采购经理):审核采购申请的审批流。',
  270. 'IT运维人员:查看MDP运行监控;监控同步任务状态。',
  271. '质量管理员:查看交货异常记录(质量追溯)。',
  272. '仓库管理员:查看采购订单和交货计划(安排收货)。',
  273. ],
  274. },
  275. ];
  276. // ═══════════════════════════════════════════════════
  277. // 生成文档
  278. // ═══════════════════════════════════════════════════
  279. function buildDocument() {
  280. const sections = [];
  281. // ── 封面/标题 ──
  282. sections.push(empty(), empty(), empty(), empty());
  283. sections.push(titlePara('供应协同业务需求描述'));
  284. sections.push(empty());
  285. // ── 文档信息 ──
  286. const infoItems = [
  287. '文档作者:彭熙玉',
  288. '创建日期:2026-06-10',
  289. '更新日期:2026-06-10',
  290. '文档编号:DOP-S3-REQ-001',
  291. '当前版本:V1.0',
  292. ];
  293. infoItems.forEach(item => sections.push(docInfoPara(item)));
  294. sections.push(empty(), empty());
  295. // ── 目录 ──
  296. sections.push(pageBreak());
  297. sections.push(new Paragraph({
  298. children: [new TextRun({ text: '目录', bold: true, size: 28, font: FONT })],
  299. heading: HeadingLevel.HEADING_2,
  300. spacing: { before: 200, after: 300 },
  301. }));
  302. sections.push(new TableOfContents('目录', {
  303. headingStyleRange: '2-3',
  304. hyperlink: true,
  305. }));
  306. sections.push(new Paragraph({
  307. children: [new TextRun({ text: '(如目录未显示,请在 Word 中右键此处 → 更新域)', size: 18, font: FONT, italics: true, color: '888888' })],
  308. spacing: { before: 40, after: 200 },
  309. }));
  310. // ── 各功能模块 ──
  311. for (let i = 0; i < modules.length; i++) {
  312. const mod = modules[i];
  313. sections.push(pageBreak());
  314. // 章节标题:(一) 物料需求计划
  315. sections.push(sectionHeading(`(${CN_NUM[i + 1]})${mod.title}`));
  316. // 功能说明
  317. sections.push(subHeading('功能说明'));
  318. (mod.funcDesc || []).forEach(desc => sections.push(normalPara(desc)));
  319. // 业务描述
  320. if (mod.bizDesc && mod.bizDesc.length) {
  321. sections.push(subHeading('业务描述'));
  322. mod.bizDesc.forEach(desc => sections.push(normalPara(desc)));
  323. }
  324. }
  325. return sections;
  326. }
  327. // ═══════════════════════════════════════════════════
  328. // 主流程
  329. // ═══════════════════════════════════════════════════
  330. async function main() {
  331. const sections = buildDocument();
  332. const doc = new Document({
  333. styles: { default: { document: { run: { font: FONT, size: 21 } } } },
  334. sections: [{
  335. properties: { page: { margin: { top: convertInchesToTwip(0.8), bottom: convertInchesToTwip(0.8), left: convertInchesToTwip(1.2), right: convertInchesToTwip(1.2) } } },
  336. children: sections,
  337. }],
  338. });
  339. const buffer = await Packer.toBuffer(doc);
  340. const outPath = 'd:\\DEMONET\\doc\\S3供应协同业务需求描述.docx';
  341. const fallbackPath = 'd:\\DEMONET\\doc\\S3供应协同业务需求描述_V2.docx';
  342. const tempPath = 'd:\\DEMONET\\doc\\S3_req_temp.docx';
  343. fs.writeFileSync(tempPath, buffer);
  344. try { fs.unlinkSync(outPath); } catch(e) {}
  345. try { fs.renameSync(tempPath, outPath); console.log(`Renamed to: ${outPath}`); }
  346. catch(e) {
  347. try { fs.unlinkSync(fallbackPath); } catch(_) {}
  348. try { fs.renameSync(tempPath, fallbackPath); console.log(`Fallback to: ${fallbackPath}`); }
  349. catch(e2) { console.log(`Generated: ${tempPath} (target locked)`); }
  350. }
  351. console.log(`Size: ${(buffer.length / 1024).toFixed(1)} KB`);
  352. }
  353. main().catch(err => { console.error('Error:', err); process.exit(1); });