补货系统文档.md 17 KB

补货系统文档

系统概览

补货系统负责管理智能售货机的商品补货流程,包含两套子体系:

  • 补货员体系:独立的补货员账号管理、微信登录认证、设备绑定,以及小程序端执行补货操作
  • 补货单体系:运营后台创建补货计划单,管理补货单的完整生命周期

系统已从 V1(t_stocker 上货员)迁移到 V2(t_replenisher 补货员),V1 表已废弃。


一、补货员管理

1.1 数据模型

t_replenisher(补货员表)

字段 类型 说明
id BIGINT 主键,雪花算法生成
name VARCHAR 姓名
phone VARCHAR 手机号
employee_id VARCHAR 工号
wechat_openid VARCHAR 微信 OpenID(绑定后写入)
avatar VARCHAR 头像 URL
status INT 状态:1=启用,0=禁用
total_tasks INT 累计任务数
last_task_time DATETIME 最后任务时间
create_time DATETIME 创建时间
update_time DATETIME 更新时间

t_replenisher_device(设备绑定表)

字段 类型 说明
id BIGINT 主键
replenisher_id BIGINT 补货员 ID
device_id VARCHAR 设备 SN 号
source VARCHAR 绑定来源:MANUAL(手动)/ QR(扫码)/ SHOP_INHERIT(门店继承)
create_time DATETIME 绑定时间

1.2 API 接口

所有接口路由前缀为 /replenishers,需要管理员权限。

补货员 CRUD

方法 路径 权限 说明
GET /replenishers/list replenisher:read 分页查询补货员列表,支持 keyword/status 筛选
GET /replenishers/{id} replenisher:read 获取补货员详情(含绑定设备数)
GET /replenishers/search replenisher:read 按姓名/手机/工号模糊搜索
POST /replenishers replenisher:create 创建补货员(name 必填)
PUT /replenishers/{id} replenisher:update 更新补货员信息
PUT /replenishers/{id}/status replenisher:update 启用/禁用补货员
DELETE /replenishers/{id} replenisher:delete 删除补货员(级联解绑所有设备)

设备绑定

方法 路径 权限 说明
GET /replenishers/{id}/devices replenisher:read 获取补货员绑定的设备 ID 列表
POST /replenishers/{id}/devices replenisher:update 绑定设备到补货员(INSERT IGNORE,幂等)
DELETE /replenishers/{id}/devices/{deviceId} replenisher:update 解绑单个设备
POST /replenishers/batch-bind replenisher:update 批量绑定多个补货员到多个设备

微信绑定

方法 路径 权限 说明
POST /replenishers/{id}/binding-code replenisher:update 生成 24 位绑定码(Redis 存储,24小时有效)

1.3 认证流程

补货员的绑定和登录全部在运营端小程序(haha-admin-mp)中完成。

创建与绑定(首次使用)

管理员在 Web 后台创建补货员 → 生成 24 位绑定码(Redis 存储,24h 有效)
→ 将绑定码告知补货员
→ 补货员打开"哈哈运营平台"小程序 → 登录页点击"已有绑定码?点击绑定微信"
→ 输入绑定码 → 微信授权 → POST /replenisher/login/bind
→ 后端校验绑定码、获取 openid、写入 wechat_openid、激活账号
→ 自动登录 → 进入补货首页

静默登录(已绑定后)

补货员打开运营端小程序 → 点击"补货员微信一键登录"
→ wx.login() 获取 code → POST /replenisher/login/wechat
→ 后端通过 code 换 openid → 查找已绑定的补货员
→ 生成 SaToken → 返回 token + 用户信息 → 进入补货首页

1.4 关联管理入口

补货员还可以通过以下入口绑定到门店/设备:

来源 接口 说明
门店管理 POST /shops/{id}/replenishers 将补货员绑定到门店下所有设备,source=SHOP_INHERIT
门店管理 GET /shops/{id}/replenishers 查询门店关联的补货员列表
设备管理 POST /devices/{deviceId}/replenishers 直接绑定补货员到设备,source=MANUAL
设备管理 GET /devices/{deviceId}/replenishers 查询设备绑定的补货员列表
设备管理 DELETE /devices/{deviceId}/replenishers/{replenisherId} 解绑设备的补货员

