文件
hyb-oa/docs/domain-events.md
T

14 KiB
原始文件 Blame 文件历史

领域事件清单(P19 / P19+IM-1 / P19+ERP-3 / P19+AI-1 / P20+TRAVEL-1 / P20+TRAVEL-2 / P20+TRAVEL-3)

快照日期:2026-03-10 目标:冻结 hyb-oa 当前采购、资产与差旅域的标准领域事件名,并补充 P19+IM-1 已实际消费的 IM 通知类型清单,以及 P19+ERP-1 / ERP-3 / AI-1 / TRAVEL-1 已实际落地的消费映射,作为后续 ERP / IM / AI / TRAVEL 适配的事实源。

1. 使用原则

  • 本文档同时维护两类事实:
    • 领域事件名(长期稳定边界)
    • IM 一期已消费的通知类型(当前运行时实现)
  • 未来若继续扩展 Outbox / webhook / MQ,领域事件名与最小载荷必须保持向后兼容。
  • 领域事件只表达“已经发生的业务事实”,不表达待办命令。

2. 标准领域事件清单

事件名 触发时机 领域对象 最小载荷字段 推荐消费者 备注
purchase_request.submitted 采购申请提交成功后 purchase_request purchaseRequestId, requestNo, applicantId, departmentId, legalEntityId, costCenterId, supplierId, budgetPoolId, totalAmount, status IM、ERP、AI 表示进入 reviewing
purchase_request.approved 采购申请审批通过后 purchase_request purchaseRequestId, requestNo, approvedBy, legalEntityId, costCenterId, supplierId, budgetPoolId, totalAmount, status ERP、IM、AI 对应预算 confirm 已完成
purchase_request.rejected 采购申请审批驳回后 purchase_request purchaseRequestId, requestNo, actorId, reason, status IM、AI 若存在预算预留,应已释放
purchase_request.withdrawn 申请人撤回采购申请后 purchase_request purchaseRequestId, requestNo, actorId, status IM、AI、ERP 补偿 表示由 reviewing 回到 draft
travel_request.submitted 差旅申请提交成功后 travel_request travelRequestId, requestNo, applicantEmployeeId, departmentId, legalEntityId, costCenterId, budgetPoolId, estimatedAmount, tripType, status IM、Budget、TRAVEL-2/3 表示进入 reviewing 且预算尝试 reserve
travel_request.approved 差旅申请审批通过后 travel_request travelRequestId, requestNo, approvedBy, legalEntityId, costCenterId, budgetPoolId, estimatedAmount, tripType, status IM、Budget、TRAVEL-2/3 对应预算 confirm 已完成;TRAVEL-1 不做 ERP 出站
travel_request.rejected 差旅申请审批驳回后 travel_request travelRequestId, requestNo, actorId, reason, status IM、Budget、AI 若存在预算预留,应已释放
travel_request.withdrawn 申请人撤回差旅申请后 travel_request travelRequestId, requestNo, actorId, status Budget、AI、TRAVEL-2/3 动作结果固定回到 draft,不是持久状态
travel_order.paid 差旅订单被财务/行政标记为已支付后 travel_order travelOrderId, travelRequestId, externalOrderNo, paymentVoucherNo, paymentDate, paymentChannel, amount, currency, status ERP、TRAVEL-3、AI TRAVEL-2 起稳定承诺,用于支付 journal 出站
purchase_order.archived PO/合同归档保存成功后 purchase_order_archive purchaseOrderArchiveId, purchaseRequestId, requestNo, poNo, contractNo, archivedAt, totalAmount ERP、AI ERP-2 以此驱动 accrual journal 与 archive summary
asset.card.created 资产卡片创建成功后 asset_card assetId, assetNo, name, categoryId, legalEntityId, costCenterId, purchaseRequestId, status ERP、IM、AI 资产域不接 workflow
asset.assigned 资产领用成功后 asset_card assetId, assetNo, employeeId, assignedAt, location, status IM、AI 对应新增 open assignment
asset.returned 资产归还成功后 asset_card assetId, assetNo, employeeId, returnedAt, location, status IM、AI 对应关闭 open assignment
asset.transferred 资产调拨成功后 asset_card assetId, assetNo, fromEmployeeId, toEmployeeId, fromLocation, toLocation, transferredAt, status IM、AI 可只改位置,不一定改归属人;ERP-3 一期不消费
inventory_check.completed 盘点任务完成后 inventory_check inventoryCheckId, checkNo, scopeType, scopeRefId, completedAt, itemCount, summary ERP、IM、AI summary 建议包含 matched / missing / extra / damaged 计数

3. 事件名与运行时对象映射

