소스 검색

新增门店校验商家审核状态

qmj 2 일 전
부모
커밋
876b079e9d

+ 10 - 1
ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ruoyi.app.order.dto.OrderCreatItem;
 import com.ruoyi.app.order.dto.OrderCreateInput;
 import com.ruoyi.app.order.dto.OrderPushBodyDto;
+import com.ruoyi.app.service.UserService;
 import com.ruoyi.app.utils.DateUtil;
 import com.ruoyi.app.utils.ImageCompressUtils;
 import com.ruoyi.app.user.dto.StoreOutput;
@@ -80,6 +81,8 @@ public class PosStoreController extends BaseController {
     private IPosOrderService posOrderService;
     @Autowired
     private IPosStoreEzpayService posStoreEzpayService;
+    @Autowired
+    private UserService userService;
 
 
 
@@ -253,9 +256,15 @@ public class PosStoreController extends BaseController {
 
     //添加门店
     @Anonymous
+    @Auth
     @PostMapping("/addmendian")
     @Transactional
-    public AjaxResult addmendian(@RequestBody PosStore posStore) {
+    public AjaxResult addmendian(@RequestHeader String token, @RequestBody PosStore posStore) {
+        if (posStore.getId() == null) {
+            Long userId = Long.valueOf(new JwtUtil().getusid(token));
+            userService.checkUserStatus(userId);
+            posStore.setUserId(userId);
+        }
         try {
             // 1. 先保存门店信息
             Boolean org = posStoreService.saveOrUpdate(posStore);

+ 130 - 0
ruoyi-admin/src/test/java/com/ruoyi/app/mendian/PosStoreControllerTest.java

@@ -0,0 +1,130 @@
+package com.ruoyi.app.mendian;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.app.service.UserService;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.framework.web.exception.GlobalExceptionHandler;
+import com.ruoyi.system.domain.InfoUser;
+import com.ruoyi.system.domain.PosStore;
+import com.ruoyi.system.service.IPosStoreService;
+import com.ruoyi.system.utils.JwtUtil;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.MockitoAnnotations;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.when;
+import static org.springframework.http.MediaType.APPLICATION_JSON;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+
+class PosStoreControllerTest {
+
+    @Mock
+    private IPosStoreService posStoreService;
+
+    @Mock
+    private UserService userService;
+
+    @InjectMocks
+    private PosStoreController controller;
+
+    private AutoCloseable mocks;
+    private MockedStatic<MessageUtils> messages;
+    private MockMvc mockMvc;
+    private ObjectMapper objectMapper;
+
+    @BeforeEach
+    void setUp() {
+        mocks = MockitoAnnotations.openMocks(this);
+        messages = org.mockito.Mockito.mockStatic(MessageUtils.class);
+        messages.when(() -> MessageUtils.message(anyString()))
+                .thenAnswer(invocation -> invocation.getArgument(0));
+        mockMvc = MockMvcBuilders.standaloneSetup(controller)
+                .setControllerAdvice(new GlobalExceptionHandler())
+                .build();
+        objectMapper = new ObjectMapper();
+        when(posStoreService.saveOrUpdate(any(PosStore.class))).thenReturn(true);
+    }
+
+    @AfterEach
+    void tearDown() throws Exception {
+        messages.close();
+        mocks.close();
+    }
+
+    @Test
+    void unauditedMerchantCannotCreateStore() throws Exception {
+        when(userService.checkUserStatus(101L))
+                .thenThrow(new ServiceException("账号状态未审核"));
+
+        mockMvc.perform(post("/chanting/store/addmendian")
+                        .header("token", tokenFor(101L))
+                        .contentType(APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(newStore(999L))))
+                .andExpect(jsonPath("$.code").value(500))
+                .andExpect(jsonPath("$.msg").value("账号状态未审核"));
+    }
+
+    @Test
+    void auditedMerchantCreatesStoreOwnedByTokenUser() throws Exception {
+        when(userService.checkUserStatus(101L)).thenReturn(auditedMerchant(101L));
+        PosStore saved = newStore(101L);
+        saved.setId(9);
+        when(posStoreService.getOne(any())).thenReturn(saved);
+
+        mockMvc.perform(post("/chanting/store/addmendian")
+                        .header("token", tokenFor(101L))
+                        .contentType(APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(newStore(999L))))
+                .andExpect(jsonPath("$.code").value(200));
+
+        ArgumentCaptor<PosStore> captor = ArgumentCaptor.forClass(PosStore.class);
+        org.mockito.Mockito.verify(posStoreService).saveOrUpdate(captor.capture());
+        assertEquals(101L, captor.getValue().getUserId());
+    }
+
+    @Test
+    void editingExistingStoreDoesNotRequireMerchantAudit() throws Exception {
+        when(userService.checkUserStatus(any()))
+                .thenThrow(new ServiceException("账号状态未审核"));
+        PosStore existing = newStore(101L);
+        existing.setId(9);
+        when(posStoreService.getById(9)).thenReturn(existing);
+
+        mockMvc.perform(post("/chanting/store/addmendian")
+                        .header("token", tokenFor(101L))
+                        .contentType(APPLICATION_JSON)
+                        .content(objectMapper.writeValueAsString(existing)))
+                .andExpect(jsonPath("$.code").value(200));
+    }
+
+    private static PosStore newStore(Long userId) {
+        PosStore store = new PosStore();
+        store.setPosName("测试门店");
+        store.setUserId(userId);
+        return store;
+    }
+
+    private static InfoUser auditedMerchant(Long userId) {
+        InfoUser user = new InfoUser();
+        user.setUserId(userId);
+        user.setUserType("1");
+        user.setAuditStatus("1");
+        return user;
+    }
+
+    private static String tokenFor(Long userId) {
+        return JwtUtil.setToken(String.valueOf(userId), "merchant");
+    }
+}

+ 3 - 3
specs/001-food-stall/tasks.md

@@ -176,6 +176,6 @@ Task: "UserWallet.java storeId + UserWalletMapper.xml" # US3 相关
 
 ## Phase 7: 普通商家新增门店审核门禁(2026-08-24)
 
-- [ ] T027 为 `PosStoreController.addmendian` 新增控制器测试,覆盖未审核拒绝、已审核新增时强制绑定 token 用户、编辑不触发新增审核门禁 — `ruoyi-admin/src/test/java/com/ruoyi/app/mendian/PosStoreControllerTest.java`
-- [ ] T028 修改 `PosStoreController.addmendian`:显式接收 `@RequestHeader String token`,仅新增时解析当前用户、调用 `UserService.checkUserStatus` 并覆盖 `PosStore.userId` — `ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java`
-- [ ] T029 使用 JDK 21 运行 `PosStoreControllerTest` 和 `ruoyi-admin` 模块构建,检查差异中无无关文件或整文件换行变化
+- [x] T027 为 `PosStoreController.addmendian` 新增控制器测试,覆盖未审核拒绝、已审核新增时强制绑定 token 用户、编辑不触发新增审核门禁 — `ruoyi-admin/src/test/java/com/ruoyi/app/mendian/PosStoreControllerTest.java`
+- [x] T028 修改 `PosStoreController.addmendian`:显式接收 `@RequestHeader String token`,仅新增时解析当前用户、调用 `UserService.checkUserStatus` 并覆盖 `PosStore.userId` — `ruoyi-admin/src/main/java/com/ruoyi/app/mendian/PosStoreController.java`
+- [x] T029 使用 JDK 21 运行 `PosStoreControllerTest` 和 `ruoyi-admin` 模块构建,检查差异中无无关文件或整文件换行变化