Files
rui-docs/frontend/design/cashier-design.md
T
vifo 7b2f3d77ca docs: 支付模块开发文档 + git 域名更新
- 新增 backend/design/支付模块架构概览.md
- 新增 backend/design/支付模块数据库设计.md (21张表 DDL)
- 新增 backend/design/支付模块接口设计.md
- git.dev.vifo.cc → git.vifo.cc 全局替换
2026-06-09 01:54:29 +08:00

55 KiB
Raw Blame History

收银系统(POS)设计文档

设计日期: 2026-06-03 版本: v2.0 状态: 设计中 目标: 为棋牌室、酒吧、KTV 等服务业态构建多端收银系统,支持多门店连锁运营


一、背景与目标

1.1 现状分析

目前运营 100+ 棋牌室门店,采用总部 → 代理商 → 门店三级管理模式。各门店急需一套收银系统来管理包间/桌台的开台、计费、结账流程。现有系统空缺,依赖人工记账,效率低、易出错、无法统一管理。

1.2 目标定义

  1. 建立标准化收银流程:支持开台、计时/计费、结账、退款的完整闭环
  2. 多门店统一管理:总部可查看所有门店数据,代理商管理名下门店,门店独立运营
  3. 多端覆盖:管理后台(Web)、收银台(APP/小程序),后续扩展收银机、PC 端
  4. 灵活计费模式:支持按时计费、包时段套餐、按局/圈等混合计费方式
  5. 复杂结算场景:预付款/后付款、小程序下单、小商品分离结算
  6. 预留扩展能力:会员钱包、优惠券/团购券、支付通道、第三方平台对接、智能设备控制

二、详细设计

2.1 项目仓库

仓库 地址 说明
前端 ssh://git@git.vifo.cc:222/rui/rui-frontend.git admin-ui + 移动端
后端 ssh://git@git.vifo.cc:222/rui/rui-cashier.git 收银系统独立后端服务
文档 ssh://git@git.vifo.cc:222/rui/rui-docs.git 共享文档中心

⚠️ 注意:收银系统相关 Issue 应提交到 rui/rui-cashier 仓库,不是 rui-framework

2.2 菜单数据结构

系统菜单使用以下 JSON 结构:

{
  "name": "cashier",
  "menus": [
    {
      "code": "cashier",
      "name": "收银系统",
      "type": 1,
      "icon": "tabler:money",
      "sortNo": 100,
      "children": [
        {
          "code": "store",
          "name": "门店管理",
          "type": 2,
          "icon": "tabler:building-store",
          "path": "/cashier/store",
          "permission": "cashier:store:list",
          "sortNo": 1,
          "buttons": [
            { "code": "btn:add", "name": "新增", "permission": "cashier:store:add" },
            { "code": "btn:edit", "name": "编辑", "permission": "cashier:store:edit" },
            { "code": "btn:del", "name": "删除", "permission": "cashier:store:delete" }
          ]
        }
      ]
    }
  ]
}

字段说明:

字段 类型 说明
code string 菜单编码,唯一标识
name string 菜单显示名称
type int 1=目录,2=菜单,3=按钮
icon string 图标,支持 tabler: 前缀或 Element Plus 图标名
path string 路由路径(type=2时必填)
permission string 权限标识,格式:模块:功能:操作
sortNo int 排序号,越小越靠前
children array 子菜单列表
buttons array 页面按钮权限(type=2时可选)

收银系统完整菜单配置见第 2.9 节。

2.3 整体架构

┌─────────────────────────────────────────────────────────────────┐
│                         前端层                                   │
├──────────────┬──────────────┬────────────────┬─────────────────┤
│  管理后台     │  收银台 APP   │   顾客小程序    │  第三方平台      │
│  (admin-ui)  │  (uni-app)   │  (独立uni-app) │  (美团等)       │
│  Vue3+Element│  Vue3语法    │   二期开发      │  三期对接       │
└──────────────┴──────────────┴────────────────┴─────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                       网关层 (rui-gateway)                      │
│              路由转发 │ 鉴权 │ 限流 │ 负载均衡                    │
└─────────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      业务服务层 (app/rui-cashier/)                   │
├──────────────┬──────────────┬────────────────┬─────────────────┤
│ rui-cashier-store│ rui-cashier-order│ rui-cashier-product│ rui-cashier-report  │
│ 门店+包间服务 │ 订单服务      │ 商品服务        │ 报表服务         │
│              │              │                │                 │
│ • 组织架构    │ • 开台/结账   │ • 商品档案      │ • 营业日报       │
│ • 门店管理    │ • 计费规则    │ • 服务分类      │ • 数据统计       │
│ • 包间/桌台   │ • 子订单管理   │ • 定价管理      │ • 趋势分析       │
│ • 套餐策略    │ • 退款处理    │                │                 │
│ • 设备管理    │              │                │                 │
└──────────────┴──────────────┴────────────────┴─────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────────┐
│                      基础设施层                                   │
│  MySQL 8.0  │  Redis  │  Nacos  │  MQ(RabbitMQ)  │  Seata       │
└─────────────────────────────────────────────────────────────────┘

2.2 服务职责划分

rui-cashier-store(门店+包间服务)

职责:组织架构、门店管理、包间/桌台管理、套餐策略、设备管理

核心实体

  • Store(门店):基本信息、所属代理商、营业状态、配置
  • StoreConfig(门店配置):预付款/后付款、余额支付商品开关等
  • Agent(代理商):基本信息、管理的门店列表
  • RoomType(包间类型):名称、容纳人数
  • Room(包间/桌台):所属门店、类型、状态、设备绑定
  • PricingStrategy(定价策略):包间类型关联的套餐集合
  • PricingPackage(套餐):具体的价格套餐,支持时段/日期限制
  • Device(设备):网关、门锁、电源、音箱、打印机、锁球器等

套餐策略设计(核心变更):

// 计费方式枚举
public enum BillingType {
    HOURLY(1, "按时计费"),           // 按小时计费,可设最低消费时长
    FIXED_PERIOD(2, "包时段"),       // 固定时段买断,如包下午场
    PER_GAME(3, "按局计费"),         // 按局/圈计费
    MIXED(4, "混合模式");            // 组合计费
}

