修改提交
This commit is contained in:
@@ -53,6 +53,8 @@ class LastlegOrderServiceTest {
|
||||
|
||||
assertEquals(11L, response.order().id());
|
||||
assertEquals("100", response.order().customerId());
|
||||
assertEquals("ONE_CLICK_DROPSHIP", response.order().orderType());
|
||||
assertEquals("一件代发", response.order().orderTypeName());
|
||||
assertTrue(java.util.Arrays.stream(response.getClass().getRecordComponents())
|
||||
.noneMatch(component -> "dropshipPallets".equals(component.getName())));
|
||||
assertTrue(java.util.Arrays.stream(com.baiyue.lastleg.dto.LastlegOrderDetailResponse.History.class.getRecordComponents())
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@ package com.baiyue.lastleg.service;
|
||||
import com.baiyue.common.event.*; import com.baiyue.lastleg.entity.*; import com.baiyue.lastleg.mapper.*; import com.baiyue.lastleg.dropship.dto.DropshipRequests; import com.baiyue.lastleg.dropship.service.DropshipOrderService; import com.baiyue.lastleg.inboundplan.dto.InboundPlanResponse; import com.baiyue.lastleg.inboundplan.mapper.InboundPlanCartonMapper; import com.baiyue.lastleg.inboundplan.service.InboundPlanService; import com.baiyue.lastleg.inventory.command.dto.InventoryCommandRequests; import com.baiyue.lastleg.inventory.command.service.InventoryCommandService; import com.fasterxml.jackson.databind.*; import org.junit.jupiter.api.*; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.*; import org.springframework.test.util.ReflectionTestUtils; import java.math.BigDecimal; import java.time.Instant; import java.util.*; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*;
|
||||
@ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class)
|
||||
class LoadingCompletedConsumerTest {
|
||||
@Mock LastlegEventInboxMapper inbox; @Mock LastlegOrderMapper orders; @Mock LastlegOrderDetailMapper details; @Mock LastlegOrderStatusHistoryMapper histories; @Mock InboundPlanCartonMapper cartons; @Mock DropshipOrderService dropshipOrders; @Mock InboundPlanService inboundPlans; @Mock InventoryCommandService inventory; ObjectMapper json=new ObjectMapper().findAndRegisterModules(); LoadingCompletedConsumer service;
|
||||
@BeforeEach void setup(){ service=new LoadingCompletedConsumer(); ReflectionTestUtils.setField(service,"inboxMapper",inbox); ReflectionTestUtils.setField(service,"orderMapper",orders); ReflectionTestUtils.setField(service,"detailMapper",details); ReflectionTestUtils.setField(service,"historyMapper",histories); ReflectionTestUtils.setField(service,"cartonMapper",cartons); ReflectionTestUtils.setField(service,"dropshipOrders",dropshipOrders); ReflectionTestUtils.setField(service,"inboundPlans",inboundPlans); ReflectionTestUtils.setField(service,"inventory",inventory); ReflectionTestUtils.setField(service,"objectMapper",json); ReflectionTestUtils.setField(service,"orderNoGenerator",new LastlegOrderNoGenerator()); lenient().doAnswer(i->{ LastlegOrder o=i.getArgument(0); o.setId(Math.abs(o.getSourceInboundId().hashCode())+1L); return 1; }).when(orders).insert(any(LastlegOrder.class)); lenient().when(inboundPlans.convert(anyString(),anyLong())).thenReturn(new InboundPlanResponse(1L,"LIP-1","100",1L,"MSCU1","PENDING_ASSIGNMENT",1,1,BigDecimal.ONE,List.of(),List.of(),List.of())); }
|
||||
@Mock LastlegEventInboxMapper inbox; @Mock LastlegOrderMapper orders; @Mock LastlegInboundOrderMapper inboundOrders; @Mock LastlegOrderDetailMapper details; @Mock LastlegOrderStatusHistoryMapper histories; @Mock InboundPlanCartonMapper cartons; @Mock DropshipOrderService dropshipOrders; @Mock InboundPlanService inboundPlans; @Mock InventoryCommandService inventory; ObjectMapper json=new ObjectMapper().findAndRegisterModules(); LoadingCompletedConsumer service;
|
||||
@BeforeEach void setup(){ service=new LoadingCompletedConsumer(); ReflectionTestUtils.setField(service,"inboxMapper",inbox); ReflectionTestUtils.setField(service,"orderMapper",orders); ReflectionTestUtils.setField(service,"inboundOrderMapper",inboundOrders); ReflectionTestUtils.setField(service,"detailMapper",details); ReflectionTestUtils.setField(service,"historyMapper",histories); ReflectionTestUtils.setField(service,"cartonMapper",cartons); ReflectionTestUtils.setField(service,"dropshipOrders",dropshipOrders); ReflectionTestUtils.setField(service,"inboundPlans",inboundPlans); ReflectionTestUtils.setField(service,"inventory",inventory); ReflectionTestUtils.setField(service,"objectMapper",json); ReflectionTestUtils.setField(service,"orderNoGenerator",new LastlegOrderNoGenerator()); lenient().doAnswer(i->{ LastlegOrder o=i.getArgument(0); o.setId(Math.abs(o.getSourceInboundId().hashCode())+1L); return 1; }).when(orders).insert(any(LastlegOrder.class)); lenient().when(inboundPlans.convert(anyString(),anyLong())).thenReturn(new InboundPlanResponse(1L,"LIP-1","100",1L,"MSCU1","PENDING_ASSIGNMENT",1,1,BigDecimal.ONE,List.of(),List.of(),List.of())); }
|
||||
@Test void createsOneOrderAndOneInboundPlanPerInbound(){ EventEnvelope event=event(); assertEquals(2,service.consume(event)); verify(orders,times(2)).insert(any(LastlegOrder.class)); verify(inboundPlans,times(2)).convert(eq("100"),anyLong()); verify(inventory,times(2)).registerInTransit(eq("100"),eq("SYSTEM"),any(InventoryCommandRequests.InTransit.class)); verify(details,times(2)).insert(any(LastlegOrderDetail.class)); verify(histories,times(2)).insert(any(LastlegOrderStatusHistory.class)); ArgumentCaptor<LastlegOrder> c=ArgumentCaptor.forClass(LastlegOrder.class); verify(orders,times(2)).insert(c.capture()); assertEquals(Set.of("in-1","in-2"),c.getAllValues().stream().map(LastlegOrder::getSourceInboundId).collect(java.util.stream.Collectors.toSet())); assertTrue(c.getAllValues().stream().allMatch(o->"PENDING_ASSIGNMENT".equals(o.getCurrentStatus()))); assertTrue(c.getAllValues().stream().allMatch(o->o.getId()!=null)); assertTrue(c.getAllValues().stream().allMatch(o->"MSCU1".equals(o.getContainerNo()))); assertEquals(1,c.getAllValues().stream().map(LastlegOrder::getOrderNo).distinct().count()); assertEquals(new LastlegOrderNoGenerator().forContainerNo("MSCU1"),c.getAllValues().get(0).getOrderNo()); }
|
||||
@Test void repeatedEventReturnsExistingEffect(){ EventEnvelope event=event(); LastlegEventInbox row=new LastlegEventInbox(); row.setPayloadHash(event.payloadHash()); when(inbox.selectById(event.eventId())).thenReturn(row); when(orders.countContainer("100","MSCU1")).thenReturn(2L); assertEquals(2,service.consume(event)); verify(orders).countContainer("100","MSCU1"); verify(orders,never()).insert(any(LastlegOrder.class)); verify(details,never()).insert(any(LastlegOrderDetail.class)); }
|
||||
@Test void sameEventWithDifferentHashIsRejected(){ EventEnvelope event=event(); LastlegEventInbox row=new LastlegEventInbox(); row.setPayloadHash("sha256:"+"0".repeat(64)); when(inbox.selectById(event.eventId())).thenReturn(row); assertThrows(IllegalArgumentException.class,()->service.consume(event)); }
|
||||
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
package com.baiyue.lastleg.service;
|
||||
|
||||
import com.baiyue.common.event.EventEnvelope;
|
||||
import com.baiyue.lastleg.dropship.service.DropshipOrderService;
|
||||
import com.baiyue.lastleg.inboundplan.pda.gateway.WarehouseResourceGateway;
|
||||
import com.baiyue.lastleg.inboundplan.service.InboundPlanService;
|
||||
import com.baiyue.lastleg.inventory.command.service.InventoryCommandService;
|
||||
import com.baiyue.lastleg.looseboard.dto.LocalLooseboardRequests;
|
||||
import com.baiyue.lastleg.looseboard.service.LocalLooseboardService;
|
||||
import com.baiyue.lastleg.relabel.dto.RelabelRequests;
|
||||
import com.baiyue.lastleg.relabel.service.RelabelApplicationService;
|
||||
import com.baiyue.lastleg.transfer.dto.WarehouseTransferRequests;
|
||||
import com.baiyue.lastleg.transfer.service.WarehouseTransferService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
@SpringBootTest(classes = TaillegRealConsumerAcceptanceTest.AcceptanceApplication.class,
|
||||
webEnvironment = SpringBootTest.WebEnvironment.NONE, properties = {
|
||||
"spring.sql.init.mode=never", "spring.cloud.nacos.discovery.enabled=false",
|
||||
"spring.cloud.nacos.discovery.register-enabled=false", "spring.cloud.nacos.config.enabled=false",
|
||||
"spring.cloud.nacos.config.import-check.enabled=false", "spring.task.scheduling.enabled=false"
|
||||
})
|
||||
@EnabledIfSystemProperty(named = "tailleg.real.consumer", matches = "true")
|
||||
class TaillegRealConsumerAcceptanceTest {
|
||||
static final String CUSTOMER = "990022";
|
||||
static final String MARKER = "REAL-TAIL-20260822-R3";
|
||||
static final String EVENT_KEY = "FIRSTLEG_LOADING_COMPLETED:990022022:990022:2";
|
||||
static final LocalDateTime RELABEL_DEADLINE = LocalDateTime.of(2026, 8, 29, 11, 1, 21, 628_000_000);
|
||||
static final LocalDateTime TRANSFER_ETA = LocalDateTime.of(2026, 9, 1, 11, 1, 21, 674_000_000);
|
||||
static final LocalDateTime RETURN_RELABEL_ETA = LocalDateTime.of(2026, 9, 1, 11, 1, 21, 756_000_000);
|
||||
static final LocalDate REQUESTED_DATE = LocalDate.of(2026, 8, 25);
|
||||
|
||||
@Autowired JdbcTemplate jdbc;
|
||||
@Autowired ObjectMapper json;
|
||||
@Autowired LoadingCompletedConsumer consumer;
|
||||
@Autowired RelabelApplicationService relabel;
|
||||
@Autowired WarehouseTransferService transfer;
|
||||
@Autowired LocalLooseboardService looseboard;
|
||||
|
||||
@SpringBootConfiguration
|
||||
@EnableAutoConfiguration(excludeName = "com.baiyue.common.security.BaiyueSecurityAutoConfiguration")
|
||||
@Import({LoadingCompletedConsumer.class, LastlegOrderNoGenerator.class, DropshipOrderService.class,
|
||||
InboundPlanService.class, InventoryCommandService.class, RelabelApplicationService.class,
|
||||
WarehouseTransferService.class, LocalLooseboardService.class})
|
||||
@MapperScan({"com.baiyue.lastleg.mapper", "com.baiyue.lastleg.dropship.mapper",
|
||||
"com.baiyue.lastleg.inboundplan.mapper", "com.baiyue.lastleg.inventory.mapper",
|
||||
"com.baiyue.lastleg.inventory.command.mapper", "com.baiyue.lastleg.relabel.mapper",
|
||||
"com.baiyue.lastleg.transfer.mapper", "com.baiyue.lastleg.looseboard.mapper"})
|
||||
static class AcceptanceApplication {
|
||||
@Bean WarehouseResourceGateway warehouseResourceGateway() {
|
||||
return new WarehouseResourceGateway() {
|
||||
public WarehousePalletReference ensureDropshipPallet(String customerId, long warehouseId, String businessId) {
|
||||
return new WarehousePalletReference(1L, "UNUSED", 1L);
|
||||
}
|
||||
public long reserve(String customerId, long warehouseId, long palletId, long locationId,
|
||||
String businessType, String businessId, String reservationKey) { return 1L; }
|
||||
public void scrap(String customerId, long resourceLockId) { }
|
||||
public void scrapPallet(String customerId, long palletId) { }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void consumesRealOutboxAndCreatesEveryTaillegOrderType() throws Exception {
|
||||
String envelopeJson = jdbc.queryForObject(
|
||||
"SELECT payload_json FROM baiyue_firstleg.fl_inbound_outbox WHERE event_key=?", String.class, EVENT_KEY);
|
||||
EventEnvelope envelope = json.readValue(envelopeJson, EventEnvelope.class);
|
||||
assertEquals(2, consumer.consume(envelope));
|
||||
|
||||
Long sourceOrderId = jdbc.queryForObject("SELECT id FROM ll_order WHERE customer_id=? AND " +
|
||||
"source_loading_plan_id='990022022' AND order_type='FIRST_LEG'", Long.class, CUSTOMER);
|
||||
String inboundCode = jdbc.queryForObject("SELECT inbound_code FROM ll_order WHERE id=?", String.class, sourceOrderId);
|
||||
assertNotNull(jdbc.queryForObject("SELECT id FROM ll_inbound_order WHERE customer_id=? AND inbound_code=?",
|
||||
Long.class, CUSTOMER, inboundCode));
|
||||
|
||||
if (!exists("ll_relabel_application", MARKER + "-RELABEL-KEY")) {
|
||||
relabel.create(CUSTOMER, "real-acceptance", new RelabelRequests.Create(
|
||||
MARKER + "-RELABEL", "92", RELABEL_DEADLINE, "验收联系人", "13800000000",
|
||||
MARKER, MARKER + "-RELABEL-KEY", List.of(new RelabelRequests.Item("SKU-REAL-A", null, null,
|
||||
null, "真实验收商品", 3, 3, MARKER + "-SHIP", MARKER + "-TRACK", "SKU-REAL-A-NEW",
|
||||
"换标验收", null, null, null))));
|
||||
}
|
||||
|
||||
createTransfer(sourceOrderId, inboundCode, false, "TRANSFER");
|
||||
createTransfer(sourceOrderId, inboundCode, true, "RETURN-RELABEL");
|
||||
|
||||
if (!exists("ll_local_looseboard_order", MARKER + "-LOOSEBOARD-KEY")) {
|
||||
looseboard.create(CUSTOMER, "real-acceptance", new LocalLooseboardRequests.Create(
|
||||
"SHARED_TRUCK", "YES", "WAREHOUSE_TO_WAREHOUSE", "洛杉矶海外仓", "Los Angeles",
|
||||
"ONT8", "FBA ONT8", "40HQ", 3, new BigDecimal("30.00"), new BigDecimal("0.40"),
|
||||
new BigDecimal("120.00"), "USD", "验收联系人", "13800000000", REQUESTED_DATE,
|
||||
MARKER, MARKER + "-LOOSEBOARD-KEY"));
|
||||
}
|
||||
|
||||
assertEquals(6, jdbc.queryForObject("SELECT COUNT(DISTINCT order_type) FROM ll_order WHERE customer_id=? " +
|
||||
"AND (source_loading_plan_id='990022022' OR source_event_id LIKE ? OR customer_remark=?)",
|
||||
Integer.class, CUSTOMER, "%" + MARKER + "%", MARKER));
|
||||
}
|
||||
|
||||
private void createTransfer(Long sourceOrderId, String inboundCode, boolean needRelabel, String suffix) {
|
||||
String idempotencyKey = MARKER + "-" + suffix + "-KEY";
|
||||
if (exists("ll_warehouse_transfer_order", idempotencyKey)) return;
|
||||
transfer.create(CUSTOMER, "real-acceptance", new WarehouseTransferRequests.Create(
|
||||
inboundCode, List.of(sourceOrderId), "92", needRelabel ? "LAX9" : "ONT8", "真实验收目的地址",
|
||||
3, new BigDecimal("0.40"), "TRUCK", needRelabel ? RETURN_RELABEL_ETA : TRANSFER_ETA,
|
||||
MARKER + "-SHIP-" + suffix,
|
||||
MARKER + "-TRACK", MARKER + "-BOXES", MARKER, needRelabel, idempotencyKey,
|
||||
List.of(new WarehouseTransferRequests.Item("SKU-REAL-A", "真实验收商品", 3, MARKER + "-MARK"))));
|
||||
}
|
||||
|
||||
private boolean exists(String table, String idempotencyKey) {
|
||||
return jdbc.queryForObject("SELECT COUNT(*) FROM " + table + " WHERE customer_id=? AND idempotency_key=?",
|
||||
Integer.class, CUSTOMER, idempotencyKey) == 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user