|
@@ -0,0 +1,112 @@
|
|
|
|
|
+# 团队页「关联订单 / 关联金额(元)」按商城商品-SKU 维度统计接口
|
|
|
|
|
+
|
|
|
|
|
+- 日期:2026-11-01
|
|
|
|
|
+- 状态:待派发(已入 tasks_backlog.json,等 hub 派发)
|
|
|
|
|
+- 优先级:P1
|
|
|
|
|
+- 模块:cfc-backend(仅后端接口,不动前端)
|
|
|
|
|
+- 需求方:廖总
|
|
|
|
|
+- 需求原文:小程序「我的团队」页(promotion/team.vue)要展示「关联订单」「关联金额(元)」,按商城商品/SKU 维度;本次只补充后台接口,前端页不动。
|
|
|
|
|
+
|
|
|
|
|
+## 1. 背景与现状
|
|
|
|
|
+
|
|
|
|
|
+小程序「我的团队」页 `cfc-frontend/pages/promotion/team.vue` 现已通过 `CommissionController` 的 `/api/commission/team/*` 系列获取团队数据:
|
|
|
|
|
+
|
|
|
|
|
+- `/team`(L1/L2 人数、团队佣金)
|
|
|
|
|
+- `/team/list`(成员列表)
|
|
|
|
|
+- `/team/consumption`(团队消费额分级汇总,按 referral_tree level 聚合 `product_orders.totalAmount`)
|
|
|
|
|
+- `/team/tree`、`/team/growth-curve`、`/team/consumption-curve`、`/team/l1-consumption-curve`、`/team/my-referrer`
|
|
|
|
|
+
|
|
|
|
|
+其中 `CommissionService.getTeamConsumption(userId, maxLevel)` 已实现「团队消费额」:用 `referral_tree`(parentId=userId, level≤maxLevel)取下级 `memberId`,再查 `product_orders`(`buyerId IN memberIds AND fulfillStatus='completed'`)汇总 `totalAmount`(单位:分)。
|
|
|
|
|
+
|
|
|
|
|
+本次新增「关联订单」「关联金额(元)」,与消费额同源(同一套团队关系 + 订单数据),只是**聚合维度从 level 改为 商城商品/SKU**,且金额换算为「元」、订单以「关联订单数(去重 orderNo)」表达。无需新建表、无需迁移。
|
|
|
|
|
+
|
|
|
|
|
+## 2. 数据模型(已核实现有代码)
|
|
|
|
|
+
|
|
|
|
|
+| 表 / 实体 | 关键字段 | 用途 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `referral_tree` | `parentId`, `memberId`, `level` | 团队关系,取 userId 的下级 memberIds(与 getTeamConsumption 同口径) |
|
|
|
|
|
+| `product_orders`(`ProductOrder`) | `orderNo`, `productId`, `skuId`, `buyerId`, `totalAmount`(Integer,分), `fulfillStatus` | 订单行;过滤 `buyerId IN memberIds AND fulfillStatus='completed'` |
|
|
|
|
|
+| `products`(`Product`) | `id`, `name` | 关联商品名 |
|
|
|
|
|
+| `order_items`(`OrderItem`) | `orderId`, `productId`, `skuId`, `skuSpecs` | SKU 规格文案(可选,非必需) |
|
|
|
|
|
+
|
|
|
|
|
+金额单位:所有金额字段为「分」,接口返回「元」需 ÷100(用 `BigDecimal` 保留 2 位)。
|
|
|
|
|
+
|
|
|
|
|
+## 3. 接口设计(定稿)
|
|
|
|
|
+
|
|
|
|
|
+### 3.1 新增端点
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+POST /api/commission/team/product-performance
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+请求体(与 `/team/consumption` 同形):
|
|
|
|
|
+
|
|
|
|
|
+```json
|
|
|
|
|
+{ "maxLevel": 3 }
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+`maxLevel` 可选,默认 3,上限 10(与 getTeamConsumption 一致)。
|
|
|
|
|
+
|
|
|
|
|
+### 3.2 响应(Result<Map<String,Object>>)
|
|
|
|
|
+
|
|
|
|
|
+```json
|
|
|
|
|
+{
|
|
|
|
|
+ "totalOrderCount": 12, // 团队关联订单数(下级全部已完成订单去重 orderNo)
|
|
|
|
|
+ "totalAmountYuan": 3580.00, // 团队关联金额(元)
|
|
|
|
|
+ "maxLevel": 3,
|
|
|
|
|
+ "items": [ // 按 商城商品/SKU 维度
|
|
|
|
|
+ {
|
|
|
|
|
+ "productId": 12,
|
|
|
|
|
+ "productName": "肠道菌群测评",
|
|
|
|
|
+ "skuId": 0, // 0/null 表示无 SKU
|
|
|
|
|
+ "orderCount": 5, // 该 SKU 关联订单数(去重 orderNo)
|
|
|
|
|
+ "amountYuan": 1495.00 // 该 SKU 关联金额(元)
|
|
|
|
|
+ }
|
|
|
|
|
+ ]
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+聚合口径:
|
|
|
|
|
+
|
|
|
|
|
+- 团队 membership:复用 `referral_tree`(parentId=userId, level≤maxLevel),收集 memberIds。
|
|
|
|
|
+- 订单过滤:`product_orders.buyerId IN memberIds AND fulfillStatus='completed'`(与 getTeamConsumption 完全一致,本期**不做**退款排除,保持与现有团队消费额口径统一;如顺手可排除 `refundStatus=2`(已退款),非强制)。
|
|
|
|
|
+- 按 `(productId, skuId)` 分组:
|
|
|
|
|
+ - `orderCount` = 该组内 `orderNo` 去重计数(同一订单含多 SKU 时不重复计入该 SKU)。
|
|
|
|
|
+ - `amountYuan` = 该组 `sum(totalAmount)` ÷ 100,`BigDecimal` 保留 2 位(HALF_UP)。
|
|
|
|
|
+ - `productName` = `products.name`(按 productId join;取不到则回退到 order 行的 `productName` 快照或空串)。
|
|
|
|
|
+ - `skuId` = 订单行 `skuId`(null→0);`skuSpecs` 本期可不返回,若实现成本低可从 `order_items` 取代表性行填入,可选。
|
|
|
|
|
+- 团队级 `totalOrderCount` = 全部下级订单 `orderNo` 去重计数(避免按 SKU 求和导致一单多 SKU 重复计数)。
|
|
|
|
|
+- 团队级 `totalAmountYuan` = 全部下级订单 `sum(totalAmount)` ÷ 100。
|
|
|
|
|
+- 空团队(无下级或下级无已完成订单):`items=[]`、`totalOrderCount=0`、`totalAmountYuan=0.00`。
|
|
|
|
|
+
|
|
|
|
|
+## 4. 涉及文件(仅后端)
|
|
|
|
|
+
|
|
|
|
|
+| 层 | 文件 | 改动 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| 服务 | `cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java` | 新增 `getTeamProductPerformance(Long userId, Integer maxLevel)` |
|
|
|
|
|
+| 控制 | `cfc-backend/src/main/java/com/etotem/cfc/controller/CommissionController.java` | 新增 `POST /team/product-performance` |
|
|
|
|
|
+
|
|
|
|
|
+不新增表、不改 `schema.sql`、不改任何前端文件(含 `promotion/team.vue`)。
|
|
|
|
|
+
|
|
|
|
|
+## 5. 实现要点(可直接照抄的模式)
|
|
|
|
|
+
|
|
|
|
|
+- 团队关系查询:照抄 `getTeamConsumption` 的 `referralTreeMapper.selectList(new LambdaQueryWrapper<ReferralTree>().eq(parentId,userId).le(level,maxLevel))`。
|
|
|
|
|
+- 订单查询:照抄 `getTeamConsumption` 的 `productOrderMapper` 查询(`in(buyerId, memberIds).eq(fulfillStatus,"completed")`)。
|
|
|
|
|
+- 分组可用 Java Stream(`Collectors.groupingBy` 按 `productId+skuId`)或一条 MyBatis 聚合 SQL(二选一,推荐 Stream 以便复用现有 Mapper,减少新 Mapper 方法)。
|
|
|
|
|
+- 金额换算:`BigDecimal.valueOf(totalAmount.longValue()).divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_UP)`。
|
|
|
|
|
+
|
|
|
|
|
+## 6. 验收标准
|
|
|
|
|
+
|
|
|
|
|
+- [ ] `mvn clean compile`(cfc-backend)通过。
|
|
|
|
|
+- [ ] `POST /api/commission/team/product-performance` 对「有下级且下级有已完成订单」的用户返回正确的 `totalOrderCount`、`totalAmountYuan` 与 `items`(按商品/SKU 分组、金额元、订单去重)。
|
|
|
|
|
+- [ ] 金额单位正确(分→元,如 `totalAmount=149500` → `1495.00`)。
|
|
|
|
|
+- [ ] 空团队 / 无订单时 `items=[]`、总额为 0,不报错。
|
|
|
|
|
+- [ ] 新增端点已同步写入 `docs/superpowers/api/API_REFERENCE.md` 的 commission/team 段(4.x),路径不与现有 `/team/*` 重复。
|
|
|
|
|
+- [ ] 未改动任何前端文件、未新增数据库迁移。
|
|
|
|
|
+
|
|
|
|
|
+## 7. 技术约束(AGENTS.md 铁律)
|
|
|
|
|
+
|
|
|
|
|
+- 后端接口统一 `@PostMapping`,禁止 `@GetMapping/@PutMapping/@DeleteMapping`;`@Resource` 注入;控制器内用 `@RequestAttribute("userId")` 取当前用户。
|
|
|
|
|
+- 统一 `Result<T>` 包装;新增接口前查阅 `docs/superpowers/api/API_REFERENCE.md` 避免重复。
|
|
|
|
|
+- MyBatis-Plus `@TableName` + 驼峰映射;本期无迁移(纯聚合查询)。
|
|
|
|
|
+- 不触碰业务无关的其它文件;改动范围严格限定 §4 两张文件。
|