Просмотр исходного кода

029范围调整:自配送仅夜市主可设置,PC端功能隐藏

saveMdSelfDeliveryHours 对普通商家门店一律拒绝(no.store.selfdelivery.nightmarket.only,
六语言);PC 从未开发自配送界面,T034-T038 标注挂起;spec 增变更记录并标注 FR-002,
tasks 增 T041;测试断言翻转(normalStoreCannotSaveSelfDeliveryConfig)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
qmj 18 часов назад
Родитель
Сommit
eaecc1d70c

Разница между файлами не показана из-за своего большого размера
+ 18 - 0
.claude/homunculus/observations.jsonl


+ 4 - 2
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java

@@ -503,7 +503,8 @@ public class PosStoreController extends BaseController {
     }
 
     /**
-     * (商家端)保存门店自配送配置(029):摊位无配置权;夜市主门店行仅夜市主本人可保存;普通门店走门店权限
+     * (商家端)保存门店自配送配置(029):摊位无配置权;夜市主门店行仅夜市主本人可保存;
+     * 2026-09-10 范围调整:普通商家门店不可设置自配送(PC 端功能同步隐藏)
      */
     @Anonymous
     @Auth(session = true)
@@ -528,7 +529,8 @@ public class PosStoreController extends BaseController {
                 throw new ServiceException(MessageUtils.message("merchant.store.access.denied"));
             }
         } else {
-            requireStoreAccess(userId, infoUserService.selectInfoUserByUserId(userId), Long.valueOf(input.getMdId()));
+            // 2026-09-10 范围调整:自配送仅夜市主可配置,普通商家门店一律拒绝
+            throw new ServiceException(MessageUtils.message("no.store.selfdelivery.nightmarket.only"));
         }
         selfDeliveryService.saveConfig(input);
         return success();

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages.properties

@@ -340,6 +340,7 @@ address.access.denied=Address does not exist or is not accessible
 address.data.invalid=Contact, address, or coordinates are invalid
 flash.delivery.rider.type.not.enabled=当前账号未开通闪送配送
 no.store.stall.selfdelivery.readonly=Phương thức giao hàng của quầy do chủ chợ đêm thiết lập thống nhất
+no.store.selfdelivery.nightmarket.only=Chỉ chủ chợ đêm mới được cấu hình tự giao hàng
 no.store.selfdelivery.hours.invalid=Cấu hình khung giờ tự giao không hợp lệ
 no.order.selfdelivery.required=Đơn hàng này không phải là đơn hàng do cửa hàng tự giao
 no.order.selfdelivery.rider.denied=Đơn hàng này do cửa hàng tự giao, không cần tài xế

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages_en_US.properties

@@ -343,6 +343,7 @@ address.access.denied=Address does not exist or is not accessible
 address.data.invalid=Contact, address, or coordinates are invalid
 flash.delivery.rider.type.not.enabled=This account is not enabled for flash delivery orders
 no.store.stall.selfdelivery.readonly=Stall delivery mode is set by the night market owner
+no.store.selfdelivery.nightmarket.only=Self-delivery can only be configured by the night market owner
 no.store.selfdelivery.hours.invalid=Invalid self-delivery time slot configuration
 no.order.selfdelivery.required=This order is not a merchant self-delivery order
 no.order.selfdelivery.rider.denied=This order is delivered by the merchant; no rider is needed

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages_th_TH.properties

@@ -340,3 +340,4 @@ flash.delivery.edit.not.allowed=แก้ไขได้เฉพาะคำส
 flash.delivery.order.version.invalid=กรุณาระบุเวอร์ชันคำสั่งซื้อที่ถูกต้อง
 flash.delivery.tip.additional.invalid=ทิปเพิ่มเติมต้องเป็นจำนวนเต็มบวกและไม่เกินวงเงินที่รองรับ
 flash.delivery.pay.type.invalid=รองรับเฉพาะการชำระเงินสดหรือโอนแบบออฟไลน์
+no.store.selfdelivery.nightmarket.only=ตั้งค่าการส่งด้วยตนเองได้เฉพาะเจ้าของตลาดกลางคืนเท่านั้น

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages_vi.properties

@@ -343,6 +343,7 @@ address.access.denied=Địa chỉ không tồn tại hoặc không có quyền
 address.data.invalid=Thông tin liên hệ, địa chỉ hoặc tọa độ không hợp lệ
 flash.delivery.rider.type.not.enabled=Tài khoản này chưa mở giao hàng nhanh
 no.store.stall.selfdelivery.readonly=Phương thức giao hàng của quầy do chủ chợ đêm thiết lập thống nhất
