front/src/views/order/orderGuide/guide.md
zzh 6441ca6543 feat: show batch track upsert responses and improve price check UX
Display track upsert request/response in batch job and order modals, relax price check dimensions with disclaimer UI, and update order guide and design docs.
2026-07-23 10:24:20 +08:00

23 KiB
Raw Blame History

订单中心新手指引

本文面向第一次接触 订单模块(OMS Order) 的运营、客服、产品与开发同学。
第三章 以 POST /order/parcel/create 为核心,用流程图拆解 CreateParcelCoreAsync 的业务校验、分区运算、计重算价、排货选渠全链路。


1. 系统是什么?

订单模块负责:查价试算、小包预报(创建订单)、订单全生命周期、Excel 导入、批量异步任务。

后端入口:OrderService(Oms.Application.Services.Orders),Swagger 分组 OMS-Order。

心智模型: 创建订单 = 预报应收流水线 — 绑快照 → 校验地址 → 计重 → 匹配分区 → 仅写应收(forecast) → 状态 predeclared。排货与渠道买价在入库环节处理(失败则 pendingAllocation 待排货,不阻断收货与应收)。

全链路: 查价(参考)→ 下单(预报应收)→ 入库(实测 + 应收 + 可选排货)→ 付款 → 出库(发货实测 + outbound 应收)。


2. 核心概念速查

概念 说明
ProductCode 客户选的运输方式,对应销售产品
ChannelCode 服务渠道,系统排货自动写入,客户不手选
Rules 快照 计重/黑名单/偏远/排货/providers,版本 SalesProductRulesVersion
Price 快照 卖价矩阵 + 价格分区明细,版本 SalesProductPriceVersion
zoneKeys 价格分区匹配后生成的「分区键」列表,用于价格矩阵行匹配
forecast 重量 预报阶段计重行,应收费用用它
downstream 重量 下游计重行,排货应付费用用它(可与 forecast 相同)
ChargingStage forecast / inbound / outbound,费用按阶段区分
AllocationPendingReason 入库排货/渠道买价未匹配时的原因(pendingAllocation 状态展示)

订单状态(生命周期相关)

状态 含义
draft 草稿;预报计费失败时保留,并写 PredeclareFailReason
predeclared 创建成功后的默认状态(仅预报应收,未排货)
pendingAllocation 待排货:已入库、应收已算,但排货/渠道买价未成功
pendingPayment 待支付(入库排货成功或手动重算应付成功后)
pendingShip 待发货(已付款)
pendingOnline 待上网(已出库)

运单号(ServiceNo)

项 规则
前缀 IDE
格式 IDE + yyMMddHHmmss(年份取后两位,如 2026 → 26)+ 4 位随机数
示例 IDE2607221859123456
自定义 请求体可传 serviceNo,须唯一;否则服务端自动生成

3. 创建订单接口全链路(重点)

3.1 API 与代码入口

项目 值
HTTP POST /order/parcel/create
方法 OrderService.CreateParcelAsync → CreateParcelCoreAsync
文件 OrderService.ParcelBilling.cs
算价引擎 ParcelBillingCalculator.cs
排货选渠 AllocationResolver.cs

以下入口最终都调用同一核心方法:

入口 API / 动作
页面下单 POST /order/parcel/create
JSON 批量 POST /order/parcel/batch-create(≤2000)
Excel 导入 POST /order/upload → 行映射后调用
MQ Worker parcel-create / import-row

3.2 总览流程图

flowchart TD
  A[POST /order/parcel/create] --> B{RequestId 已存在?}
  B -->|是| Z1[返回已有订单 BuildParcelCreateOutput]
  B -->|否| C[NormalizeParcelCreateInput<br/>清空 TrackNo/ServiceNo]
  C --> D[ResolveEffectiveCustomer 解析客户]
  D --> E[ValidateParcelCreateInputAsync<br/>业务校验]
  E -->|失败| X1[抛 BusinessException<br/>不落库]
  E --> F[加载 SalesProduct 须启用]
  F -->|失败| X1
  F --> G[ResolveSnapshotBindingAsync<br/>绑 rules+price 快照]
  G -->|失败| X1
  G --> H[解析目的国 Country]
  H --> I{IsBlacklistHitAsync?}
  I -->|命中| X1
  I --> J[生成 ServiceNo IDE+yyMMddHHmmss+随机]
  J --> K[Insert t_order 草稿]
  K --> L[SaveParcelChildren<br/>收发件/申报/4行重量]
  L --> M{预报计费 try}
  M --> N[偏远判定 IsRemote]
  N --> O[ApplyChargeableWeightAsync 计重]
  O --> P[ResolveOrderBillingContext 分区]
  P --> Q[UpsertReceivableFeesAsync 应收 forecast]
  Q --> S[OrderStatus=predeclared]
  S --> T[轨迹 Upsert + 自动触发]
  T --> Z2[返回 OrderParcelCreateOutput]
  M -->|异常| U[MarkParcelDraftFailedAsync<br/>draft + PredeclareFailReason]
  U --> X2[抛 BusinessException]

