领域驱动设计 · DDD 实战 · 物料供应链 · IMPA编码 · AI Agent · 2026-08

物料/物资管理是船舶PMS系统中功能点最多、业务链路最长的模块——从申请、询价、采购、验收、库存到费用结算,横跨63个功能点、5大业务子域。本文记录我们如何用 Coze AI Agent,以 DDD 为方法论,将这份复杂的需求转化为结构化的详细设计文档。

63 个功能点5 大业务子域10 个核心实体三级审批 + 询价比价

1. 物料管理的复杂度在哪里

备件管理聚焦于"设备维修用的零部件",而物料/物资管理覆盖的是船舶运营所需的全部物资:从日常耗材、油漆、化学品到油料、药品、电子海图。这带来了三个层次的复杂度:

第一,业务链路长。 一笔物料从需求到付款要经过:申请→审批→询价→比价→订单→跟踪→验收→库存→费用→付款,每个环节都有独立的状态和规则。

第二,物资类别差异大。 普通物料走标准采购流程,油料有月报和检测报告,化学品需要满足港口国合规要求,油漆有调配比例和膜厚管理,药品受MLC公约约束,电子海图有版本更新周期。

第三,费用结构复杂。 一笔采购订单的费用不仅是物料单价,还包括运输费、包装费、清关费、折扣、税费,并且支持多币种结算和月度费用归集。

          ┌──────────────────────────────────────────┐
          │          物料管理限界上下文                  │
          │                                          │
          │  ┌────────┐ ┌────────┐ ┌────────┐       │
          │  │ 物料申请 │→│ 询价比价 │→│ 采购订单 │       │
          │  └────────┘ └────────┘ └───┬────┘       │
          │                             ↓            │
          │  ┌────────┐ ┌────────┐ ┌────────┐       │
          │  │ 费用结算 │←│ 库存管理 │←│ 验收入库 │       │
          │  └────────┘ └────────┘ └────────┘       │
          │                                          │
          │  专项域:油料 / 化学品 / 油漆 / 药品 / 海图  │
          └──────────────────────────────────────────┘

2. 领域建模:五个核心聚合

2.1 物料申请聚合(MrpApply)

物料申请采用"主表+明细行"的双层结构。主表(MrpApplyDesc)持有申请单号、船舶、部门、申请类型、港口、到港日期等头部信息,明细行(MrpApply)持有每条物料的申请数量和三级审批数量。

聚合根MrpApplyRequest(物料申请单)
包含实体:申请主表信息(MrpApplyDesc)、申请明细行(MrpApplyItem)
聚合边界:申请单的所有明细行必须在同一个事务中提交;审批操作修改的是明细行级别的审批数量,但审批状态变更作用于整个申请单。

关键设计发现:代码中申请主表和明细行是两个独立的实体类(mrp_applydescmrp_apply),通过 ApplyCode 关联。这不是数据库设计的偶然,而是反映了一个业务事实——审批是在明细行级别进行的,每级审批人可以对不同物料行设置不同的审批数量(ApproveNum1/2/3),而不是简单的整单通过/驳回。

2.2 询价聚合(MrpInquiry)

询价是物料采购中最有特色的环节。一个询价单发给一个供应商,包含多条物料的报价;采购方可以向多个供应商发出询价,然后进行比价。

聚合根MrpInquiry(询价单)
包含实体:询价明细行(MrpInquiryMrp)
聚合边界:一个供应商的一张询价单及其所有报价明细构成一个聚合。

设计要点:

  • 询价单持有 Vendor(供应商)、Currency(币种)、CurRate(汇率)——每个供应商可以用不同币种报价
  • 明细行持有 Price(单价)、QuoteNum(报价数量)——报价是供应商维度的
  • TransportPricePackingPriceClearancePrice 三个附加费用字段出现在询价单上,说明比价不仅是比单价,还要比到岸总成本
  • GenOrder 字段标识该询价是否已生成订单,防止重复转单

2.3 采购订单聚合(MrpOrder)

采购订单是物料管理中字段最多的实体(60+字段),反映了船舶物料采购的真实复杂性。

聚合根MrpPurchaseOrder(采购订单)
包含实体:订单明细行(MrpOrderMrp)、订单跟踪记录(MrpOrderTrace)

订单主表的设计揭示了几个重要的业务规则:

字段组字段业务含义
数量确认ComfirmNum确认数量(与申请数量、询价数量可能不同)
发货记录SendDate/SendDate2, HasSend支持分批发货
费用明细Fare1-Fare8, Number1-Number68种费用类型+6种数量参数,支持灵活费用结构
付款跟踪Ispaid, PaidNumber, PaidCarNum付款状态和已付金额
多币种Currency, CurRate, UsdRate订单币种、本币汇率、美元汇率
物流DockVend, DockIntev, StockLocation码头供应商、库存位置
预算BudgType预算类型,与预算模块联动