+no.store.selfdelivery.nightmarket.only=Chỉ chủ chợ đêm mới được cấu hình tự giao hàng
 no.store.selfdelivery.hours.invalid=Cấu hình khung giờ tự giao không hợp lệ
 no.order.selfdelivery.required=Đơn hàng này không phải là đơn hàng do cửa hàng tự giao
 no.order.selfdelivery.rider.denied=Đơn hàng này do cửa hàng tự giao, không cần tài xế

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties

@@ -344,6 +344,7 @@ address.access.denied=地址不存在或无权访问
 address.data.invalid=联系人、地址或经纬度信息无效
 flash.delivery.rider.type.not.enabled=当前账号未开通闪送配送
 no.store.stall.selfdelivery.readonly=摊位配送方式由夜市主统一设置
+no.store.selfdelivery.nightmarket.only=自配送仅夜市主可设置
 no.store.selfdelivery.hours.invalid=自配送时段配置无效
 no.order.selfdelivery.required=该订单不是商家自配送订单
 no.order.selfdelivery.rider.denied=该订单为商家自配送订单,无需骑手配送

+ 1 - 0
ruoyi-admin/src/main/resources/i18n/messages_zh_TW.properties

@@ -344,6 +344,7 @@ address.access.denied=地址不存在或無權存取
 address.data.invalid=聯絡人、地址或經緯度資訊無效
 flash.delivery.rider.type.not.enabled=當前賬號未開通闁送配送
 no.store.stall.selfdelivery.readonly=攤位配送方式由夜市主統一設定
+no.store.selfdelivery.nightmarket.only=自配送僅夜市主可設定
 no.store.selfdelivery.hours.invalid=自配送時段配置無效
 no.order.selfdelivery.required=該訂單不是商家自配送訂單
 no.order.selfdelivery.rider.denied=該訂單為商家自配送訂單,無需騎手配送

+ 5 - 4
ruoyi-admin/src/test/java/com/ruoyi/app/mendian/PosStoreControllerSelfDeliveryTest.java

@@ -105,12 +105,13 @@ class PosStoreControllerSelfDeliveryTest {
     }
 
     @Test
