收银通用订单流程
一、整体架构概览
这是一个基于 WPF + Prism 的收银系统,采用 MVVM 架构,本地使用 SQLite 存储订单数据。
核心分层
| 层 | 项目 | 职责 |
|---|---|---|
| 接口层 | Interfaces | 定义 IAppOrderService、IOrderService、ITakeOrderService 等接口 |
| 服务层 | Service | 核心业务逻辑:AppOrderService、OrderService、PayService、TakeOrderService |
| 数据层 | 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
五、退款流程
OrderRefundViewModel(Order.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 等表

浙公网安备 33010602011771号