Merge test fixes into dev dropship flow

This commit is contained in:
2026-09-10 18:18:41 +08:00
131 changed files with 3062 additions and 651 deletions
@@ -34,7 +34,7 @@ paths:
summary: Query carrier schedule tasks
x-permission: platform:firstleg:port-schedule-query:list
parameters:
- {name: customerId, in: query, schema: {type: integer, format: int64, minimum: 1}}
- {name: customerId, in: query, schema: {type: integer, format: int64, minimum: 0}}
- {name: oceanBookingId, in: query, schema: {type: integer, format: int64, minimum: 1}}
- {name: containerBookingId, in: query, schema: {type: integer, format: int64, minimum: 1}}
- {name: carrierCode, in: query, schema: {$ref: '#/components/schemas/TaskCarrierCode'}}
@@ -126,7 +126,7 @@ components:
required: [expectedVersion, customerId, oceanBookingId, containerBookingId, carrierCode, trackingType, trackingNo]
properties:
expectedVersion: {type: integer, minimum: 0, maximum: 0}
customerId: {type: integer, format: int64, minimum: 1}
customerId: {type: integer, format: int64, minimum: 0}
oceanBookingId: {type: integer, format: int64, minimum: 1}
containerBookingId: {type: integer, format: int64, minimum: 1}
carrierCode: {$ref: '#/components/schemas/CarrierCode'}
@@ -123,13 +123,13 @@ components:
schemas:
LongId: {type: string, pattern: '^[1-9][0-9]*$', description: Long ID序列化为字符串}
ApiEnvelope: {type: object, required: [code, message, timestamp], properties: {code: {type: string}, message: {type: string}, requestId: {type: string, nullable: true}, traceId: {type: string, nullable: true}, timestamp: {type: string, format: date-time}}}
ContainerEnvelope: {allOf: [{$ref: '#/components/schemas/ApiEnvelope'}, {type: object, properties: {data: {$ref: '#/components/schemas/ContainerView'}}}]}
ContainerEnvelope: {allOf: [{$ref: '#/components/schemas/ApiEnvelope'}, {type: object, properties: {data: {allOf: [{$ref: '#/components/schemas/ContainerView'}], nullable: true, description: 装柜计划尚未完成时返回null,表示报关流程尚未生成}}}]}
DocumentEnvelope: {allOf: [{$ref: '#/components/schemas/ApiEnvelope'}, {type: object, properties: {data: {$ref: '#/components/schemas/DocumentView'}}}]}
ActionRequest: {type: object, required: [expectedVersion, confirm], additionalProperties: false, properties: {expectedVersion: {type: integer, minimum: 0}, confirm: {type: boolean}, remark: {type: string, maxLength: 500, nullable: true}}}
ScopeRequest: {type: object, required: [inboundIds, expectedVersion], additionalProperties: false, properties: {inboundIds: {type: array, minItems: 1, maxItems: 200, items: {$ref: '#/components/schemas/LongId'}}, expectedVersion: {type: integer, minimum: 1}}}
FileView: {type: object, required: [fileId, fileName, fileHash, sizeBytes, version, uploadedAt], properties: {fileId: {$ref: '#/components/schemas/LongId'}, fileName: {type: string}, fileHash: {type: string}, contentType: {type: string, nullable: true}, sizeBytes: {type: integer, format: int64}, version: {type: integer}, uploadedAt: {type: string, format: date-time}}}
InboundView: {type: object, required: [inboundId, orderId, orderNo, inboundCode, tenantId, customerName, taxMode, covered], properties: {inboundId: {$ref: '#/components/schemas/LongId'}, orderId: {$ref: '#/components/schemas/LongId'}, orderNo: {type: string}, inboundCode: {type: string}, tenantId: {$ref: '#/components/schemas/LongId'}, customerName: {type: string}, taxMode: {type: string, enum: [TAX_REFUND, BUY_DECLARATION]}, covered: {type: boolean}}}
DocumentView: {type: object, required: [documentId, tenantId, source, inboundIds, inboundCodes, frozen], properties: {documentId: {$ref: '#/components/schemas/LongId'}, tenantId: {$ref: '#/components/schemas/LongId'}, source: {$ref: '#/components/schemas/FileView'}, inboundIds: {type: array, items: {$ref: '#/components/schemas/LongId'}}, inboundCodes: {type: array, items: {type: string}}, frozen: {type: boolean}, completion: {allOf: [{$ref: '#/components/schemas/FileView'}], nullable: true}}}
ContainerView: {type: object, required: [aggregateId, loadingPlanId, containerBookingId, status, version, taxRefundCount, coveredTaxRefundCount, inbounds, documents], properties: {aggregateId: {$ref: '#/components/schemas/LongId'}, loadingPlanId: {$ref: '#/components/schemas/LongId'}, containerBookingId: {$ref: '#/components/schemas/LongId'}, planNo: {type: string}, cabinetNo: {type: string}, containerNo: {type: string, nullable: true}, status: {type: string, enum: [WAITING_CUSTOMER_DOCUMENTS, READY_TO_START, DECLARING, COMPLETED]}, merchantStatus: {type: string, enum: [WAITING_UPLOAD, DOCUMENT_UPLOADED, DECLARING, CUSTOMS_COMPLETED], nullable: true}, version: {type: integer}, taxRefundCount: {type: integer}, coveredTaxRefundCount: {type: integer}, inbounds: {type: array, items: {$ref: '#/components/schemas/InboundView'}}, documents: {type: array, items: {$ref: '#/components/schemas/DocumentView'}}, startedAt: {type: string, format: date-time, nullable: true}, completedAt: {type: string, format: date-time, nullable: true}}}
ContainerView: {type: object, required: [aggregateId, loadingPlanId, containerBookingId, status, hasActualCargo, version, taxRefundCount, coveredTaxRefundCount, inbounds, documents], properties: {aggregateId: {$ref: '#/components/schemas/LongId'}, loadingPlanId: {$ref: '#/components/schemas/LongId'}, containerBookingId: {$ref: '#/components/schemas/LongId'}, planNo: {type: string}, cabinetNo: {type: string}, containerNo: {type: string, nullable: true}, status: {type: string, enum: [WAITING_CUSTOMER_DOCUMENTS, READY_TO_START, DECLARING, COMPLETED]}, hasActualCargo: {type: boolean, description: 当前完成装柜计划是否仍有实际装柜货物;false时查询成功返回空明细且无需发起报关}, merchantStatus: {type: string, enum: [WAITING_UPLOAD, DOCUMENT_UPLOADED, DECLARING, CUSTOMS_COMPLETED], nullable: true}, version: {type: integer}, taxRefundCount: {type: integer}, coveredTaxRefundCount: {type: integer}, inbounds: {type: array, items: {$ref: '#/components/schemas/InboundView'}}, documents: {type: array, items: {$ref: '#/components/schemas/DocumentView'}}, startedAt: {type: string, format: date-time, nullable: true}, completedAt: {type: string, format: date-time, nullable: true}}}
ExportBatchRequest: {type: object, required: [taskId, tenantId, appCode, requestedBy, dispatchVersion, parameters, limit], properties: {taskId: {type: string}, tenantId: {type: string, enum: ['0']}, appCode: {type: string, enum: [PLATFORM]}, requestedBy: {type: string}, dispatchVersion: {type: integer}, parameters: {type: object, required: [loadingPlanId], additionalProperties: false, properties: {loadingPlanId: {type: string}}}, cursor: {type: string, nullable: true}, snapshotToken: {type: string, nullable: true}, limit: {type: integer, minimum: 1, maximum: 500}}}
ExportBatchEnvelope: {allOf: [{$ref: '#/components/schemas/ApiEnvelope'}, {type: object, properties: {data: {type: object, properties: {schemaVersion: {type: integer}, schemaHash: {type: string}, snapshotToken: {type: string}, columns: {type: array, items: {type: object}}, rows: {type: array, items: {type: object}}, nextCursor: {type: string}, hasMore: {type: boolean}, totalRows: {type: integer, format: int64, nullable: true}}}}}]}
@@ -923,6 +923,39 @@ paths:
requestId: {type: string, nullable: true}
traceId: {type: string, nullable: true}
'403': {description: 无查看权限}
/api/platform/inbounds/carton-label-pdf:
post:
summary: 批量生成入仓箱唛 PDF
description: 需要 platform:firstleg:inbound:view 权限;可跨客户选择1至200个入库单,聚合生成一个 PDF,首次调用冻结各入库单整单箱号。
requestBody:
required: true
content:
application/json:
schema:
type: array
minItems: 1
maxItems: 200
items:
type: object
required: [tenantId, inboundId]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
inboundId: {type: string, pattern: '^[1-9][0-9]*$'}
responses:
'200':
description: 成功返回聚合 PDF;业务失败返回统一 JSON 响应,调用方必须按 Content-Type 区分。
content:
application/pdf: {schema: {type: string, format: binary}}
application/json:
schema:
type: object
required: [code, message]
properties:
code: {type: string}
message: {type: string}
requestId: {type: string, nullable: true}
traceId: {type: string, nullable: true}
'403': {description: 无查看权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement:
get:
summary: 查询入库测量详情
@@ -964,6 +997,43 @@ paths:
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/calculation-strategy:
put:
summary: 更新箱规计算规则
description: >-
独立更新当前测量批次全部明细的箱规计算规则并重算体积,不覆盖整批测量数据,
不改变测量提交或审核状态。客户未确认或该票尚未装柜完成时均可修改;
仅当客户已确认费用且该票已装柜完成时冻结。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementCalculationStrategyRequest'}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/items/{itemId}/outer-dimensions:
put:
summary: 更新仓库外箱长宽高
description: >-
独立更新当前测量批次指定明细的仓库外箱尺寸并重算体积,不覆盖整批测量数据,
不改变测量提交或审核状态。客户未确认或该票尚未装柜完成时均可修改;
仅当客户已确认费用且该票已装柜完成时冻结。
parameters:
- {name: tenantId, in: query, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: inboundId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
- {name: itemId, in: path, required: true, schema: {type: string, pattern: '^[1-9][0-9]*$'}}
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/InboundMeasurementOuterDimensionsRequest'}
responses:
'200': {description: 成功或业务失败,按响应体 code 判断}
'403': {description: 无测量编辑权限}
/api/platform/v1/first-leg/inbounds/{inboundId}/measurement/carton-scans:
post:
summary: 平台模拟单箱设备扫描
@@ -1681,16 +1751,18 @@ components:
updatedAt: {type: string, format: date-time, nullable: true}
CustomerDimensionConfigInitializeRequest:
type: object
required: [tenantId, operatorId, initializationKey]
required: [tenantId, operatorId, initializationKey, customerName]
properties:
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
operatorId: {type: string, pattern: '^[0-9]+$'}
initializationKey: {type: string, minLength: 1, maxLength: 128}
customerName: {type: string, minLength: 1, maxLength: 128}
CustomerDimensionConfigInitializeResponse:
type: object
required: [configId, createdByThisInitialization]
required: [configId, chargeRuleId, createdByThisInitialization]
properties:
configId: {type: string, pattern: '^[1-9][0-9]*$'}
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$'}
createdByThisInitialization: {type: boolean}
WeightPalletSnapshot:
type: object
@@ -1933,6 +2005,25 @@ components:
minItems: 1
maxItems: 500
items: {$ref: '#/components/schemas/InboundMeasurementItemRequest'}
InboundMeasurementCalculationStrategyRequest:
type: object
required: [measurementId, version, coefficientMode]
additionalProperties: false
properties:
measurementId: {type: string, pattern: '^[1-9][0-9]*$'}
version: {type: integer, minimum: 0}
coefficientMode: {type: string, enum: [ACTUAL, ADD, MULTIPLY]}
chargeRuleId: {type: string, pattern: '^[1-9][0-9]*$', nullable: true, description: MULTIPLY 模式必填}
InboundMeasurementOuterDimensionsRequest:
type: object
required: [measurementId, version]
additionalProperties: false
properties:
measurementId: {type: string, pattern: '^[1-9][0-9]*$'}
version: {type: integer, minimum: 0}
outerLengthCm: {type: number, minimum: 0.001, nullable: true}
outerWidthCm: {type: number, minimum: 0.001, nullable: true}
outerHeightCm: {type: number, minimum: 0.001, nullable: true}
InboundMeasurementItemRequest:
type: object
required: [inboundDetailId, itemNo, boxSpecification, packageCount, lengthCm, widthCm, heightCm]
@@ -27,7 +27,7 @@ paths:
/api/platform/v1/containers/{id}/pda/photos/{fileId}/download:
get:
operationId: downloadContainerPdaPhoto
description: '权限:platform:firstleg:container:list;Firstleg按柜次、装柜计划、入库单和文件归属代理下载,不暴露内部服务令牌'
description: '权限:platform:firstleg:container:list;PDA完成及国内离仓后仍可读取ACTIVE历史照片;Firstleg按柜次、装柜计划、入库单和文件归属代理下载,不暴露内部服务令牌'
parameters: [{$ref: '#/components/parameters/ContainerId'}, {name: fileId, in: path, required: true, schema: {type: integer, format: int64}}]
responses: {'200': {description: photo bytes, content: {application/octet-stream: {schema: {type: string, format: binary}}}}, '404': {description: photo missing or not owned by the container}}
/api/platform/v1/containers/{id}/documents/{documentType}:
@@ -14,6 +14,7 @@ paths:
/api/platform/v1/terminal-drayages/{containerBookingId}:
get:
summary: 查询单柜码头拖车详情
description: 已确认国内离仓的货柜即使船节点跟踪任务尚未建立也返回WAITING_FOR_ARRIVAL空详情;实际操作仍按到港、清关和卸柜节点校验
x-permission: platform:firstleg:terminal-drayage:list
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
responses: {'200': {$ref: '#/components/responses/ViewResponse'}}
@@ -63,6 +64,7 @@ paths:
/api/platform/v1/terminal-drayages/{containerBookingId}/emails:
get:
summary: 查询最近100封车队邮件及发信开关
description: 已确认国内离仓的货柜允许读取空邮件列表,不以船节点跟踪任务是否已经建立作为货柜存在性条件
x-permission: platform:firstleg:terminal-drayage:list
parameters: [{$ref: '#/components/parameters/ContainerBookingId'}]
responses: