package cn.iocoder.yudao.module.mes.service.pro.scan; import cn.iocoder.yudao.module.mes.dal.mysql.pro.bagcode.MesProBagCodeMapper; import cn.iocoder.yudao.module.mes.dal.mysql.pro.batch.MesProBatchMapper; import cn.iocoder.yudao.module.mes.dal.mysql.pro.pallet.MesProPalletMapper; import org.apache.ibatis.annotations.Update; import org.h2.jdbcx.JdbcDataSource; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import java.util.HashMap; import java.util.Map; import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; /** 执行 Mapper 中的实际 SQL,验证混扫时状态与袋数的结果。 */ class InboundCompletionSqlTest { private JdbcTemplate db; private NamedParameterJdbcTemplate named; @BeforeEach void setup() { JdbcDataSource source = new JdbcDataSource(); source.setURL("jdbc:h2:mem:" + UUID.randomUUID() + ";MODE=MySQL;DB_CLOSE_DELAY=-1"); db = new JdbcTemplate(source); named = new NamedParameterJdbcTemplate(source); db.execute("CREATE TABLE mes_pro_batch(id BIGINT PRIMARY KEY,status INT,deleted INT DEFAULT 0,inbound_time TIMESTAMP,inbound_event_id BIGINT,inbound_device_code VARCHAR(64),inbound_line_code VARCHAR(64),inbound_bag_quantity INT,update_time TIMESTAMP)"); db.execute("CREATE TABLE mes_pro_pallet(id BIGINT PRIMARY KEY,batch_id BIGINT,status INT,deleted INT DEFAULT 0,inbound_time TIMESTAMP,inbound_event_id BIGINT,update_time TIMESTAMP)"); db.execute("CREATE TABLE mes_pro_bag_code(id BIGINT PRIMARY KEY,batch_id BIGINT,pallet_id BIGINT,status INT,deleted INT DEFAULT 0,inbound_time TIMESTAMP,inbound_event_id BIGINT,inbound_device_code VARCHAR(64),inbound_line_code VARCHAR(64),update_time TIMESTAMP)"); db.update("INSERT INTO mes_pro_batch(id,status) VALUES(1,20)"); db.update("INSERT INTO mes_pro_pallet(id,batch_id,status) VALUES(1,1,10),(2,1,10)"); db.update("INSERT INTO mes_pro_bag_code(id,batch_id,pallet_id,status) VALUES(1,1,1,20),(2,1,1,20),(3,1,2,20),(4,1,2,30)"); } private int run(Class mapper, String method, Map values) { var target = java.util.Arrays.stream(mapper.getMethods()).filter(m -> m.getName().equals(method)).findFirst().orElseThrow(); String sql = String.join(" ", target.getAnnotation(Update.class).value()).replaceAll("#\\{(\\w+)\\}", ":$1"); return named.update(sql, values); } private Map args(Long id) { Map values = new HashMap<>(); values.put("id",id);values.put("batchId",1L);values.put("palletId",id); values.put("eventId",10L);values.put("deviceCode","PDA");values.put("lineCode","L1"); return values; } private void refresh() { run(MesProPalletMapper.class,"markCompletedInboundByBatchId",args(1L)); run(MesProBatchMapper.class,"refreshInboundProgress",args(1L)); } private int batchValue(String column) { return db.queryForObject("SELECT " + column + " FROM mes_pro_batch WHERE id=1",Integer.class); } @Test void bagThenPalletThenLastBagCompletesOnlyAtTheEnd() { run(MesProBagCodeMapper.class,"markInbound",args(1L));refresh(); assertEquals(20,batchValue("status")); assertEquals(1,batchValue("inbound_bag_quantity")); assertNull(db.queryForObject("SELECT inbound_event_id FROM mes_pro_pallet WHERE id=1",Long.class)); assertEquals(1,run(MesProBagCodeMapper.class,"markInboundByPalletId",args(1L))); refresh();assertEquals(20,batchValue("status"));assertEquals(2,batchValue("inbound_bag_quantity")); assertEquals(10L,db.queryForObject("SELECT inbound_event_id FROM mes_pro_pallet WHERE id=1",Long.class)); run(MesProBagCodeMapper.class,"markInbound",args(3L));refresh(); assertEquals(30,batchValue("status"));assertEquals(3,batchValue("inbound_bag_quantity")); assertEquals(10L,db.queryForObject("SELECT inbound_event_id FROM mes_pro_pallet WHERE id=2",Long.class)); assertNull(db.queryForObject("SELECT inbound_event_id FROM mes_pro_bag_code WHERE id=4",Long.class)); assertEquals(0,run(MesProBagCodeMapper.class,"markInboundByBatchId",args(1L))); refresh();assertEquals(3,batchValue("inbound_bag_quantity")); } @Test void wholeBatchExcludesCanceledAndDeletedBags() { db.update("UPDATE mes_pro_bag_code SET deleted=1 WHERE id=2"); assertEquals(2,run(MesProBagCodeMapper.class,"markInboundByBatchId",args(1L))); refresh();assertEquals(30,batchValue("status"));assertEquals(2,batchValue("inbound_bag_quantity")); } @Test void emptyBatchDoesNotCompleteAndCanceledBatchDoesNotChange() { db.update("DELETE FROM mes_pro_bag_code");refresh();assertEquals(20,batchValue("status")); db.update("UPDATE mes_pro_batch SET status=40");refresh();assertEquals(40,batchValue("status")); } }