398 lines
20 KiB
Python
398 lines
20 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""修改人:Ld 修改时间:2026-07-31 09:04:47; 生成库房管理实施后说明书与推进方案。"""
|
||
|
||
from docx import Document
|
||
from docx.enum.section import WD_SECTION_START
|
||
from docx.enum.table import WD_ALIGN_VERTICAL
|
||
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||
from docx.oxml import OxmlElement
|
||
from docx.oxml.ns import qn
|
||
from docx.shared import Cm, Pt, RGBColor
|
||
|
||
|
||
OUTPUT = r"D:\景耀\JY1.0\docs\库房管理\库房管理方案实施后说明书与推进方案.docx"
|
||
MODIFY_TIME = "2026-07-31 09:04:47"
|
||
|
||
|
||
def set_cell_shading(cell, fill):
|
||
tc_pr = cell._tc.get_or_add_tcPr()
|
||
shd = OxmlElement("w:shd")
|
||
shd.set(qn("w:fill"), fill)
|
||
tc_pr.append(shd)
|
||
|
||
|
||
def set_cell_width(cell, width_cm):
|
||
tc_pr = cell._tc.get_or_add_tcPr()
|
||
tc_w = OxmlElement("w:tcW")
|
||
tc_w.set(qn("w:w"), str(int(width_cm * 567)))
|
||
tc_w.set(qn("w:type"), "dxa")
|
||
tc_pr.append(tc_w)
|
||
|
||
|
||
def set_cell_text(cell, text, bold=False, color=None):
|
||
cell.text = ""
|
||
p = cell.paragraphs[0]
|
||
p.paragraph_format.space_after = Pt(0)
|
||
run = p.add_run(str(text))
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.size = Pt(9)
|
||
run.bold = bold
|
||
if color:
|
||
run.font.color.rgb = RGBColor.from_string(color)
|
||
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
||
|
||
|
||
def add_table(doc, headers, rows, widths=None):
|
||
table = doc.add_table(rows=1, cols=len(headers))
|
||
table.style = "Table Grid"
|
||
table.autofit = False
|
||
header_cells = table.rows[0].cells
|
||
for i, header in enumerate(headers):
|
||
set_cell_text(header_cells[i], header, bold=True, color="0B2545")
|
||
set_cell_shading(header_cells[i], "E8EEF5")
|
||
if widths:
|
||
set_cell_width(header_cells[i], widths[i])
|
||
for row in rows:
|
||
cells = table.add_row().cells
|
||
for i, value in enumerate(row):
|
||
set_cell_text(cells[i], value)
|
||
if widths:
|
||
set_cell_width(cells[i], widths[i])
|
||
doc.add_paragraph()
|
||
return table
|
||
|
||
|
||
def add_heading(doc, text, level=1):
|
||
p = doc.add_heading(text, level=level)
|
||
for run in p.runs:
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.color.rgb = RGBColor(46, 116, 181) if level <= 2 else RGBColor(31, 77, 120)
|
||
return p
|
||
|
||
|
||
def add_para(doc, text, bold_prefix=None):
|
||
p = doc.add_paragraph()
|
||
p.paragraph_format.space_after = Pt(6)
|
||
p.paragraph_format.line_spacing = 1.25
|
||
if bold_prefix and text.startswith(bold_prefix):
|
||
r1 = p.add_run(bold_prefix)
|
||
r1.bold = True
|
||
r1.font.name = "微软雅黑"
|
||
r1._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
r1.font.size = Pt(10.5)
|
||
text = text[len(bold_prefix):]
|
||
r = p.add_run(text)
|
||
r.font.name = "微软雅黑"
|
||
r._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
r.font.size = Pt(10.5)
|
||
return p
|
||
|
||
|
||
def add_bullets(doc, items):
|
||
for item in items:
|
||
p = doc.add_paragraph(style="List Bullet")
|
||
p.paragraph_format.space_after = Pt(4)
|
||
p.paragraph_format.line_spacing = 1.25
|
||
run = p.add_run(item)
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.size = Pt(10.5)
|
||
|
||
|
||
def add_numbered(doc, items):
|
||
for item in items:
|
||
p = doc.add_paragraph(style="List Number")
|
||
p.paragraph_format.space_after = Pt(4)
|
||
p.paragraph_format.line_spacing = 1.25
|
||
run = p.add_run(item)
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.size = Pt(10.5)
|
||
|
||
|
||
def build_doc():
|
||
doc = Document()
|
||
section = doc.sections[0]
|
||
section.top_margin = Cm(2.2)
|
||
section.bottom_margin = Cm(2.0)
|
||
section.left_margin = Cm(2.2)
|
||
section.right_margin = Cm(2.2)
|
||
section.header_distance = Cm(1.25)
|
||
section.footer_distance = Cm(1.25)
|
||
|
||
styles = doc.styles
|
||
normal = styles["Normal"]
|
||
normal.font.name = "微软雅黑"
|
||
normal._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
normal.font.size = Pt(10.5)
|
||
normal.paragraph_format.space_after = Pt(6)
|
||
normal.paragraph_format.line_spacing = 1.25
|
||
|
||
title = doc.add_paragraph()
|
||
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
run = title.add_run("库房管理方案实施后说明书与推进方案")
|
||
run.bold = True
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.size = Pt(20)
|
||
run.font.color.rgb = RGBColor(11, 37, 69)
|
||
|
||
sub = doc.add_paragraph()
|
||
sub.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||
run = sub.add_run("适用范围:JY1.0 测试库库房管理模块试运行、验收、推广")
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.size = Pt(10.5)
|
||
run.font.color.rgb = RGBColor(85, 85, 85)
|
||
|
||
add_table(
|
||
doc,
|
||
["项目", "内容"],
|
||
[
|
||
["当前环境", "测试库 ERPTOOL_JY_20250826Back;正式库 ERPTOOL_JY 未修改"],
|
||
["前端页面", "src/views/WarehouseManagement/WarehouseRoomManagement/index.vue"],
|
||
["菜单路径", "WarehouseManagement/WarehouseRoomManagement;菜单标题:库房管理"],
|
||
["实施原则", "新增隔离模块,复用原组件和稳定接口,不覆盖原仓储页面、原仓储管理过程"],
|
||
["文档日期", "2026-07-31"],
|
||
],
|
||
[3.0, 12.5],
|
||
)
|
||
|
||
add_heading(doc, "1. 实施后总体说明")
|
||
add_para(
|
||
doc,
|
||
"本说明书用于库房管理模块实施后的使用、验收和推广。当前方案已经在测试库完成隔离落地,核心目标是把“库房-库区-库位-物料-库存流水”业务链路先走通,再逐步接入入库、出库、盘点等生产业务。",
|
||
)
|
||
add_bullets(
|
||
doc,
|
||
[
|
||
"库房被定义为放置库位和物料的区域,库位是具体存放位置。",
|
||
"库位归属按已有库位编码规则自动识别,不强制重建原库位数据。",
|
||
"三楼仓库提供可点击可视化布局,按 8 排、每排 24 列、3 层展示。",
|
||
"物料库位查询复用原稳定接口,并在新页面内补充库房归属,避免影响原物料库位功能。",
|
||
"所有落地对象均先在测试库验证,正式库上线前必须完成数据核对和用户验收。",
|
||
]
|
||
)
|
||
|
||
add_heading(doc, "2. 已实施内容")
|
||
add_heading(doc, "2.1 数据库对象", 2)
|
||
add_table(
|
||
doc,
|
||
["类别", "对象", "实施说明"],
|
||
[
|
||
["新表", "库房管理_库房主文件", "保存库房编号、名称、类型、地址、状态、排数、列数、层数等信息。"],
|
||
["新表", "库房管理_库区主文件", "保存库房下的库区信息,与库房主文件建立外键关系。"],
|
||
["新表", "库房管理_业务记录", "保存库房相关业务记录,为后续出入库、盘点、移库追溯预留。"],
|
||
["完善表", "库存管理_货位主文件", "补充库房流水号、库区流水号、排号、列号、层号、库位状态、库位容量、是否启用、修改人、修改时间。"],
|
||
["索引", "库房库区排列层索引", "支持按库房、库区、排、列、层快速查询可视化库位。"],
|
||
["同步过程", "库房管理_库位编码归属_同步", "按库位编码规则把原货位归属同步到二楼隔层、立库、三楼仓库。"],
|
||
],
|
||
[2.0, 4.3, 9.2],
|
||
)
|
||
|
||
add_heading(doc, "2.2 已建立过程与接口策略", 2)
|
||
add_table(
|
||
doc,
|
||
["过程/接口", "用途", "当前策略"],
|
||
[
|
||
["库房管理_库房_查询/保存/停用", "库房主数据维护", "测试库新增,前端库房管理页签调用。"],
|
||
["库房管理_库区_查询/保存", "库房下库区维护", "测试库新增,前端库区/库位页签调用。"],
|
||
["库房管理_库位_查询/保存", "库位列表维护和按布局建库位", "测试库新增,复用原货位表并补充库房字段。"],
|
||
["库房管理_可视化库位_查询", "三楼仓库可视化布局", "默认三楼仓库,未建库位按 x-xx-xx-xx 生成预览编码。"],
|
||
["仓储管理_物料库位_查询数据", "物料综合/正向/逆向查询", "复用原稳定接口,新页面内按编码规则补充库房归属。"],
|
||
["库房管理_库存流水_查询", "出入库/盘点流水查询", "测试库新增,用于后续业务记录和追溯。"],
|
||
],
|
||
[4.3, 5.3, 5.9],
|
||
)
|
||
|
||
add_heading(doc, "2.3 前端页面功能", 2)
|
||
add_table(
|
||
doc,
|
||
["页签", "主要功能", "当前用途"],
|
||
[
|
||
["库房管理", "查询、新增、编辑、停用库房;查看库区数、库位数、有库存库位数。", "维护库房基础资料,作为库区和库位的上级。"],
|
||
["库区/库位", "按库房、库区、库位名称、状态查询;新增/编辑库区和库位。", "完成库房对应库位维护。"],
|
||
["三楼仓库可视化", "按层展示 8 排 x 24 列库位;点击库位查看状态或建库位。", "对照现场三楼仓库布局进行可视化操作。"],
|
||
["物料综合查询", "综合、正向、逆向查询;支持全部库房或指定库房过滤。", "查询物料在哪些库位、某库位有哪些物料。"],
|
||
["出入库/盘点流水", "按关键字、日期、库房查询业务流水。", "为后续出入库、盘点闭环提供追溯入口。"],
|
||
],
|
||
[3.0, 6.8, 5.7],
|
||
)
|
||
|
||
add_heading(doc, "3. 库房与库位编码规则")
|
||
add_table(
|
||
doc,
|
||
["库房", "库位编码格式", "示例", "系统处理"],
|
||
[
|
||
["二楼隔层仓库", "字母数字-数字", "A1-1、K2-18", "归属到二楼隔层库区,不参与三楼可视化网格。"],
|
||
["立库仓库", "xx-xx-xx", "01-01-01、06-07-03", "归属到立库库区,可用于立库查询统计。"],
|
||
["三楼仓库", "x-xx-xx-xx", "1-01-01-01", "参与三楼可视化布局,排、列、层按编码识别。"],
|
||
["未归类库位", "不符合以上规则", "A000、耗材、毛坯库", "在物料综合查询中标识为未归类,后续由仓库确认是否纳入库房体系。"],
|
||
],
|
||
[3.2, 3.6, 3.0, 5.7],
|
||
)
|
||
|
||
add_heading(doc, "4. 实施后业务操作说明")
|
||
add_heading(doc, "4.1 建库房与建库位", 2)
|
||
add_numbered(
|
||
doc,
|
||
[
|
||
"进入“库房管理”页签,先维护库房编号、库房名称、库房类型、排数、每排列数、层数和状态。",
|
||
"进入“库区/库位”页签,选择库房后维护库区,再维护具体库位。",
|
||
"三楼仓库可进入“三楼仓库可视化”页签,点击未建库位,系统带出排、列、层和预览库位编号。",
|
||
"已发生库存业务的库位不建议物理删除;如不再使用,应先移库清空,再停用。",
|
||
],
|
||
)
|
||
add_heading(doc, "4.2 物料查询", 2)
|
||
add_numbered(
|
||
doc,
|
||
[
|
||
"综合查询:输入物料编码、名称、图号或库位关键字,可选择全部库房或指定库房。",
|
||
"正向查询:用于回答“物料在哪个库位”,按物料信息定位所有有库存的库位。",
|
||
"逆向查询:用于回答“哪个库位放置哪些物料”,可从三楼可视化库位直接跳转带入库位。",
|
||
"查询结果显示物料编码、物料名称、图号或型号、库房、库区、库位、库存数量、批次号和库存状态。",
|
||
],
|
||
)
|
||
add_heading(doc, "4.3 出入库与盘点衔接", 2)
|
||
add_para(
|
||
doc,
|
||
"当前模块已经预留出入库/盘点流水入口。后续推进时,应把现有入库、出库、调拨、盘点业务的库存变动统一写入库房业务记录或可追溯流水,避免只改结果、不留过程。",
|
||
)
|
||
add_bullets(
|
||
doc,
|
||
[
|
||
"入库:选择物料、数量、库房和库位,库存增加并写入入库流水。",
|
||
"出库:校验库位库存充足后扣减,库存减少并写入出库流水。",
|
||
"盘点:生成账面数,录入实盘数,差异确认后生成盘盈或盘亏调整流水。",
|
||
"移库:原库位扣减、目标库位增加,同一业务写入移出和移入两条流水。",
|
||
]
|
||
)
|
||
|
||
add_heading(doc, "5. 数据流说明")
|
||
add_table(
|
||
doc,
|
||
["数据流", "入口", "处理", "输出"],
|
||
[
|
||
["库房主数据", "库房管理页签", "写入库房主文件,维护状态和布局参数", "库房下拉、统计、库位归属依据"],
|
||
["库区/库位数据", "库区/库位页签或可视化点击建库位", "写入原货位表扩展字段,保留原货位主键", "库位列表、可视化单元格、物料查询维度"],
|
||
["原库位同步", "库位编码归属同步过程", "按编码规则回填库房、库区、排列层", "二楼、立库、三楼的库位归属清单"],
|
||
["物料库位查询", "物料综合查询页签", "调用原稳定接口,再按编码规则补库房归属", "物料在哪、库位放什么的正逆向查询结果"],
|
||
["业务流水", "入库、出库、盘点、移库后续接入", "写业务记录并关联物料、库位、数量变化", "出入库/盘点流水和追溯报表"],
|
||
],
|
||
[3.0, 3.8, 5.2, 3.8],
|
||
)
|
||
|
||
add_heading(doc, "6. 验收标准")
|
||
add_table(
|
||
doc,
|
||
["验收项", "验收方法", "通过标准"],
|
||
[
|
||
["不影响原功能", "原库位管理、原物料库位页面查询", "页面可正常打开,查询结果与实施前一致。"],
|
||
["库房主数据", "新增、编辑、停用测试库房", "数据写入测试库,重复编号有校验,停用状态正确。"],
|
||
["库位归属", "抽查 A1-1、01-01-01、1-01-01-01 等编码", "分别归属二楼隔层、立库、三楼仓库。"],
|
||
["三楼可视化", "切换层号并点击库位", "展示 8 排、24 列、3 层,点击后显示库位明细。"],
|
||
["物料正逆向查询", "按物料查库位、按库位查物料", "能返回库房、库区、库位和库存数量,不再出现 result=0。"],
|
||
["构建验证", "执行前端 lint 和 build", "无编译错误;允许已有体积和 Browserslist 警告。"],
|
||
],
|
||
[3.2, 5.2, 7.1],
|
||
)
|
||
|
||
add_heading(doc, "7. 推进方案")
|
||
add_heading(doc, "7.1 推进原则", 2)
|
||
add_bullets(
|
||
doc,
|
||
[
|
||
"先测试库、再小范围试点、最后正式库上线。",
|
||
"先查清现有库位数据,再让仓库人员确认库房归属。",
|
||
"先上线查询和可视化,再逐步接入会改库存的入库、出库、盘点、移库。",
|
||
"每一步都保留回退方案,正式库脚本上线前必须备份对象定义和关键数据。",
|
||
]
|
||
)
|
||
add_heading(doc, "7.2 推进计划", 2)
|
||
add_table(
|
||
doc,
|
||
["阶段", "工作内容", "责任角色", "预计工时", "交付物"],
|
||
[
|
||
["0. 方案确认", "确认库房定义、编码规则、菜单权限、试点范围。", "仓库主管、实施人员、开发", "4 小时", "确认记录和试点名单"],
|
||
["1. 测试库核对", "核对三类库房、库区、库位归属;抽样检查物料库位。", "仓库主管、实施人员", "8 小时", "数据核对表"],
|
||
["2. 页面试用", "仓库人员按实际业务试用库房、库区/库位、可视化、物料查询。", "仓库操作员、实施人员", "8 小时", "问题清单和优化记录"],
|
||
["3. 数据清洗", "处理未归类库位、异常编码、重复或废弃库位。", "仓库主管、开发", "16 小时", "清洗脚本和确认清单"],
|
||
["4. 培训与验收", "培训查询、建库位、可视化操作;按验收标准逐项签字。", "实施人员、关键用户", "8 小时", "培训签到和验收单"],
|
||
["5. 正式库上线准备", "生成正式库脚本、备份对象、安排低峰上线窗口。", "开发、DBA/管理员", "8 小时", "上线脚本、回退脚本、备份记录"],
|
||
["6. 正式上线", "执行正式库脚本、发布前端、验证菜单和查询。", "开发、实施人员", "8 小时", "上线记录和验证结果"],
|
||
["7. 运行观察", "连续观察查询性能、用户反馈、出入库/盘点接入需求。", "仓库主管、开发", "16 小时", "试运行报告和二期清单"],
|
||
],
|
||
[2.2, 5.0, 3.0, 2.0, 3.3],
|
||
)
|
||
|
||
add_heading(doc, "7.3 正式上线前检查清单", 2)
|
||
add_bullets(
|
||
doc,
|
||
[
|
||
"确认正式库脚本只包含已验收对象,不包含测试数据。",
|
||
"确认原仓储页面和原存储过程未被覆盖。",
|
||
"确认 `库存管理_货位主文件` 新增字段为兼容字段,不破坏原字段含义。",
|
||
"确认菜单权限只授权给需要使用库房管理的角色。",
|
||
"确认可回退:正式库执行前导出相关对象定义和关键表数据备份。",
|
||
"确认上线后首日安排仓库关键用户和开发人员共同值守。",
|
||
]
|
||
)
|
||
|
||
add_heading(doc, "8. 风险与控制")
|
||
add_table(
|
||
doc,
|
||
["风险", "表现", "控制措施"],
|
||
[
|
||
["库位编码不规范", "部分库位无法归属到二楼、立库、三楼", "输出未归类清单,由仓库确认后再批量修正。"],
|
||
["用户误解默认库房", "综合查询只看到某一库房", "材料查询页提供独立“全部库房/指定库房”筛选。"],
|
||
["接口兼容问题", "新建过程经接口返回 result=0", "查询类优先复用原稳定接口;新过程上线前单独做接口验证。"],
|
||
["影响原功能", "原库位管理或物料库位页面异常", "原页面不改;新增模块隔离;上线前做原功能回归。"],
|
||
["库存变动不可追溯", "只改库存结果,没有业务流水", "出入库、盘点、移库接入时必须同事务写库存变动流水。"],
|
||
],
|
||
[3.0, 5.0, 7.5],
|
||
)
|
||
|
||
add_heading(doc, "9. 后续二期建议")
|
||
add_bullets(
|
||
doc,
|
||
[
|
||
"把采购入库、自制件入库、领料出库、退料、移库、盘点全部接入库房业务记录。",
|
||
"为三楼可视化增加库位物料明细弹窗、颜色按库存/容量/异常区分。",
|
||
"增加未归类库位治理页面,支持仓库人员批量指定库房和库区。",
|
||
"增加库位容量、混放规则、冻结库存、异常库存预警。",
|
||
"形成“库存账面数-库位现存-业务流水”三方核对报表。",
|
||
]
|
||
)
|
||
|
||
add_heading(doc, "10. 使用责任分工")
|
||
add_table(
|
||
doc,
|
||
["角色", "职责"],
|
||
[
|
||
["仓库主管", "确认库房和库位规则,审核未归类库位,组织试点和验收。"],
|
||
["仓库操作员", "按实际收发料和盘点场景试用页面,反馈无法落地的问题。"],
|
||
["实施人员", "组织培训、收集问题、跟踪整改、推进验收。"],
|
||
["开发人员", "维护测试库脚本、前端页面、接口兼容和上线回退方案。"],
|
||
["系统管理员", "控制菜单权限、安排上线窗口、保存备份和发布记录。"],
|
||
],
|
||
[3.2, 12.3],
|
||
)
|
||
|
||
add_para(doc, "修改人:Ld 修改时间:" + MODIFY_TIME + ";")
|
||
|
||
footer = section.footer.paragraphs[0]
|
||
footer.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
||
run = footer.add_run("库房管理方案实施后说明书")
|
||
run.font.name = "微软雅黑"
|
||
run._element.rPr.rFonts.set(qn("w:eastAsia"), "微软雅黑")
|
||
run.font.size = Pt(9)
|
||
run.font.color.rgb = RGBColor(85, 85, 85)
|
||
|
||
doc.save(OUTPUT)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
build_doc()
|