2026-08-19 16:24:02 +08:00
|
|
|
package com.baiyue.lastleg.discard;
|
|
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
|
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
2026-10-15 15:42:10 +08:00
|
|
|
import java.sql.DriverManager;
|
|
|
|
|
import java.sql.SQLException;
|
|
|
|
|
import com.baiyue.lastleg.returnreceipt.mapper.ReturnInventoryCartonItemMapper;
|
|
|
|
|
import org.apache.ibatis.annotations.Update;
|
2026-08-19 16:24:02 +08:00
|
|
|
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
2026-10-15 15:42:10 +08:00
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
2026-08-19 16:24:02 +08:00
|
|
|
|
|
|
|
|
class CargoDiscardSchemaContractTest {
|
2026-10-15 15:42:10 +08:00
|
|
|
@Test
|
|
|
|
|
void returnCartonDeductionAllowsZeroButRejectsNegativeStock() throws Exception {
|
|
|
|
|
String baseline;
|
|
|
|
|
try (var input = getClass().getResourceAsStream("/db/lastleg.sql")) {
|
|
|
|
|
baseline = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
|
|
|
|
}
|
|
|
|
|
var constraint = java.util.regex.Pattern.compile(
|
|
|
|
|
"CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK\\(([^)]+)\\)")
|
|
|
|
|
.matcher(baseline);
|
|
|
|
|
assertTrue(constraint.find());
|
|
|
|
|
String deduction = ReturnInventoryCartonItemMapper.class.getMethod("deduct", long.class, long.class)
|
|
|
|
|
.getAnnotation(Update.class).value()[0]
|
|
|
|
|
.replace("#{quantity}", "?").replace("#{id}", "?");
|
|
|
|
|
try (var connection = DriverManager.getConnection("jdbc:h2:mem:discard_zero_quantity;MODE=MySQL")) {
|
|
|
|
|
try (var statement = connection.createStatement()) {
|
|
|
|
|
statement.execute("CREATE TABLE ll_return_inventory_carton_item (id BIGINT PRIMARY KEY, "
|
|
|
|
|
+ "quantity BIGINT NOT NULL, CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK("
|
|
|
|
|
+ constraint.group(1) + "))");
|
|
|
|
|
statement.execute("INSERT INTO ll_return_inventory_carton_item VALUES (1, 3)");
|
|
|
|
|
try (var update = connection.prepareStatement(deduction)) {
|
|
|
|
|
update.setLong(1, 3); update.setLong(2, 1); update.setLong(3, 3);
|
|
|
|
|
assertEquals(1, update.executeUpdate());
|
|
|
|
|
update.setLong(1, 1); update.setLong(3, 1);
|
|
|
|
|
assertEquals(0, update.executeUpdate());
|
|
|
|
|
}
|
|
|
|
|
try (var result = statement.executeQuery("SELECT quantity FROM ll_return_inventory_carton_item WHERE id=1")) {
|
|
|
|
|
assertTrue(result.next());
|
|
|
|
|
assertEquals(0, result.getLong(1));
|
|
|
|
|
}
|
|
|
|
|
assertThrows(SQLException.class, () -> statement.executeUpdate(
|
|
|
|
|
"UPDATE ll_return_inventory_carton_item SET quantity=-1 WHERE id=1"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-19 16:24:02 +08:00
|
|
|
@Test
|
|
|
|
|
void baselineContainsDiscardApplicationReservationAndHistoryTables() throws Exception {
|
|
|
|
|
String sql;
|
|
|
|
|
try (var input = getClass().getResourceAsStream("/db/lastleg.sql")) {
|
|
|
|
|
sql = new String(input.readAllBytes(), StandardCharsets.UTF_8);
|
|
|
|
|
}
|
|
|
|
|
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_cargo_discard_application"));
|
|
|
|
|
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_cargo_discard_item"));
|
|
|
|
|
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_cargo_discard_carton"));
|
|
|
|
|
assertTrue(sql.contains("CREATE TABLE IF NOT EXISTS ll_cargo_discard_status_history"));
|
|
|
|
|
assertTrue(sql.contains("UNIQUE KEY uk_ll_cargo_discard_carton(application_id,carton_id)"));
|
|
|
|
|
}
|
|
|
|
|
}
|