// 定价策略(一个包间类型对应一个策略,包含多条套餐)
@Data
public class PricingStrategy {
    private Long id;
    private Long roomTypeId;          // 包间类型ID
    private String strategyName;      // 策略名称,如"标准计费"
    private Integer status;           // 状态:0-禁用 1-启用
}

// 套餐(策略中的具体套餐项)
@Data
public class PricingPackage {
    private Long id;
    private Long strategyId;          // 所属策略ID
    private String packageName;       // 套餐名称,如"3小时套餐"
    private Integer billingType;      // 计费方式
    private BigDecimal price;         // 套餐价格
    private Integer duration;         // 时长(分钟),包时段时有效
    private Integer sort;             // 排序,第一条是默认/fallback
    
    // 限制条件(JSON格式)
    private String restrictions;      // {
                                      //   "weekdays": [1,2,3,4,5],     // 工作日可用
                                      //   "weekends": [6,7],           // 周末可用
                                      //   "timeRanges": [              // 时段范围
                                      //     {"start": "08:00", "end": "12:00"}
                                      //   ],
                                      //   "holidays": {                // 节假日设置
                                      //     "mode": "EXCLUDE",         // EXCLUDE-不可用 INCLUDE-仅可用
                                      //     "dates": ["2026-10-01", "2026-10-02"]
                                      //   }
                                      // }
    
    private Integer isDefault;        // 是否默认套餐(1-是 0-否),默认套餐不可配置限制条件
    private Integer status;           // 状态:0-禁用 1-启用
}

套餐匹配逻辑

public PricingPackage matchPackage(Long roomTypeId, LocalDateTime startTime) {
    // 1. 获取包间类型的定价策略
    PricingStrategy strategy = strategyService.getByRoomTypeId(roomTypeId);
    
    // 2. 获取策略下的所有套餐,按 sort 排序
    List<PricingPackage> packages = packageService.getByStrategyId(strategy.getId());
    
    // 3. 依次匹配套餐限制条件
    for (PricingPackage pkg : packages) {
        if (pkg.getIsDefault() == 1) {
            continue; // 默认套餐跳过,作为fallback
        }
        if (matchRestrictions(pkg.getRestrictions(), startTime)) {
            return pkg; // 找到匹配的套餐
        }
    }
    
    // 4. 没有匹配的,返回默认套餐(第一条)
    return packages.stream()
        .filter(p -> p.getIsDefault() == 1)
        .findFirst()
        .orElseThrow(() -> new BizException("无可用套餐"));
}

包间状态机

空闲 ──[开台]──► 使用中 ──[结账]──► 待清洁 ──[清洁完成]──► 空闲
  ▲                │                              │
  │                │ [挂单]                       │
  │                ▼                              │
  │              已挂单 ──[恢复]───────────────────┘
  │                │
  │                │ [预约](二期)
  │                ▼
  │              已预约 ──[开台]──► 使用中
  │
  └──[取消预约]─── 已预约

rui-cashier-order(订单服务)

职责:开台、计费计算、结账、退款、订单生命周期管理

核心实体

  • Order(主订单):订单整体信息
  • RoomSubOrder(包间子订单):包间消费、计时计费
  • ProductSubOrder(商品子订单):小商品消费
  • OrderTimeline(订单时间线):开台、结账等关键时间点

订单体系设计(核心变更):

// 主订单
@Data
public class Order {
    private Long id;
    private String orderNo;           // 订单编号
    private Long storeId;             // 门店ID
    private Long roomId;              // 包间ID(包间订单时)
    private Integer orderType;        // 订单类型:1-包间订单 2-纯商品订单
    private String customerName;      // 顾客姓名
    private String customerPhone;     // 顾客电话
    
    // 金额汇总
    private BigDecimal roomAmount;    // 包间费用
    private BigDecimal productAmount; // 商品费用
    private BigDecimal discountAmount;// 优惠金额
    private BigDecimal totalAmount;   // 订单总金额
    private BigDecimal payAmount;     // 实付金额
    
    // 支付信息
    private Integer payStatus;        // 支付状态:0-未支付 1-部分支付 2-已支付
    private Integer payType;          // 支付方式
    private LocalDateTime payTime;    // 支付时间
    
    // 状态
    private Integer status;           // 订单状态
    private String remark;            // 备注
    private Long cashierId;           // 收银员ID
}

// 包间子订单
@Data
public class RoomSubOrder {
    private Long id;
    private Long orderId;             // 主订单ID
    private Long roomId;              // 包间ID
    private Long packageId;           // 使用的套餐ID
    private Integer billingType;      // 计费方式
    private BigDecimal price;         // 套餐价格/单价
    private LocalDateTime startTime;  // 开台时间
    private LocalDateTime endTime;    // 结账时间
    private Integer duration;         // 使用时长(分钟)
    private Integer gameCount;        // 局数
    private BigDecimal amount;        // 包间费用
    private Integer status;           // 状态
}

// 商品子订单
@Data
public class ProductSubOrder {
    private Long id;
    private Long orderId;             // 主订单ID
    private Long productId;           // 商品ID
    private String productName;       // 商品名称
    private BigDecimal productPrice;  // 商品单价
    private Integer quantity;         // 数量
    private BigDecimal amount;        // 小计金额
    private Integer payStatus;        // 支付状态(单独控制)
    private Integer source;           // 来源:1-收银台 2-顾客小程序
    private LocalDateTime createTime; // 创建时间
}

结算场景支持

// 门店配置
@Data
public class StoreConfig {
    private Long storeId;
    private Integer productPayMode;   // 商品支付模式:1-先付款 2-后付款
    private Integer balancePayProduct;// 余额是否可支付商品:0-否 1-是
    private Integer notifyOnOrder;    // 下单是否通知:0-否 1-是(喇叭+打印)
}

