Merge remote-tracking branch 'origin/test' into dev
This commit is contained in:
@@ -30,6 +30,16 @@ spring:
|
||||
size: ${FIRSTLEG_SCHEDULING_POOL_SIZE:5}
|
||||
thread-name-prefix: firstleg-scheduler-
|
||||
baiyue:
|
||||
terminal-drayage:
|
||||
mail:
|
||||
enabled: ${TERMINAL_DRAYAGE_MAIL_ENABLED:false}
|
||||
host: ${TERMINAL_DRAYAGE_MAIL_HOST:}
|
||||
port: ${TERMINAL_DRAYAGE_MAIL_PORT:587}
|
||||
username: ${TERMINAL_DRAYAGE_MAIL_USERNAME:}
|
||||
password: ${TERMINAL_DRAYAGE_MAIL_PASSWORD:}
|
||||
from: ${TERMINAL_DRAYAGE_MAIL_FROM:}
|
||||
ssl: ${TERMINAL_DRAYAGE_MAIL_SSL:false}
|
||||
scan-delay: ${TERMINAL_DRAYAGE_MAIL_SCAN_DELAY:10000}
|
||||
carrier-schedule:
|
||||
providers:
|
||||
matson-automated: ${MATSON_TRACKING_ENABLED:false}
|
||||
|
||||
@@ -23,10 +23,33 @@ CREATE TABLE IF NOT EXISTS fl_terminal_drayage (
|
||||
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) AND
|
||||
(actual_empty_return_at IS NULL OR actual_pickup_at IS NOT NULL) AND
|
||||
(actual_empty_return_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
|
||||
(actual_empty_return_at IS NULL OR actual_pickup_at IS NULL OR actual_empty_return_at >= actual_pickup_at))
|
||||
) ENGINE=InnoDB COMMENT='目的港货柜级码头拖车与还空事实';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS fl_terminal_drayage_mail (
|
||||
id BIGINT UNSIGNED NOT NULL COMMENT '邮件任务ID',
|
||||
container_booking_id BIGINT UNSIGNED NOT NULL COMMENT '归属物理货柜ID',
|
||||
fleet_supplier_id BIGINT UNSIGNED NOT NULL COMMENT '车队供应商ID快照',
|
||||
fleet_name VARCHAR(128) NOT NULL COMMENT '车队名称快照',
|
||||
recipient VARCHAR(254) NOT NULL COMMENT '收件人邮箱',
|
||||
kind VARCHAR(32) NOT NULL COMMENT '邮件类型:REQUEST_PICKUP提柜请求、CANCEL_PICKUP取消提柜',
|
||||
subject VARCHAR(255) NOT NULL COMMENT '邮件主题',
|
||||
body TEXT NOT NULL COMMENT '邮件正文',
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'PENDING' COMMENT '投递状态:PENDING待发送、SENDING发送中、SENT已发送、FAILED失败',
|
||||
attempts INT NOT NULL DEFAULT 0 COMMENT '发送尝试次数',
|
||||
failure_reason VARCHAR(500) NULL COMMENT '发送失败原因',
|
||||
created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人ID',
|
||||
updated_by BIGINT UNSIGNED NOT NULL COMMENT '最后更新人ID',
|
||||
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
|
||||
sent_at DATETIME(3) NULL COMMENT '发送成功时间',
|
||||
PRIMARY KEY(id),
|
||||
KEY idx_terminal_mail_dispatch(status,id),
|
||||
KEY idx_terminal_mail_container(container_booking_id,id,status),
|
||||
CONSTRAINT fk_terminal_mail_container FOREIGN KEY(container_booking_id) REFERENCES fl_container_booking(id),
|
||||
CONSTRAINT chk_terminal_mail_kind CHECK(kind IN ('REQUEST_PICKUP','CANCEL_PICKUP')),
|
||||
CONSTRAINT chk_terminal_mail_status CHECK(status IN ('PENDING','SENDING','SENT','FAILED'))
|
||||
) ENGINE=InnoDB COMMENT='码头车队邮件任务与投递记录';
|
||||
CREATE TABLE IF NOT EXISTS fl_terminal_drayage_history (
|
||||
id BIGINT UNSIGNED NOT NULL COMMENT '历史ID',
|
||||
drayage_id BIGINT UNSIGNED NOT NULL COMMENT '码头拖车聚合ID',
|
||||
|
||||
@@ -2033,7 +2033,7 @@ components:
|
||||
allowedActions:
|
||||
type: array
|
||||
description: 已同时按真实业务状态与当前用户权限裁剪
|
||||
items: {type: string, enum: [EDIT_CONTAINER, MANAGE_CUSTOMS, CONFIRM_OUTBOUND, MANAGE_DESTINATION_DOCUMENTS, SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN]}
|
||||
items: {type: string, enum: [EDIT_CONTAINER, MANAGE_CUSTOMS, CONFIRM_OUTBOUND, MANAGE_DESTINATION_DOCUMENTS, SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}
|
||||
actualFacts: {$ref: '#/components/schemas/ContainerActualFacts'}
|
||||
terminalDrayage: {$ref: '#/components/schemas/ContainerTerminalDrayage'}
|
||||
ContainerWorkbenchStatusSummary:
|
||||
@@ -2080,7 +2080,7 @@ components:
|
||||
actualEmptyReturnAt: {type: string, format: date-time, nullable: true}
|
||||
unloadingCompletedAt: {type: string, format: date-time, nullable: true}
|
||||
emptyReturnWarning: {type: object, nullable: true}
|
||||
allowedActions: {type: array, items: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN]}}
|
||||
allowedActions: {type: array, items: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}}
|
||||
ContainerBooking:
|
||||
type: object
|
||||
required: [id, bookingNo, cabinetNo, sourceType, recordStatus, warehouseId, warehouseName, containerType, capacityCbm, maxWeightKg, planStatus, exceptionActive, destinationClearanceDocumentStatus, customsDeclarationDocumentStatus, deliveryOrderDocumentStatus, version]
|
||||
|
||||
@@ -88,16 +88,16 @@ paths:
|
||||
'200': {description: Original file bytes, content: {application/octet-stream: {schema: {type: string, format: binary}}}}
|
||||
/api/platform/v1/ocean-bookings/{oceanBookingId}/prints/shipping-instruction:
|
||||
get:
|
||||
summary: Render the released booking as an export shipping instruction PDF
|
||||
description: Firstleg maps the authoritative released aggregate to SEA_FREIGHT_SHIPPING_INSTRUCTION_A4_V1 and synchronously proxies the generated PDF.
|
||||
summary: Render the current saved booking as an export shipping instruction PDF
|
||||
description: Firstleg maps the authoritative saved aggregate (DRAFT or RELEASED, with missing fields displayed as —) to SEA_FREIGHT_SHIPPING_INSTRUCTION_A4_V1 and synchronously proxies the generated PDF.
|
||||
x-permission: platform:firstleg:ocean-booking:list
|
||||
parameters: [{$ref: '#/components/parameters/OceanBookingId'}]
|
||||
responses:
|
||||
'200': {description: PDF or a business-error JSON envelope, content: {application/pdf: {schema: {type: string, format: binary}}, application/json: {schema: {type: object}}}}
|
||||
/api/platform/v1/ocean-bookings/{oceanBookingId}/prints/bill-of-lading-confirmation:
|
||||
get:
|
||||
summary: Render the released booking as a bill-of-lading confirmation PDF
|
||||
description: Firstleg maps the authoritative released aggregate to BILL_OF_LADING_CONFIRMATION_A4_V1 and synchronously proxies the generated PDF.
|
||||
summary: Render the current saved booking as a bill-of-lading confirmation PDF
|
||||
description: Firstleg maps the authoritative saved aggregate (DRAFT or RELEASED, with missing fields displayed as —) to BILL_OF_LADING_CONFIRMATION_A4_V1 and synchronously proxies the generated PDF.
|
||||
x-permission: platform:firstleg:ocean-booking:list
|
||||
parameters: [{$ref: '#/components/parameters/OceanBookingId'}]
|
||||
responses:
|
||||
|
||||
@@ -52,11 +52,63 @@ paths:
|
||||
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ActualTimeRequest'}}}}
|
||||
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
||||
/api/platform/v1/terminal-drayages/{containerBookingId}/pickup-email:
|
||||
post:
|
||||
summary: 将当前车队提柜邮件加入发送队列
|
||||
description: 初次选择车队不发信;此命令携带版本和幂等键,发送成功是任务已入队,不表示已送达。首次更换车队自动原子入队取消和新提柜两封邮件。同一车队重复选择不发信。
|
||||
x-permission: platform:firstleg:terminal-drayage:fleet:edit
|
||||
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}, {$ref: '#/components/parameters/IdempotencyKey'}]
|
||||
requestBody: {required: true, content: {application/json: {schema: {type: object, required: [expectedVersion], properties: {expectedVersion: {type: integer, minimum: 0}}}}}}
|
||||
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
|
||||
/api/platform/v1/terminal-drayages/{containerBookingId}/emails:
|
||||
get:
|
||||
summary: 查询最近100封车队邮件及发信开关
|
||||
x-permission: platform:firstleg:terminal-drayage:list
|
||||
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
|
||||
responses:
|
||||
'200':
|
||||
description: 邮件记录;SENT表示SMTP已接受,不表示收件人已阅读
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
code: {type: string}
|
||||
data:
|
||||
type: object
|
||||
properties:
|
||||
deliveryEnabled: {type: boolean}
|
||||
records: {type: array, items: {$ref: '#/components/schemas/EmailTask'}}
|
||||
/api/platform/v1/terminal-drayages/{containerBookingId}/emails/{mailId}/retry:
|
||||
post:
|
||||
summary: 核对失败邮件未收到后手动重试
|
||||
description: 仅FAILED状态可重试,服务端校验mailId归属本柜;失败可能已经送达,须人工核对。同柜邮件依次发送,失败阻断后续邮件。
|
||||
x-permission: platform:firstleg:terminal-drayage:fleet:edit
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/ContainerBookingId'}
|
||||
- {name: mailId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
responses: {'200': {description: 已重新入队}}
|
||||
components:
|
||||
parameters:
|
||||
ContainerBookingId: {name: containerBookingId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
|
||||
IdempotencyKey: {name: Idempotency-Key, in: header, required: true, schema: {type: string, minLength: 1, maxLength: 255}}
|
||||
schemas:
|
||||
EmailTask:
|
||||
type: object
|
||||
properties:
|
||||
id: {type: string}
|
||||
containerBookingId: {type: string}
|
||||
fleetSupplierId: {type: string}
|
||||
fleetName: {type: string}
|
||||
recipient: {type: string, format: email}
|
||||
kind: {type: string, enum: [REQUEST_PICKUP, CANCEL_PICKUP]}
|
||||
subject: {type: string}
|
||||
body: {type: string}
|
||||
status: {type: string, enum: [PENDING, SENDING, SENT, FAILED]}
|
||||
attempts: {type: integer}
|
||||
failureReason: {type: string, nullable: true}
|
||||
createdAt: {type: string, format: date-time}
|
||||
sentAt: {type: string, format: date-time, nullable: true}
|
||||
FleetSelectionRequest:
|
||||
type: object
|
||||
required: [expectedVersion, fleetSupplierId]
|
||||
@@ -104,7 +156,7 @@ components:
|
||||
actualEmptyReturnAt: {type: string, format: date-time, nullable: true}
|
||||
unloadingCompletedAt: {type: string, format: date-time, nullable: true}
|
||||
emptyReturnWarning: {$ref: '#/components/schemas/Warning'}
|
||||
allowedActions: {type: array, items: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN]}}
|
||||
allowedActions: {type: array, items: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}}
|
||||
actualFacts: {$ref: '#/components/schemas/ContainerActualFacts'}
|
||||
updatedAt: {type: string, format: date-time, nullable: true}
|
||||
ContainerActualFacts:
|
||||
@@ -127,7 +179,7 @@ components:
|
||||
type: object
|
||||
required: [action, fromStatus, toStatus, fromVersion, toVersion, operatorId, createdAt]
|
||||
properties:
|
||||
action: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN]}
|
||||
action: {type: string, enum: [SELECT_FLEET, SCHEDULE_PICKUP, RECORD_PICKUP, RECORD_EMPTY_RETURN, SEND_PICKUP_EMAIL]}
|
||||
fromStatus: {type: string}
|
||||
toStatus: {type: string}
|
||||
fromVersion: {type: integer, minimum: 0}
|
||||
|
||||
Reference in New Issue
Block a user