110 lines
10 KiB
Java
110 lines
10 KiB
Java
package com.baiyue.lastleg.discard;
|
|
|
|
import com.baiyue.lastleg.discard.mapper.CargoDiscardInventoryMapper;
|
|
import org.apache.ibatis.mapping.Environment;
|
|
import org.apache.ibatis.session.Configuration;
|
|
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
|
|
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.jdbc.core.JdbcTemplate;
|
|
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
|
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
import static org.junit.jupiter.api.Assertions.*;
|
|
|
|
/** 使用真实 SQL 核对转运实收箱与库存仓位的关联及废弃状态流转。 */
|
|
class CargoDiscardTransferCartonMapperTest {
|
|
/** MIXED 是整托物理余额标记;精确返回剩余实箱及真实 SKU,不能降级成整仓位或混入别的来源。 */
|
|
@Test
|
|
void mixedPhysicalBalanceKeepsOnlyItsRemainingCountedCartons() {
|
|
var source = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
|
var db = new JdbcTemplate(source);
|
|
db.execute("CREATE TABLE ll_inbound_plan_carton(id BIGINT,customer_id VARCHAR(20),order_id BIGINT,warehouse_pallet_id BIGINT,status VARCHAR(30),received_at TIMESTAMP,destination_warehouse_code VARCHAR(20),carton_mark VARCHAR(80),sku_code VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_inventory_balance(id BIGINT,customer_id VARCHAR(20),inbound_order_id BIGINT,destination_warehouse_code VARCHAR(20),sku_code VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_inventory_position(id BIGINT,customer_id VARCHAR(20),balance_id BIGINT,pallet_id BIGINT,batch_no VARCHAR(80),overseas_warehouse_id VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_order(id BIGINT,customer_id VARCHAR(20),inbound_order_id BIGINT,transfer_no VARCHAR(80),operating_warehouse_id VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_pallet(id BIGINT,customer_id VARCHAR(20),transfer_order_id BIGINT,warehouse_pallet_id BIGINT,status VARCHAR(30))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_item(id BIGINT,customer_id VARCHAR(20),transfer_order_id BIGINT,sku_code VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_carton(id BIGINT,customer_id VARCHAR(20),transfer_order_id BIGINT,transfer_item_id BIGINT,transfer_pallet_id BIGINT,status VARCHAR(30),carton_mark VARCHAR(80),updated_at TIMESTAMP,sku_items_json VARCHAR(2000))");
|
|
db.update("INSERT INTO ll_inventory_balance VALUES(1,'C',10,'FBA','MIXED')");
|
|
db.update("INSERT INTO ll_inventory_position VALUES(41,'C',1,100,'TRANSFER','W'),(42,'C',1,100,'OTHER-BATCH','W'),(43,'C',1,100,'TRANSFER','OTHER-WAREHOUSE')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_order VALUES(10,'C',10,'TRANSFER','W'),(20,'C',10,'OTHER-ORDER','W')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_pallet VALUES(11,'C',10,100,'COMPLETED'),(12,'C',10,200,'COMPLETED'),(13,'C',10,100,'BOUND'),(14,'C',20,100,'COMPLETED')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_item VALUES(21,'C',10,'A'),(22,'C',10,'B'),(23,'C',20,'FOREIGN-ORDER')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_carton(id,customer_id,transfer_order_id,transfer_item_id,transfer_pallet_id,status,carton_mark,sku_items_json) VALUES " +
|
|
"(1,'C',10,21,11,'COUNTED','REMAINING-A','[{\"skuCode\":\"A\",\"quantity\":2}]')," +
|
|
"(2,'C',10,22,11,'DISPATCHED','MOVED-B','[{\"skuCode\":\"B\",\"quantity\":8}]')," +
|
|
"(3,'C',10,21,12,'COUNTED','OTHER-PALLET',NULL),(4,'OTHER',10,21,11,'COUNTED','OTHER-CUSTOMER',NULL)," +
|
|
"(5,'C',10,21,11,'EXPECTED','FORECAST',NULL),(6,'C',10,21,11,'DISCARD_PENDING','HELD',NULL)," +
|
|
"(7,'C',10,21,13,'COUNTED','NOT-STOCKED',NULL),(8,'C',20,23,14,'COUNTED','OTHER-ORDER',NULL)," +
|
|
"(9,'C',10,23,11,'COUNTED','ITEM-ORDER-MISMATCH',NULL)");
|
|
var config = new Configuration(new Environment("test", new JdbcTransactionFactory(), source));
|
|
config.setMapUnderscoreToCamelCase(true);
|
|
config.addMapper(CargoDiscardInventoryMapper.class);
|
|
try (var session = new SqlSessionFactoryBuilder().build(config).openSession(true)) {
|
|
var mapper = session.getMapper(CargoDiscardInventoryMapper.class);
|
|
var rows = mapper.genericCartons("C", 41L);
|
|
assertEquals(List.of("REMAINING-A"), rows.stream().map(c -> c.getCartonMark()).toList());
|
|
assertEquals("A", rows.get(0).getSkuCode());
|
|
assertEquals("[{\"skuCode\":\"A\",\"quantity\":2}]", rows.get(0).getSkuItemsJson());
|
|
assertTrue(mapper.genericCartons("OTHER", 41L).isEmpty());
|
|
assertTrue(mapper.genericCartons("C", 42L).isEmpty());
|
|
assertTrue(mapper.genericCartons("C", 43L).isEmpty());
|
|
db.update("UPDATE ll_warehouse_transfer_carton SET status='COUNTED',sku_items_json='[{\"skuCode\":\"A\",\"quantity\":3},{\"skuCode\":\"B\",\"quantity\":5}]' WHERE id=2");
|
|
session.clearCache();
|
|
assertEquals(List.of("REMAINING-A", "MOVED-B"), mapper.genericCartons("C", 41L).stream().map(c -> c.getCartonMark()).toList());
|
|
assertEquals("B", mapper.genericCartons("C", 41L).get(1).getSkuCode());
|
|
assertTrue(mapper.genericCartons("C", 41L).get(1).getSkuItemsJson().contains("\"quantity\":5"));
|
|
}
|
|
}
|
|
|
|
/** 同批多托盘、多 SKU 时仅返回本仓位实收箱,排除预报、短收、占用及其他客户的箱。 */
|
|
@Test
|
|
void receivedBoxesFollowTheirActualPalletAndSku() {
|
|
var source = new DriverManagerDataSource("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1", "sa", "");
|
|
var db = new JdbcTemplate(source);
|
|
db.execute("CREATE TABLE ll_inbound_plan_carton(id BIGINT,customer_id VARCHAR(20),order_id BIGINT,warehouse_pallet_id BIGINT,status VARCHAR(30),received_at TIMESTAMP,destination_warehouse_code VARCHAR(20),carton_mark VARCHAR(80),sku_code VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_inventory_balance(id BIGINT,customer_id VARCHAR(20),inbound_order_id BIGINT,destination_warehouse_code VARCHAR(20),sku_code VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_inventory_position(id BIGINT,customer_id VARCHAR(20),balance_id BIGINT,pallet_id BIGINT,batch_no VARCHAR(80),overseas_warehouse_id VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_order(id BIGINT,customer_id VARCHAR(20),inbound_order_id BIGINT,transfer_no VARCHAR(80),operating_warehouse_id VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_pallet(id BIGINT,customer_id VARCHAR(20),transfer_order_id BIGINT,warehouse_pallet_id BIGINT,status VARCHAR(30))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_item(id BIGINT,customer_id VARCHAR(20),transfer_order_id BIGINT,sku_code VARCHAR(20))");
|
|
db.execute("CREATE TABLE ll_warehouse_transfer_carton(id BIGINT,customer_id VARCHAR(20),transfer_order_id BIGINT,transfer_item_id BIGINT,transfer_pallet_id BIGINT,status VARCHAR(30),carton_mark VARCHAR(80),updated_at TIMESTAMP,sku_items_json VARCHAR(2000))");
|
|
db.update("INSERT INTO ll_inventory_balance VALUES(1,'C',10,'FBA','SKU'),(2,'C',10,'FBA','OTHER')");
|
|
db.update("INSERT INTO ll_inventory_position VALUES(41,'C',1,100,'ZY-BYWL-261019194301','W'),(42,'C',1,200,'ZY-BYWL-261019194301','W'),(43,'C',2,100,'ZY-BYWL-261019194301','W')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_order VALUES(10,'C',10,'ZY-BYWL-261019194301','W')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_pallet VALUES(11,'C',10,100,'COMPLETED'),(12,'C',10,200,'COMPLETED'),(13,'C',10,100,'BOUND')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_item VALUES(21,'C',10,'SKU'),(22,'C',10,'OTHER')");
|
|
db.update("INSERT INTO ll_warehouse_transfer_carton(id,customer_id,transfer_order_id,transfer_item_id,transfer_pallet_id,status,carton_mark) VALUES " +
|
|
"(1,'C',10,21,11,'COUNTED','BOX-1'),(2,'C',10,21,11,'COUNTED','BOX-2')," +
|
|
"(3,'C',10,21,12,'COUNTED','OTHER-PALLET'),(4,'C',10,22,11,'COUNTED','OTHER-SKU')," +
|
|
"(5,'C',10,21,11,'EXPECTED','FORECAST'),(6,'C',10,21,11,'NOT_RECEIVED','SHORT')," +
|
|
"(7,'C',10,21,11,'DISCARD_PENDING','HELD'),(8,'OTHER',10,21,11,'COUNTED','FOREIGN')," +
|
|
"(9,'C',10,21,13,'COUNTED','NOT-STOCKED')");
|
|
var config = new Configuration(new Environment("test", new JdbcTransactionFactory(), source));
|
|
config.setMapUnderscoreToCamelCase(true);
|
|
config.addMapper(CargoDiscardInventoryMapper.class);
|
|
try (var session = new SqlSessionFactoryBuilder().build(config).openSession(true)) {
|
|
var mapper = session.getMapper(CargoDiscardInventoryMapper.class);
|
|
assertEquals(List.of("BOX-1", "BOX-2"), mapper.genericCartons("C", 41L).stream().map(c -> c.getCartonMark()).toList());
|
|
assertEquals(List.of("OTHER-PALLET"), mapper.genericCartons("C", 42L).stream().map(c -> c.getCartonMark()).toList());
|
|
assertEquals(List.of("OTHER-SKU"), mapper.genericCartons("C", 43L).stream().map(c -> c.getCartonMark()).toList());
|
|
assertTrue(mapper.genericCartons("OTHER", 41L).isEmpty());
|
|
db.update("UPDATE ll_warehouse_transfer_carton SET sku_items_json=? WHERE id=1", "[{\"skuCode\":\"SKU\",\"quantity\":5},{\"skuCode\":\"OTHER\",\"quantity\":7}]");
|
|
session.clearCache();
|
|
assertEquals(List.of("OTHER-SKU"), mapper.genericCartons("C", 43L).stream().map(c -> c.getCartonMark()).toList());
|
|
assertTrue(mapper.genericCartons("C", 41L).get(0).getSkuItemsJson().contains("OTHER"));
|
|
assertEquals(1, mapper.changeTransferCartonStatus("C", 2L, "COUNTED", "DISCARD_PENDING"));
|
|
assertEquals(1, mapper.genericCartons("C", 41L).size());
|
|
assertEquals(0, mapper.changeTransferCartonStatus("OTHER", 2L, "DISCARD_PENDING", "COUNTED"));
|
|
assertEquals(1, mapper.changeTransferCartonStatus("C", 2L, "DISCARD_PENDING", "COUNTED"));
|
|
assertEquals(2, mapper.genericCartons("C", 41L).size());
|
|
assertEquals(1, mapper.changeTransferCartonStatus("C", 2L, "COUNTED", "DISCARD_PENDING"));
|
|
assertEquals(1, mapper.changeTransferCartonStatus("C", 2L, "DISCARD_PENDING", "DISCARDED"));
|
|
assertEquals(1, mapper.genericCartons("C", 41L).size());
|
|
}
|
|
}
|
|
}
|