|
|
@@ -12,7 +12,7 @@
|
|
|
通过企得宝 ERP 开放平台 API(`https://api.7debao.com/router/api`),实现:
|
|
|
|
|
|
- 将本地商品与 ERP 商品建立一对一关联
|
|
|
-- 将本地门店与 ERP 店铺建立一对一绑定
|
|
|
+- 将本地设备与 ERP 店铺建立一对一绑定(ERP 店铺对应系统设备)
|
|
|
- 后续补货单可推送至 ERP 生成采购单据
|
|
|
|
|
|
### 1.2 架构总览
|
|
|
@@ -69,13 +69,13 @@ t_product t_erp_goods 企得宝ERP
|
|
|
│ ... │ │ bar_code(JSON) │ │ ... │
|
|
|
└──────────────┘ │ modify_date │ └──────────┘
|
|
|
│ status │
|
|
|
-t_shop └──────────────────┘ 企得宝ERP
|
|
|
+t_device └──────────────────┘ 企得宝ERP
|
|
|
┌──────────────┐ t_erp_shop ┌──────────┐
|
|
|
│ id │ ┌──────────────────┐ │ shopId │
|
|
|
-│ shop_code │ │ id │ │ shopCode │
|
|
|
+│ deviceId ◄───┼────────────┤ shop_code │ │ shopCode │
|
|
|
│ erp_shop_id ├───────────►│ erp_shop_id ◄────┼──────┤ shopName │
|
|
|
-│ name │ │ shop_code │ │ ... │
|
|
|
-│ ... │ │ shop_name │ └──────────┘
|
|
|
+│ name │ │ shop_name │ │ ... │
|
|
|
+│ ... │ │ nick_name │ └──────────┘
|
|
|
└──────────────┘ │ status │
|
|
|
└──────────────────┘
|
|
|
```
|
|
|
@@ -83,8 +83,9 @@ t_shop └────────────────
|
|
|
### 2.2 关联关系
|
|
|
|
|
|
- `t_product.erp_goods_id` → `t_erp_goods.erp_goods_id`:本地商品与 ERP 商品的**一对一关联**
|
|
|
-- `t_shop.erp_shop_id` → `t_erp_shop.erp_shop_id`:本地门店与 ERP 店铺的**一对一绑定**
|
|
|
-- `t_product.name` = `t_erp_goods.goods_code`:两者业务上的对应关系(商品名称即为 ERP 编码),是一键自动关联的依据
|
|
|
+- `t_device.erp_shop_id` → `t_erp_shop.erp_shop_id`:本地设备与 ERP 店铺的**一对一绑定**(ERP 店铺对应系统中的设备,ERP 的 `shopCode` = 设备的 `deviceId`)
|
|
|
+- `t_product.name` = `t_erp_goods.goods_code`:商品名称即 ERP 编码,是一键自动关联的依据
|
|
|
+- `t_device.deviceId` = `t_erp_shop.shopCode`:设备ID即 ERP 店铺编码,是一键自动绑定的依据
|
|
|
|
|
|
### 2.3 DDL脚本
|
|
|
|
|
|
@@ -94,6 +95,7 @@ t_shop └────────────────
|
|
|
| `docs/database/create_erp_shop.sql` | 创建 `t_erp_shop` 缓存表 |
|
|
|
| `docs/database/add_erp_goods_id.sql` | `t_product` 增加 `erp_goods_id` 字段 |
|
|
|
| `docs/database/add_erp_shop_id.sql` | `t_shop` 增加 `erp_shop_id` 字段 |
|
|
|
+| `docs/database/add_device_erp_shop_id.sql` | `t_device` 增加 `erp_shop_id` 字段 |
|
|
|
| `docs/database/add_erp_goods_bar_code.sql` | `t_erp_goods` 增加 `bar_code`、`modify_date` |
|
|
|
| `docs/database/menu_add_erp_goods.sql` | 插入"ERP商品关联"菜单 |
|
|
|
| `docs/database/menu_add_erp_shop.sql` | 插入"ERP店铺管理"菜单 |
|
|
|
@@ -213,17 +215,35 @@ ERP API 统一 POST 到 `https://api.7debao.com/router/api`:
|
|
|
|
|
|
---
|
|
|
|
|
|
-## 六、ERP店铺管理
|
|
|
+## 六、ERP店铺管理(设备绑定)
|
|
|
|
|
|
### 6.1 同步
|
|
|
|
|
|
-- `POST /erp-shop/sync` — 从 ERP 查询店铺列表,缓存到 `t_erp_shop`
|
|
|
-- 当前实现为全量拉取(翻页),与商品同步类似采用异步执行
|
|
|
+- `POST /erp-shops/sync` — 从 ERP 全量翻页查询店铺列表
|
|
|
+- **名称过滤**:只保存店铺名称包含"自助售卖机"的记录到 `t_erp_shop`
|
|
|
+- **异步执行**:`@Async("taskExecutor")`,接口立即返回
|
|
|
+- 日志区分 `syncedCount` / `filteredCount`
|
|
|
|
|
|
-### 6.2 绑定
|
|
|
+### 6.2 手动绑定/解绑
|
|
|
|
|
|
-- `POST /erp-shop/bind` — 将本地门店与 ERP 店铺建立一对一绑定
|
|
|
-- `POST /erp-shop/unbind` — 解除绑定
|
|
|
+- `POST /erp-shops/bind` — 选择本地设备与 ERP 店铺一对一绑定
|
|
|
+- `POST /erp-shops/unbind` — 解除绑定(使用 `LambdaUpdateWrapper.set(null)` 强制写 NULL)
|
|
|
+- 绑定对象是 **设备**(`t_device`),非门店。ERP 店铺的 `shopCode` 对应设备的 `deviceId`
|
|
|
+
|
|
|
+### 6.3 一键自动绑定
|
|
|
+
|
|
|
+- `POST /erp-shops/auto-bind` — 遍历所有 ERP 缓存店铺,用 `shopCode` 匹配设备 `deviceId`
|
|
|
+- 匹配成功 → 自动绑定;未匹配到设备 → 跳过
|
|
|
+- **批量优化**:
|
|
|
+ - 查询已绑定:1 次 `WHERE erp_shop_id IN (...)`
|
|
|
+ - 查询设备:每 100 个 deviceId 一批 `WHERE device_id IN (...)`
|
|
|
+ - 批量 UPDATE:`CASE WHEN` SQL,每 100 条一批
|
|
|
+
|
|
|
+### 6.4 列表页
|
|
|
+
|
|
|
+- 分页展示(10/20/50 条/页),支持搜索店铺名称/卖家账号
|
|
|
+- 列:ERP店铺ID、店铺名称、卖家账号、设备ID、绑定设备、操作
|
|
|
+- 设备绑定标签悬停浮窗展示设备详情(deviceId、名称、门店、地址)
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -271,11 +291,19 @@ ERP API 统一 POST 到 `https://api.7debao.com/router/api`:
|
|
|
|
|
|
### 8.2 ERP店铺管理 `erp-shop/index.vue`
|
|
|
|
|
|
-类似商品关联页,提供店铺的同步、绑定、解除绑定功能。
|
|
|
+| 功能 | 描述 |
|
|
|
+|------|------|
|
|
|
+| 列表 | 分页展示 ERP 店铺(店铺ID、名称、卖家账号、设备ID、绑定状态) |
|
|
|
+| 搜索 | 按店铺名称/卖家账号搜索 |
|
|
|
+| 同步 | 异步后台执行,过滤"自助售卖机"名称 |
|
|
|
+| 一键绑定 | 按 shopCode 自动匹配设备 deviceId |
|
|
|
+| 手动绑定弹窗 | 选择本地设备进行绑定 |
|
|
|
+| 解除绑定 | 确认弹窗后解除 |
|
|
|
+| 设备浮窗 | 悬停已绑定设备标签时展示设备详情(deviceId、名称、门店、地址) |
|
|
|
|
|
|
### 8.3 Vite 代理配置
|
|
|
|
|
|
-`/erp-goods` 和 `/erp-shop` 路径需在 `vite.config.ts` 的 `apiPaths` 数组中注册,否则开发环境请求不会被转发到后端。
|
|
|
+`/erp-goods` 和 `/erp-shops` 路径需在 `vite.config.ts` 的 `apiPaths` 数组中注册,否则开发环境请求不会被转发到后端。
|
|
|
|
|
|
---
|
|
|
|
|
|
@@ -297,6 +325,14 @@ MyBatis-Plus 默认 `FieldStrategy.NOT_NULL`,`updateById(entity)` 会跳过 nu
|
|
|
|
|
|
原 `com.qdb:qdb-sdk:1.0.0` 是独立模块,与 `com.haha:qdb-sdk` 并存会导致 classpath 上有**两份** `GoodsApi.class`,旧版本优先加载 → NoSuchMethodError / ClassCastException。改为子模块统一 version,删除 Maven 本地旧 jar 后解决。
|
|
|
|
|
|
+### 9.5 为什么 ERP 店铺绑定的是设备而不是门店?
|
|
|
+
|
|
|
+ERP 中的店铺(自助售卖机)在业务上对应的是系统中的一个设备(售货机)。ERP 的 `shopCode` 字段存储的是设备 ID(`deviceId`),因此绑定关系建立在 `t_device` 表上。一键绑定时用 `shopCode` ↔ `deviceId` 做精确匹配。
|
|
|
+
|
|
|
+### 9.6 为什么同步和自动绑定都要用 CASE WHEN 批量 UPDATE?
|
|
|
+
|
|
|
+逐条 UPDATE 在数据量较大时性能很差(N 次网络往返)。`CASE WHEN` 将多条 UPDATE 合并为一条 SQL,每 100 行一批,大幅减少数据库交互次数。
|
|
|
+
|
|
|
---
|
|
|
|
|
|
## 十、待完成
|
|
|
@@ -304,9 +340,8 @@ MyBatis-Plus 默认 `FieldStrategy.NOT_NULL`,`updateById(entity)` 会跳过 nu
|
|
|
| 项目 | 状态 | 说明 |
|
|
|
|------|------|------|
|
|
|
| 补货单推送 ERP | TODO | `ReplenishmentOrderServiceImpl.syncToErp()` 当前为 no-op |
|
|
|
-| ERP 店铺同步 | 已实现 | 待前端完善 |
|
|
|
-| 增量同步 | 未实现 | 每次全量遍历本地商品,无时间戳过滤 |
|
|
|
-| qdb-sdk 编译 | 已验证 | 需 `mvn clean install` 后 classpath 唯一 |
|
|
|
+| 商品增量同步 | 未实现 | 每次全量遍历本地商品,无时间戳过滤 |
|
|
|
+| 店铺增量同步 | 未实现 | 每次全量翻页,无时间戳过滤 |
|
|
|
|
|
|
---
|
|
|
|