// 结算逻辑
public void checkout(Long orderId) {
    Order order = orderService.getById(orderId);
    StoreConfig config = storeService.getConfig(order.getStoreId());
    
    // 1. 计算包间费用
    RoomSubOrder roomOrder = roomSubOrderService.getByOrderId(orderId);
    BigDecimal roomAmount = calculateRoomAmount(roomOrder);
    
    // 2. 计算商品费用
    List<ProductSubOrder> products = productSubOrderService.getByOrderId(orderId);
    BigDecimal productAmount = products.stream()
        .map(ProductSubOrder::getAmount)
        .reduce(BigDecimal.ZERO, BigDecimal::add);
    
    // 3. 计算优惠(预留)
    BigDecimal discountAmount = discountService.calculate(orderId);
    
    // 4. 计算应付金额
    BigDecimal totalAmount = roomAmount.add(productAmount).subtract(discountAmount);
    
    // 5. 如果商品是先付款模式,商品费用已从实付中扣除
    if (config.getProductPayMode() == 1) {
        BigDecimal paidProductAmount = products.stream()
            .filter(p -> p.getPayStatus() == 2)
            .map(ProductSubOrder::getAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
        totalAmount = totalAmount.subtract(paidProductAmount);
    }
    
    // 6. 更新订单
    order.setRoomAmount(roomAmount);
    order.setProductAmount(productAmount);
    order.setDiscountAmount(discountAmount);
    order.setTotalAmount(totalAmount);
    order.setStatus(2); // 待支付
    orderService.update(order);
}

开台流程(支持小程序预下单):

场景1:收银台直接开台
1. 收银员选择包间 → 检查包间状态"空闲"
2. 选择套餐(系统自动匹配当前时段可用套餐)
3. 确认顾客信息
4. 创建主订单 + 包间子订单
5. 包间状态变更为"使用中"

场景2:顾客小程序预订包间
1. 顾客选择门店、包间类型、时间段
2. 系统匹配可用套餐,显示价格
3. 顾客支付包间费用(预付款)
4. 创建主订单 + 包间子订单(状态:已支付)
5. 顾客到店后,收银员确认开台,包间状态变更为"使用中"

场景3:顾客小程序购买小商品
1. 顾客扫描包间二维码
2. 浏览商品,下单
3. 如果门店配置"先付款":在线支付 → 创建商品子订单
4. 如果门店配置"后付款":创建商品子订单(未支付)
5. 触发智能喇叭通知、打印小票(如配置)
6. 后付款的商品可在收银台统一结算

rui-cashier-product(商品服务)

职责:商品/服务档案管理、分类管理、价格管理

核心实体

  • Product(商品/服务):名称、分类、价格、状态
  • ProductCategory(分类):名称、层级、排序
  • StoreProduct(门店商品):门店可售商品及自定义价格

设计要点

  • 商品分为"普通商品"(饮料、零食)和"服务商品"(加时、换桌等)
  • 支持总部统一配置,门店可自定义价格和上下架

rui-cashier-report(报表服务)

职责:营业数据统计、报表生成、数据看板

核心功能

  • 营业日报:按门店、按日期统计营业额、订单数、客单价
  • 包间利用率:各包间使用时长/空闲时长占比
  • 时段分析:高峰时段、低谷时段统计
  • 代理商汇总:名下门店汇总数据
  • 商品销售统计:各商品销量、销售额

技术要点

  • 报表数据定时从 order 服务同步,避免实时查询拖垮核心服务
  • 支持按门店、代理商、时间维度筛选

2.3 数据流

开台-结账核心流程

收银员(APP)/ 顾客(小程序)
    │
    ▼
[选择包间/商品] ──► rui-cashier-store(检查包间状态/商品库存)
    │
    ▼
[确认开台/下单] ──► rui-cashier-order(创建订单)
    │              │
    │              ├─ 创建主订单
    │              ├─ 创建包间子订单(或商品子订单)
    │              ▼
    │         包间状态变更为"使用中"
    │              │
    ▼              ▼
[追加商品] ──► rui-cashier-product(查询商品)
    │              │
    │              ▼
    │         创建商品子订单
    │         触发硬件通知(喇叭+打印,如配置)
    ▼
[结账] ─────► rui-cashier-order(计算费用)
    │              │
    │              ├─ 计算包间费用(按时/套餐)
    │              ├─ 汇总商品费用(扣除已支付的)
    │              ├─ 计算优惠(预留)
    │              ▼
    │         生成应付金额
    │              │
    ▼              ▼
[支付完成] ──► rui-cashier-order(更新订单状态)
    │              │
    │              ▼
    │         包间状态变更为"待清洁"
    ▼
[清洁完成] ──► rui-cashier-store(包间状态变更为"空闲")

2.4 接口设计

rui-cashier-store 核心接口

# 门店管理
POST   /cashier/admin/store                 # 创建门店
PUT    /cashier/admin/store/{id}            # 更新门店
GET    /cashier/admin/store/{id}            # 门店详情
GET    /cashier/admin/store/list            # 门店列表(按代理商筛选)
DELETE /cashier/admin/store/{id}            # 删除门店

# 门店配置
GET    /cashier/admin/store/{id}/config     # 获取门店配置
PUT    /cashier/admin/store/{id}/config     # 更新门店配置

# 包间类型管理
POST   /cashier/admin/room-type             # 创建包间类型
PUT    /cashier/admin/room-type/{id}        # 更新包间类型
GET    /cashier/admin/room-type/list        # 包间类型列表

# 包间管理
POST   /cashier/admin/room                  # 创建包间
PUT    /cashier/admin/room/{id}             # 更新包间
GET    /cashier/admin/room/list             # 包间列表(按门店筛选)
GET    /cashier/admin/room/{id}/status      # 包间实时状态

# 定价策略管理
POST   /cashier/admin/pricing-strategy      # 创建定价策略
PUT    /cashier/admin/pricing-strategy/{id} # 更新定价策略
GET    /cashier/admin/pricing-strategy/list # 策略列表

# 套餐管理
POST   /cashier/admin/pricing-package       # 创建套餐
PUT    /cashier/admin/pricing-package/{id}  # 更新套餐
GET    /cashier/admin/pricing-package/list  # 套餐列表(按策略筛选)

# 设备管理
POST   /cashier/admin/device                # 注册设备
PUT    /cashier/admin/device/{id}           # 更新设备
GET    /cashier/admin/device/list           # 设备列表
POST   /cashier/admin/device/{id}/control   # 设备控制(预留)

rui-cashier-order 核心接口

# 开台
POST   /cashier/admin/order/open            # 开台(创建订单)
  body: {
    "roomId": 1,
    "packageId": 1,           # 选择的套餐ID
    "customerName": "张三",    // 可选
    "customerPhone": "138...", // 可选
    "remark": "..."            // 备注
  }

# 追加商品(收银台)
POST   /cashier/admin/order/{id}/product    # 追加商品到订单
  body: {
    "productId": 1,
    "quantity": 2,
    "price": 15.00
  }

# 顾客小程序下单商品
POST   /cashier/app/order/{id}/product      # 顾客下单商品
  body: {
    "productId": 1,
    "quantity": 2,
    "source": 2                 // 来源:2-顾客小程序
  }

# 结账
POST   /cashier/admin/order/{id}/checkout   # 结账
  response: {
    "orderId": 1,
    "roomAmount": 120.00,       // 包间费用
    "productAmount": 30.00,     // 商品费用(未支付部分)
    "paidProductAmount": 20.00, // 已支付商品金额
    "discountAmount": 0.00,     // 优惠金额(预留)
    "totalAmount": 130.00,      // 应付金额
    "duration": 120,            // 使用时长(分钟)
    "startTime": "2026-06-03T10:00:00",
    "endTime": "2026-06-03T12:00:00"
  }

# 确认支付
POST   /cashier/admin/order/{id}/pay        # 确认支付(预留支付通道)
  body: {
    "payType": "CASH",          // CASH-现金, WECHAT-微信, ALIPAY-支付宝, BALANCE-余额
    "amount": 130.00,
    "remark": "..."
  }

# 商品子订单支付(小程序先付款)
POST   /cashier/app/product-order/{id}/pay  # 商品子订单支付
  body: {
    "payType": "WECHAT",
    "amount": 20.00
  }

# 退款
POST   /cashier/admin/order/{id}/refund     # 订单退款
  body: {
    "refundAmount": 130.00,
    "reason": "..."
  }

# 订单查询
GET    /cashier/admin/order/{id}            # 订单详情
GET    /cashier/admin/order/list            # 订单列表(按门店、日期筛选)
GET    /cashier/admin/order/{id}/timeline   # 订单时间线

# 包间状态操作
POST   /cashier/admin/room/{id}/clean       # 清洁完成(包间恢复空闲)

2.5 数据库设计

门店表(rui_cashier_store

CREATE TABLE #prefix#cashier_store (
    id              BIGINT PRIMARY KEY COMMENT '门店ID',
    agent_id        BIGINT NOT NULL COMMENT '所属代理商ID',
    store_name      VARCHAR(100) NOT NULL COMMENT '门店名称',
    store_code      VARCHAR(50) NOT NULL COMMENT '门店编码',
    contact_name    VARCHAR(50) COMMENT '联系人',
    contact_phone   VARCHAR(20) COMMENT '联系电话',
    address         VARCHAR(200) COMMENT '地址',
    business_hours  VARCHAR(50) COMMENT '营业时间',
    status          TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-启用',
    remark          VARCHAR(500) COMMENT '备注',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_by       BIGINT COMMENT '创建人',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_by       BIGINT COMMENT '更新人',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_store_code (store_code),
    KEY idx_agent_id (agent_id)
) COMMENT='门店表';

门店配置表(rui_cashier_store_config

CREATE TABLE #prefix#cashier_store_config (
    id                  BIGINT PRIMARY KEY COMMENT '配置ID',
    store_id            BIGINT NOT NULL COMMENT '门店ID',
    config              JSON NOT NULL COMMENT '配置内容:{
                                                  \"productPayMode\": 2,           // 商品支付模式:1-先付款 2-后付款
                                                  \"balancePayProduct\": 0,        // 余额是否可支付商品:0-否 1-是
                                                  \"notifyOnOrder\": 1,            // 下单是否通知:0-否 1-是
                                                  \"autoCleanTime\": 10,           // 自动清洁时间(分钟)
                                                  \"minDeposit\": 50.00,           // 最低押金(可选)
                                                  \"overtimeRule\": {              // 超时规则(可选)
                                                    \"type\": 1,                    // 1-按小时收费 2-按套餐收费
                                                    \"price\": 20.00
                                                  }
                                                }',
    tenant_id           BIGINT DEFAULT 0 COMMENT '租户ID',
    create_time         DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time         DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_store_id (store_id)
) COMMENT='门店配置表';

