_formalize_delivery_docs.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. # -*- coding: utf-8 -*-
  2. """正式交付稿:去掉临时/注释性文字,另存新版本。"""
  3. from __future__ import annotations
  4. import re
  5. import shutil
  6. import sys
  7. import tempfile
  8. from pathlib import Path
  9. from docx import Document
  10. HERE = Path(__file__).resolve().parent
  11. sys.path.insert(0, str(HERE))
  12. from _add_req_func_codes import set_paragraph_text # noqa: E402
  13. from _adjust_front_matter import remove_paragraph # noqa: E402
  14. from _unify_ab_delivery_vnext import ( # noqa: E402
  15. BASE,
  16. append_version_row,
  17. dest_name,
  18. ensure_version_page,
  19. find_p,
  20. iter_paras,
  21. open_via_temp,
  22. update_cover_version,
  23. version_table_after,
  24. )
  25. from _gen_delivery_sys_docs import ( # noqa: E402
  26. write_module_dds,
  27. write_module_um,
  28. write_sys_bbp,
  29. write_sys_brd,
  30. write_sys_dds,
  31. write_sys_um,
  32. )
  33. from _gen_s9_diag_impr_int_delivery import write_bbp, write_brd # noqa: E402
  34. from _gen_s9_modules_data import MODULES # noqa: E402
  35. NOTE_OLD = "统一系统名与版本记录"
  36. NOTE_NEW = "统一系统名称与文档版式,并修订范围与用词。"
  37. DROP_RE = re.compile(
  38. r"更新域|按 F9|按F9|如目录未显示|请在 Word 中右键|"
  39. r"不再使用|统一系统名与版本记录|"
  40. r"AidopDemoShell|AllowAnonymous|仅占位|规划占位|"
  41. r"本批禁用占位|写动作禁用占位|禁用占位|"
  42. r"占位与演示边界|演示基线|数据待接入|"
  43. r"实现现状(对照实际系统)|完成度:|"
  44. r"MVP 不得伪称|列为后续|缺口(|本轮不单独立册"
  45. )
  46. JOBS = [
  47. ("S0", "S0-运营建模-业务需求描述-V0.7.docx", "V0.7", "V0.8"),
  48. ("S0", "S0-运营建模-业务蓝图设计方案-V0.7.docx", "V0.7", "V0.8"),
  49. ("S0", "S0运营建模模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  50. ("S0", "S0-运营建模-用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  51. ("S1", "S1产销协同业务需求描述-V0.3.docx", "V0.3", "V0.4"),
  52. ("S1", "S1产销协同模块蓝图设计方案-V2.1.docx", "V2.1", "V2.2"),
  53. ("S1", "S1产销协同模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  54. ("S1", "S1产销协同模块用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  55. ("S2", "S2制造协同业务需求描述-V0.3.docx", "V0.3", "V0.4"),
  56. ("S2", "S2制造协同模块蓝图设计方案-V0.3.docx", "V0.3", "V0.4"),
  57. ("S2", "S2制造协同模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  58. ("S2", "S2制造协同模块用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  59. ("S3", "S3供应协同业务需求描述-V0.3.docx", "V0.3", "V0.4"),
  60. ("S3", "S3供应协同模块蓝图设计方案-V0.3.docx", "V0.3", "V0.4"),
  61. ("S3", "S3供应协同模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  62. ("S3", "S3供应协同模块用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  63. ("S4", "S4采购执行业务需求描述-V0.3.docx", "V0.3", "V0.4"),
  64. ("S4", "S4采购执行模块蓝图设计方案-V0.3.docx", "V0.3", "V0.4"),
  65. ("S4", "S4采购执行模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  66. ("S4", "S4采购执行模块用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  67. ("S5", "S5-物料仓储-业务需求描述-V1.1.docx", "V1.1", "V1.2"),
  68. ("S5", "S5-物料仓储-业务蓝图设计方案-V0.2.docx", "V0.2", "V0.3"),
  69. ("S5", "S5物料仓储模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  70. ("S5", "S5-物料仓储-用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  71. ("S6", "S6-生产执行-业务需求描述-V1.1.docx", "V1.1", "V1.2"),
  72. ("S6", "S6-生产执行-业务蓝图设计方案-V0.2.docx", "V0.2", "V0.3"),
  73. ("S6", "S6生产执行模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  74. ("S6", "S6-生产执行-用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  75. ("S7", "S7-成品仓储-业务需求描述-V1.1.docx", "V1.1", "V1.2"),
  76. ("S7", "S7-成品仓储-业务蓝图设计方案-V0.2.docx", "V0.2", "V0.3"),
  77. ("S7", "S7成品仓储模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  78. ("S7", "S7-成品仓储-用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  79. ("S8", "S8-异常监控-业务需求描述-V1.1.docx", "V1.1", "V1.2"),
  80. ("S8", "S8-异常监控-业务蓝图设计方案-V0.2.docx", "V0.2", "V0.3"),
  81. ("S8", "S8异常监控模块详细设计说明书-V1.1.docx", "V1.1", "V1.2"),
  82. ("S8", "S8-异常监控-用户操作手册-V1.1.docx", "V1.1", "V1.2"),
  83. ]
  84. def drop_or_rewrite(doc: Document) -> int:
  85. n = 0
  86. for p in list(doc.paragraphs):
  87. t = p.text.strip()
  88. if not t:
  89. continue
  90. if "临时加产" in t:
  91. continue
  92. if NOTE_OLD in t:
  93. set_paragraph_text(p, t.replace(t, NOTE_NEW) if t.startswith("统一系统名") else NOTE_NEW)
  94. n += 1
  95. continue
  96. if DROP_RE.search(t):
  97. remove_paragraph(p)
  98. n += 1
  99. for table in doc.tables:
  100. for row in table.rows:
  101. for cell in row.cells:
  102. for p in cell.paragraphs:
  103. raw = p.text
  104. if NOTE_OLD in raw or "不再使用「数据中台」" in raw:
  105. set_paragraph_text(p, NOTE_NEW)
  106. n += 1
  107. elif DROP_RE.search(raw) and "版本" not in raw[:6]:
  108. if raw.strip() in {"文档编号", "版本", "密级", "编制单位", "编制日期"}:
  109. continue
  110. if re.match(r"^V\d", raw.strip()):
  111. continue
  112. set_paragraph_text(p, NOTE_NEW if "变更" in "".join(c.text for c in row.cells) else "")
  113. n += 1
  114. return n
  115. def process_sxx(module: str, src_name: str, old_ver: str, new_ver: str) -> str:
  116. src = BASE / module / src_name
  117. if not src.exists():
  118. return f"MISSING {src}"
  119. dest = BASE / module / dest_name(src_name, new_ver)
  120. doc, _ = open_via_temp(src)
  121. n = drop_or_rewrite(doc)
  122. update_cover_version(doc, old_ver, new_ver)
  123. heading = find_p(doc, "版本记录")
  124. if heading is not None:
  125. tbl = version_table_after(heading)
  126. if tbl is not None:
  127. append_version_row(tbl, new_ver)
  128. for row in tbl.rows:
  129. for cell in row.cells:
  130. if NOTE_OLD in cell.text:
  131. set_paragraph_text(cell.paragraphs[0], NOTE_NEW)
  132. else:
  133. ensure_version_page(doc, old_ver, new_ver)
  134. else:
  135. ensure_version_page(doc, old_ver, new_ver)
  136. tmp = Path(tempfile.gettempdir()) / "aidop_unify_ab" / f"formal_{dest.stem[:40]}.docx"
  137. tmp.parent.mkdir(parents=True, exist_ok=True)
  138. doc.save(str(tmp))
  139. shutil.copy2(tmp, dest)
  140. return f"OK {dest.name} drop={n} {dest.stat().st_size // 1024}KB"
  141. def write_generated() -> list[str]:
  142. import _gen_delivery_sys_docs as sysgen
  143. msgs = []
  144. orig = sysgen.save_doc
  145. def save_ver(doc, dest):
  146. dest = Path(dest)
  147. orig(doc, dest.with_name(f"{dest.stem}-V0.4{dest.suffix}"))
  148. sysgen.save_doc = save_ver
  149. try:
  150. write_sys_brd()
  151. write_sys_bbp()
  152. write_sys_dds()
  153. write_sys_um()
  154. for key in ("运营诊断", "运营改善", "ChatBI", "系统集成"):
  155. write_module_dds(key, MODULES[key])
  156. write_module_um(key, MODULES[key])
  157. finally:
  158. sysgen.save_doc = orig
  159. msgs.append("SYS+DDS/UM V0.4 written")
  160. for key in ("S9", "运营诊断", "运营改善", "ChatBI", "系统集成"):
  161. mod = MODULES[key]
  162. folder = BASE / mod["folder"]
  163. write_brd(mod, folder / f"{Path(mod['brd_name']).stem}-V0.4.docx")
  164. write_bbp(mod, folder / f"{Path(mod['bbp_name']).stem}-V0.4.docx")
  165. msgs.append(f"{key} BRD/BBP V0.4")
  166. return msgs
  167. def main() -> None:
  168. lines = []
  169. for module, src_name, old_ver, new_ver in JOBS:
  170. print(f"formalize {module} {src_name}", flush=True)
  171. try:
  172. msg = process_sxx(module, src_name, old_ver, new_ver)
  173. except Exception as exc:
  174. msg = f"FAIL {module} {src_name}: {exc}"
  175. print(msg, flush=True)
  176. lines.append(msg)
  177. print("regenerate topic docs", flush=True)
  178. lines.extend(write_generated())
  179. print("\n".join(lines), flush=True)
  180. if __name__ == "__main__":
  181. main()