收银通用订单流程

一、整体架构概览

这是一个基于 WPF + Prism 的收银系统,采用 MVVM 架构,本地使用 SQLite 存储订单数据。

核心分层

项目 职责
接口层 Interfaces 定义 IAppOrderServiceIOrderServiceITakeOrderService 等接口
服务层 Service 核心业务逻辑:AppOrderServiceOrderServicePayServiceTakeOrderService
数据层 Order.Service、Order.Model 数据库 CRUD 操作(OrderServie
展示层 ViewModels UI 交互逻辑
实体层 OrderEntitys 订单聚合根 OrderEntity

订单聚合根 OrderEntity 包含

OrderEntity
├── LsPosOrder         → 订单主表 (ls_pos_order)
├── LsPosOrderExt      → 订单扩展信息 (ls_pos_order_ext)
├── List<LsPosOrderDetail>   → 订单商品明细 (ls_pos_order_detail)
├── List<LsPosOrderFlow>     → 订单支付流水 (ls_pos_order_flow)
└── List<LsPosOrderDiscount> → 订单优惠信息 (ls_pos_order_discount)

二、订单流程(店内订单)

1. 订单入口导航

OrderMainViewModel (OrderSource=0)
    └─→ StoreOrderView        // 店内订单
OrderMainViewModel (OrderSource=1)
    └─→ TakeoutOrderView      // 外卖订单
OrderMainViewModel (OrderSource=2)
    └─→ AfterSaleOrderView    // 售后订单

核心代码在 OrderMainViewModel.OrderSourceChanged() (OrderMainViewModel.cs),通过 Prism 的 RegionManager 导航到不同视图。

2. 创建订单

AppOrderService.CreateOrder()OrderService.CreateOrder()

流程:
1. 初始化 OrderEntity(_order.InitOrder())
2. 生成唯一订单号(OrderNoHelper.BuildOrderNo())
3. 分配雪花ID(IdWorker.Instance.nextId())
4. 设置创建时间

3. 添加商品到订单

AppOrderService.AddOrUpdateProductToOrder()(AppOrderService.cs ~L880)

流程:
1. 检查当前订单是否为空 → 为空则创建新订单
2. 不为空则清空已有商品重新添加
3. 遍历购物车商品,转换为 LsPosOrderDetail 写入内存
4. 如果商品有优惠,自动添加单品优惠(DiscountType.ProductDiscount)

4. 添加支付流水

AppOrderService.AddPayFlow(CreteFlowParam)(AppOrderService.cs ~L960)

流程:
1. 校验订单是否存在
2. 校验 traceNo、traceTime 必填
3. 创建 LsPosOrderFlow 对象
4. 写入订单内存

5. 保存订单到数据库

AppOrderService.Save(OrderParamter)OrderService.Save()

流程(Order.Main/Service/OrderService.cs ~L300):
1. 克隆订单实体
2. 开启 SQLite 事务
3. INSERT OR REPLACE → ls_pos_order(订单主表)
4. INSERT OR REPLACE → ls_pos_order_flow(支付流水)
5. INSERT OR REPLACE → ls_pos_order_detail(商品明细)
6. INSERT OR REPLACE → ls_pos_order_discount(优惠信息)
7. INSERT OR REPLACE → ls_pos_order_ext(扩展信息)
8. 提交事务

6. 订单结算

AppOrderService.OrderSettlement()(AppOrderService.cs ~L1170)

流程:
1. 设置订单状态为成功(SetOrderSuccess)
2. 获取订单快照
3. 执行优惠金额分摊(ExecuteShare)

7. 优惠分摊算法

AppOrderService.ExecuteShare()(AppOrderService.cs ~L1202)

分摊逻辑:
1. 先还原所有优惠为原价
2. 处理单品优惠(DiscountType=2):直接扣减对应商品
3. 计算整单优惠比率 = 整单优惠金额 / (原价 - 单品优惠总额)
4. 按商品金额比例分摊整单优惠
5. 最后一个商品用"剩余金额"兜底,避免精度丢失
6. 更新订单的 ProdPaidAmt(商品实付总额)

三、支付流程

1. 支付方式枚举

定义在 PaymentType.cs 和 SaoBeiPaymentMethod.cs:

pmSign 支付方式 说明
01 扫码支付 微信/支付宝扫码
02 现金支付
03 会员支付
04 离线码支付 GT离线码
05 组合支付 多种方式混合
07 小程序
08 代金券
09 会员积分
10 扫呗校园通
11 三方外卖 美团/饿了么
12 三方团购
15 扫呗团餐通
999 N7支付

2. 支付发起 → 支付结果回调

支付流程时序:

[收银台UI] → 创建订单 → 添加商品 → 添加支付流水
    ↓
发起支付请求(HTTP POST 到扫呗支付网关)
    ↓
支付网关异步返回结果
    ↓
支付结果处理:
    ├─ 成功 → SetMobilePaySuccess() → 更新流水状态
    │        → OrderSettlement()    → 结算+分摊
    │        → Save()               → 持久化到SQLite
    │        → 上报服务端            → OrderComplete()
    │
    └─ 失败 → SetMobilePayFail()   → 更新流水状态

3. 支付结果查询

PayService.QueryAsync()Order.Main/Service/PayService.cs ~L40)