关键分界: 黑名单校验在 Insert 之前,失败完全不落库;计重/分区/算价/排货在 Insert 之后 的 try 块内,失败会保留 draft 订单并记录失败原因。


3.3 阶段一:入参规范化与业务校验(落库前)

3.3.0 客户身份解析 ResolveEffectiveCustomerAsync

在规范化与校验之前,系统会先解析「这笔单属于哪个客户」:

flowchart TD
  C0[ResolveEffectiveCustomerAsync] --> C1{当前登录身份}
  C1 -->|客户账号| C2[忽略入参 CustomerId<br/>强制使用会话客户]
  C1 -->|管理员/运营| C3{入参 CustomerId > 0?}
  C3 -->|否| CE1[客户ID不能为空]
  C3 -->|是| C4[按 CustomerId 查库]
  C4 --> C5{客户存在且 Status=Normal?}
  C5 -->|否| CE2[客户不存在或状态不可用]
  C5 --> C6[写回 input.CustomerId]

客户门户下单时无需手填 CustomerId;后台代客下单必须显式传入有效客户 ID。

3.3.1 规范化 NormalizeParcelCreateInput

字段 处理
TrackNo 强制置 null(不允许客户端传入)
ServiceNo 强制置 null(系统生成)
ClientNo Trim;空则 null
RequestId Trim;用于幂等

3.3.2 业务校验 ValidateParcelCreateInputAsync

flowchart TD
  V0[开始校验] --> V1{ClientNo 非空?}
  V1 -->|否| E1[客户单号不能为空]
  V1 --> V2{CustomerId > 0?}
  V2 -->|否| E2[客户ID不能为空]
  V2 --> V3{同客户 ClientNo 唯一?}
  V3 -->|重复| E3[客户单号已存在]
  V3 --> V4{ProductCode 非空?}
  V4 -->|否| E4[产品代码不能为空]
  V4 --> V5{WarehouseId > 0?}
  V5 -->|否| E5[仓库ID不能为空]
  V5 --> V6{长宽厚实重均 > 0?}
  V6 -->|否| E6[件重尺必须大于0]
  V6 --> V7{CargoAttribute 合法?}
  V7 -->|否| E7[货物属性不合法<br/>general/electronics/sensitive]
  V7 --> V8{ExportCustomsMode 合法或空?}
  V8 -->|否| E8[出口报关方式不合法]
  V8 --> V9{DeclaredCurrency 非空?}
  V9 -->|否| E9[申报币种不能为空]
  V9 --> V10{Quantity > 0?}
  V10 -->|否| E10[包裹数量不能为空]
  V10 --> V11{收件人完整?}
  V11 -->|否| E11[收件人信息不完整<br/>姓名/国家/邮编/地址1]
  V11 --> V12{发件人姓名非空?}
  V12 -->|否| E12[发件人姓名不能为空]
  V12 --> V13{申报明细 Items 非空?}
  V13 -->|否| E13[申报明细不能为空]
  V13 --> V14[逐行校验申报品<br/>EnName/UnitPrice/UnitWeight/Quantity]
  V14 --> V15{仓库存在?}
  V15 -->|否| E15[仓库不存在]
  V15 --> V16{客户存在且状态正常?}
  V16 -->|否| E16[客户不存在或状态不可用]
  V16 --> OK[校验通过]