2.4 库存交易聚合(MrpStoreTrans)

库存管理采用"流水账"模式——MrpStoreTrans 记录每一笔库存变动,当前库存数量通过流水聚合计算。

聚合根MrpStockTransaction(库存交易记录)
聚合边界:每条交易记录是独立的不可变事件,不包含子实体。

设计亮点:

  • TransMark 字段标识交易类型(入库/出库/调整/期初/盘盈/盘亏)
  • 流水记录冗余了物料名称(CName/EName)、型号(MrpModel)、单位(MrpUnit),即使主数据变更,历史流水仍可查询
  • ApplyCodeOrderID 建立了流水与上游单据的追溯链路
  • Requirement 字段记录领用需求说明

2.5 物料费用聚合(MrpFare)

费用管理独立成聚合,因为费用有独立的审批和付款流程,且与订单是1:N关系(一个订单可能有多笔费用:货款、运费、关税等)。

聚合根MrpExpense(物料费用)
聚合边界:每笔费用独立审批、独立付款。

费用实体是所有实体中字段最多的(70+字段),体现了船舶物料采购财务处理的复杂性:

维度关键字段设计考量
报价与实际QuotePrice vs FareNum报价金额与实际金额分离
多币种QCurrency, Currency, CarCurrency报价币种/结算币种/承运币种三方汇率
税务TaxAmt税额独立计算
折扣Discount, Discount2支持双重折扣
付款PaidNum, PaidCurrency, PayDate, PaidType付款金额/币种/日期/方式
审批Approved1, Approved2, ManageSign费用审批链
预算BudgType费用归属预算类型

3. 核心流程:从申请到付款的端到端设计

3.1 三级审批机制

物料申请的审批不是简单的"一级过一级",而是有数量调整能力的:

系统三级审批二级审批一级审批申请人系统三级审批二级审批一级审批申请人创建申请单(含多条明细)提交通知审批(修改ApproveNum1,填AppMemo1)一级通过通知审批(修改ApproveNum2,填AppMemo2)二级通过通知审批(修改ApproveNum3,填AppMemo3)YesNo=Y,Status=已批准审批完成,可转询价/订单

设计要点:

  • 每级审批人可以修改审批数量(ApproveNum1/2/3),最终采购数量以最后一级为准
  • YesNo 字段是整体审批结论,但每级的审批意见独立保留
  • ApproveNumRec 字段记录审批数量的变更轨迹

3.2 询价比价流程

审批通过的申请

创建询价单

选择供应商A

选择供应商B

选择供应商C

供应商A报价

供应商B报价

供应商C报价

比价分析

选择最优方案

生成采购订单

比价的维度不仅是单价:

  • 物料单价(Price)
  • 附加费用(运费、包装费、清关费)
  • 折扣(Discount/Discount2)
  • 币种和汇率(不同供应商可能用不同币种报价)
  • 交货期(Eta/Etd)
  • 到岸总成本 = 物料总价 + 运输费 + 包装费 + 清关费 - 折扣

3.3 订单状态机

创建订单

提交

审核通过

审核驳回

发送供应商

第一批到货

最后一批到货

验收完成

费用确认

付款完成

取消订单

剩余取消

草稿

待审核

已审核

已发送

部分发货

全部到货

已验收

已结算

已付款

已取消

代码中 Status 字段为整数,结合 HasSendIspaidRecDateComfirmDate 等字段共同标识订单在不同维度的进度。设计文档将这些分散的状态字段统一为显式状态机。


4. IMPA 编码体系设计

IMPA(International Marine Purchasing Association)编码是国际海事采购的通用语言。物料管理通过 DicImpa 字典表维护IMPA编码:

字段含义设计要点
ImpaIMPA编码(6位数字)全局唯一主键
TypeCode物料类型编码分类导航
MaterialName / MaterialNameEn中英文名称双语支持
Specification / Specification_En中英文规格技术参数描述
UnitId / Unit计量单位标准计量单位
AttachmentId附件ID产品图片/技术文档

设计决策:

  • IMPA编码是岸端主数据,由公司统一维护,船端只能查询和引用
  • 船端可以创建"本机编码"(LocalCode)映射到IMPA编码,兼顾灵活性和标准化
  • 询价单和订单明细同时持有 MrpID(内部物料ID)、LocalCode(本机编码)和 ISOCode(国际编码),支持多种编码体系共存

5. 专项物资的领域设计

5.1 油料管理

油料是船舶最大的物料支出品类,有独立的管理逻辑:

  • 油料月报:按月统计各设备燃油/润滑油消耗量
  • 油料检测报告:记录润滑油品质检测结果,关联设备
  • 油料费用:按供应商维度和港口维度分别管理油料费用
  • 设备关联luboil_device 建立油料与设备的消耗关系

5.2 化学品管理

