业务架构

价值链 → 销售 / 采购 / 仓储成本 / 财务 → 商城 → 横切机制

核对状态(2026-10-05):B1–B7 的论断 已由 Codex 逐条对照「页面 ↔ 代码 ↔ 文档」,controller 抽查复跑 rg 证据通过;业务页 + 对照页合计 324 条论断中 一致 253 / 部分一致 53 / 不一致 18。不一致 / 部分一致的论断已按代码现实订正;代码偏离 PRD / ADR 或 SSOT 的项以红字标出,汇总在观察页。

B1业务价值链:标准商贸进销存 + 业财一体 + B2B 订货商城

主数据与规则引擎(所有链路共用)
master 客户/供应商/仓/员/字典item 商品档案pricing 取价级联promotion 促销引擎customfieldsysconfig 租户参数rbac 权限·数据范围
销售 O2C
报价(可选·前端预填)→ 订单 → 出库 → 收款
quotation 2220order 2221salesout 2222salesreturn 2224returnorder 3308mallcloudorder
采购 P2P
申请 → 订单 → 入库 → 付款
purchase 1207/1211/1209purchasein 1212purchasereturnout 1214freight 1217/1317finance 供应商费用 1315purchaseqcpurchaseexpense 冻结
仓储与库存
单据驱动余额 + 台账
inventorywarehouse 3315/3325transfer 3331stocktake 3300damage 3322assembly 3317/3327wmsserial
成本与关账
策略内聚在 costing
costingclosingcost_periods
财务闭环
往来台账 → 核销 → 出纳 → 总账
finance AR/APpayment 2323/1313arapoffset 1323cashier 6001–6007invoiceprepaidglassetpayroll(轻量)
履约 · 外勤 · 提成
deliverydistributionfieldworkrepair 5101salescommissionreportdashboard
平台与治理
platform 租户/订阅/席位/公告authapprovalbook 签字流水auditnotification / notifmgrbillchain 单据链printtemplate / printregistry
Non-Goals(不做 / 已裁撤):POS 门店收银(后端包与表已随 ADR-0044 删除)· 会员储值 / 离线同步 / 币种档案(代码保留、路由不挂载) · 生产 / 委外 · 重型 HR · 多级团队分销 · 外币汇率(纯 CNY)· 自动化立库 · 销售虚单出库 · 1218 采购费用单(冻结,统一走 1217)· 客户私有定制分支(冰团 / 娃哈哈 / 锁尼 / 志成兴 / 快消配送工资)。全表见 BUSINESS_DOMAIN_AND_BOUNDARIES.md §9。

B2销售链 Order-to-Cash

