data-model.md 5.4 KB

Data Model: 商家 ezPay 发票开通管理

Phase: Phase 1 — 表结构、字段、状态机 Date: 2026-06-15

变更一:pos_store 加列(已有表)

pos_store 新增一列,按全栈清单走(实体 + resultMap + select/insert/update + 前端 + i18n + SQL)。

字段 类型 默认 说明
invoice_exempt tinyint(1) 0 是否免用发票(不需开票):0需开票 / 1免用发票

不在本表加任何 ezPay 凭证字段(凭证进独立表,见决策 5)。

变更二:新增表 pos_store_ezpay(与 pos_store 1:1)

-- 2026-06-15 商家 ezPay 发票开通管理
CREATE TABLE pos_store_ezpay (
  id                 BIGINT       NOT NULL AUTO_INCREMENT COMMENT '主键',
  store_id           BIGINT       NOT NULL COMMENT '关联 pos_store.id(门店)',
  ezpay_status       TINYINT      NOT NULL DEFAULT 0 COMMENT '申请状态:0未申请/1申请中/2已开通',
  is_enabled         TINYINT      NOT NULL DEFAULT 1 COMMENT '启用开关:0停用/1启用(仅status=2有意义)',
  merchant_id        VARCHAR(32)  DEFAULT NULL COMMENT 'ezPay 商店代号 MerchantID_',
  hash_key           VARCHAR(64)  DEFAULT NULL COMMENT 'ezPay HashKey(32字节)',
  hash_iv            VARCHAR(64)  DEFAULT NULL COMMENT 'ezPay HashIV(16字节)',
  company_id         VARCHAR(32)  DEFAULT NULL COMMENT 'ezPay 会员编号 CompanyID_(字轨用,可空)',
  ubn                VARCHAR(16)  DEFAULT NULL COMMENT '统一编号(统编,商家上传)',
  apply_time         DATETIME     DEFAULT NULL COMMENT '提交申请时间(0->1)',
  approved_time      DATETIME     DEFAULT NULL COMMENT '开通时间(->2)',
  last_verify_result VARCHAR(255) DEFAULT NULL COMMENT '最近一次凭证验证结果',
  remark             VARCHAR(500) DEFAULT NULL COMMENT '备注',
  create_time        DATETIME     DEFAULT NULL COMMENT '创建时间',
  update_time        DATETIME     DEFAULT NULL COMMENT '更新时间',
  create_by          VARCHAR(64)  DEFAULT NULL COMMENT '创建人',
  update_by          VARCHAR(64)  DEFAULT NULL COMMENT '更新人',
  PRIMARY KEY (id),
  UNIQUE KEY uk_store_id (store_id),
  KEY idx_ezpay_status (ezpay_status)
) ENGINE=InnoDB DEFAULT CHARSET=utf88mb4 COMMENT='门店 ezPay 发票开通配置';

字段语义

  • store_id:唯一键,一门店一行。门店无此行 = 未申请(列表 LEFT JOIN,无行按 status=0 处理)。
  • ezpay_status:核心状态机字段(见下)。
  • is_enabled:运行时开关,仅 ezpay_status=2 时有意义;停用不影响 status。
  • merchant_id/hash_key/hash_iv:运营录入的 ezPay 凭证;company_id 字轨用可空。
  • ubn:商家在商家端上传的统一编号。
  • last_verify_result:记录最近验证的 ezPay 回应摘要,便于排查。

实体(PosStoreEzpay.java)

ruoyi-system/.../domain/PosStoreEzpay.java,MyBatis-Plus @TableName("pos_store_ezpay")@TableId(type=IdType.AUTO),字段与上表一一对应(驼峰)。

状态机

                ┌─────────────────────────────┐
                ▼                             │ 重置/重新申请
  未申请(0) ──发起申请──▶ 申请中(1) ──录入凭证+验证通过──▶ 已开通(2)
                              │                              │
                              │ 验证失败/网络异常             │ 停用
                              ▼ (保持 1)                     ▼
                          (原地,回传错误)          已开通+停用(enabled=0)
                                                             │ 恢复
                                                             ▼
                                                       已开通+启用(enabled=1)

不变量:

  • ezpay_status=2 的前置:必须经过一次成功的凭证验证(merchant_id/hash_key/hash_iv 非空且 last_verify_result 为通过)。
  • is_enabled 仅在 ezpay_status=2 时可切换为有效语义;其它状态下恒视为"不可开票"。
  • 免用发票(pos_store.invoice_exempt=1)优先于 ezPay 状态:免用门店即使有 pos_store_ezpay 行也视为不开票,且不进入待办过滤。

列表查询口径

平台后台列表 = pos_store LEFT JOIN pos_store_ezpay,过滤"实际卖货门店":

  • 纳入:普通店铺(is_stall=0)+ 摊位(is_stall=1,含夜市下摊位)
  • 排除:夜市(userType=3)本身不经 pos_store 开票;纯夜市容器门店按实现时数据口径确认

筛选维度:

  • invoice_exempt=1 → 免用发票
  • invoice_exempt=0 AND ezpay_status=0 → 未申请("还要去开通")
  • invoice_exempt=0 AND ezpay_status=1 → 申请中
  • invoice_exempt=0 AND ezpay_status=2 → 已开通
  • "还没开通" = invoice_exempt=0 AND ezpay_status IN (0,1)
  • "还要去开通" = invoice_exempt=0 AND ezpay_status=0

验证规则

  • 录入凭证:merchant_id 必填、hash_key 必填且 32 字节、hash_iv 必填且 16 字节(长度校验,ezPay 固定规格)。
  • 验证调用:超时 10s;网络异常按"未通过"处理,不抛 500,回传可重试提示。
  • 统编 ubn:商家端非免用门店建议必填(8 位数字),免用门店不强制。发起申请(apply)时强制校验:非空且为 8 位数字,不满足则拒绝推进为"申请中"。