本文说明 DGJ2.0 中服务站间调拨申请、发货站调出、申请站调入、撤销调出、调拨收付款,以及旧普通调拨 TF 与新申请式 STF 的关系。
服务站间调拨同时跨越两个服务站、两组库存空间、一个在途阶段和后续财务结算。排查时不能只看一张主表,也不能把“已出库”等同于“对方已入库”,更不能把库存完成等同于款项已结算。
阅读后应能回答:
- 谁是申请方、谁是发货方,
sid 和 toSid 在不同表中分别代表谁。 - 一次包含多个发货站的申请为什么会拆成多张申请单。
- 申请数量、出库数量、入库数量和结算金额如何传递。
- 出库、入库分别写哪些主表、明细、库存流水和实时库存。
- 调出库存为什么要扣除采购/销售锁定量。
- 出库后如何撤销,为什么已收付款后禁止撤销。
- 调拨收付款是否由入库自动生成。
t_scm_tf_invoice、t_scm_stf_invoice、t_scm_stf_apply 三套表应如何区分。- 出现“发货站已扣、收货站未加”“金额对不上”“撤销后库存没恢复”时如何定位。
结论先行:申请式 STF 的库存主链是 Apply -> Invoice::out -> Invoice::in。调出和调入都使用 transType=103092,方向由明细数量正负和 entryId 区分。调入完成不会自动创建收付款,财务结算通过独立的调拨收款 154001 / 调拨付款 154002 入口完成。
1. 业务边界
1.1 本文覆盖
1.2 不属于本文
- 普通采购入库、销售出库,见采购和销售专题。
- PDA 货位调整,见《26_PDA_GPDA扫码盘点与仓内作业》。
- 微仓补货拆单的全部业务,本文只说明它与
TF_SOURCE_TYPE_MOVE 和旧调拨入口的交点。 - 财务总账、账户分片和收付款通用规则,见《18_财务和支付排查手册》。
2. 三套“调拨”概念
2.1 申请式 STF
当前专题主流程:
t_scm_stf_apply / t_scm_stf_apply_info
-> t_scm_stf_invoice / t_scm_stf_invoice_info
-> 库存流水 / 实时库存
先由调入方发起申请,再由调出方确认出库,最后调入方入库。
2.2 旧服务站间 STF
旧控制器 scm/InvTf.php 和 InvTfService.php 仍保留 addSTF、saveTFIn、addTFpayment 等方法。历史 t_scm_stf_invoice 数据可能没有 apply_bill_no,迁移任务曾尝试补造申请记录,但任务入口当前以 exit("初始化已完成") 直接停止。
2.3 普通 TF
普通 TF 使用:
t_scm_tf_invoicet_scm_tf_invoice_infotransType=103091
它主要描述同一服务站内的自定义调拨或微仓调拨,状态由 TfInvoiceEnums 管理,不应套用申请式 STF 的状态。
flowchart TB
A["业务说‘调拨’"] --> B{"是否跨服务站?"}
B -->|否| C["普通 TF: t_scm_tf_invoice, 103091"]
B -->|是| D{"是否先有调拨申请?"}
D -->|是| E["申请式 STF: apply + stf_invoice, 103092"]
D -->|否/历史数据| F["旧 STF: InvTfService 历史入口"]
3. 角色、方向与标识
3.1 参与者
3.2 关键标识
3.3 sid / toSid 方向
在 t_scm_stf_invoice 主表中:
调出明细同样是 sid=调出方、toSid=调入方;调入明细当前代码写 sid=调入方、toSid=调入方。因此不能只靠调入明细 toSid 追溯原始发货站,必须关联调拨主表。
4. 系统和代码地图
flowchart TB
IN["申请站 PC"] --> AC["stf/Apply Controller"]
AC --> AS["Stf/ApplySer"]
AS --> AP[("stf_apply")]
AS --> MQ["RabbitMQ 站内消息"]
MQ --> OUT["发货站待办"]
OUT --> IC["stf/Invoice Controller"]
IC --> IS["Stf/InvoiceSer"]
IS --> IV[("stf_invoice")]
IS --> INV["Storage/InventorySer"]
INV --> LEDGER[("库存流水128分片")]
INV --> RT[("实时库存")]
FIN["财务人员"] --> LEG["scm/InvTf + InvTfService"]
LEG --> PAY[("Payment 32分片")]
LEG --> ACC[("Account 16分片")]
4.1 新申请式入口
4.2 核心服务
4.3 迁移和服务化痕迹
5. 数据模型
5.1 核心表
5.2 实体关系
erDiagram
STF_APPLY ||--|{ STF_APPLY_INFO : "apply_id"
STF_APPLY ||--o| STF_INVOICE : "apply_bill_no"
STF_INVOICE ||--|{ STF_INVOICE_INFO : "iid"
STF_INVOICE_INFO }o--|| INVENTORY_REAL_TIME : "库存维度"
STF_INVOICE_INFO ||--o| INVENTORY_LEDGER : "库存动作"
STF_INVOICE_INFO ||--o{ PAYMENT_INFO : "billNo_stlNo"
PAYMENT ||--|{ PAYMENT_INFO : "iid"
5.3 申请明细数量
0 <= in_qty <= out_qty <= apply_qty
并且整单 total_out_qty > 0
6. 状态机
6.1 申请状态
stateDiagram-v2
[*] --> 待出库
待出库 --> 已取消: 申请方 cancel
待出库 --> 已驳回: 发货方 cancel
待出库 --> 待入库: 发货方 out
待入库 --> 待出库: 发货方 rollback
待入库 --> 已入库: 申请方 in
已取消 --> [*]
已驳回 --> [*]
已入库 --> [*]
6.2 调拨库存主单状态
调入不是新建第二张主单,而是在原调拨主单上写 toBillNo、状态改 2,并追加 entryId=1 的调入明细。
6.3 普通 TF 状态
普通 TF 状态 1/2/3/4/5 与申请式 STF 的 0/1/2/3/4 不是同一套枚举。
7. 创建申请:按发货站拆单
7.1 代表性请求
{
"remark": "门店补货",
"data": "[{\\"deliver_sid\\":20002,\\"inv_id\\":31001,\\"apply_qty\\":3,\\"remark\\":\\"急用\\"},{\\"deliver_sid\\":20003,\\"inv_id\\":31002,\\"apply_qty\\":2,\\"remark\\":\\"\\"}]"
}
服务端从会话注入 JXCSID、JXCUID 和 JXCUNAME,业务层不应信任客户端替代会话上传申请站。
7.2 拆单流程
flowchart TD
A["接收商品数组"] --> B["逐行校验商品/数量/发货站"]
B --> C{"发货站等于当前站?"}
C -->|是| D["拒绝"]
C -->|否| E["按 deliver_sid 分组"]
E --> F["批量查服务站和商品物料"]
F --> G{"同发货站商品重复?"}
G -->|是| H["拒绝整批"]
G -->|否| I["补 SKU/单位/包装/站名"]
I --> J["返回拆单预览"]
一份数据包含两个 deliver_sid 时,format() 返回两组,create() 在同一事务中创建两张申请主单及各自明细。
7.3 创建时序
sequenceDiagram
participant U as 申请站
participant C as Apply Controller
participant S as ApplySer
participant A as stf_apply
participant D as stf_apply_info
participant Q as RabbitMQ
U->>C: create(remark,data)
C->>S: format并按发货站拆组
loop 每个发货站
S->>A: 插入申请主表
S->>D: 批量插入商品明细
end
S-->>C: messageData
C->>Q: 每张申请发送提醒
申请事务提交后控制器才逐条发消息。多张拆单消息可部分成功,MQ 失败不会回滚申请。
7.4 创建校验和代码风险
8. 通知、催办、取消和驳回
8.1 新申请消息
{
"billNo": "申请单号",
"sid": 20002,
"type": 2
}
sid 是发货服务站,type=2 是 MessageTypeEnums::APPLY。消息通过 DEST_DGJ + TYPE_CREATE_SAAS_ORDER 发送,页面指向 /stf/apply?action=list。
8.2 催办
只有申请方且状态 0 才能催办;催办只重发提醒,不改状态,代码中未见频率限制。
flowchart LR
A["申请方催办"] --> B{"当前站=apply_sid?"}
B -->|否| C["非法请求"]
B -->|是| D{"状态=0?"}
D -->|否| E["拒绝"]
D -->|是| F["重发 APPLY 消息"]
8.3 取消和驳回
此时尚未出库,只写取消时间和操作人,不恢复库存、不处理资金。
9. 调出展示与调拨价
outShow() 要求当前站是 deliver_sid 且申请状态为 0,并通过 AllotSer::getStorageAndArea() 附加可选仓库、货位和库存。
价格模板包含名称、物料编码、最近采购价、调拨价。导入按 SKU 是否属于申请判断,成功行只返回前端,最终价格仍以 out() 请求为准。
10. 发货站调出
10.1 代表性请求
{
"id": 9001,
"data": "[{\\"id\\":9101,\\"out_qty\\":3,\\"out_price\\":25.50,\\"locationId\\":101,\\"locationAreaId\\":1001}]"
}
请求中的明细 id 是申请明细主键,不是 invId。
10.2 控制器并发锁
Invoice::out() 调用:
redis_lock([Invoice, out, sid, apply_id], 3)
静态代码只能证明锁键包含站点和申请主键;参数 3 的 TTL/锁模式、是否自动释放和续期,需要结合全局 redis_lock() 实现及真实并发测试确认。
10.3 调出校验
可调数量 = 货位实时库存 - unsaleLockNum
可调数量 >= out_qty
unsaleLockNum() 来自采购订单明细模型,用于排除已经被其他业务锁定、不可再调出的库存。
10.4 调出明细符号
10.5 调出事务
sequenceDiagram
participant O as 发货站
participant C as Invoice Controller
participant S as InvoiceSer
participant A as 申请表
participant T as STF调拨表
participant I as InventorySer
participant R as 实时库存
participant Q as MQ
O->>C: out(apply_id,lines)
C->>C: Redis并发锁
C->>S: out
S->>A: 校验状态0和发货站
S->>S: 校验仓库货位/库存/锁定量
S->>T: 插主表status=1和负数明细
S->>A: 状态0到1,写数量价格时间
S->>I: save负数明细
I->>R: 扣发货站实时库存
S->>S: 提交MySQL事务
S->>Q: sendInventoryEvent
10.6 调出后应有事实
11. 在途阶段
WAIT_IN=1 表示发货站已出库、申请站尚未入库:
flowchart LR
A["发货站库存 -N"] --> B["在途 N"]
B --> C["申请站库存尚未 +N"]
C --> D{"申请站执行 in?"}
D -->|是| E["申请站库存 +实际入库量"]
D -->|否| F["保持待入库"]
若没有独立在途库存表,在途量应由有效调出明细减调入明细推导,不能在申请站实时库存中查到。
12. 申请站调入
12.1 代表性请求
{
"id": 9001,
"data": "[{\\"id\\":9101,\\"in_qty\\":3,\\"locationId\\":201,\\"locationAreaId\\":2001}]"
}
12.2 调入规则
12.3 数据库行锁
select id, billStatus
from t_scm_stf_invoice
where apply_bill_no = :apply_bill_no
and isDelete = 0
for update;
同一申请的并发调入会串行读取主表,第二个请求看到状态 2 后返回“已调拨入库,请勿重复入库”。
12.4 调入明细
12.5 调入事务
sequenceDiagram
participant I as 申请站
participant C as Invoice Controller
participant S as InvoiceSer
participant A as 申请表
participant T as STF调拨表
participant W as InventoryService
participant V as InventorySer
participant Q as MQ
I->>C: in(apply_id,lines)
C->>C: Redis锁
C->>S: in
S->>A: 校验状态1和申请站
S->>T: SELECT FOR UPDATE
S->>T: 状态1到2,生成toBillNo
S->>T: 原出库明细isEnter=1,追加调入明细
S->>A: 状态1到2,写入库数量金额时间
S->>W: updateCost
S->>V: save正数明细
S->>S: 提交MySQL事务
S->>Q: sendInventoryEvent
12.6 入库金额
真正落主表的口径:
单行入库金额 = abs(调出单价) * in_qty
整单 in_price = 所有单行入库金额之和
inFormat() 内另有一个未返回使用的局部 totalInAmount,且使用 out_qty 计算。维护时不能把该废弃局部值当作最终入库金额。
13. 少入、零入与数量差异
验证允许 in_qty=0,也允许 in_qty < out_qty;调入完成后主单仍整体进入状态 2。
flowchart TD
A["out_qty=10"] --> B{"in_qty"}
B -->|10| C["库存跨站守恒"]
B -->|8| D["2件形成跨站差异"]
B -->|0| E["整行未入但主单可完成"]
D --> F["确认损耗/拒收/财务差异规则"]
E --> F
少入差异不会自动回补发货站库存。运输损耗、拒收、补发或财务差异由业务规则承担,必须在联调和结算口径中明确。
14. 撤销调出
14.1 允许条件
- 当前站是
deliver_sid。 - 申请状态是
WAIT_IN=1。 - 尚未执行调入。
PaymentInfoModel::getInfoByApplyNo() 查不到该申请收付款。
14.2 撤销事务
sequenceDiagram
participant O as 发货站
participant S as InvoiceSer
participant A as 申请表
participant T as STF调拨表
participant V as InventorySer
participant Q as MQ
O->>S: rollback(apply_id)
S->>A: 校验发货站和状态1
S->>S: 检查未收付款
S->>A: 状态1到0,out_price/out_qty归零
S->>T: 主明细isDelete=1并记删除人
S->>V: delete(iid,TRANSFER,103092)
V->>V: 恢复实时库存并作废流水
S->>S: 提交事务
S->>Q: 发送库存撤销事件
撤销后可重新调出并产生新 STF 主单;旧主单保留为 isDelete=1 的历史。排查“重复调拨单”必须先区分有效和已撤销记录。
14.3 已结算为何禁止撤销
库存撤销会恢复发货站库存,但不会自动反冲收付款和账户事实。代码因此阻断已有结算的申请,避免“库存恢复、资金仍已结算”。
15. 调拨收款和付款
15.1 与库存链分离
InvoiceSer::out() 和 in() 都不创建 Payment/Account。财务通过旧 InvTf 控制器的:
addTFpaymentpaymentListpaymentInfoupdatePaymentdeletePayment
完成独立结算。
15.2 交易类型
15.3 待结算列表
旧模型通过 stlNo 把 PaymentInfo 与调拨 billNo 关联,待结算金额由调拨金额扣除已结算金额和 diffAmount 得出。
flowchart LR
A["调拨明细 amount"] --> D["待结算金额"]
B["PaymentInfo 已结算 amount"] --> D
C["diffAmount"] --> D
D --> E["创建154001或154002"]
15.4 资金排查层次
- 调拨出/入明细金额。
- 当前站应收还是应付。
- Payment 主表 32 分片。
- PaymentInfo 32 分片的
stlNo、amount、diffAmount。 - Account 和账户流水 16 分片。
- 修改/删除收付款后的反向事实。
16. 事务与异步边界
flowchart TD
A["MySQL事务提交"] --> B["发送MQ"]
B -->|成功| C["下游同步"]
B -->|失败| D["本地主事实成功,下游滞后"]
D --> E["按申请号/调拨单号补发"]
E --> F["禁止重做out/in来补消息"]
多发货站申请的提醒是逐条发送,可能部分成功。补偿前应逐个 billNo 查消费结果。
17. 幂等、并发与唯一性
17.1 现有防线
17.2 待环境验证
apply_bill_no 是否有数据库唯一索引。- 调出 Redis 锁过期后能否并发插入两张有效 STF。
- MQ 是否有 publisher confirm、重试、死信或 outbox。
- 收付款
stlNo 是否有防重复结算唯一约束。 - 库存实时账和流水在回滚中的顺序。
17.3 客户端超时
重试前按顺序查:
- 申请状态。
apply_bill_no 对应的有效/删除 STF 数量。- 出入明细和单号。
- 两站库存流水。
- 两站实时库存。
- 再判断是否允许重试。
18. 易错代码和维护风险
19. 典型故障决策树
19.1 发货站已扣、申请站没加
flowchart TD
A["发货站已扣,申请站没加"] --> B["查申请状态"]
B -->|1 待入库| C["正常在途,确认是否执行in"]
B -->|2 已入库| D["查toBillNo和entryId=1明细"]
D --> E["查申请站103092正流水"]
E --> F["查申请站实时库存"]
F --> G{"流水和实时库存一致?"}
G -->|否| H["库存服务/分表/货位异常"]
G -->|是| I["页面缓存或查询维度错误"]
19.2 同一申请出现两张调出单
- 按
apply_bill_no 查所有 STF 主单,包括 isDelete=1。 - 一张删除、一张有效,可能是撤销后重出。
- 多张均有效时查调出时间、Redis 锁和申请状态更新时间。
- 按每张
iid 查库存流水,判断是否重复扣减。 - 修复必须成对处理 STF、流水、实时库存,禁止只软删主表。
19.3 已入库但金额对不上
flowchart TD
A["已入库金额异常"] --> B["逐行查申请/出/入数量和价格"]
B --> C["重算out_price=sum(out_qty*price)"]
B --> D["重算in_price=sum(in_qty*abs(price))"]
C --> E{"是否少入?"}
D --> E
E -->|是| F["出入金额不同可能符合当前规则"]
E -->|否| G["查价格导入/请求/重复明细"]
F --> H["再查PaymentInfo和diffAmount"]
G --> H
19.4 撤销成功但库存没恢复
- 申请是否回到状态 0。
- 原 STF 主/明细是否
isDelete=1。 - 原
iid + TRANSFER + 103092 流水是否被反向处理。 - 发货站原仓库货位实时库存是否恢复。
InventorySer::delete() 是否抛错。- 撤销库存 MQ 是否仅下游滞后。
19.5 调拨收付款没有候选
- 当前站是申请方还是发货方。
settleList.type 是 payment 还是 receipt。- 对应阶段是否已经出库/入库。
- 调拨金额是否为 0。
- PaymentInfo 已结算金额和
diffAmount 是否已覆盖全部金额。
20. 只读 SQL
以下为模板。先确认环境和字段版本,只读执行;库存、Payment、Account 按 sid 算分表。
20.1 申请主表
select id, bill_no, apply_sid, deliver_sid, bill_status,
out_price, in_price, create_time, out_time, in_time,
cancel_time, cancel_u_id, cancel_u_name
from t_scm_stf_apply
where bill_no = :apply_bill_no
or id = :apply_id;
20.2 申请明细
select id, apply_id, bill_no, inv_id, sku_id,
apply_qty, out_qty, in_qty, price, remark
from t_scm_stf_apply_info
where apply_id = :apply_id
order by id;
20.3 调拨主表
select id, apply_bill_no, billNo, toBillNo,
sid, toSid, billStatus, totalQty, totalAmount,
isDelete, createTime, delete_time, delete_uid
from t_scm_stf_invoice
where apply_bill_no = :apply_bill_no
order by id;
20.4 调拨明细
select id, iid, billNo, entryId, sid, toSid,
invId, skuId, qty, price, amount,
locationId, locationAreaId, isEnter, isDelete
from t_scm_stf_invoice_info
where iid = :iid
order by entryId desc, id;
20.5 核对跨站数量
select invId,
sum(case when entryId = 2 then abs(qty) else 0 end) as out_qty,
sum(case when entryId = 1 then abs(qty) else 0 end) as in_qty,
sum(case when entryId = 2 then abs(qty) else 0 end)
- sum(case when entryId = 1 then abs(qty) else 0 end) as diff_qty
from t_scm_stf_invoice_info
where iid = :iid and isDelete = 0
group by invId;
20.6 发货站库存流水
{out_shard}=deliver_sid%128:
select id, sid, iid, billNo, billType, transType,
invId, locationId, locationAreaId, qty, price, amount
from t_scm_inventory_0_{out_shard}
where sid = :deliver_sid
and billType = 'TRANSFER'
and transType = 103092
and billNo = :out_bill_no;
20.7 申请站库存流水
{in_shard}=apply_sid%128:
select id, sid, iid, billNo, billType, transType,
invId, locationId, locationAreaId, qty, price, amount
from t_scm_inventory_0_{in_shard}
where sid = :apply_sid
and billType = 'TRANSFER'
and transType = 103092
and billNo = :in_bill_no;
20.8 两站实时库存
select sid, inv_id, sku_id, location_id, location_area_id, qty
from t_scm_inventory_real_time
where sid in (:deliver_sid, :apply_sid)
and inv_id = :inv_id
order by sid, location_id, location_area_id;
20.9 调拨收付款
{pay_shard}=sid%32:
select p.id, p.sid, p.billNo, p.transType, p.totalAmount,
i.stlNo, i.amount, i.diffAmount, i.accId, i.isDelete
from t_scm_payment_{pay_shard} p
join t_scm_payment_info_{pay_shard} i on i.iid = p.id
where p.sid = :sid
and p.transType in (154001, 154002)
and i.stlNo in (:out_bill_no, :in_bill_no);
21. 代码和日志定位
21.1 新申请式 STF
rg -n "function (format|create|hasten|cancel|getWaitSettleList)" application/Services/Stf/ApplySer.php
rg -n "function (out|in|rollback|outFormat|inFormat)" application/Services/Stf/InvoiceSer.php
rg -n "redis_lock|for update" application/controllers/stf application/Services/Stf
21.2 库存和消息
rg -n "TRANSTYPE_TRANSFER_S|103092|BillTypeEnums::TRANSFER" application
rg -n "sendInventoryEvent|sendMailToMq|MessageTypeEnums::APPLY" application/Services application/controllers/stf
rg -n "function (save|delete)" application/Services/Storage/InventorySer.php
21.3 旧 TF/STF 和结算
rg -n "function (addSTF|saveTFIn|addTFpayment|paymentList|updatePayment)" application/controllers/scm/InvTf.php application/service/scm/InvTfService.php
rg -n "154001|154002|TFPAYMENT|stlNo|diffAmount" application/service/scm application/models
rg -n "TF_SOURCE_TYPE_|TF_BILL_STATUS_" application/KzData/Enums/TfInvoiceEnums.php
21.4 服务化路由
rg -n "SwitchRouterTransfer|NEW_DGJ_SERVICE|TransferUriProvider" application
rg -n "request-to-dgj-service|新站管家路由服务开关" application
22. 故障证据顺序
23. 回归测试矩阵
23.1 申请
23.2 调出
23.3 调入
23.4 撤销和财务
23.5 新旧兼容
24. 高风险改动
25. 已确认事实
apply_sid 是申请/调入站,deliver_sid 是发货/调出站。- 创建按
deliver_sid 拆单。 - 状态 0 才能取消、驳回、催办和调出。
- 调出数量可小于申请数量,但整单必须大于 0。
- 发货库存校验扣除
unsaleLockNum。 - 微仓不能作为调出或调入仓库。
- 调出负数量、调入正数量,交易类型均为 103092。
- 调入在 MySQL 行锁内防重复。
- 撤销只允许待入库且未收付款。
- 入库不会自动创建收付款。
- 调拨收款/付款分别为 154001/154002。
- 普通 TF 使用 103091 和另一套状态。
26. 环境待确认
27. 源码证据
28. 一页式排查顺序
flowchart TD
A["收到调拨问题"] --> B["确认新申请STF/旧STF/普通TF"]
B --> C["确认申请站、发货站、申请号"]
C --> D["查申请状态和三种数量"]
D --> E["查有效/删除STF和出入单号"]
E --> F["按entryId核对负调出和正调入"]
F --> G["分别按两个sid算库存分表"]
G --> H["核对两站流水和实时库存"]
H --> I["核对MQ是否仅下游滞后"]
I --> J["金额问题再查154001/154002"]
J --> K["按业务事实补偿,禁止只改状态"]
调拨的最小闭环不是“一张单状态正确”,而是申请状态、STF 主明细、发货站负库存事实、申请站正库存事实、在途差异和资金结算分别可解释。
请求-日志-数据变更追踪卡
多入口请求链路
日志证据矩阵
| 链路段 | 日志来源 | 可检索锚点 | 成功信号 | 失败信号 | 与下一段关联方式 | | --- | --- | --- | --- | --- | --- | --- | | 申请 | Controller/Apply Service | request_id、申请单、两端 sid、SKU | 主明细 commit | 同站调拨、重复申请、不可调商品 | 申请单映射 STF 单 | | 出库 | STF/Inventory Service | STF 单、出库单、SKU、transType | 发站库存 -n、状态 WAIT_IN | 超发、重复出库、部分成功 | 出库单查库存流水/在途 | | 入库 | STF/Inventory Service | 原调拨单、入库单、SKU | 收站库存 +n、状态 IN_FINISH | 超收、重复收货、仓位错误 | 原单串联两站流水 | | 取消结算 | 调拨/财务日志 | 调拨单、取消动作、支付单 | 未履约关闭且账款一次结算 | 已发后误全取消、重复退款 | 调拨单关联支付/账户 |
环节数据变更台账
子模块追踪:stf-apply 服务站调拨申请
子模块追踪:stf-audit 申请审核与供给确认
子模块追踪:stf-outbound 供给站调拨出库
子模块追踪:stf-intransit 调拨在途
子模块追踪:stf-inbound 申请站调拨入库
子模块追踪:stf-cancel 调拨取消与剩余量关闭
子模块追踪:stf-settlement 调拨资金结算