包间类型表(rui_cashier_room_type

CREATE TABLE #prefix#cashier_room_type (
    id              BIGINT PRIMARY KEY COMMENT '类型ID',
    store_id        BIGINT NOT NULL COMMENT '所属门店ID',
    type_name       VARCHAR(50) NOT NULL COMMENT '类型名称',
    capacity        INT DEFAULT 4 COMMENT '容纳人数',
    icon            VARCHAR(200) COMMENT '图标',
    sort            INT DEFAULT 0 COMMENT '排序',
    status          TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-启用',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    KEY idx_store_id (store_id)
) COMMENT='包间类型表';

包间表(rui_cashier_room

CREATE TABLE #prefix#cashier_room (
    id              BIGINT PRIMARY KEY COMMENT '包间ID',
    store_id        BIGINT NOT NULL COMMENT '所属门店ID',
    room_type_id    BIGINT NOT NULL COMMENT '包间类型ID',
    room_name       VARCHAR(50) NOT NULL COMMENT '包间名称',
    room_no         VARCHAR(20) NOT NULL COMMENT '包间编号',
    room_status     TINYINT DEFAULT 0 COMMENT '状态:0-空闲 1-使用中 2-待清洁 3-已挂单 4-已预约',
    current_order_id BIGINT COMMENT '当前订单ID',
    device_config   JSON COMMENT '设备配置(关联的设备ID列表)',
    sort            INT DEFAULT 0 COMMENT '排序',
    enabled         TINYINT DEFAULT 1 COMMENT '启用状态:0-禁用 1-启用',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_room_no (store_id, room_no),
    KEY idx_store_id (store_id),
    KEY idx_room_status (room_status)
) COMMENT='包间表';