二、补货操作

2.1 权限控制

补货员只能操作自己绑定的设备。操作前系统会:

  1. 从当前登录的 SaToken session 中获取补货员 ID
  2. 查询补货员绑定的设备 ID 列表
  3. 校验目标设备是否在绑定列表中,不在则拒绝访问

2.2 API 接口

所有接口路由前缀为 /replenisher,需要补货员角色(REPLENISHER)。

方法 路径 说明
GET /replenisher/my-info 获取当前补货员个人信息
GET /replenisher/device/list 获取绑定设备列表(含各设备库存概览、在线状态)
GET /replenisher/device/inventory/{deviceId} 获取设备库存详情(含商品信息、层模板分组)
POST /replenisher/stock/replenish 执行补货操作,逐商品增加库存

2.3 补货操作流程

补货员选择设备 → GET /replenisher/device/inventory/{deviceId} → 查看当前库存
→ 输入各商品补货数量 → POST /replenisher/stock/replenish
→ 后端逐商品调用 deviceInventoryService.increaseStock()
→ 库存增加成功 → 返回执行结果(成功/失败明细)

补货请求体(ReplenishDTO):

{
  "deviceId": "SN20250101001",
  "items": [
    {
      "productId": 1001,
      "productCode": "P001",
      "productName": "可口可乐",
      "shelfNum": 1,
      "position": "left",
      "quantity": 10
    }
  ]
}

2.4 库存记录