entityType 推荐事件前缀 当前事实源
purchase_request purchase_request.* P17A / P17B
travel_request travel_request.* P20+TRAVEL-1
purchase_order_archive purchase_order.* P17B / P19+ERP-2
asset_card asset.* P18A / P18B
inventory_check inventory_check.* P18B

4. 最小 Envelope 建议

未来若继续扩展事件投递,建议统一使用如下 envelope:

{
  "eventName": "purchase_request.submitted",
  "eventId": "uuid",
  "occurredAt": "2026-03-08T12:18:10+08:00",
  "actorId": "user-id",
  "entityType": "purchase_request",
  "entityId": "entity-id",
  "payloadVersion": 1,
  "payload": {}
}

5. 兼容性规则

  • 事件一旦对外承诺,名称不得随意修改。
  • 新增字段必须保持向后兼容;删除字段需要单独版本升级。
  • 载荷字段命名应与 HTTP camelCase 输出保持一致,不直接暴露数据库 snake_case 列名。

6. 明确不纳入当前事件主表的事项

  • purchase_order.cancelled:待未来采购撤销 / 作废专项再冻结
  • inventory_check.started:当前不是对外关键事实源
  • asset.repaired / asset.retired:待未来维修 / 报废专项后再定义

7. 推荐消费场景

  • IM:采购审批结果、报销结果、资产领用归还、盘点完成提醒
  • ERP:采购审批 commitment、PO/合同归档 accrual / summary、资产卡片 ledger summary、盘点完成摘要
  • AI:审批摘要、异常提示、主数据重复建议、盘点结果总结

8. P19+IM-1 已消费通知类型

说明:IM 一期运行时并未新增新的领域事件名,而是基于现有业务事实统一沉淀为通知类型,再通过 notification.im Outbox 异步派发。

通知类型 当前来源事实 默认 targetType 默认 targetPath 说明
workflow.task_assigned workflow 新待办 / 转审待办 workflow_task /workflow/tasks/:taskId 当前唯一待办类通知
reimbursement.approved 报销审批通过 reimbursement_form /reimbursements/:id 结果通知
reimbursement.rejected 报销驳回 reimbursement_form /reimbursements/:id 结果通知
reimbursement.returned 报销退回 reimbursement_form /reimbursements/:id 结果通知
reimbursement.paid 报销付款完成 reimbursement_form /reimbursements/:id 财务结果通知
leave.approved 请假审批通过 leave_request /leave-requests 结果通知
leave.rejected 请假驳回 leave_request /leave-requests 结果通知
purchase_request.approved 采购审批通过 purchase_request /purchase-requests 结果通知
purchase_request.rejected 采购驳回 purchase_request /purchase-requests 结果通知
travel_request.approved 差旅审批通过 travel_request /travel-requests?id=<id> 结果通知
travel_request.rejected 差旅审批驳回 travel_request /travel-requests?id=<id> 结果通知
asset.assigned 资产领用成功 asset_card /assets 通知新领用人
asset.returned 资产归还成功 asset_card /assets 通知原持有人
asset.transferred 资产调拨成功 asset_card /assets 通知归属变更涉及人员
inventory_check.completed 盘点完成 inventory_check /inventory-checks 通知创建人与 finance_mgr 角色

9. 当前仍未接入 IM 的冻结事件

  • purchase_request.submitted
  • purchase_request.withdrawn
  • travel_request.submitted
  • travel_request.withdrawn
  • inventory_check.started

这些事件名称仍保留在长期蓝图中,但不属于 P19+IM-1 的首批协同覆盖范围。

10. P19+ERP-1 / ERP-3 已实现消费映射

  • P19+ERP-1 没有新增新的领域事件名;ERP 一期真正落地消费的既有业务事实是 reimbursement.paid,运行时会先构建标准化 ReimbursementJournalSlice,再通过 erp.journal.export 写入 IntegrationOutbox 异步派发。
  • ReimbursementJournalSlice.sourceEventName 固定为 reimbursement.paid,用于标记该凭证切片来源于“报销付款完成”这一既有业务事实;历史 erp.reimbursement.paid outbox 仍继续兼容。
  • P19+ERP-2 正式冻结新增领域事件名 purchase_order.archived,并消费两类采购事实:
    • purchase_request.approved → PurchaseCommitmentJournalSlice → erp.journal.export
    • purchase_order.archived → PurchaseAccrualJournalSlice + purchase_order_archive summary → erp.journal.export / erp.procurement.export
  • 采购 ERP 成功派发后,运行时统一把外部 ERP 编号回写到 integration_bindings,分别对应 purchase_request_commitment_journal、purchase_order_accrual_journal、purchase_order_po、purchase_order_contract。
  • ERP 主数据同步(LegalEntity / CostCenter / Supplier)仍属于主动 Pull,不作为新的领域事件名纳入本表;IntegrationSyncState 也继续只承载主数据资源级同步状态,而不承载采购或资产单据轨道。
  • P19+ERP-3 一期已落地资产消费映射:
    • asset.card.created → AssetLedgerSummaryPayload → erp.asset.export
    • PATCH /api/assets/:id 导致 legalEntityId / costCenterId / status(retired|archived) 变化 → 资产 ERP 内部集成事实 → erp.asset.export
  • 资产 ERP 成功派发后,运行时统一把外部 ERP 资产编号回写到 integration_bindings(provider=erp, entity_type=asset_erp_card);领用 / 归还 / 位置调拨仍不进入 ERP 消费映射。

