技术管理板块作为ERP(离散制造-MTO)系统中连接业务与实施的关键:它把产品定义、BOM、工序、工艺文件、变更控制等知识化、结构化,直接影响交付周期、制造成本与质量。本文将带你从为什么要做、什么是、到怎么搭建技术管理板块(含架构图、流程图、与完整的参考代码)一步到位,帮助企业把技术数据变成可落地的生产指令。
本文你将了解
- 为什么要讲 ERP(离散制造-MTO)里的技术管理?
- 什么是 ERP(离散制造-MTO)系统(简述)
- 技术管理板块要解决的问题与目标
- 总体架构(附架构图)与关键组件说明
- 主要功能模块(方案设计 / 产品信息 / 产品BOM / 生产工序 / 产品列表)
- 业务流程(附流程图)
- 开发技巧与最佳实践(数据库、并发、变更管理、权限、集成)
- 代码参考(一个较完整的示例后端 + 前端片段)
- 实现效果与落地建议
注:本文示例所用方案模板:简道云ERP系统,给大家示例的是一些通用的功能和模块,都是支持自定义修改的,你可以根据自己的需求修改里面的功能。
一、为什么要讲 ERP(离散制造-MTO)里的技术管理?
离散制造的MTO本质是“按订单设计/配置/生产”。技术管理板块把“产品的技术定义”标准化,直接决定生产是否可重复、订单能否准时交付、成本是否可控。很多企业的痛点来自于:
BOM不一致、工艺文件版本混乱、工序执行不到位、工装/夹具信息丢失。
把这些整理成系统化的、可追溯的数据,是提升制造稳定性的第一步。
二、到底什么是 ERP(离散制造-MTO)系统
简单说,ERP是企业资源计划;
离散制造强调单件或小批量、具有结构化BOM和工序的产品;
MTO表示“按订单生产”。
因此,ERP(离散制造-MTO)是一个覆盖报价 → 技术设计 → 物料准备 → 生产计划 → 车间执行 → 交付与结案的闭环系统。其中“技术管理”是把技术文档、BOM、工艺路线、标准工时等转为可供系统消费的核心数据层。
三、技术管理板块要解决的关键问题与目标
- 信息结构化:把产品信息、BOM、工序、设备/工装形成标准数据模型。
- 版本与变更管理:支持工程变更(ECO/ECN)与回退、对生产影响评估。
- 工艺下发:把工艺路由和作业指导书以生产可执行的任务下发到MES或车间终端。
- 可追溯性:生产跟踪与技术数据挂靠,出现问题能快速定位责任与版本。
- 高复用性:零部件、工序模板可复用,缩短新订单准备时间。
四、总体架构
下面给出一个简化的架构图(可通过 Mermaid 渲染)——核心思想是把技术管理作为“产品主数据层”,通过REST/GraphQL对上游(ERP销售/订单)和下游(MES / WMS / PLC / 设备)提供服务。
flowchart LR
subgraph UI
A[技术管理前端]
end
subgraph Backend
B[API 层 (Auth, RBAC)]
C[技术管理服务]
D[BOM 服务]
E[工序/路线服务]
F[版本/变更服务]
end
subgraph Data
DB[(关系型数据库:Postgres/MySQL)]
FS[(文件存储:对象存储/文档库)]
ES[(全文/检索:Elasticsearch)]
end
A --> B
B --> C
C --> D
C --> E
C --> F
D --> DB
E --> DB
F --> DB
C --> FS
C --> ES
C --> MES[下发到 MES / WMS / PLC]
说明:
- API 层负责鉴权与权限控制(操作级控制,工程师/技术员/生产管理不同权限)。
- 技术管理服务是核心,分解为产品信息、BOM、工序、变更模块。
- 文件(如图纸、工艺文档)放到对象存储并与记录关联。
- 使用 Elasticsearch 做快速检索(按物料号、版本、工序关键字等)。
五、主要功能模块
5.1 方案设计
业务目的:支持面向客户/订单的技术方案,包含选型、配置、成本估算、关键工艺说明。 功能点:
- 方案创建/复制/版本化(关联产品主数据,生成临时BOM)。
- 方案评审(审批流,支持多级审批和审批意见记录)。
- 方案到BOM的转换(把确认的方案推送为正式BOM)。
关键技术点:方案常是临时数据,设计为“方案表 + 方案BOM快照”,审批通过后快照转入正式BOM。
5.2 产品信息
业务目的:记录产品的基础信息(编码、名称、规格、型号、图纸、关键参数)。 功能点:
- CRUD 产品,维护产品属性(可扩展属性/自定义字段)。
- 多语言/多单位支持(计量单位转换)。
- 产品与技术文档、标准件库、供应商的关联。
数据模型要点:产品表 + 产品属性表(键值对)+ 文档关联表。
5.3 产品 BOM
业务目的:结构化描述产品的组成(多级BOM),支持物料替代、版本、工程变更。 功能点:
- 多级BOM展示、编辑(树形或表格形式)。
- 变体BOM(配置项)、可替代件管理(替代优先级)。
- BOM 版本管理(ECO 流程、锁定BOM对生产影响)。
实现建议:BOM 使用父子结构 + 层级路径索引字段(便于快速查询子树);对于大量BOM,考虑物料树缓存与差异化变更。
5.4 生产工序
业务目的:定义制造工序、工时、设备/人员技能与质量检查点。 功能点:
- 工序模板库(复用常见工艺)。
- 每道工序绑定设备、工装、标准工时、作业指导书(SOP)与质量点。
- 工序间的并行/串行关系定义与资源占用模型(工位负载)。
注意:工序需能下发到MES作为工单执行步骤。
5.5 产品列表
业务目的:对外展示的可销售项、配置项归类。 功能点:
- 支持产品目录分类、快速搜索、SKU 管理(若有成品SKU)。
- 支持按订单生成配置(MTO 的关键点)。
六、业务流程
下面给出典型技术管理流(从方案到生产)的流程图:
graph TD
Order[客户订单]
CreateScheme[创建方案]
Review[方案评审]
ConvertBOM[方案 -> 正式BOM]
CreateRouting[定义工序]
ECO[工程变更审批(ECO)]
Release[发布给 MES ]
Produce[车间生产执行]
Close[完工归档]
Order --> CreateScheme
CreateScheme --> Review
Review -->|通过| ConvertBOM
ConvertBOM --> CreateRouting
CreateRouting --> ECO
ECO -->|通过| Release
Release --> Produce
Produce --> Close
流程要点说明:
- 方案评审未通过可回退到方案修改。
- ECO(Engineering Change Order)是贯穿全链路的关键:审批通过后自动触发BOM/工序的版本升级并通知采购/生产。
- 发布给MES前,应进行“影响评估”(物料可用性、设备负载、工装是否就位)。
七、开发技巧与最佳实践
- 数据建模:BOM 用父子表设计,同时加 path 或 ancestor 字段便于子树查询。 产品属性用 KV 表或 JSON 字段(Postgres JSONB),灵活扩展。
- 版本管理与变更:每条配置(BOM/工序/文档)都带 version、status(Draft/Released/Obsolete)和 effective_date。 ECO 流程记录变更原因、影响范围(哪些生产订单受影响),并提供回滚路径。
- 并发与事务:变更发布使用数据库事务+乐观锁(version/timestamp)避免脏写。 大批量BOM操作(树的修改)建议用批量差异更新并记录操作日志。
- 文件和文档管理:图纸/表格等放对象存储(S3),数据库只保存元数据与访问权限;文档带签名与版本号。
- 权限与审计 细粒度 RBAC(角色+资源+操作),并强制审计日志记录(谁在何时做了什么)。
- 与 MES / WMS 的集成:使用消息队列(Kafka/RabbitMQ)发布 “BOM/Route Released” 事件,下游系统异步消费并反馈执行结果。 提供 REST API 与 Webhook,保证同步/异步场景皆可覆盖。
- 性能:对BOM、工序等经常查询的数据做缓存(Redis),但变更发布时需双写/失效策略。 搜索使用 Elasticsearch 提高模糊查找效率(按料号、图纸名、关键字检索)。
- 测试覆盖:关键是变更逻辑、BOM整合与下发场景做大量集成测试(包含回滚路径)。
八、代码参考
下面给出基于 Node.js (TypeScript) + Express + Sequelize (或 TypeORM) 的简化后端参考代码,涵盖产品、BOM、工序的模型、基本 API 和一个变更发布示例。注:代码为示例,真实项目需补充异常处理、鉴权、事务封装、日志与测试。
后端:src/models.ts(简化)
// src/models.ts
import { Sequelize, DataTypes, Model } from 'sequelize';
export const sequelize = new Sequelize(process.env.DATABASE_URL || 'sqlite::memory:');
class Product extends Model {}
Product.init({
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
code: { type: DataTypes.STRING, unique: true },
name: { type: DataTypes.STRING },
spec: { type: DataTypes.TEXT }, // 简单规格
attrs: { type: DataTypes.JSONB } // 可扩展属性
}, { sequelize, modelName: 'product' });
class BomItem extends Model {}
BomItem.init({
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
productId: { type: DataTypes.INTEGER, allowNull: false }, // 父产品
componentId: { type: DataTypes.INTEGER, allowNull: false }, // 子件(也可指向另一product)
qty: { type: DataTypes.FLOAT, defaultValue: 1 },
level: { type: DataTypes.INTEGER, defaultValue: 1 },
path: { type: DataTypes.STRING }, // e.g. /1/5/9
version: { type: DataTypes.INTEGER, defaultValue: 1 },
status: { type: DataTypes.STRING, defaultValue: 'Draft' } // Draft/Released/Obsolete
}, { sequelize, modelName: 'bom_item' });
class Routing extends Model {}
Routing.init({
id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
productId: { type: DataTypes.INTEGER },
name: { type: DataTypes.STRING },
stepIndex: { type: DataTypes.INTEGER },
machine: { type: DataTypes.STRING },
stdTimeMin: { type: DataTypes.FLOAT },
sopUrl: { type: DataTypes.STRING },
version: { type: DataTypes.INTEGER, defaultValue: 1 },
status: { type: DataTypes.STRING, defaultValue: 'Draft' }
}, { sequelize, modelName: 'routing' });
Product.hasMany(BomItem, { foreignKey: 'productId', as: 'bom' });
Product.hasMany(Routing, { foreignKey: 'productId', as: 'routing' });
export { Product, BomItem, Routing };
后端:src/api.ts(简化 API)
// src/api.ts
import express from 'express';
import bodyParser from 'body-parser';
import { Product, BomItem, Routing, sequelize } from './models';
const app = express();
app.use(bodyParser.json());
// 初始化 DB
app.get('/init', async (req, res) => {
await sequelize.sync({ alter: true });
res.json({ ok: true });
});
// 产品 CRUD
app.post('/product', async (req, res) => {
const p = await Product.create(req.body);
res.json(p);
});
app.get('/product/:id', async (req, res) => {
const p = await Product.findByPk(req.params.id, { include: ['bom', 'routing'] });
res.json(p);
});
// 添加 BOM 子件(简化:手动设置 path, level)
app.post('/product/:id/bom', async (req, res) => {
const { componentId, qty, parentPath } = req.body;
const path = parentPath ? `${parentPath}/${req.params.id}` : `/${req.params.id}`;
const item = await BomItem.create({
productId: parseInt(req.params.id, 10),
componentId, qty, path, level: (path.split('/').length - 1)
});
res.json(item);
});
// 发布 BOM(版本 + status)
app.post('/bom/:productId/release', async (req, res) => {
const t = await sequelize.transaction();
try {
// 简化逻辑:把该产品的所有 Draft 改为 Released 并 version++
const productId = parseInt(req.params.productId, 10);
const items = await BomItem.findAll({ where: { productId, status: 'Draft' }, transaction: t });
for (const it of items) {
it.version = (it.version || 1) + 1;
it.status = 'Released';
await it.save({ transaction: t });
}
// 这里可以 publish message to MQ
await t.commit();
res.json({ ok: true, releasedCount: items.length });
} catch (err) {
await t.rollback();
res.status(500).json({ error: err.message });
}
});
// 简化的工序创建
app.post('/product/:id/routing', async (req, res) => {
const r = await Routing.create({ productId: req.params.id, ...req.body });
res.json(r);
});
export default app;前端参考(React + Hooks,产品BOM展示和发布按钮)
说明与扩展建议:
- 实际项目中,BOM 的编辑建议用可拖拽树形组件并在前端做局部校验(避免循环引用)。
- 发布流程应与审批流结合(比如触发一个工作流引擎:Camunda / Zeebe / 自研)。
- 代码示例缺少鉴权/权限/全量校验,这些在生产系统必须补齐。
九、实现效果与落地建议
- 小步快跑:先把“产品/单级BOM/工序模板/发布”做成可用的MVP,把变更流、审批和MES对接留作第二阶段。MTO 场景下,快速交付能立刻降低时间成本。
- 先解决数据质量:很多企业的问题不是系统缺功能,而是基础数据(物料编码、图纸、技术参数)混乱。建议先进行“数据清洗+主数据管理”项目。
- 与车间同步:技术管理发布前必须与生产、采购和质量沟通。建立变更评估模板(影响物料、计划、工装、检验)。
- 培训与治理:制定操作手册 & 角色权限,落实审批职责;上线初期安排驻厂 support 以便快速修正流程。
- 持续改进:通过系统埋点(谁修改、何时、为什么)得到改进方向,把常见工序模板标准化形成知识库。
FAQ
Q1:在离散制造-MTO 环境下,BOM 的版本管理应该怎样做才能既保证变更灵活又不影响正在生产的订单?
A1:BOM 版本管理的原则是“新变更不影响已在制的订单”。
实现方式通常是:每个生产订单在创建时“绑定”当时的BOM版本(snapshot),变更发布后只对新订单生效。系统应保存 BOM 的历史快照并且标注生效时间与变更原因(ECO),这样当出现质量问题或返工时可以回溯到具体版本。
同时,在发布变更前进行自动影响分析:列出哪些进行中订单、待发料订单会受影响,并给出建议(如暂停变更或局部替代)。技术管理系统应提供回滚或补丁式变更功能(在特殊场景下),并强制要求变更审批与测试验证,避免线上直接替换正在作业的BOM。
Q2:如何把技术管理系统与已有 MES/WMS 平滑对接?有哪些注意点?
A2:平滑对接的关键是“契约化接口”和“事件驱动”。
首先和 MES/WMS 明确定义接口契约:BOM/Route 发布时的消息格式、变更通知、以及 MES 对下发任务状态的反馈接口(如工序开始/完成/异常)。
技术管理系统在发布时采用异步消息(RabbitMQ/Kafka)通知下游,同时保留 REST 接口用于同步查询。
注意点包括:消息幂等性(防止重复消费)、版本兼容(消息里带上 BOM/Route 的版本号)、变更窗口(在关键生产期限制变更)、以及错误补偿机制(如果下游拒绝或执行失败,需要回滚或人工介入)。
另外,文件(如SOP)若需在车间展示,建议使用 CDN/对象存储并通过临时签名URL下发,避免文件同步延迟。
Q3:企业规模小、不想一次性投入大量开发成本,如何渐进式构建该模块?
A3:对于预算有限或刚起步的企业,建议采用“分阶段上线”策略:
第一阶段实现最小可用核心——产品主数据、单级BOM、工序模板与发布机制,能让生产按订单基本执行;同时使用现成工具(如 Git/共享文件夹)存放SOP,后台只记录文档链接。
第二阶段加入版本管理、ECO 流程与审批(使用低代码工作流或集成开源工作流引擎);
第三阶段与 MES/WMS 做消息总线对接并实现多级BOM与替代件管理。
每阶段都要保证数据治理与培训,优先解决“最痛”的节点(比如BOM不一致或工序无法下发),这样既能快速看到收益,又能逐步完善系统。
行动建议
技术管理板块不是“单纯的模块”,而是制造企业运营能力的根基。落地时既要重视技术实现,也要做好组织与流程配套:主数据治理、变更管理、与车间的沟通机制都必须到位。按本文思路实现一个逐步迭代的技术管理板块,能显著提升交付确定性、降低返工与成本,并最终把企业的“经验”变成可复制的数据资产。