校验项 规则 失败文案
幂等 RequestId 已有订单则直接返回 —
客户单号 非空;同 CustomerId 下唯一 客户单号不能为空 / 已存在
产品 ProductCode 非空 产品代码不能为空
仓库 WarehouseId > 0 且记录存在 仓库ID不能为空 / 仓库不存在
件重尺 长/宽/高/实重均 > 0 件重尺必须大于0
货物属性 general / electronics / sensitive 货物属性不合法
申报 币种、数量、明细行必填完整 见上
收件人 姓名、国家、邮编、地址1 收件人信息不完整
客户 存在且 Status=Normal 客户不存在或状态不可用

3.3.3 产品与快照(仍在落库前)

flowchart TD
  P1[GetByProductCode] --> P2{产品存在且 IsActive?}
  P2 -->|否| E[销售产品不存在或未启用]
  P2 --> P3[ResolveSnapshotBindingAsync bindTime=Now]
  P3 --> P4[取 rules 生效发布记录]
  P3 --> P5[取 price 生效发布记录]
  P4 -->|无| P4L[BuildLiveRulesSnapshot 内存拼装]
  P4 -->|有| P4S[反序列化 rules Content]
  P5 -->|无| P5L[BuildLivePriceSnapshot]
  P5 -->|有| P5S[反序列化 price Content]
  P5L --> P5C{Prices.Count>0?}
  P5C -->|否| E2[未命中价格快照版本]
  P4L --> P4R{WeightRuleId 有值?}
  P4R -->|否| E3[未命中规则快照版本]
  P3 --> P6[写入绑定版本号<br/>RulesVersion / PriceVersion]
  P6 --> P7[解析目的国 CountryCode]
  P7 --> P8{黑名单命中?}
  P8 -->|是| E4[收件地址命中黑名单区域]

快照选取规则: PublishTime <= bindTime 且 Status=生效 的最新发布记录;无记录则 LIVE-{productId},价格侧必须有启用价格项,规则侧 LIVE 时必须有 WeightRuleId。


3.4 阶段二:落库草稿

步骤 动作 写入表/字段
1 ResolveServiceNoAsync 运单号 IDE{yyMMddHHmmss}{4位随机}
2 BuildDraftOrderEntity t_order:产品、国家、快照版本、初始 draft;创建阶段不写 ChannelCode 排货结果
3 BuildInitialWeightRows t_order_weight 四行:forecast / receive / ship / downstream
4 SaveParcelChildren t_order_sender、t_order_recipient、t_order_declaration

初始重量行: 四行复制同一套长宽厚实重;Cubic = L×W×H/1,000,000;后续计重结果通过 SyncWeightRows 同步到全部四行。


3.5 阶段三:预报计费(try 块内)

3.5.1 子流程总图

flowchart TD
  T1[偏远 IsRemoteHitAsync] --> T2[ApplyChargeableWeightAsync<br/>仅算 forecast 行]
  T2 --> T3[SyncWeightRows 同步四行重量]
  T3 --> T4[ResolvePriceZoneKeysAsync]
  T4 --> T5{zoneKeys 非空?}
  T5 -->|否| E1[价格分区未匹配]
  T5 --> T6[UpsertReceivableFeesAsync<br/>ChargingStage=forecast]
  T6 --> T8[status=predeclared]

创建阶段不算应付、不排货。 渠道与买价在 入库 ApplyReceiveBillingByWaybillAsync 中通过 TryConfirmServiceChannelAndPayableAsync 尝试;失败写入 AllocationPendingReason,订单进 pendingAllocation,仍保留入库实测与 inbound 应收。


3.5.2 偏远判定 IsRemoteHitAsync

与黑名单逻辑对称,但不阻断创建,只写 order.IsRemote:

  1. 解析有效 RemoteAreaId(产品 → 规则快照 → 快照内 Product);
  2. 优先用快照内 RemoteAreaInfos 匹配;
  3. 否则查库 t_kpi_area_info;
  4. 匹配规则:国/省/市相等 + 邮编区间 左开右闭 (left, right]。

3.5.3 计重运算 ApplyChargeableWeightAsync