定价策略表(rui_cashier_pricing_strategy

CREATE TABLE #prefix#cashier_pricing_strategy (
    id              BIGINT PRIMARY KEY COMMENT '策略ID',
    room_type_id    BIGINT NOT NULL COMMENT '包间类型ID',
    strategy_name   VARCHAR(50) NOT NULL COMMENT '策略名称',
    status          TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-启用',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_room_type_id (room_type_id),
    KEY idx_status (status)
) COMMENT='定价策略表';

套餐表(rui_cashier_pricing_package

CREATE TABLE #prefix#cashier_pricing_package (
    id              BIGINT PRIMARY KEY COMMENT '套餐ID',
    strategy_id     BIGINT NOT NULL COMMENT '策略ID',
    package_name    VARCHAR(50) NOT NULL COMMENT '套餐名称',
    billing_type    TINYINT NOT NULL COMMENT '计费方式:1-按时 2-包时段 3-按局',
    price           DECIMAL(19,4) NOT NULL COMMENT '套餐价格',
    duration        INT COMMENT '时长(分钟),包时段时有效',
    min_duration    INT DEFAULT 60 COMMENT '最低消费时长(分钟),按时计费时有效',
    restrictions    JSON COMMENT '限制条件(时段、工作日、节假日)',
    is_default      TINYINT DEFAULT 0 COMMENT '是否默认套餐:0-否 1-是',
    sort            INT DEFAULT 0 COMMENT '排序',
    status          TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-启用',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    KEY idx_strategy_id (strategy_id),
    KEY idx_status (status)
) COMMENT='套餐表';

设备表(rui_cashier_device

CREATE TABLE #prefix#cashier_device (
    id              BIGINT PRIMARY KEY COMMENT '设备ID',
    store_id        BIGINT NOT NULL COMMENT '所属门店ID',
    room_id         BIGINT COMMENT '关联包间ID(设备可在公共区域,此时为空)',
    location        VARCHAR(100) COMMENT '设备位置:前台、茶水间、大厅等(设备在公共区域时填写)',
    device_name     VARCHAR(50) NOT NULL COMMENT '设备名称',
    device_code     VARCHAR(50) NOT NULL COMMENT '设备编号(唯一标识)',
    device_type     TINYINT NOT NULL COMMENT '设备类型:1-网关 2-门锁 3-电源 4-音箱 5-打印机 6-锁球器',
    parent_id       BIGINT COMMENT '父设备ID(门锁/电源等关联网关)',
    online_status   TINYINT DEFAULT 0 COMMENT '在线状态:0-离线 1-在线',
    last_heartbeat  DATETIME(3) COMMENT '最后心跳时间',
    -- 4G设备信息
    imei            VARCHAR(20) COMMENT 'IMEI号(4G设备)',
    sim_card_no     VARCHAR(20) COMMENT '流量卡号(4G设备)',
    sim_operator    VARCHAR(20) COMMENT '运营商(移动/联通/电信)',
    sim_expire_date DATE COMMENT '流量卡到期日期',
    -- 设备功能配置
    functions       JSON COMMENT '设备功能配置:{
                                        \"speaker\": {                   // 音箱功能(电源控制器自带音箱时)
                                          \"enabled\": true,
                                          \"type\": \"EXTERNAL\",          // EXTERNAL-外置 INTERNAL-内置
                                          \"volume\": 80                  // 音量 0-100
                                        },
                                        \"power\": {                     // 电源功能
                                          \"channels\": 4,                // 通道数
                                          \"channelNames\": [\"照明\", \"空调\", \"插座\", \"备用\"]
                                        }
                                      }',
    config          JSON COMMENT '扩展配置',
    sort            INT DEFAULT 0 COMMENT '排序',
    status          TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-启用',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_device_code (device_code),
    KEY idx_store_id (store_id),
    KEY idx_room_id (room_id),
    KEY idx_device_type (device_type),
    KEY idx_imei (imei)
) COMMENT='设备表';

主订单表(rui_cashier_order

CREATE TABLE #prefix#cashier_order (
    id              BIGINT PRIMARY KEY COMMENT '订单ID',
    order_no        VARCHAR(32) NOT NULL COMMENT '订单编号',
    store_id        BIGINT NOT NULL COMMENT '门店ID',
    room_id         BIGINT COMMENT '包间ID(包间订单时)',
    order_type      TINYINT DEFAULT 1 COMMENT '订单类型:1-包间订单 2-纯商品订单',
    customer_name   VARCHAR(50) COMMENT '顾客姓名',
    customer_phone  VARCHAR(20) COMMENT '顾客电话',
    room_amount     DECIMAL(19,4) DEFAULT 0 COMMENT '包间费用',
    product_amount  DECIMAL(19,4) DEFAULT 0 COMMENT '商品费用',
    discount_amount DECIMAL(19,4) DEFAULT 0 COMMENT '优惠金额',
    total_amount    DECIMAL(19,4) DEFAULT 0 COMMENT '订单总金额',
    pay_amount      DECIMAL(19,4) DEFAULT 0 COMMENT '实付金额',
    pay_status      TINYINT DEFAULT 0 COMMENT '支付状态:0-未支付 1-部分支付 2-已支付',
    pay_type        VARCHAR(20) COMMENT '支付方式:CASH/WECHAT/ALIPAY/BALANCE',
    pay_time        DATETIME(3) COMMENT '支付时间',
    status          TINYINT DEFAULT 0 COMMENT '状态:0-开台中 1-已挂单 2-待支付 3-已完成 4-已退款',
    remark          VARCHAR(500) COMMENT '备注',
    refund_amount   DECIMAL(19,4) DEFAULT 0 COMMENT '退款金额',
    refund_reason   VARCHAR(500) COMMENT '退款原因',
    refund_time     DATETIME(3) COMMENT '退款时间',
    cashier_id      BIGINT COMMENT '收银员ID',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_order_no (order_no),
    KEY idx_store_id (store_id),
    KEY idx_room_id (room_id),
    KEY idx_status (status),
    KEY idx_create_time (create_time)
) COMMENT='主订单表';