补货操作后系统自动记录上货日志:

  • 日志类型:InventoryLog.TYPE_RESTOCK(补货上货)
  • 数据库表:t_inventory_log 记录 beforeStock → afterStock 变动
  • 可通过 POST /inventory/records/v2 创建上货记录时关联补货员信息(replenisherIdreplenisherNamereplenisherPhone

三、补货单管理

补货单用于运营人员制定补货计划,管理补货任务从创建到完成的全流程。

3.1 数据模型

t_replenishment_order(补货单表)

字段 类型 说明
id BIGINT 主键
order_no VARCHAR 补货单号,规则:RO + yyyyMMdd + 4位序号
device_id VARCHAR 目标设备 SN
shop_id BIGINT 目标门店 ID
status INT 状态:0 草稿 / 1 已提交 / 2 已同步ERP / 3 已完成 / 4 已取消
erp_order_no VARCHAR ERP 采购单号(同步后回填)
erp_sync_time DATETIME ERP 同步时间
supplier_name VARCHAR 供应商名称
warehouse_name VARCHAR 发货仓库
expected_arrival_time DATETIME 预计到货时间
total_quantity INT 补货总数量
total_amount DECIMAL 补货总金额
remark VARCHAR 备注
creator_id BIGINT 创建人 ID
creator_name VARCHAR 创建人姓名

t_replenishment_order_item(补货单明细表)

字段 类型 说明
id BIGINT 主键
order_id BIGINT 关联补货单 ID
device_id VARCHAR 设备 SN(冗余)
product_id BIGINT 商品 ID
product_code VARCHAR 商品编码
product_name VARCHAR 商品名称
planned_quantity INT 计划补货数量(≥1)
actual_quantity INT 实际补货数量
before_stock INT 补货前库存
after_stock INT 补货后库存
unit_price DECIMAL 单价
total_price DECIMAL 小计金额
shelf_num INT 货架层号
position VARCHAR 货道位置(left/right)

3.2 状态流转

草稿(0) ──提交──→ 已提交(1) ──同步ERP──→ 已同步ERP(2) ──完成──→ 已完成(3)
  │                  │                                    │
  └──取消──→ 已取消(4) ←──取消──┘                        │
       ↑                                                   │
       └───────────────────────────────────────────────────┘
                          (已完成也可以取消)

状态说明:

状态码 状态名 标签色 说明
0 草稿 info 可编辑、可删除、可提交、可取消
1 已提交 warning 可同步ERP、可取消
2 已同步ERP primary 已推送至采购系统,可完成、可取消
3 已完成 success 终态(也可取消)
4 已取消 danger 终态

3.3 API 接口

路由前缀为 /replenishment-orders,需要相应权限。

方法 路径 权限 说明
GET /replenishment-orders/list replenishment:order:read 分页查询,支持 orderNo/deviceId/shopId/status/时间范围/创建人 筛选
GET /replenishment-orders/{id} replenishment:order:read 获取补货单详情
GET /replenishment-orders/{id}/items replenishment:order:read 获取补货单商品明细列表
POST /replenishment-orders replenishment:order:create 创建补货单(含商品明细)
PUT /replenishment-orders replenishment:order:update 更新补货单(仅草稿状态可更新)
DELETE /replenishment-orders/{id} replenishment:order:delete 删除补货单(仅草稿状态可删除)
POST /replenishment-orders/{id}/submit replenishment:order:submit 提交补货单(草稿 → 已提交)
POST /replenishment-orders/{id}/sync-erp replenishment:order:sync 同步到 ERP 系统(已提交 → 已同步ERP)
POST /replenishment-orders/{id}/complete replenishment:order:complete 完成补货单(已同步ERP → 已完成)
POST /replenishment-orders/{id}/cancel replenishment:order:update 取消补货单

3.4 操作约束

  • 创建:需传入 deviceId(必填)、商品明细列表(plannedQuantity ≥ 1),系统自动生成单号
  • 更新:仅草稿状态可更新,更新时重新计算 totalQuantity 和 totalAmount
  • 删除:仅草稿状态可删除,删除时级联删除明细
  • 提交:草稿 → 已提交,此后不可再编辑
  • 同步 ERP:目前为桩代码,预留企得宝 SDK 集成接口
  • 完成:已同步ERP → 已完成
  • 取消:草稿、已提交、已同步ERP、已完成 均可取消(取消是终态)

四、前端页面

4.1 Web 管理后台(haha-admin-web)

页面 路由 说明
补货员列表 /operation/replenisher 补货员 CRUD、设备绑定/解绑、绑定码生成
补货单列表 侧边栏「库存管理 → 补货单列表」 补货单查询、新建、状态操作
补货单详情 侧边栏「库存管理 → 补货单详情」 补货单完整信息 + 商品明细
设备管理 设备列表页内嵌弹窗 为指定设备绑定/解绑补货员
门店管理 门店列表页内嵌弹窗 为门店批量绑定补货员到其下所有设备
库存记录 库存管理 → 上货记录 上货记录中可关联补货员信息(V2 补货员体系)

4.2 运营端小程序(haha-admin-mp)

页面 路径 说明
补货首页 pages/replenish/index 补货员信息卡片、绑定设备列表、待补货统计、扫码开柜按钮
补货操作 pages/replenish/operation 设备商品清单、补货数量输入、提交补货
绑定微信 pages/replenish/bind 通过小程序码/绑定码参数进入,完成微信授权绑定
补货员管理 pages/replenisher/list 管理员查看补货员列表
编辑补货员 pages/replenisher/form 管理员新增/编辑补货员
设备绑定 pages/replenisher/bind-device 管理员为补货员绑定设备(门店设备树)
配置补货员 pages/device/replenisher-config 从设备端配置其绑定的补货员

4.3 扫码开柜

补货首页提供"扫码开柜"按钮,补货员可扫描设备机身二维码直接进入补货操作:

  1. 点击「扫码开柜」→ 调用 uni.scanCode 扫描设备二维码
  2. 机身二维码格式:https://dev-haha.kuaiyuman.cn/{deviceId}
  3. 解析提取 deviceId → 校验是否在绑定设备列表中
  4. 跳转 /pages/replenish/operation?deviceId=xxx 执行补货

五、数据库变更记录

文件 说明
docs/database/migrate_replenisher.sql V1 t_stocker → V2 t_replenisher 数据迁移
docs/database/migrate_replenishment_to_inventory.sql 补货单菜单注册到库存管理模块下
haha-admin/src/main/resources/sql/replenishment_order.sql t_replenishment_ordert_replenishment_order_item 建表 DDL

六、技术要点

6.1 库存操作

补货操作调用 DeviceInventoryService.increaseStock() 增加库存,该方法:

  • 若库存记录不存在则创建(stock = quantity)
  • 若已存在则累加(stock = beforeStock + quantity)
  • 无上限限制
  • 写入 t_inventory_log 记录变动
  • 使用乐观锁(version 字段)防止并发冲突

6.2 绑定码机制

  • 管理员在 Web 后台补货员列表点击「绑定码」按钮调用 POST /replenishers/{id}/binding-code
  • 后端生成 24 位随机字符串(UUID 截取)存入 Redis,Key 格式为 replenisher:bind:code:{code},TTL 24 小时
  • 将绑定码告知补货员,补货员在运营端小程序登录页输入绑定码完成微信绑定
  • 绑定码一次性使用,验证后立即从 Redis 删除

6.3 补货单号规则

  • 格式:RO + yyyyMMdd + 4位自增序号(如 RO202507060001
  • 通过查询当天最大单号 + 1 生成
  • 数据库 order_no 字段有 UNIQUE 索引保证唯一性
  • 日订单量超过 9999 会报错

6.4 ERP 集成状态

syncToErp 接口目前为桩代码,日志记录"模拟同步ERP成功"。企得宝 SDK 已在 haha-sdk 模块中预留,后续接入时需实现真实推送逻辑。


七、相关文件索引

后端核心文件

haha-entity/src/main/java/com/haha/entity/
├── Replenisher.java                    # 补货员实体
├── ReplenisherDevice.java              # 设备绑定实体
├── ReplenishmentOrder.java             # 补货单实体
├── ReplenishmentOrderItem.java         # 补货单明细实体
└── dto/
    ├── ReplenishDTO.java               # 补货操作请求 DTO
    ├── ReplenisherCreateDTO.java       # 创建补货员 DTO
    ├── ReplenisherUpdateDTO.java       # 更新补货员 DTO
    ├── ReplenisherQueryDTO.java        # 补货员查询 DTO
    ├── ReplenisherBindDTO.java         # 微信绑定 DTO
    ├── BindReplenisherDTO.java         # 门店绑定补货员 DTO
    ├── ReplenishmentOrderCreateDTO.java    # 创建补货单 DTO
    ├── ReplenishmentOrderUpdateDTO.java    # 更新补货单 DTO
    └── ReplenishmentOrderQueryDTO.java     # 补货单查询 DTO

haha-admin/src/main/java/com/haha/admin/controller/
├── ReplenisherController.java          # 补货员管理接口
├── ReplenisherLoginController.java     # 补货员认证接口
├── ReplenisherOperationController.java # 补货员操作接口
└── ReplenishmentOrderController.java   # 补货单管理接口

haha-service/src/main/java/com/haha/service/
├── ReplenisherService.java             # 补货员服务接口
├── ReplenishmentOrderService.java      # 补货单服务接口
└── impl/
    ├── ReplenisherServiceImpl.java     # 补货员服务实现
    └── ReplenishmentOrderServiceImpl.java  # 补货单服务实现

haha-mapper/src/main/java/com/haha/mapper/
├── ReplenisherMapper.java
├── ReplenisherDeviceMapper.java
├── ReplenishmentOrderMapper.java
└── ReplenishmentOrderItemMapper.java

haha-common/src/main/java/com/haha/common/enums/
└── ReplenishmentOrderStatusEnum.java   # 补货单状态枚举

前端核心文件

haha-admin-web/src/
├── views/replenisher/                  # 补货员管理页面
│   ├── index.vue
│   └── utils/
│       ├── hook.tsx
│       └── types.ts
├── views/replenishment-order/          # 补货单管理页面
│   ├── index.vue
│   ├── detail.vue
│   └── components/
│       └── CreateDialog.vue
└── api/
    ├── replenisher.ts
    └── replenishmentOrder.ts

haha-admin-mp/src/
├── pages/replenish/                    # 补货员小程序页面
│   ├── index.vue
│   ├── operation.vue
│   └── bind.vue
├── pages/replenisher/                  # 补货员管理页面
│   ├── list.vue
│   ├── form.vue
│   └── bind-device.vue
├── pages/device/
│   └── replenisher-config.vue
└── api/
    ├── replenish.ts
    └── replenisher.ts

haha-mp/src/
└── pages/replenish/
    └── bind.vue                       # 用户端绑定页面