diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index ec6953f55..9f0c87d39 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -104,6 +104,13 @@ services: CARRIER_SCHEDULE_BATCH_SIZE: ${CARRIER_SCHEDULE_BATCH_SIZE:-20} CARRIER_SCHEDULE_MAX_TASKS_PER_TRIGGER: ${CARRIER_SCHEDULE_MAX_TASKS_PER_TRIGGER:-2000} CARRIER_SCHEDULE_LEASE_DURATION: ${CARRIER_SCHEDULE_LEASE_DURATION:-PT5M} + TERMINAL_DRAYAGE_MAIL_ENABLED: ${TERMINAL_DRAYAGE_MAIL_ENABLED:-false} + TERMINAL_DRAYAGE_MAIL_HOST: ${TERMINAL_DRAYAGE_MAIL_HOST:-} + TERMINAL_DRAYAGE_MAIL_PORT: ${TERMINAL_DRAYAGE_MAIL_PORT:-587} + TERMINAL_DRAYAGE_MAIL_USERNAME: ${TERMINAL_DRAYAGE_MAIL_USERNAME:-} + TERMINAL_DRAYAGE_MAIL_PASSWORD: ${TERMINAL_DRAYAGE_MAIL_PASSWORD:-} + TERMINAL_DRAYAGE_MAIL_SSL: ${TERMINAL_DRAYAGE_MAIL_SSL:-false} + TERMINAL_DRAYAGE_MAIL_SCAN_DELAY: ${TERMINAL_DRAYAGE_MAIL_SCAN_DELAY:-10000} finance: <<: *common diff --git a/deploy/scripts/deploy-built-service.sh b/deploy/scripts/deploy-built-service.sh index d4ad1ad7d..a351a7a9a 100644 --- a/deploy/scripts/deploy-built-service.sh +++ b/deploy/scripts/deploy-built-service.sh @@ -130,6 +130,14 @@ if [ "$SERVICE" = "firstleg" ]; then echo "部署 firstleg 时,环境文件必须包含非空 LASTLEG_EVENT_BRIDGE_URL" >&2 exit 2 fi + if [ "$(env_file_value TERMINAL_DRAYAGE_MAIL_ENABLED)" = "true" ]; then + for key in TERMINAL_DRAYAGE_MAIL_HOST TERMINAL_DRAYAGE_MAIL_PORT TERMINAL_DRAYAGE_MAIL_USERNAME TERMINAL_DRAYAGE_MAIL_PASSWORD; do + if ! env_file_has_key "$key" || [ -z "$(env_file_value "$key")" ]; then + echo "启用码头车队邮件时,环境文件必须包含非空 $key" >&2 + exit 2 + fi + done + fi fi if [ "$SERVICE" = "lastleg-service" ]; then diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index c4fc1a9a8..48e19d649 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -18269,7 +18269,7 @@ CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history ( KEY idx_terminal_drayage_history(container_booking_id,created_at,id), CONSTRAINT fk_terminal_drayage_history FOREIGN KEY(drayage_id) REFERENCES fl_terminal_drayage(id), CONSTRAINT chk_terminal_drayage_history_action CHECK(action IN - ('SELECT_FLEET','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN')) + ('SELECT_FLEET','SEND_PICKUP_EMAIL','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN')) ) ENGINE=InnoDB COMMENT='目的港码头拖车不可变操作历史'; CREATE TABLE IF NOT EXISTS fl_terminal_drayage_operation ( id BIGINT UNSIGNED NOT NULL COMMENT '幂等操作ID', container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '货柜ID', @@ -18304,6 +18304,9 @@ ALTER TABLE fl_terminal_drayage MODIFY COLUMN updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间'; ALTER TABLE fl_terminal_drayage_history + DROP CHECK chk_terminal_drayage_history_action, + ADD CONSTRAINT chk_terminal_drayage_history_action CHECK(action IN + ('SELECT_FLEET','SEND_PICKUP_EMAIL','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN')), MODIFY COLUMN id BIGINT UNSIGNED NOT NULL COMMENT '历史ID', MODIFY COLUMN drayage_id BIGINT UNSIGNED NOT NULL COMMENT '码头拖车聚合ID', MODIFY COLUMN container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '货柜ID快照', diff --git a/firstleg/src/main/resources/db/phase3-terminal-drayage-schema.sql b/firstleg/src/main/resources/db/phase3-terminal-drayage-schema.sql index 4edf7ade9..eaf6d8cdc 100644 --- a/firstleg/src/main/resources/db/phase3-terminal-drayage-schema.sql +++ b/firstleg/src/main/resources/db/phase3-terminal-drayage-schema.sql @@ -67,7 +67,7 @@ CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history ( KEY idx_terminal_drayage_history(container_booking_id,created_at,id), CONSTRAINT fk_terminal_drayage_history FOREIGN KEY(drayage_id) REFERENCES fl_terminal_drayage(id), CONSTRAINT chk_terminal_drayage_history_action CHECK(action IN - ('SELECT_FLEET','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN')) + ('SELECT_FLEET','SEND_PICKUP_EMAIL','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN')) ) ENGINE=InnoDB COMMENT='目的港码头拖车不可变操作历史'; CREATE TABLE IF NOT EXISTS fl_terminal_drayage_operation ( diff --git a/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/mapper/TerminalDrayageSqlContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/mapper/TerminalDrayageSqlContractTest.java index e98489c6d..7eecedd62 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/mapper/TerminalDrayageSqlContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/mapper/TerminalDrayageSqlContractTest.java @@ -23,7 +23,10 @@ class TerminalDrayageSqlContractTest { if (name.equals("pendingMails")) assertThat(sql).contains("earlier.container_booking_id=m.container_booking_id", "earlier.id'SENT'"); } for (Path path : java.util.List.of(Path.of("src/main/resources/db/phase3-terminal-drayage-schema.sql"), Path.of("../deploy/sql/头程数据库统一增量-MySQL8.sql"))) { - assertThat(Files.readString(path)).contains("CREATE TABLE IF NOT EXISTS fl_terminal_drayage_mail (", "CHECK(status IN ('PENDING','SENDING','SENT','FAILED'))"); + assertThat(Files.readString(path)).contains( + "CREATE TABLE IF NOT EXISTS fl_terminal_drayage_mail (", + "CHECK(status IN ('PENDING','SENDING','SENT','FAILED'))", + "('SELECT_FLEET','SEND_PICKUP_EMAIL','SCHEDULE_PICKUP','RECORD_PICKUP','RECORD_EMPTY_RETURN')"); } } @@ -38,7 +41,9 @@ class TerminalDrayageSqlContractTest { } 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("); + "ADD CONSTRAINT chk_terminal_drayage_times CHECK(", + "DROP CHECK chk_terminal_drayage_history_action", + "ADD CONSTRAINT chk_terminal_drayage_history_action CHECK(action IN"); } @Test diff --git a/scripts/test-environment-pipeline-contract.test.mjs b/scripts/test-environment-pipeline-contract.test.mjs index 560845a5c..584e27f08 100644 --- a/scripts/test-environment-pipeline-contract.test.mjs +++ b/scripts/test-environment-pipeline-contract.test.mjs @@ -130,6 +130,26 @@ test('development publishes every service on loopback without changing test defa assert.doesNotMatch(directDeployScript, /gateway\|gateway-overseas\) (?:export )?PUBLISHED_BIND_ADDRESS=0\.0\.0\.0/) }) +test('Firstleg deployment passes terminal drayage SMTP settings into the container', () => { + const firstlegService = serviceCompose.slice( + serviceCompose.indexOf(' firstleg:\n'), + serviceCompose.indexOf(' finance:\n') + ) + for (const key of [ + 'TERMINAL_DRAYAGE_MAIL_ENABLED', + 'TERMINAL_DRAYAGE_MAIL_HOST', + 'TERMINAL_DRAYAGE_MAIL_PORT', + 'TERMINAL_DRAYAGE_MAIL_USERNAME', + 'TERMINAL_DRAYAGE_MAIL_PASSWORD', + 'TERMINAL_DRAYAGE_MAIL_SSL', + 'TERMINAL_DRAYAGE_MAIL_SCAN_DELAY' + ]) { + assert.match(firstlegService, new RegExp(`^ ${key}: ` + '\\$\\{' + key, 'm')) + } + assert.match(directDeployScript, /TERMINAL_DRAYAGE_MAIL_ENABLED/) + assert.match(directDeployScript, /TERMINAL_DRAYAGE_MAIL_HOST TERMINAL_DRAYAGE_MAIL_PORT TERMINAL_DRAYAGE_MAIL_USERNAME TERMINAL_DRAYAGE_MAIL_PASSWORD/) +}) + test('parallel image publications isolate registry credentials per Jenkins job', () => { const imageStage = pipeline.slice( pipeline.indexOf("stage('构建并发布单服务镜像')"),