flowchart TD
  W1[取 WeightRuleId] --> W2{有计重规则?}
  W2 -->|否| E1[未配置计重规则]
  W2 --> W3[加载规则明细 ruleInfos<br/>优先快照 WeightRuleInfos]
  W3 --> W4[CalculateRawBillableWeight]
  W4 --> W5[逐条规则按 Id 排序]
  W5 --> W6[体积重 vw = L×W×H / 泡比因子]
  W6 --> W7{Condition 命中?<br/>gw/vw 表达式}
  W7 -->|否| W5
  W7 -->|是| W8[raw = BillableWeight 为 gw 或 vw]
  W8 --> W9[ApplyRounding 进位]
  W9 --> W10[命中进位区间 Start~End]
  W10 --> W11[ChargeableWeight = ceil raw/unit × unit]
  W11 --> W12[写 forecast.VolumetricWeight / ChargeableWeight]
运算 公式/规则
体积 Cubic = L×W×H / 1,000,000(保留 6 位)
体积重 vw = L×W×H / VolumetricFactor(保留 3 位)
条件 Condition 表达式,变量 gw/vw,如 gw>=vw
原始计费重 BillableWeight=gw 取实重,否则取体积重
进位 找 StartValue ≤ raw ≤ EndValue 的区间,ceil(raw/Public)×Public

失败文案: 未配置计重规则 / 计重进位 / 计重规则条件均未命中 / 计重进位区间未匹配。


3.5.4 价格分区匹配 ResolvePriceZoneKeysAsync

flowchart TD
  Z1{price 快照含 PriceAreaInfos?}
  Z1 -->|是| Z2[快照内逐条匹配国省市邮编]
  Z1 -->|否| Z3[ResolveEffectivePriceAreaId]
  Z3 --> Z4[查 t_kpi_area + info 明细]
  Z2 --> Z5{命中一条?}
  Z4 --> Z5
  Z5 -->|否| Z6[返回 null → 创建失败]
  Z5 --> Z7[BuildPriceZoneKeys]
  Z7 --> Z8[生成 zoneKeys 列表<br/>分区名/Id/省/市等]

地址匹配规则(黑名单/偏远/价格分区通用):

维度 规则
国家 配置了则必须相等(忽略大小写)
省/市 配置了则必须相等
邮编 配置了左右端点则必须落在区间内;数字按数值比,否则按字符串比
邮编区间 左开右闭 (left, right]

失败文案: 价格分区未匹配(规则快照)


3.5.5 应收费用 UpsertReceivableFeesAsync

输入:price 快照、forecast.ChargeableWeight、zoneKeys、CargoAttribute、CustomerGroup、chargingStage=forecast。

flowchart TD
  R1[遍历卖价快照中 Status=1 的价格项] --> R2[MatchPriceDetail 匹配明细行]
  R2 --> R3{分区因素匹配 zoneKeys?}
  R3 --> R4{货物属性匹配?}
  R4 --> R5{仓库因素匹配?}
  R5 --> R6{重量区间匹配?<br/>左开右闭}
  R6 -->|命中| R7[CalculateDetailAmount]
  R7 --> R8{公式类型}
  R8 -->|total| R9[客户组价或 CalculatedValue]
  R8 -->|unit| R10[单价 × 计费重]
  R8 -->|continue| R11[首重价 + 续重 × 续单价]
  R9 --> R12[写入 OrderFee type=receivable]
  R10 --> R12
  R11 --> R12
  R2 -->|无匹配| R1
  R12 --> R13{有费用行 或 无启用项?}
  R13 -->|有启用项但零匹配| E[产品卖价快照未配置或未匹配到有效价格]
价格明细匹配 说明
分区因素 FactorValuesJson 中「分区」须与 zoneKeys 任一相等
货物属性 因素含货物类型时须匹配 general/electronics/sensitive
重量段 (start, end],多段命中取区间最窄的一条
客户组价 CustomerGroupValues 按客户组取价,否则 CalculatedValue

3.5.5.1 价格明细匹配 MatchPriceDetail(应收/应付共用)

flowchart TD
  M0[遍历价格项全部 Details] --> M1{分区因素与 zoneKeys 相交?}
  M1 -->|否| M0
  M1 --> M2{货物类型因素匹配?<br/>无因素则跳过}
  M2 -->|否| M0
  M2 --> M3{仓库因素匹配?<br/>创建订单时通常无仓库因素}
  M3 -->|否| M0
  M3 --> M4{明细含重量因素?}
  M4 -->|否| M5[暂记为候选 bestMatch]
  M4 -->|是| M6[解析重量区间 左开右闭]
  M6 --> M7{chargeableWeight 在区间内?}
  M7 -->|否| M0
  M7 --> M8[区间宽度 = end - start]
  M8 --> M9{比当前 best 更窄?}
  M9 -->|是| M10[更新 bestMatch]
  M9 -->|否| M0
  M5 --> M0
  M10 --> M0
  M0 -->|遍历结束| M11[返回 bestMatch 或 null]