flowchart TB
  Q["报价 2220
quotation
与订单解耦 · 可选"] -. "前端预填(ADR-0001)
后端无源单关联" .-> O["销售订单 2221
order
draft → approved"] O -- "审核:只占用
不出库 · 不写应收(ADR-0011)" --> O2["order approved"] subgraph ENTRY["出库三入口"] E1["ERP 手动转单
POST /salesOutBills/fromOrder"] E2["商城 Checkout
支付成功后建单送审"] E3["WMS 验货完成
adapter 注入"] end O2 --> E1 E1 --> S["销售出库 2222
salesout"] E2 --> S E3 --> S S -- "终审同事务" --> X1["inventory.ApplyMovement
扣减 + 台账"] S --> X2["costing.Outbound 结转成本"] S --> X3["finance.CreateReceivableTx 应收
条件:有客户 · 金额>0 · settlement_basis≠invoice"] S --> X4["order.ApplyFulfillment
回写 order_items.fulfilled_qty"] S --> AS["payment.AutoSettleForBillTx
按已有 2323 自动核销"] PAY["收款 2323 payment
创建即 ReceivePaymentTx 减应收"] -- "手动选单" --> SET["核销 settlement_details"] AS --> SET S -.可选.-> INV["发票 invoice"] RQ["退货申请 3308
returnorder
终审仅标记通过"] -. "快照引用 · 不联动" .-> RB["销售退货 2224
salesreturn
可独立手建"] S -. "快照引用" .-> RB RB -- "终审同事务" --> Y["加库存 + 入库成本
+ ReverseReceivableTx 冲应收"] classDef deepc fill:#0f172a,color:#fff,stroke:#0f172a; class S deepc

B3采购链 Procure-to-Pay

flowchart TB
  PR["采购申请 / 报价 1207
purchase_requests
两者合一(ADR-0045)"] -- "下推" --> PO["采购订单 1211
purchase_orders
draft → approved → completed"] PO -- "选单生成入库(手工)" --> IN["采购入库 1212
purchasein"] IN -. "终审 / 反审回写 received_qty
syncPurchaseOrderCompletion
自动置 / 回退 completed" .-> PO RET -. "1214 终审 / 反审同样重判完成态" .-> PO IN -- "终审同事务" --> A1["inventory.ApplyMovement
加库存 + 台账"] IN --> A2["costing.Inbound
FIFO 租户建层 · 月加权由关账统一处理
其它策略保留手录成本"] IN -- "仅赊账 credit 且 settlement_basis≠invoice" --> AP["应付台账
finance.CreatePayableTx"] IN --> A4["回写订单 received_qty
仅带 ref_order_id 的行"] AP --> PAY["付款 1313
payment"] PAY --> SET["应付核销"] FR["采购运费 1217
freight"] -- "按金额 / 数量 / 重量 / 手工分摊
AddUnitCost 回写 1212 行成本" --> IN SE["供应商费用 1315
internal/finance"] -- "审核写应付
不进入库成本" --> AP IN -. "可选快照引用原入库行" .-> RET["采购退货 1214
purchasereturnout
可独立手建 · 扣库存 + ReversePayableTx"] DS["直运单 1209
direct_bills
独立建单:无采购订单引用列"] -- "终审同事务:同仓 1212 + 2222
瞬时过账,净额为零" --> IN DS --> D2["2222 销售出库 → 采购 / 销售发票 1318 / 2328
→ billchain → 回写"] classDef deepc fill:#0f172a,color:#fff,stroke:#0f172a; class IN deepc

B4仓储、库存与成本

flowchart TB
  subgraph DOCS["出入库单据模块:只陈述业务事实"]
    D1["销售侧
salesout 2222 · salesreturn 2224"] D3["采购侧
purchasein 1212 · purchasereturnout 1214"] D5["库内单据
warehouse 3315/3325 · 盘盈 3311 · 盘亏 3321
transfer 3331 · damage 3322 · assembly 3317/3327"] end DV["directvendor
三方供应商虚拟仓库存 · 无单据 · ledger=3318"] DOCS -- "costing.Inbound / Outbound
(directvendor 不入 costing)" --> CO DOCS -- "inventory.ApplyMovement" --> INV DV -- "ApplyMovement" --> INV D1 & D3 -- "反审 ReverseByLedgerNet
仅 salesout · salesreturn · purchasereturnout" --> INV subgraph CO["costing(deep)"] direction LR M1["月加权平均(默认)"] M2["先进先出 FIFO"] M3["最后进价"] M4["最后进价 + 运费"] M5["指定成本价"] M6["不处理"] end subgraph INV["inventory(deep · 唯一写入方 ADR-0056)"] direction LR I1["策略解析:deny / warn / allow"] I2["原子条件 UPDATE(持行级锁)"] I3["余额 upsert"] I4["台账追加(带符号金额 = 余额变动)"] end CO -- "FIFO 层归 costing" --> FL[("fifo_in_layers
fifo_out_layers")] INV --> IB[("inventory")] INV --> IL[("inventory_ledger")] ST["stocktake 3300
Confirm 编排生成 3311 / 3321
经 warehouse Create → Submit → Approve
各步独立事务,失败可留中间态"] --> D5 WMS["wms 拣货 / 验货 / 上下架
不直接写库存"] -. "adapter → salesout" .-> D1 SRC["各出入库专表
(19 张 UNION,期间聚合源)"] --> CL IL -. "库存金额 ↔ 台账对账" .-> CL CL["closing(编排)→ costing.ClosePeriod → 期间 → gl
预检:未审核 / 未过账凭证 + 金额-台账对账
月加权重算 · FIFO 对账 · 其它策略只写快照
当期 end_* 落 cost_periods,下期读取为 begin_*"] --> CP[("cost_periods")] classDef deepc fill:#0f172a,color:#fff,stroke:#0f172a; class M1,M2,I2,I4 deepc
成本方式(cost_method.go)

月加权平均(默认,空值同)· 先进先出 · 最后进价 · 最后进价+运费 · 指定成本价 · 不处理。未知值:关账入口拒绝(fail-closed),日常出库暂按月加权兜底并告警。调用方不再选策略(SSOT §4.1)。真实签名是 costing.Inbound(ctx, db, tx, billID, lines),DESIGN_PATTERNS 里的 Inbound(ctx, tx, bill) 是目标态示意。

负库存策略

仓库级三态回退到租户级 stock_policy.allow_negative:deny 返回类型化错误 · warn 条件扣减后记日志 · allow 不检查。迁移期兼容例外(movement.go:31-50):damage 仅租户级、purchasereturnout strict warn(缺行 fail-loud、不写日志)、purchasein 不检查;收敛另立 PRD 规则。

旧系统概念 → 新系统(不是一一对应)

期间数量 / 金额台账 → cost_periods;实时快照 → inventory;逐笔事件 → inventory_ledger;日结高频缓存 → 无直接对应。

B5财务闭环:往来 → 核销 → 出纳 → 总账

flowchart LR
  subgraph DOC["单据终审"]
    OUT["销售出库 2222"]
    SR["销售退货 2224"]
    IN["采购入库 1212"]
    PRT["采购退货 1214"]
  end
  subgraph INVO["发票 / 费用"]
    INV28["销项发票 2328"]
    INV18["进项发票 1318"]
    SE["供应商费用 1315"]
  end
  OUT -- "CreateReceivableTx
有客户 · 金额>0 · basis≠invoice" --> AR["应收台账
finance"] SR -- "ReverseReceivableTx" --> AR INV28 -- "仅 basis=invoice" --> AR IN -- "CreatePayableTx
赊账 credit 且 basis≠invoice" --> AP["应付台账
finance"] PRT -- "ReversePayableTx(credit)" --> AP INV18 -- "仅 basis=invoice" --> AP SE -- "审核写应付" --> AP RECV["收款 2323
创建即生效"] -- "ReceivePaymentTx 减应收" --> AR PAYB["付款 1313
创建即生效"] -- "MakePaymentTx 减应付" --> AP RECV & PAYB -- "AutoSettle / 手动选单" --> SD["核销记录
settlement_details"] RECV -- "writeCashierFlows
2323→6001 · 退款冲回→6002" --> CASH["出纳日记账
cashier"] PAYB -- "1313→6002 · 冲回→6001" --> CASH AR -. "同一单位既是客户又是供应商" .- OFF["往来对冲 1323
arapoffset"] AP -.- OFF

图一:往来、核销与出纳的子账层。三种「核销」分属 payment / finance / arapoffset 三个模块(见下方卡片)。

flowchart LR
  SRC["push 来源:采购入库 1212 · 收款 2323 · 付款 1313
往来对冲 1323 · 出纳 · 发票 1318 / 2328 · 供应商费用 1315"] -- "commit 后 push:TryAutoGenerate
失败仅记日志 · 出纳需 AtCNGenVoucher=1" --> V["机制凭证
gl.is_machine = true"] OUT["销售出库 2222"] -. "无 push · 走 pull
GenerateFromBills" .-> V V -- "PostVouchers" --> BAL["科目余额
gl_balances"] BAL -. "独立操作(关账前)" .-> PNL["CarryForwardProfitLoss
结转损益"] BAL -- "gl.ClosePeriod:余额结转下期
+ 总账期间指针推进" --> CLS["总账期间关闭"] classDef deepc fill:#0f172a,color:#fff,stroke:#0f172a; class V,BAL deepc
三种「核销」,三个模块

payment:收付款单 ↔ 业务单据(settlement_details);finance:台账本身(余额 / 坏账 / 佣金 / 供应商费用);arapoffset:应收 ↔ 应付互抵。账龄分析在 report(五桶 0-30 / 31-60 / 61-90 / 91-180 / 180+,参数 FinanceAgingBuckets 默认 30,60,90,180),不在 finance。

gl 是叶子,push 在 commit 之后

gl 不 import 任何 internal 包(11 个业务包依赖它);push 调用方为 payment / invoice / finance / arapoffset / cashier / freight / purchasein / asset / prepaid(cmd/server/main.go:633-652),2222 没有 push,走 pull。机制凭证限制手改,删除先删关联再软删。

金额纪律(MONEY_SPEC)

纯 CNY;金额路径禁 float64,经 pkg/money;草稿服务端重算,审核后金额冻结。历史 float64 为已登记债务。出纳 6003 是现金调拨,与收付款无关(出纳域 6001–6007)。

B6商城与多端:B2B 订货

flowchart TB
  C["客户
PC 商城 / 小程序 / 移动 App"] --> CART["购物车 · 目录
mall"] CART --> PRC["pricing 取价管线"] PRC --> PRM["promotion 促销引擎
单品特价 · 搭赠 · 整单满减 / 满赠 · 组合套餐
时段折扣 / 特价 · 抢购 · 混搭满量送减
优惠券为独立子系统"] PRM --> CHK["Checkout 编排
mall:只编排,不发明规则"] CHK -- "创建订单" --> ORD["order 2221"] CHK --> PI["payintegration
微信支付 / 支付宝 / 银联(ChannelProvider 可插拔)
cash / member_card 为线下渠道 · 租户开关门控"] PI -- "支付成功回调
幂等:status=paid 即返回" --> OUT["salesout:建单 + 送审
禁止未付先出库"] OUT --> APP["终审事务内:CreatePaymentTx 建 2323
无默认现金账户则失败
+ 应收 + AutoSettle"] CRON["每 5 分钟
取消超时未支付订单"] -.-> ORD CO["cloudorder
商城配置展示 · 不做订单交易"] -.配置.-> CART classDef deepc fill:#0f172a,color:#fff,stroke:#0f172a; class CHK deepc

B7横切业务机制:审批、权限、期间、编号、红冲

审批:模块自管状态机 + 统一签字流水
stateDiagram-v2
  [*] --> unsubmitted
  unsubmitted --> pending: Submit
  rejected --> pending: 修改后 Submit(编辑保持 rejected)
  pending --> approved: Approve level 1(业务闸门)
  pending --> rejected: Reject
  approved --> approved: Approve level 2/3(可选叠加签字)
  approved --> approved: 反审 level 3/2(仅删签)
  approved --> pending: 反审 level 1(业务回退)
            

level=1 即业务终审(库存 / 成本 / 信用等副作用)并置 approved;level=2/3 是 approved 之后可选叠加的签字,不改主表。权限码 bill.{domain}.{billType}.approve{level}。「去央批化」(2026-09-06)后无中心审批引擎;反审按 3→2→1 逐级删签,只有 level 1 反审才把主表退回 pending。approval_records 并非只追加:level 1 把 pending 行 UPDATE 为 approved,Reject 同样 UPDATE,反审 DELETE(approvalbook/service.go:193-295),与 SSOT 的 Append-Only 清单冲突,见观察页。

权限:四道关(旧系统规格,新系统对应实现)
  1. 模块访问:RequireModuleAccess
  2. 按钮动作:查看 / 新增 / 修改 / 删除 / 作废 / 一二三审 / 反审 / 打印导出
  3. 行级数据范围:仓库、部门、业务员(白名单 / 黑名单模式)
  4. 列级脱敏:成本价、进价等敏感列服务端掩码
期间与关账

供应链期间指针(CurrentYear/Period)与总账期间指针(GLCurrentYear/Period)分别维护;关账后该期间单据禁止审核、数据冻结。

单据编号与追溯

pkg/billno 统一取号(事务版 GenerateTx);billchain 记 LinkBills / GetChain;明细行 ref_*_item_id 行级匹配回写源单执行量,全执行完关闭源单。

终态与更正

completed / cancelled 为硬终态(ADR-0009);作废仅限 status=draft 且未过一审(warehouse / damage 等族允许被驳回的单据作废),已审核先反审;冲回库存 / 成本 / 流水 / 履行量只在反审里做;已关账期间只能走红字。

上一站
技术架构
进程、请求链路、模块拓扑、数据与事务
桥
业务×技术对照
业务域 × 单据 × 模块 × 表
回到
首页
全部架构图入口