Files
JY1.0/scripts/generate_scheduling_optimization_doc.py

322 lines
19 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 修改人:Ld 修改时间:2026-08-03 14:07:13; 生成排产优化方案 Word 文档。
from docx import Document
from docx.enum.section import WD_SECTION
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_CELL_VERTICAL_ALIGNMENT
from docx.enum.text import WD_ALIGN_PARAGRAPH
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Inches, Pt, RGBColor
OUTPUT = r"D:\景耀\JY1.0\docs\排产优化方案.docx"
MOD_TIME = "2026-08-03 14:07:13"
def set_run_font(run, size=11, bold=False, color=None, name="Calibri"):
run.font.name = name
run._element.rPr.rFonts.set(qn("w:ascii"), name)
run._element.rPr.rFonts.set(qn("w:hAnsi"), name)
run._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei")
run.font.size = Pt(size)
run.bold = bold
if color:
run.font.color.rgb = RGBColor.from_string(color)
def set_para_format(paragraph, before=0, after=6, line=1.10):
paragraph.paragraph_format.space_before = Pt(before)
paragraph.paragraph_format.space_after = Pt(after)
paragraph.paragraph_format.line_spacing = line
def add_heading(doc, text, level=1):
p = doc.add_paragraph()
set_para_format(p, before=16 if level == 1 else 10, after=8 if level == 1 else 5)
r = p.add_run(text)
if level == 1:
set_run_font(r, size=16, bold=True, color="2E74B5")
else:
set_run_font(r, size=13, bold=True, color="2E74B5")
return p
def add_para(doc, text, bold_prefix=None):
p = doc.add_paragraph()
set_para_format(p)
if bold_prefix and text.startswith(bold_prefix):
r1 = p.add_run(bold_prefix)
set_run_font(r1, bold=True)
r2 = p.add_run(text[len(bold_prefix):])
set_run_font(r2)
else:
r = p.add_run(text)
set_run_font(r)
return p
def add_bullet(doc, text):
p = doc.add_paragraph(style="List Bullet")
set_para_format(p, after=4, line=1.167)
r = p.add_run(text)
set_run_font(r)
return p
def add_number(doc, text):
p = doc.add_paragraph(style="List Number")
set_para_format(p, after=4, line=1.167)
r = p.add_run(text)
set_run_font(r)
return p
def shade_cell(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_text(cell, text, bold=False, align=WD_ALIGN_PARAGRAPH.LEFT):
cell.text = ""
p = cell.paragraphs[0]
p.alignment = align
set_para_format(p, after=0, line=1.10)
r = p.add_run(text)
set_run_font(r, size=10.5, bold=bold)
cell.vertical_alignment = WD_CELL_VERTICAL_ALIGNMENT.CENTER
def add_table(doc, headers, rows, widths):
table = doc.add_table(rows=1, cols=len(headers))
table.alignment = WD_TABLE_ALIGNMENT.CENTER
table.style = "Table Grid"
for i, header in enumerate(headers):
set_cell_text(table.rows[0].cells[i], header, bold=True, align=WD_ALIGN_PARAGRAPH.CENTER)
shade_cell(table.rows[0].cells[i], "F2F4F7")
table.rows[0].cells[i].width = Inches(widths[i])
for row in rows:
cells = table.add_row().cells
for i, value in enumerate(row):
set_cell_text(cells[i], str(value), align=WD_ALIGN_PARAGRAPH.LEFT if i > 0 else WD_ALIGN_PARAGRAPH.CENTER)
cells[i].width = Inches(widths[i])
doc.add_paragraph()
return table
def add_callout(doc, title, body):
table = doc.add_table(rows=1, cols=1)
table.alignment = WD_TABLE_ALIGNMENT.CENTER
table.style = "Table Grid"
cell = table.rows[0].cells[0]
shade_cell(cell, "F4F6F9")
p = cell.paragraphs[0]
set_para_format(p, after=3)
r = p.add_run(title)
set_run_font(r, size=11, bold=True, color="1F4D78")
p2 = cell.add_paragraph()
set_para_format(p2, after=0)
r2 = p2.add_run(body)
set_run_font(r2, size=10.5)
doc.add_paragraph()
def main():
doc = Document()
section = doc.sections[0]
section.top_margin = Inches(1)
section.bottom_margin = Inches(1)
section.left_margin = Inches(1)
section.right_margin = Inches(1)
section.header_distance = Inches(0.492)
section.footer_distance = Inches(0.492)
styles = doc.styles
normal = styles["Normal"]
normal.font.name = "Calibri"
normal._element.rPr.rFonts.set(qn("w:eastAsia"), "Microsoft YaHei")
normal.font.size = Pt(11)
normal.paragraph_format.space_after = Pt(6)
normal.paragraph_format.line_spacing = 1.10
header = section.header.paragraphs[0]
header.alignment = WD_ALIGN_PARAGRAPH.RIGHT
set_para_format(header, after=0)
rh = header.add_run("景耀 JY1.0 MES | 排产优化方案")
set_run_font(rh, size=9, color="555555")
footer = section.footer.paragraphs[0]
footer.alignment = WD_ALIGN_PARAGRAPH.CENTER
rf = footer.add_run("内部方案讨论稿")
set_run_font(rf, size=9, color="555555")
title = doc.add_paragraph()
set_para_format(title, before=10, after=4)
tr = title.add_run("排产优化方案")
set_run_font(tr, size=24, bold=True, color="0B2545")
subtitle = doc.add_paragraph()
set_para_format(subtitle, after=14)
sr = subtitle.add_run("结合 JY1.0 现有销售合同、补货、生产计划、工序派工与设备任务链路")
set_run_font(sr, size=12, color="555555")
meta = [
["适用系统", "景耀 JY1.0 MES 前端Vue 2 + Element UI及 ASP.NET .ashx 后端"],
["数据库范围", "测试库 ERPTOOL_JY_20250826Back正式库 ERPTOOL_JY 上线前同步评审"],
["方案版本", "V1.0"],
["生成时间", MOD_TIME],
]
add_table(doc, ["项目", "说明"], meta, [1.5, 5.0])
add_callout(
doc,
"核心结论",
"建议采用“两步走”:第一阶段先做订单补货可溯源、当前工序高亮、机台任务看板三项可视化闭环;第二阶段在数据稳定后接入有限产能、交期、设备状态、工序前后置约束的自动排产建议。这样能最大限度复用现有页面和 MESCommonBase.ashx 通信模式,避免一次性重构带来的风险。",
)
add_heading(doc, "一、现有系统依据")
add_para(doc, "本次方案基于代码结构和现有业务链路梳理,重点参考以下模块:")
for item in [
"仓储补货src/views/WarehouseManagement/Replenishment/index.vue已具备报缺补货、外购/自制补货中间表、提交补货、补货期限、补货图片、打回通知等能力。",
"销售订单src/views/SalesManagement/OrderInquiry/index.vue 与 OrderRelease/index.vue已具备订单编号、合同类型、补货明细查询/修改、订单投产、订单分配等能力。",
"销售合同src/views/SalesManagement/SalesContractNew/index.vue 与 ContractSearchNew/index.vue已具备合同编号、项目流水号、客户、合同状态和资料留存等合同主数据能力。",
"生产计划src/views/SeikoWorkshop/ProductionPlan/index.vue已具备月度计划、状态、完成率、OP010-OP110 工序列和可视化看板雏形。",
"生产任务查询与追溯src/views/SeikoWorkshop/ProductionTaskQuery/index.vue已具备任务状态、派工、零件追溯、工序明细、加工设备和工序状态变色能力。",
"生产执行/派工src/views/SeikoWorkshop/ProductionExecution/index.vue已具备设备查询、工序信息查询、工序编辑及派工、上移/下移/插入/删除工序、工艺保存派工等能力。",
"设备监控src/views/SeikoWorkshop/EquipmentMonitoringNew/index.vue 与 ManufacturingCenter/EquipmentMonitoringNew/index.vue已具备设备状态展示和设备状态分布图基础。",
]:
add_bullet(doc, item)
add_heading(doc, "二、目标与边界")
add_para(doc, "本方案优先解决“计划看得见、任务找得到、来源追得回”的排产基础问题,再逐步进入算法优化。")
add_table(
doc,
["目标", "说明", "优先级"],
[
["补货订单可溯源", "创建补货订单时必须关联销售合同或销售订单,后续可从补货单反查合同、客户、订单、零件、需求来源。", "P0"],
["当前工序凸显", "生产计划和任务查询中对正在加工/待处理的当前工序做高亮、标签和进度提示,减少人工查找。", "P0"],
["机台任务显示", "按设备/工位展示当前任务、下一任务、排队任务、预计开完工、异常状态,为排产调整提供现场视角。", "P1"],
["排产算法建议", "在数据字段稳定后,按交期、工序顺序、设备能力、在制数量、设备状态给出推荐排产。", "P2"],
],
[1.25, 4.2, 1.05],
)
add_heading(doc, "三、方案一:补货订单关联销售合同")
add_para(doc, "现状:补货页面已能按物料选择补货并提交,但补货提交参数当前主要围绕“是否外购、操作者、补货期限、订单备注”;需求明细弹窗已能展示订单编号、需求量、客户。建议在补货创建时把合同/订单来源显式固化。")
add_number(doc, "在补货单提交弹窗中增加“关联销售合同”选择框,支持合同编号、客户、订单编号模糊查询。")
add_number(doc, "选择合同后,联动显示该合同下未完成订单;如用户从需求量明细进入,可自动带入订单编号和合同编号。")
add_number(doc, "补货中间表增加合同与订单字段,选入物料时即记录来源;提交生成补货单时把来源写入补货单主表和明细表。")
add_number(doc, "补货查询、新补货查询、销售订单补货明细中增加合同编号、客户名称、来源订单编号列,并提供跳转到合同查询/订单查询的入口。")
add_table(
doc,
["位置", "建议字段/控件", "处理逻辑"],
[
["补货创建弹窗", "关联销售合同、来源订单编号、客户名称", "提交前必填;若为安全库存补货可选择“库存备货”,但需填写备货原因。"],
["补货中间表", "项目流水号、合同编号、订单流水号、订单编号、来源类型", "选入物料时写入,选出时同步清理。"],
["补货单主表/明细表", "补货单号、合同编号、订单编号、客户名称、补货原因", "生成正式补货单后用于追溯、看板统计和报表导出。"],
["订单查询", "补货明细关联合同", "现有“订单信息_补货明细_查询/修改”扩展返回字段。"],
],
[1.35, 2.0, 3.15],
)
add_heading(doc, "四、方案二:生产计划当前工序高亮")
add_para(doc, "现状:生产计划已有 OP010-OP110 横向工序列,生产任务查询的工序明细已有 tableRowClassName1 变色逻辑,完成工序会显示为蓝色背景。建议扩展为“已完成、正在进行、待开始、异常/超期”四类视觉状态。")
add_table(
doc,
["状态", "判断规则", "前端表现"],
[
["已完成", "工序状态大于完成阈值、存在加工完成时间或完成状态=1", "浅蓝底 + 完成标签"],
["正在进行", "存在开始加工时间且无完成时间;或工序状态=加工中", "绿色高亮边框/底色 + “当前”标签"],
["待开始", "前序已完成、本工序未开始", "淡黄底 + “待加工”标签"],
["异常/超期", "超过精工期限、设备停机、暂停时间过长、质检不良待处理", "红色文字/标签 + 置顶或筛选项"],
],
[1.2, 3.2, 2.1],
)
add_para(doc, "前端建议:在 ProductionPlan 的 OP 列中增加 scoped-slot根据后端返回的“当前工序顺序/当前工序状态/当前设备”或前端解析后的状态决定 class在 ProductionTaskQuery 的工序追溯弹窗中把“当前工序”与“已完成工序”区分开。")
add_para(doc, "后端建议:生产计划查询过程返回 当前工序顺序、当前工序名称、当前工序状态、当前设备、当前操作者、计划开始、计划完成、实际开始、实际完成、是否超期。前端只负责展示,不在页面内重复推导复杂状态。")
add_heading(doc, "五、方案三:机台生产任务显示")
add_para(doc, "现状:生产执行已有设备下拉和工序派工,设备监控已有设备状态分布图,但缺少按机台汇总的“当前正在做什么、后面排了什么”。建议新增“机台任务看板”,可挂在精工车间或设备监控模块下。")
add_table(
doc,
["看板区块", "显示内容", "数据来源建议"],
[
["机台卡片", "设备名称/工位号、设备状态、当前订单、零件、图号、当前工序、操作者、已完成/计划数量", "基础数据_设备工位点检表 + 车间生产管理_零件工序_视图 + 完成过程情况"],
["当前任务", "正在加工任务、开始时间、已用时、预计剩余、是否超期", "工序完成过程情况、工序状态、设备状态"],
["排队任务", "下一道/后续任务,按交期、优先级、工序顺序排序", "派工表/工艺计划表/生产计划查询过程"],
["异常提示", "停机、暂停、质检不良、缺料、未派设备、超期", "设备状态、质检、仓储需求、任务状态"],
["操作入口", "跳转生产任务查询、工序追溯、生产执行派工", "保持现有路由跳转方式"],
],
[1.25, 2.75, 2.5],
)
add_para(doc, "第一版建议只做展示和筛选,不直接在看板上拖拽改排产;待现场认可数据准确性后,再开放“调整设备/调整顺序/插单”的受控操作。")
add_heading(doc, "六、数据库与接口改造建议")
add_table(
doc,
["类型", "名称建议", "用途"],
[
["查询", "仓储管理_补货关联合同_查询数据", "按合同编号、客户、订单编号查询可关联的销售合同/订单。"],
["编辑", "报缺补货_选入_带来源", "在选入补货物料时同步写入项目流水号、合同编号、订单流水号、订单编号。"],
["编辑", "报缺补货_提交_带来源", "提交补货单时校验合同/订单来源并写入正式单据。"],
["查询", "车间生产管理_生产计划_查询数据", "扩展返回当前工序、当前设备、工序状态码、计划/实际时间等字段。"],
["查询", "精工车间_机台任务看板_查询数据", "按设备/工位汇总当前任务和排队任务。"],
],
[1.1, 2.4, 3.0],
)
add_para(doc, "所有接口继续走 MESCommonBase.ashx前端仍使用 this.CreateData 和 this.ExecDatabase参数仍按 key=value 字符串规则由全局方法生成,避免新增 Axios 封装。")
add_heading(doc, "七、前端改造建议")
add_bullet(doc, "WarehouseManagement/Replenishment提交弹窗增加合同选择、来源订单选择、备货原因表格右侧补货单增加合同编号/订单编号隐藏列或 tooltip。")
add_bullet(doc, "WarehouseManagement/NewReplenishmentQuery增加合同编号、订单编号、客户名称列和筛选条件补货单号点击可查看来源。")
add_bullet(doc, "SalesManagement/OrderInquiry补货明细弹窗增加合同关联和修改记录展示补货订单可反跳补货查询。")
add_bullet(doc, "SeikoWorkshop/ProductionPlanOP 列改为状态单元格,增加当前工序高亮;看板图表增加按设备、按当前工序、按超期统计。")
add_bullet(doc, "SeikoWorkshop/ProductionTaskQuery工序追溯弹窗区分当前工序、已完成工序、待开始工序、异常工序。")
add_bullet(doc, "SeikoWorkshop 或 DeviceManagement新增机台任务看板页面沿用 app-container > el-card > 搜索栏 + 表格/卡片布局。")
add_heading(doc, "八、实施阶段")
add_table(
doc,
["阶段", "范围", "交付物", "建议周期"],
[
["阶段1", "补货订单关联合同/订单;补货查询追溯字段", "数据库字段、接口、补货页面、查询页面", "2-4天"],
["阶段2", "生产计划当前工序高亮;任务查询工序状态优化", "生产计划 OP 状态单元格、工序追溯弹窗优化", "2-3天"],
["阶段3", "机台任务看板", "设备筛选、当前任务、排队任务、异常提示、跳转入口", "4-6天"],
["阶段4", "排产算法建议", "规则配置、推荐顺序、人工确认、调整记录", "视规则复杂度评估"],
],
[1.0, 2.35, 2.2, 0.95],
)
add_heading(doc, "九、验收标准")
for item in [
"创建补货订单时,除库存备货场景外,必须能看到并保存销售合同/订单来源。",
"从补货查询能反查到合同编号、客户、订单编号、物料、补货数量、补货人、补货期限和当前状态。",
"生产计划列表中当前工序一眼可识别,且已完成、待开始、异常状态不会混淆。",
"机台任务看板能按设备查看当前任务和后续任务,当前任务字段与生产任务查询一致。",
"所有新增接口均遵循 MESCommonBase.ashx + CreateData/ExecDatabase 模式,正式库上线前在测试库完成验证。",
"所有新增代码注释和文档末尾记录满足“修改人:Ld 修改时间”规则。",
]:
add_bullet(doc, item)
add_heading(doc, "十、需要业务补充确认的问题")
for item in [
"补货订单是否必须关联“销售合同”,还是关联到“销售订单/订单编号”即可,合同通过订单反推?建议两者都保存,页面主选订单、自动带出合同。",
"安全库存补货、备品备件补货是否允许没有销售合同?如果允许,需要定义来源类型和审批/备注要求。",
"当前工序的业务定义:以“已开始未完成”为准,还是以前序完成后下一道未开始为准?建议同时显示“正在加工”和“下一待加工”。",
"机台任务看板需要显示哪些设备范围:仅精工车间设备,还是包含装配/外协/仓储相关工位?",
"是否需要在第一版支持手动调整机台任务顺序?建议第一版只展示,第二版再加受控调整和操作日志。",
"排产优先级规则:交期优先、客户优先、订单加急、设备能力、换型成本、工序等待时间,各项权重需业务确认。",
]:
add_bullet(doc, item)
add_heading(doc, "十一、推荐落地口径")
add_para(doc, "建议第一版不要直接宣传为“自动排产”,而定义为“排产可视化与任务追溯增强”。先把补货来源、当前工序、机台任务三块数据打通,现场使用一周后再根据实际反馈调整排产规则。这样既能快速解决当前痛点,也能为后续真正的排产优化算法沉淀可靠数据。")
add_para(doc, f"修改人:Ld 修改时间:{MOD_TIME};")
doc.save(OUTPUT)
if __name__ == "__main__":
main()