油品运输调度计划系统设计

本文探讨油品运输监控系统中调度计划模块的设计思路,覆盖核心实体建模、多对多关系处理、状态机设计以及自动推荐方案框架。

业务背景

油品运输的核心流程是:油站客户下订单 → 系统生成调度计划 → 车辆执行提油、运输、卸油

只有调度计划内授权的车辆,才可以合法地执行整个配送任务。这一机制既是业务流程的起点,也是安全管控的关键节点。

在设计之前,先明确几条关键业务约束:

  • 一个调度计划 = 一辆车,车辆跑完所有配送点后返回
  • 一个订单 = 一种油品,订单可按车次拆分到多个调度
  • 订单与调度是多对多关系,通过明细层桥接
  • 油罐车有多个仓(舱),每仓容量固定,不同仓容量可不同
  • 同仓可混装来自不同订单的同种油品
  • 调度变更时作废原计划,新建替代计划,保留完整历史

核心实体设计

整体分为三层:

1
订单层(Order)  →  调度层(DispatchPlan)  →  执行层(Task)

调度计划主表 dispatch_plan

1
2
3
4
5
6
7
8
9
10
11
12
dispatch_plan
├── id
├── plan_no -- 调度单号(业务标识)
├── depot_id -- 提油油库
├── vehicle_id -- 执行车辆(唯一)
├── plan_date -- 计划执行日期
├── status -- 见状态机设计
├── plan_type -- AUTO(自动生成)/ MANUAL(手动创建)
├── parent_plan_id -- 变更前的原计划ID(追溯变更链)
├── remark
├── created_by
└── created_at

变更处理原则:调度计划变更时,作废原计划并新建新计划,parent_plan_id 指向被替代的旧计划,形成完整变更链,便于审计追溯。


仓位装载表 dispatch_compartment

描述”这辆车的哪个仓,装了什么油,装多少“,与订单无关:

1
2
3
4
5
6
7
dispatch_compartment
├── id
├── plan_id
├── compartment_id -- 使用哪个车仓
├── oil_type -- 本仓装载的油品(一仓一品)
├── planned_load_qty -- 计划装载总量(≤ 仓容量)
└── actual_load_qty -- 实际提油量(提油环节填写)

订单配送明细表 dispatch_order_item

描述”哪个订单、分配多少量、从哪个仓卸、送到哪个站、第几站卸“:

1
2
3
4
5
6
7
8
9
10
dispatch_order_item
├── id
├── plan_id
├── compartment_id -- 关联仓位(从哪个仓卸给这个站)
├── order_id -- 来源订单
├── station_id -- 配送目标油站(冗余,方便查询)
├── oil_type -- 油品(冗余)
├── planned_qty -- 本次调度分配给该订单的量
├── actual_unload_qty -- 实际卸油量(卸油环节填写)
└── delivery_seq -- 配送顺序(调度员手动指定)

为什么要拆成两张明细表?

这是设计的关键决策。允许”同仓混装不同订单的同种油品”后,仓位和订单之间形成了一对多关系:

1
2
3
4
5
6
dispatch_compartment(仓192号,5000L)
├── dispatch_order_item(订单AA油站,3000L,第1站)
└── dispatch_order_item(订单BB油站,2000L,第2站)

dispatch_compartment(仓295号,5000L)
└── dispatch_order_item(订单C,C油站,5000L,第3站)

如果只用一张明细表,混装场景会导致仓位信息冗余存储,计划量和实际量的统计也会出现歧义。拆成两张表后,仓位层管理装载,明细层管理配送,职责清晰。


车辆与车仓表

1
2
3
4
5
6
7
8
9
10
11
vehicle
├── id
├── plate_no -- 车牌号
├── total_capacity -- 总容量(各仓之和)
└── status -- 可用 / 维修 / 执行中

vehicle_compartment
├── id
├── vehicle_id
├── compartment_no -- 仓号(如 1/2/3/4)
└── capacity -- 本仓固定容量

订单表

1
2
3
4
5
6
7
8
order
├── id
├── order_no
├── station_id -- 下单油站
├── oil_type -- 油品类型(一单一品)
├── ordered_qty -- 订单总量
├── dispatched_qty -- 已调度量(冗余,方便查询剩余待调度量)
└── status -- PENDING / PARTIAL / DISPATCHED / COMPLETED

dispatched_qty 随调度创建和取消实时更新,用于快速判断订单是否还有待调度量,避免每次都联表聚合计算。


订单与调度的多对多拆分示例