11. P19+AI-1 已实现消费说明

  • P19+AI-1 不新增新的公开领域事件名;AI 一期只消费既有报销、采购、资产事实,并保持同步只读建议形态。
  • 报销详情 AI 建议消费的事实锚点为 reimbursement_form 当前详情、预算提示与待办节点;采购详情 AI 建议消费 purchase_request 当前详情、归档摘要与资产候选信息;资产详情 AI 建议消费 asset_card 当前卡片摘要与财务维度信息。
  • AI 一期的三条建议接口均采用白名单快照,不提升为长期公共事件,也不改变 asset.card.created、purchase_request.*、purchase_order.archived 等既有事件名的稳定性承诺。
  • AI 输出仅形成 summary / riskHints / nextActions 结构化建议,并通过审计动作 AI_SUGGESTION_REQUESTED 记录请求摘要;不写库、不派发 Outbox、不回写业务状态。

12. P20+TRAVEL-1 已实现消费说明

  • P20+TRAVEL-1 新增稳定事件名 travel_request.submitted、travel_request.approved、travel_request.rejected、travel_request.withdrawn,用于冻结差旅申请一期的业务事实边界。
  • 差旅一期运行时会在 travel_request.submitted 时创建 workflow 实例、分派 workflow.task_assigned 待办,并按预算池解析结果尝试 reserve;travel_request.approved / travel_request.rejected 则分别驱动预算 confirm / release。
  • 当前 IM 已实际消费差旅审批结果通知 travel_request.approved 与 travel_request.rejected;travel_request.submitted 与 travel_request.withdrawn 仍作为稳定领域事实保留,不额外新增结果类通知。
  • travel_order.imported 在 TRAVEL-1 当前仍只作为内部集成事实和入站表更新使用,不提升为稳定公共事件,也不在本表作为长期承诺事件名登记。

13. P20+TRAVEL-2 已实现消费说明

  • P20+TRAVEL-2 新增稳定事件名 travel_order.paid,并明确 card_authorization.imported、card_transaction.imported、card_transaction.reversed 当前都只保留为内部支付轨道事实,不进入稳定公共事件表。
  • CardAuthorization 导入成功后写支付预算 authorize;CardTransaction 的 charge + settled 写 settle,refund / reversal 写 reverse,且这些支付账轨不回改 travel_request 在 TRAVEL-1 已冻结的申请预算确认点。
  • 差旅订单只有在已结算交易与订单金额/币种完全匹配时才会从 imported 推进到 confirmed;之后由 mark-paid 手工结算动作把订单推进到 paid,形成运营闭环。
  • travel_order.paid 的固定消费路径为:travel_order.paid → TravelOrderPaymentJournalSlice → erp.journal.export;若 erp_sync feature flag 未开启,仅记录审计摘要,不进入 Outbox。

14. P20+TRAVEL-3 已实现消费说明

  • P20+TRAVEL-3 不新增新的公开业务领域事件名;TravelReconciliationBatch / TravelReconciliationItem 当前只作为内部运营事实与批次快照存在,不进入稳定公共事件表。
  • travel_order.paid 继续保持 TRAVEL-2 已冻结的稳定承诺,并作为 TRAVEL-3 对账批次生成时的只读事实来源之一;对账批次不会反向改写该事件的消费语义。
  • erp.travel.export 在 TRAVEL-3 中新增,但它被固定归类为批次级集成事件,不计入公开业务领域事件名;其消费路径为 TravelReconciliationBatch(reconciled) → TravelReconciliationSummaryPayload → erp.travel.export。
  • card_authorization.imported、card_transaction.imported、card_transaction.reversed 仍只保留为内部支付轨道事实;TRAVEL-3 只读取这些事实构建 snapshot,不提升为新的稳定公共事件名。