feat: complete overseas pda warehouse operations

This commit is contained in:
2026-08-25 11:20:36 +08:00
parent 45a3b9adfd
commit 042d0b738a
69 changed files with 4679 additions and 4 deletions
@@ -744,6 +744,72 @@ CREATE TABLE IF NOT EXISTS ll_pda_operation_history (
KEY idx_ll_pda_history_business(overseas_warehouse_id,operation_type,business_key)
) ENGINE=InnoDB COMMENT='海外PDA真实作业历史';
CREATE TABLE IF NOT EXISTS ll_pda_pallet_operation (
id BIGINT NOT NULL COMMENT 'PDA托盘作业ID', overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID',
operator_key VARCHAR(128) NOT NULL COMMENT 'PDA操作账号标识', idempotency_key VARCHAR(128) NOT NULL COMMENT '设备幂等键',
operation_type VARCHAR(64) NOT NULL COMMENT '托盘作业类型', request_hash VARCHAR(128) NOT NULL COMMENT '请求内容摘要',
status VARCHAR(32) NOT NULL COMMENT '处理状态:PROCESSING、COMPLETED、FAILED_COMPENSATED、COMPENSATION_REQUIRED',
result_json LONGTEXT NULL COMMENT '成功响应快照', remote_transitions_json LONGTEXT NULL COMMENT '实物托盘状态变更回执',
last_error VARCHAR(2000) NULL COMMENT '最后失败原因', 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 '更新时间',
PRIMARY KEY(id), UNIQUE KEY uk_ll_pda_pallet_idempotency(operator_key,idempotency_key),
KEY idx_ll_pda_pallet_warehouse(overseas_warehouse_id,status,updated_at)
) ENGINE=InnoDB COMMENT='海外PDA托盘作业幂等、补偿与结果记录';
CREATE TABLE IF NOT EXISTS ll_pda_stocktake_task (
id BIGINT NOT NULL COMMENT '盘点任务ID', task_no VARCHAR(64) NOT NULL COMMENT '盘点任务号',
overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID', scope_type VARCHAR(16) NOT NULL COMMENT '盘点范围类型LOCATION或PALLET',
scope_resource_id BIGINT NOT NULL COMMENT '盘点库位或托盘资源ID', scope_code VARCHAR(128) NOT NULL COMMENT '盘点库位码或托盘码快照',
status VARCHAR(32) NOT NULL COMMENT '盘点任务状态', position_count INT NOT NULL COMMENT '库存位置总数',
counted_count INT NOT NULL DEFAULT 0 COMMENT '已盘库存位置数', difference_count INT NOT NULL DEFAULT 0 COMMENT '存在差异的库存位置数',
created_by VARCHAR(128) NOT NULL COMMENT '创建操作账号标识', submitted_by VARCHAR(128) NULL COMMENT '提交操作账号标识',
submit_reason VARCHAR(500) NULL COMMENT '盘点差异提交原因', idempotency_key VARCHAR(128) NOT NULL COMMENT '创建幂等键',
request_hash VARCHAR(128) NOT NULL COMMENT '创建请求哈希', version BIGINT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间',
submitted_at DATETIME(3) NULL COMMENT '提交完成时间', PRIMARY KEY(id), UNIQUE KEY uk_ll_pda_stocktake_no(task_no),
UNIQUE KEY uk_ll_pda_stocktake_create(overseas_warehouse_id,created_by,idempotency_key),
KEY idx_ll_pda_stocktake_list(overseas_warehouse_id,status,created_at)
) ENGINE=InnoDB COMMENT='海外PDA库存盘点任务';
CREATE TABLE IF NOT EXISTS ll_pda_stocktake_item (
id BIGINT NOT NULL COMMENT '盘点明细ID', task_id BIGINT NOT NULL COMMENT '盘点任务ID', customer_id VARCHAR(128) NOT NULL COMMENT '库存所属客户标识',
balance_id BIGINT NOT NULL COMMENT '库存余额ID', position_id BIGINT NOT NULL COMMENT '库存位置ID', sku_code VARCHAR(128) NULL COMMENT 'SKU快照',
product_name VARCHAR(255) NULL COMMENT '品名快照', inbound_code VARCHAR(128) NULL COMMENT '入仓码快照', pallet_id BIGINT NOT NULL COMMENT '实物托盘ID',
pallet_code VARCHAR(128) NOT NULL COMMENT '实物托盘码快照', location_id BIGINT NOT NULL COMMENT '库位ID快照', location_code VARCHAR(128) NOT NULL COMMENT '库位码快照',
book_packages BIGINT NOT NULL COMMENT '任务创建时账面总箱数', actual_packages BIGINT NULL COMMENT '现场实盘总箱数',
difference_packages BIGINT NULL COMMENT '实盘与账面箱数差异', status VARCHAR(32) NOT NULL COMMENT '盘点明细状态',
position_version BIGINT NOT NULL COMMENT '任务创建时库存位置版本', counted_by VARCHAR(128) NULL COMMENT '盘点操作账号标识',
version BIGINT NOT NULL DEFAULT 0 COMMENT '明细乐观锁版本', counted_at DATETIME(3) NULL COMMENT '盘点时间',
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间',
PRIMARY KEY(id), UNIQUE KEY uk_ll_pda_stocktake_item(task_id,position_id), KEY idx_ll_pda_stocktake_item_task(task_id,status,id)
) ENGINE=InnoDB COMMENT='海外PDA库存盘点位置明细';
CREATE TABLE IF NOT EXISTS ll_pda_stocktake_action (
id BIGINT NOT NULL COMMENT '盘点动作ID', overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID',
operator_key VARCHAR(128) NOT NULL COMMENT 'PDA操作账号标识', idempotency_key VARCHAR(128) NOT NULL COMMENT '动作幂等键',
action_type VARCHAR(32) NOT NULL COMMENT '盘点动作类型', task_id BIGINT NULL COMMENT '盘点任务ID', request_hash VARCHAR(128) NOT NULL COMMENT '动作请求哈希',
status VARCHAR(32) NOT NULL COMMENT '动作处理状态', result_json LONGTEXT NULL COMMENT '成功响应JSON',
created_at DATETIME(3) NOT NULL COMMENT '创建时间', updated_at DATETIME(3) NOT NULL COMMENT '更新时间', PRIMARY KEY(id),
UNIQUE KEY uk_ll_pda_stocktake_action(overseas_warehouse_id,operator_key,idempotency_key), KEY idx_ll_pda_stocktake_action_task(task_id,created_at)
) ENGINE=InnoDB COMMENT='海外PDA盘点动作幂等记录';
CREATE TABLE IF NOT EXISTS ll_pda_inventory_move (
id BIGINT NOT NULL COMMENT '移库操作ID', move_no VARCHAR(64) NOT NULL COMMENT '移库操作单号',
overseas_warehouse_id BIGINT NOT NULL COMMENT 'Token冻结的海外实际仓ID', pallet_id BIGINT NOT NULL COMMENT '整托移库的实物托盘ID',
pallet_code VARCHAR(128) NOT NULL COMMENT '实物托盘码快照', source_location_id BIGINT NOT NULL COMMENT '来源库位ID',
source_location_code VARCHAR(128) NOT NULL COMMENT '来源库位码快照', target_location_id BIGINT NOT NULL COMMENT '目标库位ID',
target_location_code VARCHAR(128) NOT NULL COMMENT '目标库位码快照', customer_count INT NOT NULL COMMENT '托盘涉及客户数',
position_count INT NOT NULL COMMENT '迁移库存位置数', package_count BIGINT NOT NULL COMMENT '迁移总箱数',
pallet_version_before INT NOT NULL COMMENT '迁移前托盘版本', pallet_version_after INT NULL COMMENT '迁移后托盘版本',
operator_key VARCHAR(128) NOT NULL COMMENT 'PDA操作账号标识', reason VARCHAR(500) NOT NULL COMMENT '移库原因',
idempotency_key VARCHAR(128) NOT NULL COMMENT '移库幂等键', request_hash VARCHAR(128) NOT NULL COMMENT '移库请求哈希',
status VARCHAR(32) NOT NULL COMMENT '移库处理状态', result_json LONGTEXT NULL COMMENT '成功响应JSON',
created_at DATETIME(3) NOT NULL COMMENT '创建时间', completed_at DATETIME(3) NULL COMMENT '完成时间', PRIMARY KEY(id),
UNIQUE KEY uk_ll_pda_inventory_move_no(move_no),
UNIQUE KEY uk_ll_pda_inventory_move_key(overseas_warehouse_id,operator_key,idempotency_key),
KEY idx_ll_pda_inventory_move_pallet(overseas_warehouse_id,pallet_id,created_at)
) ENGINE=InnoDB COMMENT='海外PDA同仓整托移库记录';
CREATE TABLE IF NOT EXISTS ll_inbound_fba_appointment (
id BIGINT NOT NULL COMMENT '主键ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID',
@@ -1236,6 +1302,90 @@ CREATE TABLE IF NOT EXISTS ll_relabel_status_history (
KEY idx_ll_relabel_status_history_application (customer_id,application_id,created_at)
) ENGINE=InnoDB COMMENT='换标状态变更历史';
CREATE TABLE IF NOT EXISTS ll_relabel_pda_task (
id BIGINT NOT NULL COMMENT '换标PDA任务ID',
application_id BIGINT NOT NULL COMMENT '换标申请单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键',
relabel_no VARCHAR(64) NOT NULL COMMENT '换标申请单号快照',
overseas_warehouse_id BIGINT NOT NULL COMMENT 'PDA令牌冻结的海外实际作业仓ID',
status VARCHAR(32) NOT NULL COMMENT '任务状态:PROCESSING、WAIT_REVIEW或COMPLETED',
operator_key VARCHAR(128) NOT NULL COMMENT '认领操作账号标识',
operator_name VARCHAR(255) NOT NULL COMMENT '认领操作员名称快照',
reviewer_key VARCHAR(128) NULL COMMENT '复核账号标识',
reviewer_name VARCHAR(255) NULL COMMENT '复核员名称快照',
expected_packages INT NOT NULL COMMENT '申请单通知的应换标箱数',
relabelled_packages INT NOT NULL DEFAULT 0 COMMENT '已正常换标箱数',
skipped_packages INT NOT NULL DEFAULT 0 COMMENT '已说明原因跳过箱数',
exception_packages INT NOT NULL DEFAULT 0 COMMENT '已登记异常箱数',
completion_photo_file_ids JSON NULL COMMENT '换标完成现场照片文件ID列表',
completion_remark VARCHAR(1000) NULL COMMENT '完成提交备注',
review_decision VARCHAR(16) NULL COMMENT '最近复核结论:APPROVE或REWORK',
review_remark VARCHAR(1000) NULL COMMENT '最近复核备注',
claimed_at DATETIME(3) NOT NULL COMMENT '任务认领时间',
submitted_at DATETIME(3) NULL COMMENT '提交复核时间',
reviewed_at DATETIME(3) NULL COMMENT '最近复核时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本',
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 '更新时间',
PRIMARY KEY (id),
UNIQUE KEY uk_ll_relabel_pda_task_application (customer_id,application_id),
UNIQUE KEY uk_ll_relabel_pda_task_no (relabel_no),
KEY idx_ll_relabel_pda_task_warehouse (overseas_warehouse_id,status,updated_at),
KEY idx_ll_relabel_pda_task_operator (operator_key,status,updated_at)
) ENGINE=InnoDB COMMENT='海外PDA换标现场作业任务';
CREATE TABLE IF NOT EXISTS ll_relabel_pda_unit_fact (
id BIGINT NOT NULL COMMENT '逐件换标事实ID',
task_id BIGINT NOT NULL COMMENT '换标PDA任务ID',
application_id BIGINT NOT NULL COMMENT '换标申请单ID',
item_id BIGINT NOT NULL COMMENT '换标申请明细ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键',
old_label VARCHAR(255) NULL COMMENT '扫描的实物旧标签或箱标',
new_label VARCHAR(255) NULL COMMENT '扫描的换标后新标签',
result VARCHAR(32) NOT NULL COMMENT '逐件结果:RELABELLED、SKIPPED或EXCEPTION',
exception_code VARCHAR(32) NULL COMMENT '异常编码',
reason VARCHAR(1000) NULL COMMENT '跳过或异常原因',
operator_key VARCHAR(128) NOT NULL COMMENT '操作账号标识',
operator_name VARCHAR(255) NOT NULL COMMENT '操作员名称快照',
occurred_at DATETIME(3) NOT NULL COMMENT '逐件事实发生时间',
PRIMARY KEY (id),
UNIQUE KEY uk_ll_relabel_pda_old_label (old_label),
KEY idx_ll_relabel_pda_unit_task (customer_id,task_id,occurred_at,id),
KEY idx_ll_relabel_pda_unit_item (customer_id,application_id,item_id)
) ENGINE=InnoDB COMMENT='海外PDA逐件换标扫码与异常事实';
CREATE TABLE IF NOT EXISTS ll_relabel_pda_operation (
id BIGINT NOT NULL COMMENT '换标PDA幂等操作ID',
task_id BIGINT NOT NULL COMMENT '换标PDA任务ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键',
operator_key VARCHAR(128) NOT NULL COMMENT '请求操作账号标识',
action VARCHAR(32) NOT NULL COMMENT '幂等操作动作',
idempotency_key VARCHAR(255) NOT NULL COMMENT '设备生成的幂等键',
request_hash CHAR(64) NOT NULL COMMENT '请求内容哈希',
result_json LONGTEXT NOT NULL COMMENT '成功响应快照JSON',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (id),
UNIQUE KEY uk_ll_relabel_pda_operation_key (operator_key,idempotency_key),
KEY idx_ll_relabel_pda_operation_task (customer_id,task_id,created_at)
) ENGINE=InnoDB COMMENT='海外PDA换标写操作幂等记录';
CREATE TABLE IF NOT EXISTS ll_relabel_pda_history (
id BIGINT NOT NULL COMMENT '换标PDA任务历史ID',
task_id BIGINT NOT NULL COMMENT '换标PDA任务ID',
application_id BIGINT NOT NULL COMMENT '换标申请单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户数据隔离键',
action VARCHAR(32) NOT NULL COMMENT '现场动作类型',
from_status VARCHAR(32) NULL COMMENT '动作前任务状态',
to_status VARCHAR(32) NOT NULL COMMENT '动作后任务状态',
operator_key VARCHAR(128) NOT NULL COMMENT '操作账号标识',
operator_name VARCHAR(255) NOT NULL COMMENT '操作员名称快照',
detail_json LONGTEXT NULL COMMENT '动作详情JSON',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
PRIMARY KEY (id),
KEY idx_ll_relabel_pda_history_task (customer_id,task_id,created_at,id),
KEY idx_ll_relabel_pda_history_application (customer_id,application_id,created_at)
) ENGINE=InnoDB COMMENT='海外PDA换标任务不可变操作历史';
CREATE TABLE IF NOT EXISTS ll_dropship_order_profile (
id BIGINT NOT NULL COMMENT '主键ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户租户ID', order_id BIGINT NOT NULL COMMENT '订单ID',
warehouse_pallet_id BIGINT NULL COMMENT '仓库实物托盘ID', pallet_no VARCHAR(128) NULL COMMENT '托盘号',
@@ -0,0 +1,256 @@
openapi: 3.0.3
info:
title: Lastleg Overseas PDA Warehouse Operations API
version: 1.0.0
description: 海外仓PDA盘点、同仓整托移库、托盘作业与换标现场作业;全部范围从PDA Token解析。
security:
- bearerAuth: []
paths:
/api/pda/v1/last-leg/stocktakes:
get:
summary: 查询Token绑定仓盘点任务
parameters:
- { name: page, in: query, schema: { type: integer, minimum: 1, default: 1 } }
- { name: size, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 20 } }
- { name: status, in: query, schema: { type: string, enum: [IN_PROGRESS, SUBMITTED] } }
responses: { '200': { description: 盘点任务分页 } }
post:
summary: 按库位或托盘创建盘点任务
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeCreate' } } } }
responses: { '200': { description: 创建后的完整盘点任务 } }
/api/pda/v1/last-leg/stocktakes/{taskNo}:
get:
summary: 查询盘点任务详情
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
responses: { '200': { description: 盘点任务及冻结库存位置 } }
/api/pda/v1/last-leg/stocktakes/{taskNo}/counts:
post:
summary: 提交一个库存位置的实盘箱数
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeCount' } } } }
responses: { '200': { description: 已计数明细 }, '409': { description: 版本或幂等冲突 } }
/api/pda/v1/last-leg/stocktakes/{taskNo}/submit:
post:
summary: 提交盘点并按差异调整库存
parameters: [{ name: taskNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/StocktakeSubmit' } } } }
responses: { '200': { description: 已提交盘点任务 }, '409': { description: 未全盘、库存版本变化或负库存风险 } }
/api/pda/v1/last-leg/inventory-moves:
post:
summary: 同仓整托移库
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/InventoryMove' } } } }
responses: { '200': { description: 移库结果 }, '409': { description: 跨仓、资源或库存版本冲突 } }
/api/pda/v1/last-leg/pallet-operations/pallets/resolve:
post:
summary: 扫码查询托盘及库存内容
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/ScanCode' } } } }
responses: { '200': { description: Token绑定仓托盘内容 } }
/api/pda/v1/last-leg/pallet-operations/assemble:
post:
summary: 将多个来源托盘的指定库存行组到目标托盘
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletAssemble' } } } }
responses: { '200': { description: 组托及实物托盘状态结果 }, '409': { description: 目的仓、库存或资源版本冲突 } }
/api/pda/v1/last-leg/pallet-operations/disassemble:
post:
summary: 将来源托盘库存拆到一个或多个目标托盘
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletDisassemble' } } } }
responses: { '200': { description: 拆托结果 }, '409': { description: 库存或资源版本冲突 } }
/api/pda/v1/last-leg/pallet-operations/swap:
post:
summary: 将整托库存更换到空目标托盘
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletSwap' } } } }
responses: { '200': { description: 换托结果 }, '409': { description: 目标托盘非空或版本冲突 } }
/api/pda/v1/last-leg/pallet-operations/unbind:
post:
summary: 解除整托库存与实物托盘绑定
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/PalletUnbind' } } } }
responses: { '200': { description: 解绑结果 }, '409': { description: 库存或资源版本冲突 } }
/api/pda/v1/last-leg/relabel-tasks/candidates:
get:
summary: 查询Token绑定仓可执行换标任务
responses: { '200': { description: 待认领、处理中或待复核换标任务 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}:
get:
summary: 查询换标现场任务详情
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
responses: { '200': { description: 申请明细、逐件事实、照片与历史 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/claim:
post:
summary: 认领换标任务并推进申请至处理中
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/IdempotentAction' } } } }
responses: { '200': { description: 已认领任务 }, '409': { description: 仓库、状态或幂等冲突 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/units:
post:
summary: 登记一件正常换标事实
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelUnit' } } } }
responses: { '200': { description: 更新后的任务 }, '409': { description: 旧标重复、新标不符或版本冲突 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/units/skip:
post:
summary: 登记一件有原因的跳过事实
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelSkip' } } } }
responses: { '200': { description: 更新后的任务 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/exceptions:
post:
summary: 登记一件换标异常事实
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelException' } } } }
responses: { '200': { description: 更新后的任务 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/photos/files:
post:
summary: 上传换标完成现场照片
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { multipart/form-data: { schema: { type: object, required: [file], properties: { file: { type: string, format: binary } } } } } }
responses: { '200': { description: OVERSEAS_RELABEL_PHOTO文件元数据 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/complete:
post:
summary: 提交现场任务等待复核,不提前完成申请
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelComplete' } } } }
responses: { '200': { description: WAIT_REVIEW任务 }, '409': { description: 箱数未核平、照片或版本冲突 } }
/api/pda/v1/last-leg/relabel-tasks/{relabelNo}/review:
post:
summary: 现场复核;APPROVE才完成既有换标申请,REWORK退回处理
parameters: [{ name: relabelNo, in: path, required: true, schema: { type: string } }]
requestBody: { required: true, content: { application/json: { schema: { $ref: '#/components/schemas/RelabelReview' } } } }
responses: { '200': { description: COMPLETED或PROCESSING任务 }, '409': { description: 状态或版本冲突 } }
components:
securitySchemes:
bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT }
schemas:
ScanCode:
type: object
required: [code]
properties: { code: { type: string, minLength: 1, maxLength: 128 } }
IdempotentAction:
type: object
required: [idempotencyKey]
properties: { idempotencyKey: { type: string, minLength: 1, maxLength: 255 } }
StocktakeCreate:
type: object
required: [scopeType, scopeCode, idempotencyKey]
properties:
scopeType: { type: string, enum: [LOCATION, PALLET] }
scopeCode: { type: string, maxLength: 128 }
idempotencyKey: { type: string, maxLength: 128 }
StocktakeCount:
type: object
required: [positionId, actualPackages, expectedVersion, idempotencyKey]
properties:
positionId: { type: string, pattern: '^[0-9]+$' }
actualPackages: { type: integer, format: int64, minimum: 0 }
expectedVersion: { type: integer, format: int64, minimum: 0 }
idempotencyKey: { type: string, maxLength: 128 }
StocktakeSubmit:
type: object
required: [expectedVersion, reason, idempotencyKey]
properties:
expectedVersion: { type: integer, format: int64, minimum: 0 }
reason: { type: string, minLength: 1, maxLength: 500 }
idempotencyKey: { type: string, maxLength: 128 }
InventoryMove:
type: object
required: [sourcePalletCode, targetLocationCode, expectedPalletVersion, idempotencyKey, reason]
properties:
sourcePalletCode: { type: string, maxLength: 128 }
targetLocationCode: { type: string, maxLength: 128 }
expectedPalletVersion: { type: integer, minimum: 0 }
idempotencyKey: { type: string, maxLength: 128 }
reason: { type: string, minLength: 1, maxLength: 500 }
PalletExpectation:
type: object
required: [palletCode, expectedVersion]
properties:
palletCode: { type: string, maxLength: 128 }
expectedVersion: { type: integer, minimum: 0 }
PalletMoveLine:
type: object
required: [positionId, packages, expectedPositionVersion]
properties:
positionId: { type: string, pattern: '^[0-9]+$' }
packages: { type: integer, format: int64, minimum: 1 }
expectedPositionVersion: { type: integer, format: int64, minimum: 0 }
PalletAssemble:
type: object
required: [idempotencyKey, target, sources, lines]
properties:
idempotencyKey: { type: string, maxLength: 128 }
target: { $ref: '#/components/schemas/PalletExpectation' }
sources: { type: array, minItems: 1, maxItems: 20, items: { $ref: '#/components/schemas/PalletExpectation' } }
lines: { type: array, minItems: 1, maxItems: 200, items: { $ref: '#/components/schemas/PalletMoveLine' } }
reason: { type: string, maxLength: 500 }
PalletTargetMove:
type: object
required: [target, lines]
properties:
target: { $ref: '#/components/schemas/PalletExpectation' }
lines: { type: array, minItems: 1, maxItems: 200, items: { $ref: '#/components/schemas/PalletMoveLine' } }
PalletDisassemble:
type: object
required: [idempotencyKey, source, targets]
properties:
idempotencyKey: { type: string, maxLength: 128 }
source: { $ref: '#/components/schemas/PalletExpectation' }
targets: { type: array, minItems: 1, maxItems: 20, items: { $ref: '#/components/schemas/PalletTargetMove' } }
reason: { type: string, maxLength: 500 }
PalletSwap:
type: object
required: [idempotencyKey, source, target]
properties:
idempotencyKey: { type: string, maxLength: 128 }
source: { $ref: '#/components/schemas/PalletExpectation' }
target: { $ref: '#/components/schemas/PalletExpectation' }
reason: { type: string, maxLength: 500 }
PalletUnbind:
type: object
required: [idempotencyKey, source]
properties:
idempotencyKey: { type: string, maxLength: 128 }
source: { $ref: '#/components/schemas/PalletExpectation' }
reason: { type: string, maxLength: 500 }
RelabelUnit:
type: object
required: [itemId, oldLabel, newLabel, expectedVersion, idempotencyKey]
properties:
itemId: { type: string, pattern: '^[0-9]+$' }
oldLabel: { type: string, maxLength: 255 }
newLabel: { type: string, maxLength: 255 }
expectedVersion: { type: integer, minimum: 0 }
idempotencyKey: { type: string, maxLength: 255 }
RelabelSkip:
type: object
required: [itemId, oldLabel, reason, expectedVersion, idempotencyKey]
properties:
itemId: { type: string, pattern: '^[0-9]+$' }
oldLabel: { type: string, maxLength: 255 }
reason: { type: string, maxLength: 1000 }
expectedVersion: { type: integer, minimum: 0 }
idempotencyKey: { type: string, maxLength: 255 }
RelabelException:
type: object
required: [itemId, exceptionCode, reason, expectedVersion, idempotencyKey]
properties:
itemId: { type: string, pattern: '^[0-9]+$' }
oldLabel: { type: string, maxLength: 255, nullable: true }
exceptionCode: { type: string, enum: [DAMAGED, MISSING_LABEL, LABEL_MISMATCH, UNREADABLE, OTHER] }
reason: { type: string, maxLength: 1000 }
expectedVersion: { type: integer, minimum: 0 }
idempotencyKey: { type: string, maxLength: 255 }
RelabelComplete:
type: object
required: [photoFileIds, expectedVersion, idempotencyKey]
properties:
photoFileIds: { type: array, minItems: 1, maxItems: 20, items: { type: string, pattern: '^[0-9]+$' } }
expectedVersion: { type: integer, minimum: 0 }
idempotencyKey: { type: string, maxLength: 255 }
remark: { type: string, maxLength: 1000, nullable: true }
RelabelReview:
type: object
required: [decision, expectedVersion, idempotencyKey]
properties:
decision: { type: string, enum: [APPROVE, REWORK] }
expectedVersion: { type: integer, minimum: 0 }
idempotencyKey: { type: string, maxLength: 255 }
remark: { type: string, maxLength: 1000, nullable: true }