|
@@ -0,0 +1,144 @@
|
|
|
|
|
+package com.ruoyi.app.order;
|
|
|
|
|
+
|
|
|
|
|
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
|
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
|
|
+import com.ruoyi.common.exception.ServiceException;
|
|
|
|
|
+import com.ruoyi.common.utils.MessageUtils;
|
|
|
|
|
+import com.ruoyi.system.domain.InfoUser;
|
|
|
|
|
+import com.ruoyi.system.domain.PosOrder;
|
|
|
|
|
+import com.ruoyi.system.service.IInfoUserService;
|
|
|
|
|
+import com.ruoyi.system.service.IPosOrderService;
|
|
|
|
|
+import com.ruoyi.system.service.MerchantStoreAccessService;
|
|
|
|
|
+import com.ruoyi.system.utils.AuthContext;
|
|
|
|
|
+import org.apache.ibatis.builder.MapperBuilderAssistant;
|
|
|
|
|
+import org.junit.jupiter.api.*;
|
|
|
|
|
+import org.junit.jupiter.params.ParameterizedTest;
|
|
|
|
|
+import org.junit.jupiter.params.provider.ValueSource;
|
|
|
|
|
+import org.mockito.MockedStatic;
|
|
|
|
|
+import org.springframework.test.util.ReflectionTestUtils;
|
|
|
|
|
+
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+
|
|
|
|
|
+import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
|
+import static org.mockito.ArgumentMatchers.*;
|
|
|
|
|
+import static org.mockito.Mockito.*;
|
|
|
|
|
+
|
|
|
|
|
+class MerchantTodayOrderCountsTest {
|
|
|
|
|
+ private final PosOrderShOprateController controller = new PosOrderShOprateController();
|
|
|
|
|
+ private final IPosOrderService orders = mock(IPosOrderService.class);
|
|
|
|
|
+ private final IInfoUserService users = mock(IInfoUserService.class);
|
|
|
|
|
+ private final MerchantStoreAccessService access = mock(MerchantStoreAccessService.class);
|
|
|
|
|
+ private final InfoUser user = new InfoUser();
|
|
|
|
|
+ private final List<LambdaQueryWrapper<PosOrder>> counts = new ArrayList<>();
|
|
|
|
|
+ private MockedStatic<AuthContext> auth;
|
|
|
|
|
+ private MockedStatic<MessageUtils> messages;
|
|
|
|
|
+
|
|
|
|
|
+ @BeforeAll static void metadata() {
|
|
|
|
|
+ TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), PosOrder.class);
|
|
|
|
|
+ }
|
|
|
|
|
+ @BeforeEach void setup() {
|
|
|
|
|
+ auth = mockStatic(AuthContext.class);
|
|
|
|
|
+ auth.when(AuthContext::requireUserId).thenReturn(801L);
|
|
|
|
|
+ messages = mockStatic(MessageUtils.class);
|
|
|
|
|
+ messages.when(() -> MessageUtils.message(anyString())).thenAnswer(i -> i.getArgument(0));
|
|
|
|
|
+ user.setUserId(801L); user.setUserType("1");
|
|
|
|
|
+ when(users.getOne(any())).thenReturn(user);
|
|
|
|
|
+ when(access.getAccessibleStoreIds(801L)).thenReturn(Set.of(11L,12L));
|
|
|
|
|
+ ReflectionTestUtils.setField(controller,"infoUserService",users);
|
|
|
|
|
+ ReflectionTestUtils.setField(controller,"posOrderService",orders);
|
|
|
|
|
+ ReflectionTestUtils.setField(controller,"merchantStoreAccessService",access);
|
|
|
|
|
+ ReflectionTestUtils.setField(controller,"invoicePrintAvailability",mock(com.ruoyi.app.order.invoice.OrderInvoicePrintAvailabilityService.class));
|
|
|
|
|
+ when(orders.count(any())).thenAnswer(i -> {
|
|
|
|
|
+ counts.add(i.getArgument(0));
|
|
|
|
|
+ return (long)counts.size();
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ @AfterEach void close() { auth.close(); messages.close(); }
|
|
|
|
|
+
|
|
|
|
|
+ private Object invoke(Long mdId,String type) {
|
|
|
|
|
+ return controller.todayOrderCounts("token",mdId,type);
|
|
|
|
|
+ }
|
|
|
|
|
+ private String sql(LambdaQueryWrapper<PosOrder> query) {
|
|
|
|
|
+ String result=query.getSqlSegment();
|
|
|
|
|
+ for(var e:query.getParamNameValuePairs().entrySet())
|
|
|
|
|
+ result=result.replace("#{ew.paramNameValuePairs."+e.getKey()+"}",String.valueOf(e.getValue()));
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+ @Test void countsPendingAndPreparingTodayButReadyAcrossAllDates() {
|
|
|
|
|
+ LocalDate day=LocalDate.now(ZoneId.of("Asia/Taipei"));
|
|
|
|
|
+ var json=com.alibaba.fastjson2.JSON.parseObject(com.alibaba.fastjson2.JSON.toJSONString(invoke(null,null)));
|
|
|
|
|
+ assertEquals(200,json.getIntValue("code"));
|
|
|
|
|
+ assertEquals(1,json.getJSONObject("data").getLongValue("pendingCount"));
|
|
|
|
|
+ assertEquals(2,json.getJSONObject("data").getLongValue("preparingCount"));
|
|
|
|
|
+ assertEquals(3,json.getJSONObject("data").getLongValue("readyCount"));
|
|
|
|
|
+ for(var query:counts.subList(0,2)) {
|
|
|
|
|
+ String statement=sql(query);
|
|
|
|
|
+ assertTrue(statement.contains("cretim >="),statement);
|
|
|
|
|
+ assertTrue(statement.contains("cretim <"),statement);
|
|
|
|
|
+ assertFalse(statement.contains("ORDER BY"));
|
|
|
|
|
+ assertTrue(query.getParamNameValuePairs().containsValue(Date.from(day.atStartOfDay(ZoneId.of("Asia/Taipei")).toInstant())));
|
|
|
|
|
+ assertTrue(query.getParamNameValuePairs().containsValue(Date.from(day.plusDays(1).atStartOfDay(ZoneId.of("Asia/Taipei")).toInstant())));
|
|
|
|
|
+ }
|
|
|
|
|
+ // 已出餐不带时间限制,但保留原ready状态及售后条件,不纳入已完成订单。
|
|
|
|
|
+ assertFalse(sql(counts.get(2)).contains("cretim"));
|
|
|
|
|
+ assertFalse(sql(counts.get(2)).contains("ORDER BY"));
|
|
|
|
|
+ assertTrue(sql(counts.get(0)).contains("state = 0"));
|
|
|
|
|
+ assertTrue(sql(counts.get(0)).contains("pay_status = 1 OR (pay_type IN (1,4) AND type IN (1,2))"));
|
|
|
|
|
+ assertTrue(sql(counts.get(1)).contains("state = 1"));
|
|
|
|
|
+ assertTrue(sql(counts.get(2)).contains("state = 2 AND after_sale_status = 0"));
|
|
|
|
|
+ verify(users,times(1)).getOne(any());
|
|
|
|
|
+ }
|
|
|
|
|
+ @ParameterizedTest @ValueSource(strings={"1","3","4","5"})
|
|
|
|
|
+ void matchesExistingListScopeAndStateConditions(String role) {
|
|
|
|
|
+ user.setUserType(role); user.setStoreId(11L);
|
|
|
|
|
+ invoke(11L,"0");
|
|
|
|
|
+ List<LambdaQueryWrapper<PosOrder>> lists=new ArrayList<>();
|
|
|
|
|
+ when(orders.page(any(Page.class),any(Wrapper.class))).thenAnswer(i->{lists.add(i.getArgument(1));return new Page<PosOrder>();});
|
|
|
|
|
+ for(String tab:List.of("pending","preparing","ready")) controller.orderList("token",1,10,tab,11L,"0");
|
|
|
|
|
+ for(int i=0;i<3;i++) {
|
|
|
|
|
+ String list=sql(lists.get(i)).replace(" ORDER BY cretim DESC","");
|
|
|
|
|
+ String count=sql(counts.get(i)).replaceAll(" AND cretim >= .*? AND cretim < .*?(?= AND state)","");
|
|
|
|
|
+ assertEquals(list,count);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ @Test void rejectsUnauthorizedStoreBeforeCounting() {
|
|
|
|
|
+ doThrow(new ServiceException("denied")).when(access).requireStoreAccess(801L,99L);
|
|
|
|
|
+ assertThrows(ServiceException.class,()->invoke(99L,null));
|
|
|
|
|
+ verify(orders,never()).count(any());
|
|
|
|
|
+ }
|
|
|
|
|
+ @Test void emptyAuthorizationCannotCountAllOrders() {
|
|
|
|
|
+ user.setUserType("5");
|
|
|
|
|
+ when(access.getAccessibleStoreIds(801L)).thenReturn(Set.of());
|
|
|
|
|
+ doAnswer(i->{counts.add(i.getArgument(0));return 0L;}).when(orders).count(any());
|
|
|
|
|
+ var json=com.alibaba.fastjson2.JSON.parseObject(com.alibaba.fastjson2.JSON.toJSONString(invoke(null,null)));
|
|
|
|
|
+ assertEquals(0,json.getJSONObject("data").getLongValue("pendingCount"));
|
|
|
|
|
+ for(var query:counts) assertTrue(sql(query).contains("1 = 0"));
|
|
|
|
|
+ }
|
|
|
|
|
+ @ParameterizedTest @ValueSource(strings={"0","2","unknown"})
|
|
|
|
|
+ void rejectsNonMerchant(String role) {
|
|
|
|
|
+ user.setUserType(role);
|
|
|
|
|
+ assertThrows(ServiceException.class,()->invoke(null,null));
|
|
|
|
|
+ verify(orders,never()).count(any());
|
|
|
|
|
+ }
|
|
|
|
|
+ @Test void rejectsMissingUserAndWrongStallStore() {
|
|
|
|
|
+ when(users.getOne(any())).thenReturn(null);
|
|
|
|
|
+ assertThrows(ServiceException.class,()->invoke(null,null));
|
|
|
|
|
+ when(users.getOne(any())).thenReturn(user);
|
|
|
|
|
+ user.setUserType(null);
|
|
|
|
|
+ assertThrows(ServiceException.class,()->invoke(null,null));
|
|
|
|
|
+ user.setUserType("4"); user.setStoreId(11L);
|
|
|
|
|
+ assertThrows(ServiceException.class,()->invoke(12L,null));
|
|
|
|
|
+ verify(orders,never()).count(any());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest @ValueSource(strings={"abc","-1","3"})
|
|
|
|
|
+ void rejectsInvalidOrderType(String type) {
|
|
|
|
|
+ assertThrows(ServiceException.class,()->invoke(null,type));
|
|
|
|
|
+ verify(orders,never()).count(any());
|
|
|
|
|
+ }
|
|
|
|
|
+}
|