发布当前测试版本至临时灰度环境 #19
@@ -11,12 +11,24 @@ import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface LoadingPalletLabelMapper {
|
||||
// Remainder slices inherit bound slots, not new weight records. Their slot/weight
|
||||
// identity survives release or transfer; preserved empty slots are not pallets.
|
||||
@Select("""
|
||||
SELECT p.id AS plan_id,p.plan_no,p.plan_status,b.container_no,b.cabinet_no,b.warehouse_id,
|
||||
i.id AS item_id,i.account_id,i.inbound_id,i.inbound_code,i.destination_warehouse_id,
|
||||
i.destination_warehouse_code,i.destination_warehouse_name,
|
||||
COALESCE(NULLIF(i.pallet_count,0),
|
||||
CEIL(COALESCE(NULLIF(o.pallet_count,0),
|
||||
NULLIF((SELECT COUNT(DISTINCT weight.id)
|
||||
FROM fl_inbound_pallet_allocation allocation
|
||||
JOIN fl_inbound_weight_result weight
|
||||
ON weight.id=allocation.weight_result_id AND weight.tenant_id=allocation.tenant_id
|
||||
AND weight.deleted=0 AND weight.recognition_status='CONFIRMED'
|
||||
AND (weight.inbound_id=o.id OR weight.inbound_id=o.root_inbound_id)
|
||||
WHERE allocation.tenant_id=i.account_id AND allocation.inbound_id=i.inbound_id
|
||||
AND allocation.block_id>0 AND allocation.slot_no>0 AND allocation.reservation_id>0
|
||||
AND allocation.allocated_package_count>0
|
||||
AND allocation.allocation_status IN ('CONFIRMED','TRANSFERRED','RELEASED')),0),
|
||||
(SELECT COUNT(*) FROM fl_inbound_weight_result weight
|
||||
WHERE weight.tenant_id=i.account_id AND weight.inbound_id=i.inbound_id
|
||||
AND weight.deleted=0 AND weight.recognition_status='CONFIRMED'),0)
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.baiyue.firstleg.mapper;
|
||||
|
||||
import org.apache.ibatis.datasource.unpooled.UnpooledDataSource;
|
||||
import org.apache.ibatis.mapping.Environment;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
|
||||
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/** Execute the production MyBatis query, including inherited weight/slot joins. */
|
||||
class LoadingPalletLabelMapperTest {
|
||||
private SqlSession session;
|
||||
|
||||
@BeforeEach
|
||||
void schema() throws Exception {
|
||||
var dataSource = new UnpooledDataSource("org.h2.Driver",
|
||||
"jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL", "sa", "");
|
||||
var configuration = new Configuration(new Environment("test", new JdbcTransactionFactory(), dataSource));
|
||||
configuration.setMapUnderscoreToCamelCase(true);
|
||||
configuration.addMapper(LoadingPalletLabelMapper.class);
|
||||
session = new SqlSessionFactoryBuilder().build(configuration).openSession();
|
||||
execute("CREATE TABLE fl_loading_plan(id BIGINT PRIMARY KEY,plan_no VARCHAR,plan_status VARCHAR,container_booking_id BIGINT)");
|
||||
execute("CREATE TABLE fl_container_booking(id BIGINT PRIMARY KEY,container_no VARCHAR,cabinet_no VARCHAR,warehouse_id BIGINT,record_status VARCHAR)");
|
||||
// MySQL '/' preserves fractional results for integer operands; H2's integer
|
||||
// division truncates. Decimal scale zero models MySQL's existing CEIL formula.
|
||||
execute("CREATE TABLE fl_loading_plan_item(id BIGINT PRIMARY KEY,loading_plan_id BIGINT,account_id BIGINT,inbound_id BIGINT,inbound_code VARCHAR,destination_warehouse_id BIGINT,destination_warehouse_code VARCHAR,destination_warehouse_name VARCHAR,pallet_count INT,package_count DECIMAL(10,0),load_sequence INT,deleted INT)");
|
||||
execute("CREATE TABLE fl_inbound_order(id BIGINT PRIMARY KEY,tenant_id BIGINT,root_inbound_id BIGINT,pallet_count INT,total_package_count DECIMAL(10,0),fulfillment_type VARCHAR,destination_type VARCHAR,deleted INT)");
|
||||
execute("CREATE TABLE fl_inbound_weight_result(id BIGINT PRIMARY KEY,tenant_id BIGINT,inbound_id BIGINT,pallet_id BIGINT,recognition_status VARCHAR,deleted INT)");
|
||||
execute("CREATE TABLE fl_inbound_pallet_allocation(id BIGINT PRIMARY KEY,tenant_id BIGINT,inbound_id BIGINT,block_id BIGINT,slot_no INT,reservation_id BIGINT,weight_result_id BIGINT,allocated_package_count INT,picked_package_count INT,allocation_status VARCHAR)");
|
||||
execute("INSERT INTO fl_loading_plan VALUES(1,'LP-1','LOADING',2)");
|
||||
execute("INSERT INTO fl_container_booking VALUES(2,'MSCU6639870','D0001',3,'ACTIVE')");
|
||||
execute("INSERT INTO fl_inbound_order VALUES(20,100,30,0,2,'STANDARD','FBA',0)");
|
||||
execute("INSERT INTO fl_loading_plan_item VALUES(10,1,100,20,'IN-CHILD',200,'ONT8','ONT8',0,2,1,0)");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void close() { if (session != null) session.close(); }
|
||||
|
||||
private void execute(String sql) throws Exception {
|
||||
try (var statement = session.getConnection().createStatement()) { statement.execute(sql); }
|
||||
session.clearCache();
|
||||
}
|
||||
|
||||
private void inherited(long id, int slot, int boxes) throws Exception {
|
||||
execute("INSERT INTO fl_inbound_weight_result VALUES(" + id + ",100,30,900,'CONFIRMED',0)");
|
||||
execute("INSERT INTO fl_inbound_pallet_allocation VALUES(" + id + ",100,20,600," + slot
|
||||
+ "," + (700 + slot) + "," + id + "," + boxes + ",0,'CONFIRMED')");
|
||||
}
|
||||
|
||||
private int count() {
|
||||
var rows = session.getMapper(LoadingPalletLabelMapper.class).lockSources(1L);
|
||||
assertThat(rows).hasSize(1);
|
||||
assertThat(rows.get(0).getInboundId()).isEqualTo(20L);
|
||||
assertThat(rows.get(0).getAccountId()).isEqualTo(100L);
|
||||
return rows.get(0).getPalletCount();
|
||||
}
|
||||
|
||||
@Test
|
||||
void childUsesInheritedConfirmedSlotWithoutCreatingItsOwnWeightAndKeepsReleasedSnapshot() throws Exception {
|
||||
inherited(50, 1, 2);
|
||||
assertThat(count()).isEqualTo(1);
|
||||
execute("UPDATE fl_inbound_pallet_allocation SET picked_package_count=allocated_package_count,allocation_status='RELEASED'");
|
||||
assertThat(count()).isEqualTo(1);
|
||||
execute("UPDATE fl_inbound_pallet_allocation SET allocation_status='TRANSFERRED'");
|
||||
assertThat(count()).isEqualTo(1);
|
||||
try (var statement = session.getConnection().createStatement();
|
||||
var result = statement.executeQuery("SELECT COUNT(*) FROM fl_inbound_weight_result WHERE inbound_id=20")) {
|
||||
result.next(); assertThat(result.getInt(1)).isZero();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void countsWeightSlotIdentityOnceAndDoesNotCollapseReusedPhysicalPalletIds() throws Exception {
|
||||
inherited(50, 1, 1);
|
||||
execute("INSERT INTO fl_inbound_pallet_allocation VALUES(51,100,20,601,1,702,50,1,0,'CONFIRMED')");
|
||||
assertThat(count()).isEqualTo(1);
|
||||
inherited(52, 2, 1);
|
||||
assertThat(count()).isEqualTo(2);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"empty", "no-weight", "wrong-customer", "wrong-child", "other-child-weight",
|
||||
"unconfirmed", "deleted-weight", "invalid-block", "invalid-slot", "invalid-reservation", "reserved"})
|
||||
void invalidOrUnrelatedSnapshotsNeverInventOnePallet(String scenario) throws Exception {
|
||||
inherited(50, 1, 2);
|
||||
execute(switch (scenario) {
|
||||
case "empty" -> "UPDATE fl_inbound_pallet_allocation SET allocated_package_count=0";
|
||||
case "no-weight" -> "UPDATE fl_inbound_pallet_allocation SET weight_result_id=NULL";
|
||||
case "wrong-customer" -> "UPDATE fl_inbound_weight_result SET tenant_id=101";
|
||||
case "wrong-child" -> "UPDATE fl_inbound_pallet_allocation SET inbound_id=21";
|
||||
case "other-child-weight" -> "UPDATE fl_inbound_weight_result SET inbound_id=21";
|
||||
case "unconfirmed" -> "UPDATE fl_inbound_weight_result SET recognition_status='PENDING'";
|
||||
case "deleted-weight" -> "UPDATE fl_inbound_weight_result SET deleted=1";
|
||||
case "invalid-block" -> "UPDATE fl_inbound_pallet_allocation SET block_id=0";
|
||||
case "invalid-slot" -> "UPDATE fl_inbound_pallet_allocation SET slot_no=0";
|
||||
case "invalid-reservation" -> "UPDATE fl_inbound_pallet_allocation SET reservation_id=0";
|
||||
case "reserved" -> "UPDATE fl_inbound_pallet_allocation SET allocation_status='RESERVED'";
|
||||
default -> throw new IllegalArgumentException(scenario);
|
||||
});
|
||||
assertThat(count()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void preservesPlanThenInboundPriorityAndRoundsActualSliceUp() throws Exception {
|
||||
inherited(50, 1, 1); inherited(51, 2, 1); inherited(52, 3, 1);
|
||||
execute("UPDATE fl_inbound_order SET total_package_count=8");
|
||||
execute("UPDATE fl_loading_plan_item SET package_count=3");
|
||||
assertThat(count()).isEqualTo(2);
|
||||
execute("UPDATE fl_inbound_order SET pallet_count=4");
|
||||
assertThat(count()).isEqualTo(2);
|
||||
execute("UPDATE fl_loading_plan_item SET pallet_count=5");
|
||||
assertThat(count()).isEqualTo(5);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"NULL", "0"})
|
||||
void rootWithoutRootPointerStillUsesItsOwnConfirmedWeight(String rootId) throws Exception {
|
||||
execute("UPDATE fl_inbound_order SET root_inbound_id=" + rootId);
|
||||
execute("INSERT INTO fl_inbound_weight_result VALUES(50,100,20,900,'CONFIRMED',0)");
|
||||
assertThat(count()).isEqualTo(1);
|
||||
execute("INSERT INTO fl_inbound_pallet_allocation VALUES(50,100,20,600,1,701,50,2,0,'CONFIRMED')");
|
||||
assertThat(count()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void anotherChildMayOnlyUseASourceWeightThroughItsOwnSnapshot() throws Exception {
|
||||
inherited(50, 1, 2);
|
||||
execute("INSERT INTO fl_inbound_order VALUES(21,100,30,0,2,'STANDARD','FBA',0)");
|
||||
execute("UPDATE fl_loading_plan_item SET inbound_id=21,inbound_code='OTHER-CHILD'");
|
||||
assertThat(session.getMapper(LoadingPalletLabelMapper.class).lockSources(1L).get(0).getPalletCount()).isZero();
|
||||
execute("INSERT INTO fl_inbound_pallet_allocation VALUES(51,100,21,600,1,701,50,2,0,'CONFIRMED')");
|
||||
assertThat(session.getMapper(LoadingPalletLabelMapper.class).lockSources(1L).get(0).getPalletCount()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user