包间子订单表(rui_cashier_room_sub_order

CREATE TABLE #prefix#cashier_room_sub_order (
    id              BIGINT PRIMARY KEY COMMENT '子订单ID',
    order_id        BIGINT NOT NULL COMMENT '主订单ID',
    room_id         BIGINT NOT NULL COMMENT '包间ID',
    package_id      BIGINT COMMENT '套餐ID',
    billing_type    TINYINT NOT NULL COMMENT '计费方式:1-按时 2-包时段 3-按局',
    price           DECIMAL(19,4) NOT NULL COMMENT '套餐价格/单价',
    start_time      DATETIME(3) COMMENT '开台时间',
    end_time        DATETIME(3) COMMENT '结账时间',
    duration        INT COMMENT '使用时长(分钟)',
    game_count      INT DEFAULT 0 COMMENT '局数',
    amount          DECIMAL(19,4) DEFAULT 0 COMMENT '包间费用',
    status          TINYINT DEFAULT 0 COMMENT '状态:0-进行中 1-已完成 2-已取消',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_order_id (order_id),
    KEY idx_room_id (room_id)
) COMMENT='包间子订单表';

商品子订单表(rui_cashier_product_sub_order

CREATE TABLE #prefix#cashier_product_sub_order (
    id              BIGINT PRIMARY KEY COMMENT '子订单ID',
    order_id        BIGINT NOT NULL COMMENT '主订单ID',
    product_id      BIGINT NOT NULL COMMENT '商品ID',
    product_name    VARCHAR(100) NOT NULL COMMENT '商品名称',
    product_price   DECIMAL(19,4) NOT NULL COMMENT '商品单价',
    quantity        INT NOT NULL COMMENT '数量',
    amount          DECIMAL(19,4) NOT NULL COMMENT '小计金额',
    pay_status      TINYINT DEFAULT 0 COMMENT '支付状态:0-未支付 1-部分支付 2-已支付',
    source          TINYINT DEFAULT 1 COMMENT '来源:1-收银台 2-顾客小程序',
    status          TINYINT DEFAULT 0 COMMENT '状态:0-待处理 1-已确认 2-已取消',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    KEY idx_order_id (order_id),
    KEY idx_product_id (product_id)
) COMMENT='商品子订单表';

商品表(rui_cashier_product

CREATE TABLE #prefix#cashier_product (
    id              BIGINT PRIMARY KEY COMMENT '商品ID',
    category_id     BIGINT COMMENT '分类ID',
    product_name    VARCHAR(100) NOT NULL COMMENT '商品名称',
    product_code    VARCHAR(50) COMMENT '商品编码',
    product_type    TINYINT DEFAULT 1 COMMENT '类型:1-普通商品 2-服务商品',
    unit            VARCHAR(20) COMMENT '单位',
    sale_price      DECIMAL(19,4) NOT NULL COMMENT '售价',
    cost_price      DECIMAL(19,4) COMMENT '成本价',
    status          TINYINT DEFAULT 1 COMMENT '状态:0-禁用 1-启用',
    sort            INT DEFAULT 0 COMMENT '排序',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    deleted         TINYINT DEFAULT 0 COMMENT '删除标志',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    KEY idx_category_id (category_id)
) COMMENT='商品表';

2.6 错误码设计

收银系统错误码区间:5000-5999

错误码 含义 场景
5000 门店不存在 操作不存在的门店
5001 门店已禁用 门店状态为禁用
5010 包间不存在 操作不存在的包间
5011 包间已占用 开台时包间不是空闲状态
5012 包间已禁用 包间状态为禁用
5020 订单不存在 操作不存在的订单
5021 订单状态错误 操作与当前状态不符
5022 订单已支付 重复支付
5023 退款金额超过订单金额 退款金额校验失败
5030 商品不存在 添加商品时商品不存在或已下架
5040 定价策略不存在 包间类型没有配置定价策略
5041 无可用套餐 当前时段没有匹配的套餐
5050 设备不存在 操作不存在的设备
5051 设备离线 设备控制时设备离线
5060 门店配置不存在 门店未配置

三、验收标准

MVP 阶段验收标准

  • 门店管理:可创建、编辑、禁用门店,支持按代理商筛选
  • 门店配置:可配置商品支付模式、余额支付开关、下单通知开关
  • 包间管理:可创建包间类型和包间,配置设备绑定
  • 套餐策略:可创建定价策略,添加多个套餐,支持排序和默认套餐
  • 开台流程:收银员可选择空闲包间开台,系统自动匹配当前时段可用套餐
  • 计费计算:按时计费正确计算时长和费用,支持最低消费时长
  • 商品管理:可添加商品,支持收银台追加到订单
  • 结账流程:可正常结账,生成订单,支持预付款/后付款模式
  • 退款功能:可对已支付订单进行部分或全额退款
  • 营业报表:可查看门店营业日报(营业额、订单数、包间利用率)
  • 权限控制:不同角色(总部/代理商/店长/收银员)看到不同数据和功能

性能标准

  • 包间状态查询响应时间 < 200ms
  • 套餐匹配响应时间 < 300ms
  • 开台操作响应时间 < 500ms
  • 结账计算响应时间 < 500ms
  • 报表查询响应时间 < 2s(支持日期范围筛选)

四、风险与依赖

风险 影响 缓解措施
多门店数据量大 报表服务独立,定时同步数据;数据库按租户分表
套餐策略复杂 策略+套餐两级设计,限制条件JSON化;充分测试边界场景
支付 SDK 延迟 先实现现金支付,预留支付接口;等 SDK 就绪后对接
uni-app 性能 收银场景简单,无复杂动画;如性能不足可考虑原生小程序
智能设备对接 预留设备控制接口;等 IOT 平台就绪后对接;APP 端先集成插件
并发开台 包间状态变更加分布式锁;订单号使用雪花算法
第三方平台对接 预留开放平台 API;三期按需对接美团等平台
子订单分离 商品子订单独立支付状态,需保证数据一致性

五、预留扩展设计

5.1 会员钱包预留