重量区间解析规则:

配置写法 解析结果 示例
单值 0.5 (0, 0.5] 0.5kg 以内
区间 0,0.5 或 0-0.5 (0, 0.5] 同上
区间 0.5,1 (0.5, 1] 0.5kg 以上至 1kg

3.5.5.2 金额计算公式 CalculateDetailAmount

匹配到明细行后,按 CalculationFormula 计算金额:

flowchart TD
  F0[命中明细行] --> F1{CalculationFormula}
  F1 -->|total| F2[客户组价 ?? CalculatedValue]
  F1 -->|unit| F3[单价 × 计费重<br/>round 4 位小数]
  F1 -->|continue| F4{能关联上一档 total 价?}
  F4 -->|是| F5[basePrice + 计费重-区间起点 × 续单价]
  F4 -->|否| F6[首重价 + ceil溢出/续重单位 × 续单价]
  F1 -->|其他| F7[CalculatedValue 或 0]
公式类型 计算逻辑 展示公式示例
total 固定总价;优先读 CustomerGroupValues[客户组] 12.5
unit 单价 × ChargeableWeight 3.2*1.5
continue(关联上档) 找同分区上一重量档的 total 价为 base,超出部分 × 续单价 10+(1.5-0.5)*8
continue(单行首续重) 首重价 + ceil((计费重-首重)/续重单位) × 续单价 10+2*5

应收遍历卖价快照全部 Status=1 价格项,每项独立匹配明细;应付对渠道买价快照做同样逻辑。若存在启用项但全部匹配失败且金额为 0,则抛错。


3.5.6 入库排货与应付(创建时不执行)

排货逻辑在 入库收货 时调用 TryConfirmServiceChannelAndPayableAsync(失败不抛异常):

flowchart TD
  A1[入库实测件重尺 receive 行] --> A2[重算 inbound 应收]
  A2 --> A3[TryConfirmServiceChannelAndPayableAsync]
  A3 -->|成功| A4[OrderStatus=pendingPayment<br/>清空 AllocationPendingReason]
  A3 -->|失败| A5[OrderStatus=pendingAllocation<br/>写 AllocationPendingReason]
Scheme 选渠规则
costLowest(默认) 应付总额最小,同价按序号
timeFastest 渠道 MinTime 最小
overallBest 服务商 Weight(评分)最大

注意: 入库排货应付使用 receive 行的 ChargeableWeight(实测后重算)。手动「重算应付」成功也会清原因并改为 pendingPayment。

写入订单字段(排货成功时): ChannelCode、DownstreamSupplierCode、DownstreamAppKey、ChannelForecastCode 等。


3.6 阶段四:成功收尾与失败处理

成功

步骤 说明
状态 OrderStatus = predeclared,清空 PredeclareFailReason
轨迹 EnqueueSmallBagTrackUpsertAsync 异步小包轨迹
触发 AutoTriggerRuntimeService.FireAsync(OrderCreate),失败不影响主流程
返回 OrderParcelCreateOutput(运单号、费用摘要等)

失败 MarkParcelDraftFailedAsync

场景 订单状态 字段
计重/分区/应收/排货任一抛错 保持 draft PredeclareFailReason = 异常信息

落库前校验失败(黑名单、快照缺失等):不 Insert,直接 BusinessException。
落库后计费失败:订单已存在,状态 draft,便于排查与重试。


3.7 创建过程数据流一览

flowchart LR
  subgraph Input
    I1[OrderParcelCreateInput]
  end
  subgraph Snapshot
    S1[Rules Snapshot]
    S2[Price Snapshot]
    S3[Channel Price Snapshot]
  end
  subgraph Compute
    C1[ChargeableWeight]
    C2[zoneKeys]
    C3[Receivable Fees]
    C4[Payable Fees]
  end
  subgraph DB
    D1[t_order]
    D2[t_order_weight x4]
    D3[t_order_fee]
  end
  I1 --> S1
  I1 --> S2
  S1 --> C1
  C1 --> C2
  S2 --> C2
  C2 --> C3
  S1 --> C4
  S3 --> C4
  C3 --> D3
  C4 --> D3
  I1 --> D1
  I1 --> D2
  C1 --> D2

