|
|
@@ -0,0 +1,218 @@
|
|
|
+package com.ruoyi.system.service.impl;
|
|
|
+
|
|
|
+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.ruoyi.system.domain.PosOrder;
|
|
|
+import com.ruoyi.system.domain.PushMessage;
|
|
|
+import com.ruoyi.system.domain.flash.FlashDeliveryOrder;
|
|
|
+import com.ruoyi.system.domain.flash.FlashDeliveryOrderImage;
|
|
|
+import com.ruoyi.system.mapper.PosOrderMapper;
|
|
|
+import com.ruoyi.system.mapper.flash.FlashDeliveryOrderImageMapper;
|
|
|
+import com.ruoyi.system.mapper.flash.FlashDeliveryOrderMapper;
|
|
|
+import org.apache.ibatis.builder.MapperBuilderAssistant;
|
|
|
+import org.junit.jupiter.api.BeforeAll;
|
|
|
+import org.junit.jupiter.api.BeforeEach;
|
|
|
+import org.junit.jupiter.api.Test;
|
|
|
+import org.mockito.ArgumentCaptor;
|
|
|
+import org.springframework.test.util.ReflectionTestUtils;
|
|
|
+
|
|
|
+import java.util.Collections;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertNull;
|
|
|
+import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
|
+import static org.mockito.ArgumentMatchers.any;
|
|
|
+import static org.mockito.Mockito.mock;
|
|
|
+import static org.mockito.Mockito.never;
|
|
|
+import static org.mockito.Mockito.verify;
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 消息列表订单信息回填:外卖消息(push_type=1)批量反查 pos_order 取商家名+收货地址;
|
|
|
+ * 闪送消息(push_type=3)反查 flash_delivery_order 取取件/收件地址;
|
|
|
+ * 无订单指针、非订单类型或订单已删时不回填,也不报错。
|
|
|
+ */
|
|
|
+class PushMessageServiceImplTest {
|
|
|
+
|
|
|
+ private final PosOrderMapper posOrderMapper = mock(PosOrderMapper.class);
|
|
|
+ private final FlashDeliveryOrderMapper flashDeliveryOrderMapper = mock(FlashDeliveryOrderMapper.class);
|
|
|
+ private final FlashDeliveryOrderImageMapper flashDeliveryOrderImageMapper = mock(FlashDeliveryOrderImageMapper.class);
|
|
|
+ private final PushMessageServiceImpl service = new PushMessageServiceImpl();
|
|
|
+
|
|
|
+ @BeforeAll
|
|
|
+ static void initTableInfo() {
|
|
|
+ // 纯单测下初始化 MP 实体元数据,否则 LambdaWrapper 解析列名时无缓存可用
|
|
|
+ MapperBuilderAssistant assistant = new MapperBuilderAssistant(new MybatisConfiguration(), "");
|
|
|
+ TableInfoHelper.initTableInfo(assistant, PosOrder.class);
|
|
|
+ TableInfoHelper.initTableInfo(assistant, FlashDeliveryOrder.class);
|
|
|
+ TableInfoHelper.initTableInfo(assistant, FlashDeliveryOrderImage.class);
|
|
|
+ }
|
|
|
+
|
|
|
+ @BeforeEach
|
|
|
+ void setUp() {
|
|
|
+ ReflectionTestUtils.setField(service, "posOrderMapper", posOrderMapper);
|
|
|
+ ReflectionTestUtils.setField(service, "flashDeliveryOrderMapper", flashDeliveryOrderMapper);
|
|
|
+ ReflectionTestUtils.setField(service, "flashDeliveryOrderImageMapper", flashDeliveryOrderImageMapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void foodOrderMessageGetsShopNameAndDeliveryAddress() {
|
|
|
+ PushMessage message = message("991790045286244", 1);
|
|
|
+ PosOrder order = new PosOrder();
|
|
|
+ order.setDdId("991790045286244");
|
|
|
+ order.setPosName("阿寶早餐店");
|
|
|
+ order.setShAddress("台北市大安區仁愛路一段1號");
|
|
|
+ when(posOrderMapper.selectList(any(Wrapper.class))).thenReturn(List.of(order));
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ assertEquals("阿寶早餐店", message.getShopName());
|
|
|
+ assertEquals("台北市大安區仁愛路一段1號", message.getShAddress());
|
|
|
+ verify(flashDeliveryOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ ArgumentCaptor<Wrapper<PosOrder>> captor = ArgumentCaptor.forClass(Wrapper.class);
|
|
|
+ verify(posOrderMapper).selectList(captor.capture());
|
|
|
+ // 反查必须按订单号过滤且不逐条查询(in 参数由 MP 惰性注册,断言以 sqlSegment 为准)
|
|
|
+ LambdaQueryWrapper<PosOrder> queryWrapper = (LambdaQueryWrapper<PosOrder>) captor.getValue();
|
|
|
+ String sqlSegment = queryWrapper.getSqlSegment();
|
|
|
+ assertTrue(sqlSegment.contains("dd_id"));
|
|
|
+ assertTrue(sqlSegment.contains("IN"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void flashOrderMessageGetsPickupAndDeliveryAddress() {
|
|
|
+ PushMessage message = message("F20260924001", 3);
|
|
|
+ FlashDeliveryOrder order = new FlashDeliveryOrder();
|
|
|
+ order.setOrderNo("F20260924001");
|
|
|
+ order.setPickupAddress("台中市西屯區文華路100號");
|
|
|
+ order.setPickupAddressDetail("3樓之2");
|
|
|
+ order.setDeliveryAddress("台中市北區三民路三段129號");
|
|
|
+ order.setDeliveryAddressDetail("B1");
|
|
|
+ when(flashDeliveryOrderMapper.selectList(any(Wrapper.class))).thenReturn(List.of(order));
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ assertEquals("台中市西屯區文華路100號", message.getPickupAddress());
|
|
|
+ assertEquals("3樓之2", message.getPickupAddressDetail());
|
|
|
+ assertEquals("台中市北區三民路三段129號", message.getDeliveryAddress());
|
|
|
+ assertEquals("B1", message.getDeliveryAddressDetail());
|
|
|
+ verify(posOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void foodOrderMessageBackfillsFirstFoodImage() {
|
|
|
+ PushMessage message = message("991790045286244", 1);
|
|
|
+ PosOrder order = new PosOrder();
|
|
|
+ order.setDdId("991790045286244");
|
|
|
+ order.setPosName("阿寶早餐店");
|
|
|
+ // food 快照行结构(App 下单传入):id/name/image/price/otherPrice/number/ask/beizhu/addType
|
|
|
+ order.setFood("[{\"id\":9079,\"name\":\"草莓冰淇淋\",\"image\":\"/profile/upload/2026/08/18/a.png\",\"price\":55,\"otherPrice\":20,\"number\":1},"
|
|
|
+ + "{\"id\":9080,\"name\":\"蛋餅\",\"image\":\"/profile/upload/2026/08/18/b.png\",\"price\":40,\"otherPrice\":0,\"number\":2}]");
|
|
|
+ when(posOrderMapper.selectList(any(Wrapper.class))).thenReturn(List.of(order));
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ // 只取第一行商品的 image
|
|
|
+ assertEquals("/profile/upload/2026/08/18/a.png", message.getOrderImage());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void foodOrderWithoutUsableFoodJsonLeavesOrderImageNull() {
|
|
|
+ PushMessage message = message("991790045286244", 1);
|
|
|
+ PosOrder order = new PosOrder();
|
|
|
+ order.setDdId("991790045286244");
|
|
|
+ order.setFood("not-a-json");
|
|
|
+ when(posOrderMapper.selectList(any(Wrapper.class))).thenReturn(List.of(order));
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ assertNull(message.getOrderImage());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void flashOrderMessageBackfillsFirstSenderImage() {
|
|
|
+ PushMessage message = message("F20260924001", 3);
|
|
|
+ FlashDeliveryOrder order = new FlashDeliveryOrder();
|
|
|
+ order.setId(77L);
|
|
|
+ order.setOrderNo("F20260924001");
|
|
|
+ order.setPickupAddress("台中市西屯區文華路100號");
|
|
|
+ when(flashDeliveryOrderMapper.selectList(any(Wrapper.class))).thenReturn(List.of(order));
|
|
|
+ when(flashDeliveryOrderImageMapper.selectList(any(Wrapper.class))).thenReturn(List.of(
|
|
|
+ senderImage(77L, 1, "/profile/upload/2026/09/24/second.png"),
|
|
|
+ senderImage(77L, 0, "/profile/upload/2026/09/24/first.png"),
|
|
|
+ proofImage(77L, "PICKUP", "/profile/upload/2026/09/24/pickup.png")));
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ // 寄件凭证按 sortOrder 取第一张;取件/送达凭证不作为缩略图
|
|
|
+ assertEquals("/profile/upload/2026/09/24/first.png", message.getOrderImage());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void messageWithoutDdIdStaysUntouched() {
|
|
|
+ PushMessage message = message(null, 1);
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ verify(posOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ verify(flashDeliveryOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ assertNull(message.getShopName());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void nonOrderPushTypeStaysUntouched() {
|
|
|
+ PushMessage message = message("R20260924001", 2);
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ verify(posOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ verify(flashDeliveryOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ assertNull(message.getShopName());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void missingOrderLeavesMessageUntouched() {
|
|
|
+ PushMessage message = message("991790045286244", 1);
|
|
|
+ when(posOrderMapper.selectList(any(Wrapper.class))).thenReturn(Collections.emptyList());
|
|
|
+
|
|
|
+ service.attachOrderInfo(List.of(message));
|
|
|
+
|
|
|
+ assertNull(message.getShopName());
|
|
|
+ assertNull(message.getShAddress());
|
|
|
+ }
|
|
|
+
|
|
|
+ @Test
|
|
|
+ void emptyListTouchesNothing() {
|
|
|
+ service.attachOrderInfo(Collections.emptyList());
|
|
|
+
|
|
|
+ verify(posOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ verify(flashDeliveryOrderMapper, never()).selectList(any(Wrapper.class));
|
|
|
+ }
|
|
|
+
|
|
|
+ private PushMessage message(String ddId, Integer pushType) {
|
|
|
+ PushMessage message = new PushMessage();
|
|
|
+ message.setDdId(ddId);
|
|
|
+ message.setPushType(pushType);
|
|
|
+ return message;
|
|
|
+ }
|
|
|
+
|
|
|
+ private FlashDeliveryOrderImage senderImage(Long orderId, int sortOrder, String url) {
|
|
|
+ return proofImage(orderId, "SENDER", url, sortOrder);
|
|
|
+ }
|
|
|
+
|
|
|
+ private FlashDeliveryOrderImage proofImage(Long orderId, String proofType, String url) {
|
|
|
+ return proofImage(orderId, proofType, url, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ private FlashDeliveryOrderImage proofImage(Long orderId, String proofType, String url, int sortOrder) {
|
|
|
+ FlashDeliveryOrderImage image = new FlashDeliveryOrderImage();
|
|
|
+ image.setOrderId(orderId);
|
|
|
+ image.setProofType(proofType);
|
|
|
+ image.setImageUrl(url);
|
|
|
+ image.setSortOrder(sortOrder);
|
|
|
+ return image;
|
|
|
+ }
|
|
|
+}
|