-- 会员钱包表(二期)
CREATE TABLE #prefix#cashier_member_wallet (
    id              BIGINT PRIMARY KEY COMMENT '钱包ID',
    member_id       BIGINT NOT NULL COMMENT '会员ID',
    real_balance    DECIMAL(19,4) DEFAULT 0 COMMENT '实际金额',
    gift_balance    DECIMAL(19,4) DEFAULT 0 COMMENT '赠送金额',
    total_balance   DECIMAL(19,4) DEFAULT 0 COMMENT '总余额',
    status          TINYINT DEFAULT 1 COMMENT '状态',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
    UNIQUE KEY uk_member_id (member_id)
) COMMENT='会员钱包表';

-- 钱包流水表(二期)
CREATE TABLE #prefix#cashier_wallet_transaction (
    id              BIGINT PRIMARY KEY COMMENT '流水ID',
    wallet_id       BIGINT NOT NULL COMMENT '钱包ID',
    transaction_type TINYINT NOT NULL COMMENT '类型:1-充值 2-消费 3-退款',
    amount          DECIMAL(19,4) NOT NULL COMMENT '金额',
    real_amount     DECIMAL(19,4) COMMENT '实际金额变动',
    gift_amount     DECIMAL(19,4) COMMENT '赠送金额变动',
    order_no        VARCHAR(32) COMMENT '关联订单号',
    remark          VARCHAR(500) COMMENT '备注',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    KEY idx_wallet_id (wallet_id)
) COMMENT='钱包流水表';
// 余额支付接口(预留)
public interface BalancePaymentService {
    // 检查余额是否足够
    boolean checkBalance(Long memberId, BigDecimal amount);
    
    // 扣款(先扣赠送金额,再扣实际金额)
    PaymentResult deduct(Long memberId, BigDecimal amount, String orderNo);
    
    // 退款(退回实际金额)
    PaymentResult refund(Long memberId, BigDecimal amount, String orderNo);
}

// 门店配置余额支付范围
// StoreConfig.balance_pay_product0-余额不可支付商品 1-余额可支付商品

5.2 优惠券/团购券预留

-- 优惠券表(二期)
CREATE TABLE #prefix#cashier_coupon (
    id              BIGINT PRIMARY KEY COMMENT '优惠券ID',
    coupon_name     VARCHAR(100) NOT NULL COMMENT '优惠券名称',
    coupon_type     TINYINT NOT NULL COMMENT '类型:1-满减 2-折扣 3-立减',
    face_value      DECIMAL(19,4) NOT NULL COMMENT '面值',
    min_amount      DECIMAL(19,4) DEFAULT 0 COMMENT '最低消费金额',
    valid_days      INT COMMENT '有效天数',
    status          TINYINT DEFAULT 1 COMMENT '状态',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    update_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间'
) COMMENT='优惠券表';

-- 第三方团购券表(二期)
CREATE TABLE #prefix#cashier_third_party_voucher (
    id              BIGINT PRIMARY KEY COMMENT '券ID',
    platform        VARCHAR(20) NOT NULL COMMENT '平台:MEITUAN/DIANPING',
    voucher_code    VARCHAR(50) NOT NULL COMMENT '券码',
    voucher_name    VARCHAR(100) COMMENT '券名称',
    face_value      DECIMAL(19,4) NOT NULL COMMENT '面值',
    status          TINYINT DEFAULT 0 COMMENT '状态:0-未使用 1-已使用 2-已过期',
    use_time        DATETIME(3) COMMENT '使用时间',
    order_no        VARCHAR(32) COMMENT '关联订单号',
    tenant_id       BIGINT DEFAULT 0 COMMENT '租户ID',
    create_time     DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
    UNIQUE KEY uk_voucher_code (voucher_code)
) COMMENT='第三方团购券表';
// 优惠计算接口(预留)
public interface DiscountService {
    // 计算订单可使用的优惠
    List<DiscountVO> calculateAvailableDiscounts(Long orderId, Long memberId);
    
    // 应用优惠
    DiscountResult applyDiscount(Long orderId, List<Long> couponIds, List<String> voucherCodes);
    
    // 核销团购券
    VoucherResult verifyVoucher(String voucherCode);
}

5.3 支付通道预留

// 支付接口(预留)
public interface PaymentService {
    // 发起支付
    PaymentResult pay(Long orderId, String payType, BigDecimal amount);
    
    // 查询支付状态
    PaymentStatus queryStatus(String payOrderNo);
    
    // 退款
    RefundResult refund(Long orderId, BigDecimal amount, String reason);
}

// 当前实现:现金支付
@Component
public class CashPaymentService implements PaymentService {
    // 仅记录支付流水,不调用第三方
}

// 后续扩展:微信支付、支付宝、余额支付等
@Component
public class WechatPaymentService implements PaymentService {
    // 对接支付平台 SDK
}

5.4 第三方平台对接预留

// 开放平台接口(预留)
@RestController
@RequestMapping("/cashier/open")
public class OpenPlatformController {
    
    // 查询包间可用性
    @GetMapping("/room/availability")
    public Result<List<RoomAvailabilityVO>> queryAvailability(
            @RequestParam Long storeId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {
        // 返回各包间在指定时段的可用状态
    }
    
    // 查询套餐价格
    @GetMapping("/room/{roomTypeId}/packages")
    public Result<List<PackageVO>> queryPackages(
            @PathVariable Long roomTypeId,
            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime) {
        // 返回当前时段可用套餐
    }
    
    // 第三方下单
    @PostMapping("/order/create")
    public Result<OrderVO> createOrder(@RequestBody @Valid OpenOrderDTO dto) {
        // 创建订单,返回订单信息
    }
    
    // 订单状态同步
    @GetMapping("/order/{orderNo}/status")
    public Result<OrderStatusVO> queryStatus(@PathVariable String orderNo) {
        // 返回订单当前状态
    }
    
    // 退款
    @PostMapping("/order/{orderNo}/refund")
    public Result<RefundVO> refund(@PathVariable String orderNo, @RequestBody RefundDTO dto) {
        // 处理退款
    }
}

5.5 智能设备控制预留

// 设备控制服务(预留)
public interface DeviceControlService {
    // 开锁
    Result<Void> unlock(Long roomId);
    
    // 关锁
    Result<Void> lock(Long roomId);
    
    // 通电
    Result<Void> powerOn(Long roomId);
    
    // 断电
    Result<Void> powerOff(Long roomId);
    