查询逻辑:
1. 构造查询参数(merchant_no, terminal_id, terminal_trace, terminal_time)
2. 计算签名(KeySignUtil.KeySign)
3. POST 到 /pay/open/query
4. 解析 ResponsePayDto
    ├─ return_code="01" && result_code="01" → 支付成功
    ├─ return_code="01" && result_code="02" → 支付失败
    └─ 其他 → 支付中/未知

4. 待收款订单(异常订单)处理

PendingPayOrderViewModel + OrderPendingService

当支付过程中出现网络异常等导致无法确认支付结果时,订单进入"待收款"状态:

待收款订单查询条件(OrderPendingService.GetAllPendingOrders()):
- payStatus = 0(未确认)
- localStatus = 0(未上传)
- 最近7天内

自动核验流程(AutoRefreshPendingOrder):
1. 查询本地待收款订单
2. 对每笔订单调用 PayService.IsOrderPaySuccess()
3. 根据 pmSign 区分查询方式:
   ├─ 校园通 → GetSchoolOrderAsync()
   ├─ N7支付 → QueryPrePay()(POST /open/middleware/query)
   └─ 其他   → QueryAsync()(POST /pay/open/query)
4. 查询成功 → OrderComplete() 上报服务端 + SetErrorOrderResult() 更新本地
5. 查询失败 → 标记为支付失败

5. 离线订单完成上报

AppOrderService.OrderComplete()Order.Main/Service/AppOrderService.cs ~L2274)

流程:
1. 将 OrderCompleteReqestDto 转为字典
2. POST 到服务端 /open/orderComplete
3. 服务端返回 Success=true 表示核销成功

6. 移动支付成功/失败回调

SetMobilePaySuccess(PayResultDataDto) / SetMobilePayFail(PayResultDataDto)

支付成功:
1. 更新 LsPosOrderFlow 的 PayStatusCode=1
2. 发布 OrderFlowChangeEvent 通知UI刷新

支付失败:
1. 更新 LsPosOrderFlow 的 PayStatusCode=2

四、三方外卖接单流程(TakeOrder)

TakeOrderService 处理美团、饿了么、京东等到店自取/外卖订单:

接单流程:
1. 拉取订单列表 → GetTakeOrderPageList()
   - 从本地视图 ls_order_take_view 查询
   - 支持按 orderStatus、foodType、orderSource 筛选
2. 接单/拒单 → 通过 HTTP 接口操作
3. 叫号取餐 → GetCallNumOrdersAsnyc()
   - 查询 orderStatus=3(待取餐)的订单
4. 售后退款 → AfterSaleOrderViewModel

五、退款流程

OrderRefundViewModelOrder.Main/ViewModels/OrderRefundViewModel.cs

退款流程:
1. 查询原单信息 → OrderDetailsService.GetRefundOrderByDB()
   - 获取可退商品列表(排除已全退商品)
   - 获取可退支付流水(payStatusCode=1 的流水)
2. 选择退款商品 → 支持单品勾选/全选
3. 计算退款金额 → 按商品实付金额比例计算
4. 发起退款请求 → RefundRequest → 扫呗退款接口
5. 更新订单退款状态
6. 打印退款小票 → OrderPrintService

六、关键数据流图

|商品列表| B[AppOrderService.CreateOrder]

B -->|创建订单| C[OrderService._order 内存对象]
C -->|添加商品| D[AddOrUpdateProductToOrder]
D -->|添加优惠| E[AddDiscount]
E -->|添加流水| F[AddPayFlow]
F -->|发起支付| G[扫呗支付网关]
G -->|支付回调| H{支付结果}
H -->|成功| I[SetMobilePaySuccess]
H -->|失败| J[SetMobilePayFail]
H -->|未知| K[待收款订单]
I -->|结算| L[OrderSettlement]
L -->|分摊| M[ExecuteShare]
M -->|持久化| N[OrderService.Save → SQLite]
N -->|上报| O[OrderComplete → 服务端]
K -->|轮询查询| P[PayService.IsOrderPaySuccess]
P -->|确认成功| I
P -->|确认失败| J

Q[三方外卖平台] -->|推送订单| R[TakeOrderService]
R -->|接单| S[本地SQLite]
R -->|拒单| T[HTTP接口] -->


七、数据库表关系

ls_pos_order(订单主表)
  ├── 1:N → ls_pos_order_detail(商品明细)
  ├── 1:N → ls_pos_order_flow(支付流水)
  ├── 1:N → ls_pos_order_discount(优惠明细)
  ├── 1:1 → ls_pos_order_ext(扩展信息)
  └── 1:1 → t_member_score(会员积分变动)

ls_order_take_view(三方外卖订单视图)
  └── 关联 ls_pos_order 等表
posted @ 2026-08-04 22:40  blade13  阅读(0)  评论(0)    收藏  举报