|
|
@@ -262,7 +262,7 @@ foodie-admin-vue/
|
|
|
Set-Location E:\QtwCode\foodie\foodie_server
|
|
|
$env:JAVA_HOME='C:\Users\qmj\.jdks\graalvm-jdk-21.0.7'
|
|
|
$env:PATH="$env:JAVA_HOME\bin;$env:PATH"
|
|
|
-mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryPricingCalculatorTest,FlashDeliveryApplicationServiceTest,FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryAvailableOrderViewTest,FlashDeliveryI18nContractTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
+mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryPricingCalculatorTest,FlashDeliveryApplicationServiceTest,FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest,FlashDeliveryI18nContractTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
mvn -pl ruoyi-admin -am -DskipTests package
|
|
|
git diff --check
|
|
|
|
|
|
@@ -272,3 +272,250 @@ npx eslint --no-ignore src/api/flashDelivery/index.js src/api/flashDelivery/cont
|
|
|
npm run build:prod
|
|
|
git diff --check
|
|
|
```
|
|
|
+
|
|
|
+# 闪送 App 订单列表与详情精简 Implementation Plan
|
|
|
+
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
+
|
|
|
+**Goal:** 将用户端和骑手端闪送订单接口收敛为与页面一致的轻量列表与直接详情响应,并让骑手列表复用外卖订单的分页、页签和位置参数。
|
|
|
+
|
|
|
+**Architecture:** Controller 只暴露新的显式查询参数;`FlashDeliveryApplicationService` 在数据库分页前完成用户归属、骑手页签、预约可抢和附近距离条件。列表分别使用用户/骑手卡片 DTO,App 详情使用继承订单业务字段的直接 DTO;平台审计详情继续独立保留实体、图片和日志。
|
|
|
+
|
|
|
+**Tech Stack:** JDK 21、Spring Boot、MyBatis-Plus、MySQL、JUnit 5、Mockito、Lombok。
|
|
|
+
|
|
|
+## Global Constraints
|
|
|
+
|
|
|
+- 不新建分支或 worktree,在当前 `test` 分支连续实施。
|
|
|
+- 不保留开发测试阶段的 `/orders/available`、`/orders/mine`、`scene`、`status`、`serviceType` 兼容入口。
|
|
|
+- 用户和骑手身份只从 `@RequestHeader String token` 解析;查询参数全部显式使用 `@RequestParam`。
|
|
|
+- App 列表和详情禁止返回实体、幂等号、内部用户 ID、计价审计字段或原始状态日志。
|
|
|
+- 骑手接单前显示完整取送文字地址,但不返回联系人、电话、实际 PIN、精确坐标或履约图片。
|
|
|
+- 后端业务错误同步 `messages.properties`、`messages_zh_CN.properties`、`messages_zh_TW.properties`、`messages_en_US.properties` 和 `messages_vi.properties`。
|
|
|
+- 不执行数据库迁移;本次接口精简不需要表结构变更。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 1: 固定 Controller 与 DTO 契约
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryControllerContractTest.java`
|
|
|
+- Delete: `ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryAvailableOrderViewTest.java`
|
|
|
+- Create: `ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListViewTest.java`
|
|
|
+- Modify: `ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryOrderViewTest.java`
|
|
|
+- Create: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryUserOrderListView.java`
|
|
|
+- Create: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListView.java`
|
|
|
+- Create: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderPageView.java`
|
|
|
+- Modify: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryOrderDetailView.java`
|
|
|
+- Delete: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryAvailableOrderView.java`
|
|
|
+- Delete: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryImageView.java`
|
|
|
+- Delete: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryLogView.java`
|
|
|
+
|
|
|
+**Interfaces:**
|
|
|
+- Produces: `FlashDeliveryUserOrderListView` for user cards.
|
|
|
+- Produces: `FlashDeliveryRiderOrderListView` for all rider tabs.
|
|
|
+- Produces: `FlashDeliveryRiderOrderPageView(records,total,current,size,nearbyTaskCount,highestOrderAmount)`.
|
|
|
+- Produces: direct `FlashDeliveryOrderDetailView extends FlashDeliveryOrderView` with `senderImageUrls,pickupImageUrls,deliveryImageUrls,rider,deliveryPinCode`.
|
|
|
+
|
|
|
+- [ ] **Step 1: Write failing reflection and whitelist tests**
|
|
|
+
|
|
|
+```java
|
|
|
+Method userOrders = FlashDeliveryUserController.class.getMethod(
|
|
|
+ "orders", String.class, int.class, int.class);
|
|
|
+Method riderOrders = FlashDeliveryRiderController.class.getMethod(
|
|
|
+ "orders", String.class, int.class, int.class, String.class,
|
|
|
+ BigDecimal.class, BigDecimal.class);
|
|
|
+assertThrows(NoSuchFieldException.class,
|
|
|
+ () -> FlashDeliveryOrderDetailView.class.getDeclaredField("order"));
|
|
|
+assertTrue(riderFields.containsAll(Set.of("pickupAddress", "deliveryAddress",
|
|
|
+ "pickupDistanceMeters", "pinRequired")));
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: Run tests and verify the old contract fails**
|
|
|
+
|
|
|
+```powershell
|
|
|
+$env:JAVA_HOME='C:\Users\qmj\.jdks\graalvm-jdk-21.0.7'
|
|
|
+$env:PATH="$env:JAVA_HOME\bin;$env:PATH"
|
|
|
+mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
+```
|
|
|
+
|
|
|
+Expected: compilation or reflection failure because the old controllers and wrapper DTO still exist.
|
|
|
+
|
|
|
+- [ ] **Step 3: Add the minimal DTO types**
|
|
|
+
|
|
|
+```java
|
|
|
+@Data
|
|
|
+public class FlashDeliveryOrderDetailView extends FlashDeliveryOrderView {
|
|
|
+ private List<String> senderImageUrls = List.of();
|
|
|
+ private List<String> pickupImageUrls = List.of();
|
|
|
+ private List<String> deliveryImageUrls = List.of();
|
|
|
+ private FlashDeliveryRiderSummaryView rider;
|
|
|
+ private String deliveryPinCode;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+`FlashDeliveryUserOrderListView` 固定卡片字段为订单标识、服务/包裹、状态、配送方式/预约时段、取送文字地址、预计时长、金额、送达时间和创建时间。`FlashDeliveryRiderOrderListView` 固定增加重量档、`pinRequired`、`pickupDistanceMeters` 和路线距离。分页 DTO 只使用上述六个分页/摘要属性。
|
|
|
+
|
|
|
+- [ ] **Step 4: Run DTO tests**
|
|
|
+
|
|
|
+```powershell
|
|
|
+mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
+```
|
|
|
+
|
|
|
+Expected: DTO whitelist tests pass; controller reflection test remains red until Task 2.
|
|
|
+
|
|
|
+### Task 2: 实现轻量列表、统一骑手页签和直接详情
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryUserController.java`
|
|
|
+- Modify: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryRiderController.java`
|
|
|
+- Modify: `ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java`
|
|
|
+- Modify: `ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationServiceTest.java`
|
|
|
+- Modify: `ruoyi-admin/src/main/resources/i18n/messages.properties`
|
|
|
+- Modify: `ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties`
|
|
|
+- Modify: `ruoyi-admin/src/main/resources/i18n/messages_zh_TW.properties`
|
|
|
+- Modify: `ruoyi-admin/src/main/resources/i18n/messages_en_US.properties`
|
|
|
+- Modify: `ruoyi-admin/src/main/resources/i18n/messages_vi.properties`
|
|
|
+
|
|
|
+**Interfaces:**
|
|
|
+- Consumes: Task 1 DTOs.
|
|
|
+- Produces: `userOrders(Long userId,int page,int size)`.
|
|
|
+- Produces: `riderOrders(Long riderId,int page,int size,String tab,BigDecimal longitude,BigDecimal latitude)`.
|
|
|
+- Produces: `riderDetail(Long riderId,Long orderId)` returning `FlashDeliveryOrderDetailView`, never `Object`.
|
|
|
+
|
|
|
+- [ ] **Step 1: Write failing service tests**
|
|
|
+
|
|
|
+```java
|
|
|
+var userPage = fixture.service.userOrders(7L, 1, 10);
|
|
|
+var newTasks = fixture.service.riderOrders(8L, 1, 10, "newTask",
|
|
|
+ new BigDecimal("121.5"), new BigDecimal("25.0"));
|
|
|
+assertEquals("台北市中山區南京東路二段 100 號",
|
|
|
+ newTasks.getRecords().get(0).getPickupAddress());
|
|
|
+assertNull(fixture.service.riderDetail(8L, 10L).getPickup().getPhone());
|
|
|
+verify(fixture.logMapper, never()).selectList(any());
|
|
|
+```
|
|
|
+
|
|
|
+Tests must also capture SQL segments for all five tab mappings, reject `refund`/unknown tabs, reject half/malformed coordinates, keep scheduled orders hidden before their start, restrict non-new tabs to `rider_id`, and verify direct photo arrays grouped by `SENDER/PICKUP/DELIVERY`.
|
|
|
+
|
|
|
+- [ ] **Step 2: Run service and controller tests and verify failure**
|
|
|
+
|
|
|
+```powershell
|
|
|
+mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryApplicationServiceTest,FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
+```
|
|
|
+
|
|
|
+Expected: failure on old method signatures, routes, scene filtering and wrapped detail response.
|
|
|
+
|
|
|
+- [ ] **Step 3: Implement controllers and query mapping**
|
|
|
+
|
|
|
+```java
|
|
|
+@GetMapping("/orders")
|
|
|
+public AjaxResult orders(@RequestHeader String token,
|
|
|
+ @RequestParam(defaultValue = "1") int page,
|
|
|
+ @RequestParam(defaultValue = "10") int size,
|
|
|
+ @RequestParam(defaultValue = "newTask") String tab,
|
|
|
+ @RequestParam(required = false) BigDecimal longitude,
|
|
|
+ @RequestParam(required = false) BigDecimal latitude) {
|
|
|
+ return success(service.riderOrders(userId(token), page, size, tab, longitude, latitude));
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+User Controller uses only `page,size`. Service maps `newTask/toPickup/delivering/completed/cancelled` before `selectPage`; `newTask` applies `WAITING_ACCEPTANCE`、`rider_id IS NULL`、预约开始时间条件 and, when coordinates exist, the same `sys_qs_newtask_distance` radius and distance sorting used by `PosOrderQsOprateController.orderList`.
|
|
|
+
|
|
|
+- [ ] **Step 4: Implement list mapping and direct detail**
|
|
|
+
|
|
|
+```java
|
|
|
+private FlashDeliveryOrderDetailView participantDetail(FlashDeliveryOrder order,
|
|
|
+ boolean userView, boolean protectedRiderView) {
|
|
|
+ FlashDeliveryOrderDetailView view = detailOrderView(order, !protectedRiderView);
|
|
|
+ if (!protectedRiderView) groupImageUrls(view, selectImages(order.getId()));
|
|
|
+ if (userView) {
|
|
|
+ view.setDeliveryPinCode(Boolean.TRUE.equals(order.getPinRequired())
|
|
|
+ ? order.getDeliveryPinCode() : null);
|
|
|
+ view.setRider(riderSummary(order));
|
|
|
+ }
|
|
|
+ return view;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+Do not query `FlashDeliveryOrderLogMapper` while building App details. Pre-accept address views copy `city,area,handoffMethod,address,addressDetail` only; assigned rider/user detail additionally copies contact and exact coordinates. `newTask` page summary uses filtered page total as `nearbyTaskCount` and a same-condition maximum amount query as `highestOrderAmount`.
|
|
|
+
|
|
|
+- [ ] **Step 5: Add localized parameter errors and run targeted tests**
|
|
|
+
|
|
|
+Add `flash.delivery.tab.invalid` and `flash.delivery.coordinates.invalid` to all five message bundles, then run:
|
|
|
+
|
|
|
+```powershell
|
|
|
+mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryApplicationServiceTest,FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
+```
|
|
|
+
|
|
|
+Expected: PASS.
|
|
|
+
|
|
|
+### Task 3: 更新契约文档并统一验证
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `docs/flash-delivery-app-api.md`
|
|
|
+- Modify: `specs/024-flash-delivery/quickstart.md`
|
|
|
+- Modify: `specs/024-flash-delivery/tasks.md`
|
|
|
+
|
|
|
+**Interfaces:**
|
|
|
+- Consumes: the implemented Controller routes and DTO field names from Tasks 1–2.
|
|
|
+- Produces: App integration examples that exactly match production code.
|
|
|
+
|
|
|
+- [ ] **Step 1: Replace obsolete request and response examples**
|
|
|
+
|
|
|
+Document only:
|
|
|
+
|
|
|
+```text
|
|
|
+GET /system/flashDelivery/orders?page=1&size=10
|
|
|
+GET /system/flashDelivery/rider/orders?page=1&size=10&tab=newTask&longitude=121.5&latitude=25.0
|
|
|
+```
|
|
|
+
|
|
|
+Remove `/available`、`/mine`、`scene`、`serviceType` list filters, approximate coordinates, `{order,images,logs}` App wrappers and App raw log examples. Keep platform audit response unchanged.
|
|
|
+
|
|
|
+- [ ] **Step 2: Run all affected tests and package**
|
|
|
+
|
|
|
+```powershell
|
|
|
+$env:JAVA_HOME='C:\Users\qmj\.jdks\graalvm-jdk-21.0.7'
|
|
|
+$env:PATH="$env:JAVA_HOME\bin;$env:PATH"
|
|
|
+mvn -pl ruoyi-admin -am -Dtest='FlashDeliveryApplicationServiceTest,FlashDeliveryControllerContractTest,FlashDeliveryOrderViewTest,FlashDeliveryRiderOrderListViewTest,FlashDeliveryI18nContractTest' -Dsurefire.failIfNoSpecifiedTests=false test
|
|
|
+mvn -pl ruoyi-admin -am -DskipTests package
|
|
|
+git diff --check
|
|
|
+```
|
|
|
+
|
|
|
+Expected: all targeted tests pass, package succeeds and diff check is clean.
|
|
|
+
|
|
|
+- [ ] **Step 3: Audit scope and commit**
|
|
|
+
|
|
|
+```powershell
|
|
|
+git diff --name-only
|
|
|
+$flashFiles = @(
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryUserController.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryRiderController.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationService.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryUserOrderListView.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListView.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderPageView.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryOrderDetailView.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryAvailableOrderView.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryImageView.java',
|
|
|
+ 'ruoyi-admin/src/main/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryLogView.java',
|
|
|
+ 'ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/controller/FlashDeliveryControllerContractTest.java',
|
|
|
+ 'ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryAvailableOrderViewTest.java',
|
|
|
+ 'ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryRiderOrderListViewTest.java',
|
|
|
+ 'ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/dto/FlashDeliveryOrderViewTest.java',
|
|
|
+ 'ruoyi-admin/src/test/java/com/ruoyi/app/flashdelivery/service/FlashDeliveryApplicationServiceTest.java',
|
|
|
+ 'ruoyi-admin/src/main/resources/i18n/messages.properties',
|
|
|
+ 'ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties',
|
|
|
+ 'ruoyi-admin/src/main/resources/i18n/messages_zh_TW.properties',
|
|
|
+ 'ruoyi-admin/src/main/resources/i18n/messages_en_US.properties',
|
|
|
+ 'ruoyi-admin/src/main/resources/i18n/messages_vi.properties',
|
|
|
+ 'docs/flash-delivery-app-api.md',
|
|
|
+ 'specs/024-flash-delivery/quickstart.md',
|
|
|
+ 'specs/024-flash-delivery/tasks.md'
|
|
|
+)
|
|
|
+git add -- $flashFiles
|
|
|
+git diff --cached --check
|
|
|
+git diff --cached --name-only
|
|
|
+git commit -m "精简闪送 App 订单接口"
|
|
|
+git push origin test
|
|
|
+```
|
|
|
+
|
|
|
+The staged list must not contain `.claude/homunculus/observations.jsonl`、`.tmp/` or `docs/merchant-subaccount-api.md`.
|