This commit is contained in:
2026-09-09 13:51:01 +08:00
parent a3354c92c2
commit 1a092bc9d7
6 changed files with 39 additions and 4 deletions
@@ -18131,8 +18131,7 @@ CREATE TABLE IF NOT EXISTS fl_terminal_drayage (
KEY idx_terminal_drayage_warning(actual_empty_return_at,estimated_empty_return_at), KEY idx_terminal_drayage_warning(actual_empty_return_at,estimated_empty_return_at),
CONSTRAINT fk_terminal_drayage_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id), CONSTRAINT fk_terminal_drayage_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id),
CONSTRAINT chk_terminal_drayage_times CHECK((actual_pickup_at IS NULL OR pickup_appointment_at IS NOT NULL) CONSTRAINT chk_terminal_drayage_times CHECK((actual_pickup_at IS NULL OR pickup_appointment_at IS NOT NULL)
AND (actual_empty_return_at IS NULL OR actual_pickup_at IS NOT NULL) AND (actual_empty_return_at IS NULL OR actual_pickup_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
AND (actual_empty_return_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
) ENGINE=InnoDB COMMENT='目的港货柜级码头拖车与还空事实'; ) ENGINE=InnoDB COMMENT='目的港货柜级码头拖车与还空事实';
CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history ( CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history (
id BIGINT UNSIGNED NOT NULL COMMENT '历史ID', drayage_id BIGINT UNSIGNED NOT NULL COMMENT '码头拖车聚合ID', id BIGINT UNSIGNED NOT NULL COMMENT '历史ID', drayage_id BIGINT UNSIGNED NOT NULL COMMENT '码头拖车聚合ID',
@@ -18158,6 +18157,10 @@ CREATE TABLE IF NOT EXISTS fl_terminal_drayage_operation (
-- MySQL DDL 会隐式提交;如果前次执行在末段校验失败,重跑时需把已创建表的列注释收敛到当前基线。 -- MySQL DDL 会隐式提交;如果前次执行在末段校验失败,重跑时需把已创建表的列注释收敛到当前基线。
ALTER TABLE fl_terminal_drayage ALTER TABLE fl_terminal_drayage
DROP CHECK chk_terminal_drayage_times,
ADD CONSTRAINT chk_terminal_drayage_times CHECK(
(actual_pickup_at IS NULL OR pickup_appointment_at IS NOT NULL) AND
(actual_empty_return_at IS NULL OR actual_pickup_at IS NULL OR actual_empty_return_at >= actual_pickup_at)),
MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '目的港码头拖车聚合ID', MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '目的港码头拖车聚合ID',
MODIFY COLUMN container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '唯一归属物理货柜ID', MODIFY COLUMN container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '唯一归属物理货柜ID',
MODIFY COLUMN fleet_supplier_id BIGINT UNSIGNED NULL COMMENT 'Warehouse ACTIVE/TRUCKING供应商ID快照', MODIFY COLUMN fleet_supplier_id BIGINT UNSIGNED NULL COMMENT 'Warehouse ACTIVE/TRUCKING供应商ID快照',
+1
View File
@@ -5,6 +5,7 @@
<parent><groupId>com.baiyue.firstleg</groupId><artifactId>baiyue-firstleg-platform</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent> <parent><groupId>com.baiyue.firstleg</groupId><artifactId>baiyue-firstleg-platform</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent>
<artifactId>firstleg-service</artifactId> <artifactId>firstleg-service</artifactId>
<dependencies> <dependencies>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>
<dependency><groupId>com.baiyue.shared</groupId><artifactId>baiyue-common-core</artifactId><version>${project.version}</version></dependency> <dependency><groupId>com.baiyue.shared</groupId><artifactId>baiyue-common-core</artifactId><version>${project.version}</version></dependency>
<dependency><groupId>com.baiyue.shared</groupId><artifactId>common-event-contract</artifactId><version>${project.version}</version></dependency> <dependency><groupId>com.baiyue.shared</groupId><artifactId>common-event-contract</artifactId><version>${project.version}</version></dependency>
<dependency><groupId>com.baiyue.shared</groupId><artifactId>baiyue-common-audit</artifactId><version>${project.version}</version></dependency> <dependency><groupId>com.baiyue.shared</groupId><artifactId>baiyue-common-audit</artifactId><version>${project.version}</version></dependency>
@@ -24,4 +24,10 @@ public interface WarehouseSupplierClient {
record Snapshot(long supplierId, String name, String category, String status, record Snapshot(long supplierId, String name, String category, String status,
List<String> carrierCodes) {} List<String> carrierCodes) {}
@GetMapping("/{supplierId}/trucking-contact")
ApiResponse<TruckingContact> truckingContact(@RequestHeader("X-Internal-Service-Token") String token,
@PathVariable long supplierId, @RequestParam boolean requireActive);
record TruckingContact(long supplierId, String name, String email) {}
} }
@@ -23,8 +23,7 @@ CREATE TABLE IF NOT EXISTS fl_terminal_drayage (
CONSTRAINT fk_terminal_drayage_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id), CONSTRAINT fk_terminal_drayage_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id),
CONSTRAINT chk_terminal_drayage_times CHECK( CONSTRAINT chk_terminal_drayage_times CHECK(
(actual_pickup_at IS NULL OR pickup_appointment_at IS NOT NULL) AND (actual_pickup_at IS NULL OR pickup_appointment_at IS NOT NULL) AND
(actual_empty_return_at IS NULL OR actual_pickup_at IS NOT NULL) AND (actual_empty_return_at IS NULL OR actual_pickup_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
(actual_empty_return_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
) ENGINE=InnoDB COMMENT='目的港货柜级码头拖车与还空事实'; ) ENGINE=InnoDB COMMENT='目的港货柜级码头拖车与还空事实';
CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history ( CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history (
@@ -8,6 +8,20 @@ import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
class TerminalDrayageSqlContractTest { class TerminalDrayageSqlContractTest {
@Test
void bothSqlEntrypointsAllowReturnWithoutPickupAndRetainKnownTimeOrdering() throws Exception {
for (Path path : java.util.List.of(
Path.of("src/main/resources/db/phase3-terminal-drayage-schema.sql"),
Path.of("../deploy/sql/头程数据库统一增量-MySQL8.sql"))) {
String sql = Files.readString(path);
assertThat(sql).contains("actual_empty_return_at IS NULL OR actual_pickup_at IS NULL OR actual_empty_return_at >= actual_pickup_at")
.doesNotContain("actual_empty_return_at IS NULL OR actual_pickup_at IS NOT NULL");
}
String release = Files.readString(Path.of("../deploy/sql/头程数据库统一增量-MySQL8.sql"));
assertThat(release).contains("DROP CHECK chk_terminal_drayage_times",
"ADD CONSTRAINT chk_terminal_drayage_times CHECK(");
}
@Test @Test
void schemaKeepsOneAggregatePerContainerAndImmutableAudit() throws Exception { void schemaKeepsOneAggregatePerContainerAndImmutableAudit() throws Exception {
String sql = Files.readString(Path.of("src/main/resources/db/phase3-terminal-drayage-schema.sql")); String sql = Files.readString(Path.of("src/main/resources/db/phase3-terminal-drayage-schema.sql"));
@@ -37,5 +37,17 @@ public class InternalSupplierController {
return ApiResponse.success(service.internalBookingCandidates(carrierCode)); return ApiResponse.success(service.internalBookingCandidates(carrierCode));
} }
public record TruckingContact(long supplierId, String name, String email) {}
@GetMapping("/{supplierId}/trucking-contact")
public ApiResponse<TruckingContact> truckingContact(
@RequestHeader(value="X-Internal-Service-Token", required=false) String token,
@PathVariable long supplierId, @RequestParam(defaultValue="true") boolean requireActive) {
requireToken(token);
service.internalSnapshot(supplierId, requireActive, "TRUCKING");
var supplier = service.detail(supplierId);
return ApiResponse.success(new TruckingContact(supplierId, supplier.name(), supplier.email()));
}
private void requireToken(String token) { if (token == null || !MessageDigest.isEqual(expected, token.getBytes(StandardCharsets.UTF_8))) throw new BizException(ResultCode.FORBIDDEN, "内部服务凭证无效"); } private void requireToken(String token) { if (token == null || !MessageDigest.isEqual(expected, token.getBytes(StandardCharsets.UTF_8))) throw new BizException(ResultCode.FORBIDDEN, "内部服务凭证无效"); }
} }