3.8 常见失败原因速查(创建/预报)

报错关键词 排查方向
销售产品不存在或未启用 渠道 → 销售产品状态
未命中价格/规则快照 是否发布;LIVE 时是否有价格项/计重规则
收件地址命中黑名单 黑名单分区明细 + 产品关联
价格分区未匹配 价格分区是否覆盖目的邮编/省市
未配置计重规则/进位 产品配置 + 规则发布快照
计重规则条件均未命中 件重尺与规则 Condition
卖价未匹配到有效价格 卖价矩阵分区/重量段/货物属性
卖价未匹配到有效价格 卖价矩阵分区/重量段/货物属性
入库排货失败 订单为 待排货,查 AllocationPendingReason;补排货规则/渠道买价后重算应付
客户单号已存在 同客户重复下单

4. 查价 vs 创建 vs 入库 vs 出库

4.1 环节对比

对比 查价 下单(预报) 入库 出库
接口 POST /order/price-check POST /order/parcel/create POST /operation/inbound/create POST /operation/outbound/create
落库 否 是 写入库记录 + 订单 写出库记录 + 订单
尺寸 可选(全空按实重估算) 必填 长/宽/高/实重 > 0 实测必填 实测必填
邮编/黑名单 无邮编则跳过黑名单/偏远 必填邮编,黑名单硬拦截 用订单已有地址 —
计费 参考价,queryHint + quoteLevel 仅 forecast 应收 inbound 应收 + 可选排货应付 outbound 应收
排货 不执行 不执行 可选;失败 → pendingAllocation 不执行
状态 — predeclared pendingPayment 或 pendingAllocation pendingOnline(须已付款)

4.2 查价宽松规则(对客)

  • 必填:目的国 + 实重 > 0。
  • 尺寸:全空或三者齐全;部分填写会报错。
  • 未填邮编:不校验黑名单;分区无匹配时可 zone 兜底(取最低价分区,标记为估算)。
  • 未选货物属性/仓库:按 全部启用产品 × 全部仓库 × 货物类型展开(general/electronics/sensitive)试算。
  • 响应 queryHint.disclaimers、每行 quoteLevel(exact / estimated)提示「仅供参考,入库实测后可能调整」。

4.3 共用校验 ParcelBillingValidators

方法 用途
EnsurePriceCheckDimensions 查价:尺寸全空或齐全
EnsurePositiveDimensions 下单/入库/出库:件重尺均 > 0
EnsureInboundOrderStatus 入库:仅 predeclared / pendingAllocation

5. 其他菜单(简表)

菜单 路径 功能
新手指引 /order/guide 本文档
我要查价 /order/priceCheck 运费试算
我要下单 /order/placeOrder 单笔/Excel 导入
我的订单 /order/myOrders 列表/付款/拦截/费用
模板字段映射 /order/templateMapping 自定义 Excel 列映射
批量任务 /order/batchJobs MQ 批处理监控

6. 后端代码索引

主题 文件 / 方法
创建主流程 OrderService.ParcelBilling.cs → CreateParcelCoreAsync
入参校验 ValidateParcelCreateInputAsync + ParcelBillingValidators
快照绑定 ResolveSnapshotBindingAsync / ResolveOrderBillingContextAsync
计重 ApplyChargeableWeightAsync + ParcelBillingCalculator
应收 UpsertReceivableFeesAsync
入库排货 ApplyReceiveBillingByWaybillAsync → TryConfirmServiceChannelAndPayableAsync
出库 ApplyShipBillingByWaybillAsync
查价 OrderService.ParcelQuote.cs + PriceCheckHintBuilder
运单号 ResolveServiceNoAsync → IDE{yyMMddHHmmss}{随机}
API 路由 OrderService.cs → CreateParcelAsync

7. 推荐阅读顺序

  1. 本文 §3 创建流程 + §4 全链路对比;
  2. 渠道新手指引(快照发布、排货配置、渠道买价);
  3. 用 我要查价 看参考价,再 我要下单 下测试单;
  4. 运营 入库/出库 扫描,在「我的订单」核对状态与费用;
  5. 预报失败对照 §3.8 与 PredeclareFailReason;待排货对照 AllocationPendingReason。