用一个具体例子说明拆分和合并场景:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
订单AA油站,92号汽油,8000L
订单B:B油站,92号汽油,3000L
订单C:C油站,95号汽油,5000L

车辆X:3仓 → 仓1=5000L,仓2=5000L,仓3=3000L
车辆Y:2仓 → 仓1=5000L,仓2=3000L

━━━ 调度计划1(车辆X)━━━
192号,5000L)
├── 订单AA油站,3000L,第1
└── 订单B → B油站,2000L,第2站 ← 同仓混装不同订单
295号,5000L)
└── 订单C → C油站,5000L,第3
392号,3000L)
└── 订单B → B油站,1000L,第2站 ← 订单B分布在两个仓

━━━ 调度计划2(车辆Y)━━━
192号,5000L)
└── 订单AA油站,5000L,第1站 ← 订单A被拆到两个调度

订单A的 8000L 被拆到调度1(3000L)和调度2(5000L),两条 dispatch_order_item 都关联同一个 order_idorder.dispatched_qty 累加为 8000L 即标记为全量调度。


状态机设计

调度计划状态流转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
DRAFT(草稿)

├─[调度员审核确认]──→ APPROVED(已审批)
│ │
│ ├─[车辆出发/开始提油]──→ IN_PROGRESS(执行中)
│ │ │
│ │ ┌─────────┴──────────┐
│ │ [正常完成] [异常终止]
│ │ ↓ ↓
[变更/取消] COMPLETED ABNORMAL
│ ↓
└──────────────────→ CANCELLED(已取消)

└─[触发]──→ 新建替代计划(parent_plan_id 指向本计划)

几个关键设计决策:

  1. 审批后才锁定车辆和仓位分配,草稿阶段可以自由调整
  2. 执行中的计划不允许直接修改,需走取消流程后重新调度
  3. 自动生成的计划只创建草稿,调度员始终保有最终决策权

订单状态联动

订单状态随调度计划的创建和取消实时联动:

1
2
3
4
PENDING(待调度)
→ PARTIAL(部分调度) dispatched_qty > 0 且 < ordered_qty
DISPATCHED(全量调度) dispatched_qty = ordered_qty
→ COMPLETED(已完成) 所有关联调度均为 COMPLETED 状态

回退逻辑:关联调度被 CANCELLED 时,dispatched_qty 需回退,订单状态可能从 DISPATCHED 退回 PARTIALPENDING


自动推荐方案框架

调度员触发”系统推荐”时,系统执行以下三步:

第一步:需求聚合

1
2
3
收集所有 status = PENDING 或 PARTIAL 的订单
按油品类型分组
计算每种油品的待调度总量和油站分布

第二步:车辆匹配

1
2
3
4
5
6
筛选 status = 可用 的车辆
按仓位容量和油品组合尝试装载方案
优先原则:
① 尽量装满车(减少空仓浪费)
② 同路线订单合并(减少趟次)
③ 大仓对大订单(减少跨仓拆分)

第三步:生成草稿

1
2
3
生成若干个 DRAFT 状态的调度计划
调度员在草稿基础上手动调整仓位分配和配送顺序
确认后提交审批,进入 APPROVED 状态

自动推荐只是”辅助决策”,不替代调度员的最终判断。这一设计平衡了系统效率与人工灵活性。


整体实体关系总览

1
2
3
4
5
6
7
8
9
10
order ──────────────────────────────────────────────┐
(station_id, oil_type, ordered_qty)
│ 多对多(通过明细桥接)
dispatch_plan
├── vehicle ──→ vehicle_compartment │
├── depot │
└── dispatch_compartment
(仓位 + 油品 + 计划量) │
└──→ dispatch_order_item ──────────────┘
(订单 + 站点 + 分配量 + 配送顺序)

小结

本方案的几个核心设计思路:

  1. 两张明细表分离关注点dispatch_compartment 管装载,dispatch_order_item 管配送,清晰应对混装场景
  2. parent_plan_id 实现变更链:作废重建而非原地修改,保留完整历史
  3. dispatched_qty 冗余字段:空间换时间,避免高频联表聚合
  4. 自动推荐只生成草稿:人机协同,系统提效但不替代人工决策
  5. delivery_seq 显式记录配送顺序:支持调度员手动调整,也为后续路线优化预留扩展点

后续可进一步扩展的方向包括:路线优化算法、实际量与计划量的偏差处理、跨库调度支持等。


油品运输调度计划系统设计
http://eevann.cn/2026/04/17/oil-dispatch-plan-design/
作者
月下独白
发布于
2026年4月17日
许可协议