买家端模块实现 - xych5q/online-shop GitHub Wiki

买家端模块实现(含交易流转与单元测试)

第 1 组 · 在线购物系统 | 完成人:林初俊 | 完成日期:2026-10-07 对应提交:cac53ac | 代码位置:server/src/main/java/.../ 与 server/src/test/java/.../

一、交付内容

文件 行数 职责
service/IntentService.java 216 提交意向、口令码查询、修改信息、撤销意向、当前商品查询
service/TradeService.java 184 交易流转核心:进入交易、标记结果、处置失败意向、交易中撤销
controller/BuyerController.java 92 5 个买家端 REST 接口
test/.../BuyerApiTest.java 252 JUnit 5 + MockMvc,18 组用例中的第 1~11 组
test/.../TradeFlowTest.java 240 JUnit 5,第 12~18 组(直调 TradeService + MockMvc 验证对外行为)

业务代码 492 行 + 测试 492 行。

二、5 个买家端接口

# 接口 关键规则
1 GET /api/product 买家浏览当前在售商品
2 POST /api/intents 生成 8 位口令码(字符集剔除易混淆的 I/O/0/1),查库保证全库唯一,仅在提交响应中返回一次
3 GET /api/intents/lookup/{code} 返回位次与状态;进入交易时 position=null、inTransaction=true;无效或已终态码返回 404
4 PUT /api/intents/lookup/{code} 只更新姓名电话,submittedAt 不动 → 排队位次不变
5 POST /api/intents/lookup/{code}/cancel 交易中拒绝撤销;其余置 cancelled(终态留痕)

三、交易流转规则

规则逐条依据 需求规格说明书 第 4.1~4.3 节的状态机与排队规则实现,未作改动:

  1. 进入交易:取队列首位(submittedAt 正序、id 兜底,卖家不可挑人)置 in_transaction;商品自动置冻结、frozenBy='auto';队列为空则拒绝。
  2. 标记成功:当前意向置成功且已处置;队列剩余全部转失败并已处置;商品下架进历史,全部口令码失效。
  3. 标记失败:当前意向转失败待处置;队列有人 → 下一位自动递补进入交易(商品保持冻结);队列无人 → 商品恢复在售。
  4. 处置失败意向:void 只作废;requeue 新建排队记录、沿用原口令码、submittedAt 刷新(排到队尾)、requeuedFrom 指向原意向。

技术说明(TD-1):Intent.code 有数据库唯一约束,重排沿用原码时两行不能同码。处理为:已终态原记录改码为 原码#r{id} 占位(终态意向对外不返回口令码)、新记录沿用原码。本模块进一步修复了原临时实现中 Hibernate「INSERT 先于 UPDATE」会撞唯一约束的缺陷,改为 saveAndFlush 先落库。

四、单元测试(JUnit 5)

组长本地复跑实测结果:

[INFO] Tests run: 11, Failures: 0, Errors: 0, Skipped: 0 -- in BuyerApiTest
[INFO] Tests run: 7,  Failures: 0, Errors: 0, Skipped: 0 -- in TradeFlowTest
[INFO] Tests run: 18, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESS
# 用例 # 用例
1 错误密码登录返回 401 9 修改电话后位次不变
2 不带 X-Token 访问后台返回 401 10 撤销意向后该口令码查询返回 404
3 发布价格为 -1 的商品返回 400 11 商品冻结后提交意向返回 400
4 发布成功且价格保留两位小数 12 交易中手动解冻返回 400
5 已有在售商品时再次发布返回 400 13 标记失败后下一位自动递补进入交易
6 三个买家依次入队,位次 1、2、3 14 失败买家重排后原口令码仍有效且排到队尾
7 姓名或电话为空提交意向返回 400 15 标记成功后队列剩余意向全部转为失败
8 无效口令码查询返回 404 16 历史详情的意向流水中不包含 code 字段

测试设计:@SpringBootTest + @AutoConfigureMockMvc 走真实 Spring MVC 链路(含统一异常处理),每个用例前清空数据保证相互独立,断言 HTTP 状态码与错误文案。

五、集成处理(技术债清理)

技术债 处理
TD-2 ProductService 注入 TradeService,删除三个带 TODO 的临时方法(enterDealTemp / markResultTemp / disposeFailedTemp),改为正式调用
TD-3 从 SellerController 删除临时 GET /api/product,仅保留在 BuyerController,避免 Spring Boot 重复映射导致启动失败

六、相关文档