package com.baiyue.lastleg.delivery; import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import com.baiyue.lastleg.delivery.mapper.DispatchFeeCargoMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mybatis.spring.SqlSessionTemplate; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; import java.util.UUID; import static org.assertj.core.api.Assertions.*; class DispatchFeeCargoMapperTest { /** 原退回实收只重派其已冻结货量,不借同托其他货物放大来源。 */ @Test void returnedReceiptRetainsItsExactSourceInsteadOfBecomingAWholePallet() { var item = new com.baiyue.lastleg.dispatch.entity.DispatchItem(); item.setId(201L); item.setWarehousePalletId(501L); item.setReturnReceiptId(701L); item.setSourceStage("RECEIVED"); item.setInboundCode("IN-A"); item.setPackageCount(2); item.setDestinationType("FBA"); item.setDestinationWarehouseCode("ONT8"); var query = nativeGateway(item); assertThat(query.sourceCargo("DP-1", "101")).singleElement().satisfies(source -> { assertThat(source.inboundCode()).isEqualTo("IN-A"); assertThat(source.packages()).isEqualTo(2); }); } /** 展示普通货或外接货均不能改变真实组成;保留同客户、同仓及本次拣货边界。 */ @org.junit.jupiter.params.ParameterizedTest @org.junit.jupiter.params.provider.ValueSource(strings={"IN-A", "IN-B"}) void actualSourceQueryDoesNotDependOnWhichInboundWasChosenForDisplay(String displayInbound) { jdbc.update("UPDATE ll_dispatch_item SET inbound_code=?,plan_pallet_id=801", displayInbound); var item = new com.baiyue.lastleg.dispatch.entity.DispatchItem(); item.setId(201L); item.setWarehousePalletId(501L); item.setInboundCode(displayInbound); item.setPackageCount(20); item.setDestinationType("FBA"); item.setDestinationWarehouseCode("ONT8"); var query = nativeGateway(item); var sources = query.sourceCargo("DP-1", "101"); assertThat(sources).extracting(com.baiyue.lastleg.fleet.trip.FleetDispatchGateway.SourceCargo::inboundCode).containsExactly("IN-A", "IN-B"); assertThat(sources).extracting(com.baiyue.lastleg.fleet.trip.FleetDispatchGateway.SourceCargo::packages).containsExactly(10, 10); item.setPackageCount(19); assertThatThrownBy(() -> query.sourceCargo("DP-1", "101")).hasMessageContaining("箱数未核平"); } /** 使用当前Fleet整车来源入口,隔离无关资源写链,不保留旧客户主单查询类。 */ private com.baiyue.lastleg.dispatch.fleet.DispatchFleetAdapter nativeGateway(com.baiyue.lastleg.dispatch.entity.DispatchItem item) { var aggregates = org.mockito.Mockito.mock(com.baiyue.lastleg.dispatch.repository.DispatchAggregateRepository.class); var dispatch = new com.baiyue.lastleg.dispatch.entity.DispatchAggregate(); dispatch.setId(1L); dispatch.setDispatchNo("DP-1"); item.setCustomerId("101"); item.setDispatchOrderId(1L); org.mockito.Mockito.when(aggregates.find("DP-1")).thenReturn(dispatch); org.mockito.Mockito.when(aggregates.cargo(1L)).thenReturn(java.util.List.of(item)); return new com.baiyue.lastleg.dispatch.fleet.DispatchFleetAdapter(aggregates,null,null,null, new com.baiyue.lastleg.delivery.repository.DispatchCargoSourceRepository(mapper),null, new com.fasterxml.jackson.databind.ObjectMapper()); } JdbcTemplate jdbc; DispatchFeeCargoMapper mapper; @BeforeEach void setup() throws Exception { var dataSource = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", ""); jdbc = new JdbcTemplate(dataSource); jdbc.execute("CREATE TABLE ll_dispatch_item(id BIGINT,dispatch_order_id BIGINT,customer_id VARCHAR(64),warehouse_pallet_id BIGINT,pallet_no VARCHAR(64),overseas_warehouse_id VARCHAR(64),plan_pallet_id BIGINT,inbound_code VARCHAR(64))"); jdbc.execute("CREATE TABLE ll_inventory_position(id BIGINT,customer_id VARCHAR(64),pallet_id BIGINT,overseas_warehouse_id VARCHAR(64),balance_id BIGINT,available_packages BIGINT)"); jdbc.execute("CREATE TABLE ll_inventory_balance(id BIGINT,customer_id VARCHAR(64),inbound_order_id BIGINT,inbound_code VARCHAR(64))"); jdbc.execute("CREATE TABLE ll_order(id BIGINT,customer_id VARCHAR(64),source_region VARCHAR(32),source_inbound_id VARCHAR(64))"); jdbc.execute("CREATE TABLE ll_dispatch_pda_task(id BIGINT,dispatch_order_id BIGINT UNIQUE)"); jdbc.execute("CREATE TABLE ll_dispatch_pda_pick(task_id BIGINT,customer_id VARCHAR(64),dispatch_item_id BIGINT,inventory_position_id BIGINT,packages BIGINT)"); jdbc.execute("CREATE TABLE ll_inbound_plan_pallet_allocation(pallet_id BIGINT,line_id BIGINT)"); jdbc.execute("CREATE TABLE ll_inbound_plan_line(id BIGINT,customer_id VARCHAR(64),order_id BIGINT)"); jdbc.update("INSERT INTO ll_dispatch_item VALUES(201,1,'101',501,'PLT-501','WH-1',NULL,'IN-A')"); jdbc.update("INSERT INTO ll_inventory_position VALUES(101,'101',501,'WH-1',301,8),(102,'101',501,'WH-1',302,6),(103,'202',501,'WH-1',303,50),(104,'101',501,'WH-2',301,50)"); jdbc.update("INSERT INTO ll_inventory_balance VALUES(301,'101',401,'IN-A'),(302,'101',402,'IN-B'),(303,'202',403,'IN-OTHER')"); jdbc.update("INSERT INTO ll_order VALUES(401,'101','FIRSTLEG','11'),(402,'101','FIRSTLEG','12'),(403,'202','FIRSTLEG','13')"); jdbc.update("INSERT INTO ll_dispatch_pda_task VALUES(601,1),(602,2)"); jdbc.update("INSERT INTO ll_dispatch_pda_pick VALUES(601,'101',201,101,2),(601,'101',201,102,4),(602,'101',201,101,50)"); var config = new MybatisConfiguration(); config.addMapper(DispatchFeeCargoMapper.class); var factory = new MybatisSqlSessionFactoryBean(); factory.setDataSource(dataSource); factory.setConfiguration(config); factory.afterPropertiesSet(); mapper = new SqlSessionTemplate(factory.getObject()).getMapper(DispatchFeeCargoMapper.class); } @Test void preservesEveryInboundOnSharedPalletAndIncludesOnlyThisDispatchsPickedPackages() { var rows = mapper.list("101", 1); assertThat(rows).hasSize(2); assertThat(rows).extracting(row -> row.sourceInboundId()).containsExactly("11", "12"); assertThat(rows).extracting(row -> row.packages()).containsExactly(10L, 10L); assertThat(mapper.list("202", 1)).isEmpty(); } /** 同一整车与任务内按真实明细和拣货客户分别统计,不借其他客户货量。 */ @Test void sharedDispatchAndTaskKeepEachCustomersSourcesSeparate() { jdbc.update("INSERT INTO ll_dispatch_item VALUES(202,1,'202',501,'PLT-501','WH-1',NULL,'IN-OTHER')"); jdbc.update("INSERT INTO ll_dispatch_pda_pick VALUES(601,'202',202,103,7)"); assertThat(mapper.list("101",1)).extracting(row -> row.packages()).containsExactly(10L,10L); assertThat(mapper.list("202",1)).singleElement().satisfies(row -> { assertThat(row.inboundCode()).isEqualTo("IN-OTHER"); assertThat(row.packages()).isEqualTo(57L); }); assertThat(mapper.list("303",1)).isEmpty(); } @Test void aPhysicalSharedPalletIncludesEveryActualSourceRegardlessOfItsDisplayPlan() { jdbc.update("UPDATE ll_dispatch_item SET plan_pallet_id=801"); jdbc.update("INSERT INTO ll_inbound_plan_pallet_allocation VALUES(801,901)"); jdbc.update("INSERT INTO ll_inbound_plan_line VALUES(901,'101',401)"); assertThat(mapper.list("101", 1)).extracting(row -> row.sourceInboundId()).containsExactly("11", "12"); } }