-    void normalStoreSaveGoesThroughStoreAccess() {
+    void normalStoreCannotSaveSelfDeliveryConfig() {
+        // 2026-09-10 范围调整:仅夜市主可配置,普通商家门店保存一律拒绝
         when(stores.getById(9)).thenReturn(store(9, 0, 0, 101L));
         login(101L, "1");
-        controller.saveMdSelfDeliveryHours("t", config(9));
-        verify(access).requireStoreAccess(101L, 9L);
-        verify(selfDelivery).saveConfig(any());
+        assertThrows(ServiceException.class,
+                () -> controller.saveMdSelfDeliveryHours("t", config(9)));
+        verify(selfDelivery, never()).saveConfig(any());
     }
 
     @Test

+ 9 - 1
specs/029-merchant-self-delivery/spec.md

@@ -8,6 +8,14 @@
 
 **Input**: User description: "商家自配送:商家在门店信息勾选自配送并设置时段(全天/自定义多时段),命中时段的外送订单不进骑手抢单池、由商家自行配送;夜市由夜市主统一配置并对旗下摊位生效、夜市主操作送达;运费归配送方结算;前端显示'商家自配送'。合并订单/同一骑手多单机制不在本次范围(另立需求)。"
 
+## 变更记录
+
+### 2026-09-10 范围调整(用户确认)
+
+- **普通商家门店不可设置自配送**,仅夜市主可设置夜市是否自配送:`saveMdSelfDeliveryHours` 对非夜市主门店行一律拒绝(提示 `no.store.selfdelivery.nightmarket.only`,六语言)。原 US1/FR-002 中"普通商家配置自己门店"的口径按此收紧;普通商家门店的自配送开关恒为关,订单判定自然走骑手池,判定/快照/结算链路不变。
+- **PC 端(foodie-store)功能先隐藏**:T034-T038 挂起不做(PC 从未开发自配送界面,无需代码改动);商家 App(外部)同步只对夜市主展示设置入口,普通商家不展示。
+- 已知缺口备查:`messages_th_TH.properties` 缺 029 的 `no.store.*`/`no.order.*` 系列 key(本变更的新 key 已补,其余历史 key 待统一补译)。
+
 ## Clarifications
 
 ### Session 2026-09-08
@@ -133,7 +141,7 @@
 ### Functional Requirements
 
 - **FR-001**: 门店信息 MUST 提供自配送开关与时段设置:全天模式或自定义模式;自定义模式 MUST 按星期几配置,每天可设置一个或多个时间段,每个时间段含开始与结束时刻(与营业时段的配置模式一致)
-- **FR-002**: 配置权限 MUST 按商家类型区分:普通商家配置自己门店的自配送;夜市摊位门店 MUST NOT 提供独立配置入口,其配送方式由所属夜市的夜市主统一配置并对该夜市全部摊位生效
+- **FR-002**: 配置权限 MUST 按商家类型区分:~~普通商家配置自己门店的自配送~~【2026-09-10 变更:普通商家门店不可设置,接口一律拒绝,仅夜市主本人可配置】;夜市摊位门店 MUST NOT 提供独立配置入口,其配送方式由所属夜市的夜市主统一配置并对该夜市全部摊位生效
 - **FR-003**: 系统 MUST 在外送订单创建并支付成功时判定配送方式并固化到订单:即时单按下单时刻判定,预约单按预约送达时间判定;时段判定含开始时刻、不含结束时刻([开始, 结束));命中自配送时段则订单永久标记为"商家自配送",判定结果 MUST NOT 受后续配置变更影响
 - **FR-004**: 自配送订单 MUST NOT 进入骑手抢单池,MUST NOT 出现在骑手端任何订单列表,骑手 MUST NOT 能通过任何操作接口接单或操作该订单
 - **FR-005**: 商家端 MUST 为自配送订单提供配送操作:出餐后可标记"开始配送"与"确认送达";"开始配送"为可选步骤,MUST 允许出餐后直接"确认送达"(状态机允许跳过"配送中");"确认送达"后订单进入完成状态并记录送达时间;操作后配送状态向用户可见

+ 3 - 1
specs/029-merchant-self-delivery/tasks.md

@@ -118,7 +118,7 @@ description: "Task list for 029-merchant-self-delivery"
 **Independent Test**: quickstart 场景 7。
 
 - [x] T033 [P] [US6] 定位前端结构:阅读 foodie-store 门店信息页(营业时段编辑所在组件)与订单列表/详情组件、`src/lang/` 四语言文件对应对象层级,输出改动点清单(无代码改动)
-- [ ] T034 [US6] 门店信息页加自配送区块:开关 + 模式(全天/自定义)+ 星期×多时段编辑(复用营业时段编辑交互),调 get/saveMdSelfDeliveryHours;摊位主只读展示"由夜市主统一配送"(foodie-store 对应门店设置组件,Python 脚本编辑保 CRLF)- [ ] T035 [P] [US6] i18n:foodie-store `src/lang/zh.js`、`tw.js`、`en.js`、`vi.js` 四文件同步加 selfDelivery.* keys(有意义英文驼峰、按对象层级插入、四文件 key 一致)- [ ] T036 [US6] 订单列表/详情:selfDelivery=1 显示"自配送"标签($t),不显示等待骑手类状态- [ ] T037 [US6] 【可裁剪:依赖 clarify Q2 端覆盖决策,未决策前跳过】PC 配送操作按钮:开始配送/确认送达调 `/system/orderShOprate/selfDeliveryStart|Complete`
+- [ ] T034 [US6] 【2026-09-10 决策:PC 端功能先隐藏,T034-T038 挂起不做】门店信息页加自配送区块:开关 + 模式(全天/自定义)+ 星期×多时段编辑(复用营业时段编辑交互),调 get/saveMdSelfDeliveryHours;摊位主只读展示"由夜市主统一配送"(foodie-store 对应门店设置组件,Python 脚本编辑保 CRLF)- [ ] T035 [P] [US6] i18n:foodie-store `src/lang/zh.js`、`tw.js`、`en.js`、`vi.js` 四文件同步加 selfDelivery.* keys(有意义英文驼峰、按对象层级插入、四文件 key 一致)- [ ] T036 [US6] 订单列表/详情:selfDelivery=1 显示"自配送"标签($t),不显示等待骑手类状态- [ ] T037 [US6] 【可裁剪:依赖 clarify Q2 端覆盖决策,未决策前跳过】PC 配送操作按钮:开始配送/确认送达调 `/system/orderShOprate/selfDeliveryStart|Complete`
 - [ ] T038 [US6] 冒烟:quickstart 场景 7(配置保存回显、标识、四语言、摊位主无编辑入口)
 ---
 
@@ -182,3 +182,5 @@ description: "Task list for 029-merchant-self-delivery"
 - foodie-store 文件 CRLF,一律 Python 脚本编辑(项目规则)
 - T028 若 type="5" 被占用:换值后同步更新 data-model.md 与 contracts/api.md
 - 不触碰废弃代码清单(research.md「涉及的废弃代码」)
+
+- [x] T041 【2026-09-10 变更】普通门店保存自配送配置改为一律拒绝:仅夜市主门店行且夜市主本人可保存;新增提示 `no.store.selfdelivery.nightmarket.only`(六语言,th_TH 顺带补本 key);测试 `PosStoreControllerSelfDeliveryTest.normalStoreCannotSaveSelfDeliveryConfig`(原 normalStoreSaveGoesThroughStoreAccess 断言翻转)

Некоторые файлы не были показаны из-за большого количества измененных файлов