    // 语音播报
    Result<Void> playVoice(Long roomId, String content);
    
    // 打印小票
    Result<Void> printTicket(Long roomId, String content);
}

// 当前实现:空实现(记录日志)
@Component
public class DummyDeviceControlService implements DeviceControlService {
    // 仅记录操作日志,等 IOT 平台对接后替换
}

六、模块结构

app/rui-cashier/
├── pom.xml                              # 聚合 POM
├── rui-cashier-store/                       # 门店+包间服务
│   ├── rui-cashier-store-common/            # DTO、枚举、常量
│   ├── rui-cashier-store-core/              # Entity、Mapper、Service
│   └── rui-cashier-store-api/               # REST API
├── rui-cashier-order/                       # 订单服务
│   ├── rui-cashier-order-common/
│   ├── rui-cashier-order-core/
│   └── rui-cashier-order-api/
├── rui-cashier-product/                     # 商品服务
│   ├── rui-cashier-product-common/
│   ├── rui-cashier-product-core/
│   └── rui-cashier-product-api/
└── rui-cashier-report/                      # 报表服务
    ├── rui-cashier-report-common/
    ├── rui-cashier-report-core/
    └── rui-cashier-report-api/

七、实施阶段规划

阶段一:MVP6-8 周)

  • 搭建项目结构
  • 实现 rui-cashier-store(门店+包间+套餐策略+设备管理)
  • 实现 rui-cashier-order(开台、计费、结账、退款、子订单)
  • 实现 rui-cashier-product(商品管理)
  • 实现基础报表
  • 开发管理后台页面(admin-ui
  • 开发收银台 APPuni-app

阶段二:会员+营销+顾客小程序(4-6 周)

  • 会员系统(注册、积分、储值)
  • 会员钱包(实际金额+赠送金额)
  • 优惠券、营销活动
  • 顾客小程序(预约、扫码开台、在线支付)

阶段三:生态对接(4-6 周)

  • 支付通道对接(微信、支付宝、余额)
  • 第三方平台对接(美团等)
  • 第三方团购券对接
  • IOT 设备对接(通过 IOT 平台)
  • 收银机/PC 端开发

八、收银系统菜单配置

8.1 完整菜单 JSON

{
  "name": "cashier",
  "menus": [
    {
      "code": "cashier",
      "name": "收银系统",
      "type": 1,
      "icon": "tabler:money",
      "sortNo": 100,
      "children": [
        {
          "code": "store",
          "name": "门店管理",
          "type": 2,
          "icon": "tabler:building-store",
          "path": "/cashier/store",
          "permission": "cashier:store:list",
          "sortNo": 1,
          "buttons": [
            { "code": "btn:add", "name": "新增", "permission": "cashier:store:add" },
            { "code": "btn:edit", "name": "编辑", "permission": "cashier:store:edit" },
            { "code": "btn:del", "name": "删除", "permission": "cashier:store:delete" }
          ]
        },
        {
          "code": "room",
          "name": "包间管理",
          "type": 2,
          "icon": "tabler:door",
          "path": "/cashier/room",
          "permission": "cashier:room:list",
          "sortNo": 2,
          "buttons": [
            { "code": "btn:add", "name": "新增", "permission": "cashier:room:add" },
            { "code": "btn:edit", "name": "编辑", "permission": "cashier:room:edit" },
            { "code": "btn:del", "name": "删除", "permission": "cashier:room:delete" }
          ]
        },
        {
          "code": "product",
          "name": "商品管理",
          "type": 2,
          "icon": "tabler:package",
          "path": "/cashier/product",
          "permission": "cashier:product:list",
          "sortNo": 3,
          "buttons": [
            { "code": "btn:add", "name": "新增", "permission": "cashier:product:add" },
            { "code": "btn:edit", "name": "编辑", "permission": "cashier:product:edit" },
            { "code": "btn:del", "name": "删除", "permission": "cashier:product:delete" }
          ]
        },
        {
          "code": "pricing",
          "name": "定价策略",
          "type": 2,
          "icon": "tabler:tags",
          "path": "/cashier/pricing",
          "permission": "cashier:pricing:list",
          "sortNo": 4,
          "buttons": [
            { "code": "btn:add", "name": "新增", "permission": "cashier:pricing:add" },
            { "code": "btn:edit", "name": "编辑", "permission": "cashier:pricing:edit" },
            { "code": "btn:del", "name": "删除", "permission": "cashier:pricing:delete" }
          ]
        },
        {
          "code": "order",
          "name": "订单管理",
          "type": 2,
          "icon": "tabler:file-invoice",
          "path": "/cashier/order",
          "permission": "cashier:order:list",
          "sortNo": 5,
          "buttons": [
            { "code": "btn:add", "name": "开台", "permission": "cashier:order:add" },
            { "code": "btn:checkout", "name": "结账", "permission": "cashier:order:checkout" },
            { "code": "btn:refund", "name": "退款", "permission": "cashier:order:refund" }
          ]
        },
        {
          "code": "report",
          "name": "营业报表",
          "type": 2,
          "icon": "tabler:chart-bar",
          "path": "/cashier/report",
          "permission": "cashier:report:list",
          "sortNo": 6
        }
      ]
    }
  ]
}

8.2 权限标识汇总

模块 权限标识 说明
门店 cashier:store:list 查询门店
门店 cashier:store:add 新增门店
门店 cashier:store:edit 编辑门店
门店 cashier:store:delete 删除门店
包间 cashier:room:list 查询包间
包间 cashier:room:add 新增包间
包间 cashier:room:edit 编辑包间
包间 cashier:room:delete 删除包间
商品 cashier:product:list 查询商品
商品 cashier:product:add 新增商品
商品 cashier:product:edit 编辑商品
商品 cashier:product:delete 删除商品
定价 cashier:pricing:list 查询定价策略
定价 cashier:pricing:add 新增定价策略
定价 cashier:pricing:edit 编辑定价策略
定价 cashier:pricing:delete 删除定价策略
订单 cashier:order:list 查询订单
订单 cashier:order:add 开台
订单 cashier:order:checkout 结账
订单 cashier:order:refund 退款
报表 cashier:report:list 查看报表

文档结束