Files
jsowell-charger-web/docs/coupon-impl-progress.md
2026-03-05 08:58:24 +08:00

136 lines
5.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 优惠券功能实现进度
**需求文档**: [PRD-积分兑换洗车券功能.md](./PRD-积分兑换洗车券功能.md)
**开始日期**: 2026-03-04
**当前版本**: v1.0(首期洗车券)
---
## 进度总览
| # | 子任务 | 状态 | 文件 |
|---|--------|------|------|
| 1 | Domain 实体类 | ✅ 完成 | `jsowell-pile/.../domain/` |
| 2 | Mapper 接口和 XML | ✅ 完成 | `jsowell-pile/.../mapper/` + `resources/mapper/pile/` |
| 3 | Service 层 | ✅ 完成 | `jsowell-pile/.../service/` |
| 4 | 管理后台 Controller | ✅ 完成 | `jsowell-admin/.../web/controller/pile/` |
| 5 | 用户端 API Controller | ✅ 完成 | `jsowell-admin/.../api/uniapp/customer/` |
| 6 | Quartz 过期归档任务 | ✅ 完成 | `jsowell-quartz/.../task/JsowellTask.java`(方法 `expireCoupons` |
> 状态图例:⬜ 待开始 / 🔄 进行中 / ✅ 完成
---
## Task 1Domain 实体类
**状态**: ✅ 完成
### 文件清单
| 文件 | 路径 |
|------|------|
| `CouponTemplate.java` | `jsowell-pile/src/main/java/com/jsowell/pile/domain/` |
| `CouponTemplateScope.java` | `jsowell-pile/src/main/java/com/jsowell/pile/domain/` |
| `MemberCoupon.java` | `jsowell-pile/src/main/java/com/jsowell/pile/domain/` |
| `CouponVerifyRecord.java` | `jsowell-pile/src/main/java/com/jsowell/pile/domain/` |
---
## Task 2Mapper 接口和 XML
**状态**: ✅ 完成
### 文件清单
| 文件 | 路径 |
|------|------|
| `CouponTemplateMapper.java` | `jsowell-pile/src/main/java/com/jsowell/pile/mapper/` |
| `CouponTemplateScopeMapper.java` | `jsowell-pile/src/main/java/com/jsowell/pile/mapper/` |
| `MemberCouponMapper.java` | `jsowell-pile/src/main/java/com/jsowell/pile/mapper/` |
| `CouponVerifyRecordMapper.java` | `jsowell-pile/src/main/java/com/jsowell/pile/mapper/` |
| `CouponTemplateMapper.xml` | `jsowell-pile/src/main/resources/mapper/pile/` |
| `CouponTemplateScopeMapper.xml` | `jsowell-pile/src/main/resources/mapper/pile/` |
| `MemberCouponMapper.xml` | `jsowell-pile/src/main/resources/mapper/pile/` |
| `CouponVerifyRecordMapper.xml` | `jsowell-pile/src/main/resources/mapper/pile/` |
---
## Task 3Service 层
**状态**: ✅ 完成
### 文件清单
| 文件 | 路径 |
|------|------|
| `CouponTemplateService.java` | `jsowell-pile/src/main/java/com/jsowell/pile/service/` |
| `CouponTemplateServiceImpl.java` | `jsowell-pile/src/main/java/com/jsowell/pile/service/impl/` |
| `MemberCouponService.java` | `jsowell-pile/src/main/java/com/jsowell/pile/service/` |
| `MemberCouponServiceImpl.java` | `jsowell-pile/src/main/java/com/jsowell/pile/service/impl/` |
### 核心方法
**CouponTemplateService**
- `listForAdmin(CouponTemplate query, String merchantId)` - 后台列表(带权限过滤)
- `add(CouponTemplate template, String loginMerchantId, boolean isPlatformAdmin)` - 新增(含 scope 校验)
- `edit(CouponTemplate template, String loginMerchantId, boolean isPlatformAdmin)` - 编辑(含冻结字段校验)
- `changeStatus(Long id, Integer status, String loginMerchantId)` - 上下架
**MemberCouponService**
- `listAvailableTemplates(String memberId, Long stationId, int pageNum, int pageSize)` - 用户可兑换列表
- `exchange(String memberId, Long templateId, String requestId)` - 兑换(原子:扣积分+生成券)
- `myList(String memberId, Integer status, int pageNum, int pageSize)` - 我的券包
- `detail(String memberId, String couponNo)` - 券详情
- `verify(String couponNo, Long storeId, String requestId, String operatorId)` - 核销
---
## Task 4管理后台 Controller
**状态**: ✅ 完成
### 文件清单
| 文件 | 路径 |
|------|------|
| `CouponTemplateController.java` | `jsowell-admin/src/main/java/com/jsowell/web/controller/pile/` |
| `CouponRecordController.java` | `jsowell-admin/src/main/java/com/jsowell/web/controller/pile/` |
---
## Task 5用户端 API Controller
**状态**: ✅ 完成
### 文件清单
| 文件 | 路径 |
|------|------|
| `CouponController.java` | `jsowell-admin/src/main/java/com/jsowell/api/uniapp/customer/` |
---
## Task 6Quartz 过期归档任务
**状态**: ✅ 完成
方法 `expireCoupons()` 已合并到 `JsowellTask.java`,调用目标:`jsowellTask.expireCoupons()`Cron`0 5 0 * * ?`
---
## 前端页面
| # | 子任务 | 状态 | 文件 |
|---|--------|------|------|
| F1 | API 文件 | ✅ 完成 | `jsowell-charge-ui/src/api/coupon/template.js` / `record.js` |
| F2 | 券模板管理页 | ✅ 完成 | `jsowell-charge-ui/src/views/coupon/template/index.vue` |
| F3 | 兑换记录页 | ✅ 完成 | `jsowell-charge-ui/src/views/coupon/record/index.vue` |
| F4 | 路由注册 | ✅ 完成 | `jsowell-charge-ui/src/router/index.js` |
1. **兑换幂等**`member_coupon.exchange_request_id` 唯一索引,捕获 `DuplicateKeyException` 返回已有结果
2. **库存扣减**`UPDATE ... SET stock_remain=stock_remain-1 WHERE id=? AND (stock_remain>0 OR stock_remain=-1)`
3. **积分扣减**:复用现有 `MemberPointsInfoService.deductPoints()``type=3`(兑换消耗)
4. **scope 校验**:查询用户可见券时 JOIN `coupon_template_scope`,通过 `idx_scope_lookup` 索引反查
5. **过期判断**:查询侧用 `expire_time > NOW()` 动态判断Quartz 仅做离线归档
6. **二维码安全**:券详情接口返回短时签名 tokenHMAC-SHA2565分钟有效核销接口接受 token 或 couponNo 两种方式