化学品管理的核心驱动是海事合规

  • 按港口查询:某港口允许/禁止哪些化学品
  • 按船舶查询:某船舶当前持有哪些化学品
  • 按供应商查询:某供应商能提供哪些化学品
  • 这些查询维度反映了港口国监督(PSC)检查的实际需求

5.3 油漆管理

油漆管理有独特的技术参数:

  • PntKnd(油漆种类)、PndTpy(涂料类型)、PntRate(涂布率)
  • BlstClass(喷砂等级)、FilmDpth(膜厚)
  • 这些字段出现在询价单和订单明细中,说明油漆采购需要指定技术参数

5.4 药品管理

药品管理受MLC(海事劳工公约)约束,需要管理药品清单、有效期和定期检查。功能优先级为P2,属于合规支撑域。


6. 多币种与费用设计

船舶物料采购天然是多币种场景。设计中采用汇率快照模式:

订单创建时 → 锁定 Currency + CurRate + UsdRate
询价报价时 → 每个供应商各自锁定汇率
费用录入时 → QCurrency(报价币种) + Currency(结算币种) + CarCurrency(承运币种)

三级汇率设计:

  1. CurRate:订单币种→本币汇率
  2. UsdRate:订单币种→美元汇率(用于跨币种比价)
  3. CERate:费用层的承运汇率(运费可能用第三种币种结算)

这个设计的核心原则是:历史财务数据使用交易发生时的汇率快照,不随汇率波动而变化。


7. 跨域集成

物料管理与以下上下文有集成关系:

集成域集成方式数据流向
备件管理共享物料编码备件编码 ↔ 物料编码映射
预算管理BudgType关联物料费用→预算执行
供应商管理Vendor引用询价/订单→供应商信息
设备管理油料消耗关联设备→油料消耗记录
修理管理IsRepair标识修理物料→修理工程单
报表域读模型库存/费用→统计报表

8. AI 做了什么,人做了什么

AI 完成的工作(约75%)

  1. 10个实体类的字段提取:共提取约300个字段,生成完整字段设计表
  2. 聚合边界识别:从实体关系中识别5个核心聚合,区分主表/明细结构
  3. 审批流程还原:从三级审批字段(Manager1/2/3 + ApproveNum1/2/3)推导出审批时序
  4. 状态机推导:从Status、HasSend、Ispaid等字段组合推导出订单状态机
  5. 费用结构分析:从Fare1-8/Number1-6等字段分析出灵活费用模型
  6. 比价维度识别:从运输费/包装费/清关费/折扣等字段发现"到岸总成本"比价逻辑
  7. 多币种设计:从三级汇率字段推导出汇率快照模式
  8. 专项物资分类:从油漆技术参数、化学品查询维度、油料月报等识别专项域

人需要决策的部分(约25%)

  1. 聚合边界确认:费用是否独立于订单成聚合——AI 建议独立,但需要人确认审批流程确实独立
  2. 库存模式选择:流水账 vs 余额表,需要根据船端离线场景和性能要求决策
  3. 专项物资的范围:哪些专项物资需要独立聚合,哪些只作为属性字段
  4. 多客户变体处理:电子海图是MH变体独有,HKMW有独立的实体继承体系
  5. 费用类型标准化:Fare1-8 的具体业务含义需要领域专家确认

9. 经验总结

9.1 字段数量不等于领域复杂度

物料费用实体有70+字段,但这并不意味着领域逻辑复杂——很多字段是不同费用类型、不同币种、不同审批级别的平铺展开。AI 的价值在于将这些平铺字段重新组织为聚合内的值对象(如 Money、FeeBreakdown、ApprovalTrail),让设计更清晰。

9.2 主从表结构揭示聚合边界

代码中 mrp_applydesc(主表)和 mrp_apply(明细表)的分离,直接揭示了"申请单"是一个聚合根,明细行是聚合内实体。这种从代码结构反推聚合边界的方法,比纯从需求文档推理更可靠。

9.3 冗余字段是有意设计

询价单和订单明细都冗余了物料名称、型号、单位。这些冗余不是疏忽,而是为了:

  • 船端离线时数据自包含
  • 历史单据保留交易时的快照
  • 查询性能优化

AI 一开始建议"规范化"去除冗余,经过分析后保留了这些字段并在 ADR 中记录了决策理由。

9.4 专项物资的 DDD 处理

化学品、油漆、油料等专项物资,DDD 中应该作为核心域内的子域处理,而不是独立限界上下文。它们共享申请-采购-库存的主干流程,只是在明细行上扩展了各自的技术参数。这种"共享内核+扩展属性"的模式,比为每种物资建独立模块更合理。

9.5 Mermaid 图表的价值

AI 生成的 Mermaid 类图、时序图和状态机,在评审中起到了关键作用——团队可以围绕可视化模型快速讨论,而不是面对大段文字。特别是订单状态机,将散落在多个字段中的状态信息聚合为一张图,业务方一眼就能发现遗漏的状态转换。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