优化
This commit is contained in:
@@ -133,4 +133,54 @@ CREATE TABLE IF NOT EXISTS wh_location_occupancy (
|
||||
CONSTRAINT ck_occupancy_volume CHECK (allocated_volume_cbm > 0)
|
||||
) ENGINE=InnoDB COMMENT='已确认的库位占用事实记录,托盘字段仅为主数据快照';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wh_location_block (
|
||||
id BIGINT UNSIGNED NOT NULL COMMENT '整票库位块ID',
|
||||
tenant_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '平台公共仓储资源域,固定为0',
|
||||
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID',
|
||||
source_service VARCHAR(40) NOT NULL COMMENT '来源服务',
|
||||
business_id BIGINT UNSIGNED NOT NULL COMMENT '当前归属入库单业务ID',
|
||||
inbound_code VARCHAR(40) NOT NULL COMMENT '当前归属入仓码',
|
||||
slot_count INT UNSIGNED NOT NULL COMMENT '整票独占槽位数',
|
||||
idempotency_key VARCHAR(128) NOT NULL COMMENT '预占幂等键',
|
||||
block_status VARCHAR(20) NOT NULL COMMENT 'RESERVED、OCCUPIED或RELEASED',
|
||||
expires_at DATETIME(3) NOT NULL COMMENT '预占过期时间',
|
||||
last_operation_key VARCHAR(128) NULL COMMENT '最近确认、转移或释放幂等键',
|
||||
created_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 '更新时间',
|
||||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||||
active_business_block TINYINT GENERATED ALWAYS AS
|
||||
(CASE WHEN block_status IN ('RESERVED','OCCUPIED') THEN 1 ELSE NULL END) STORED
|
||||
COMMENT '同一来源入库单仅允许一个活动整票块',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_location_block_idempotency (tenant_id, source_service, idempotency_key),
|
||||
UNIQUE KEY uk_location_block_active_business (tenant_id, source_service, business_id, active_business_block),
|
||||
KEY idx_location_block_business (tenant_id, source_service, business_id, block_status),
|
||||
CONSTRAINT fk_location_block_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id),
|
||||
CONSTRAINT ck_location_block_slot_count CHECK (slot_count BETWEEN 1 AND 200)
|
||||
) ENGINE=InnoDB COMMENT='一票入仓码原子持有的稳定库位块';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS wh_location_block_slot (
|
||||
id BIGINT UNSIGNED NOT NULL COMMENT '槽位预占ID,对外作为reservationId',
|
||||
tenant_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '平台公共仓储资源域,固定为0',
|
||||
block_id BIGINT UNSIGNED NOT NULL COMMENT '整票库位块ID',
|
||||
slot_no INT UNSIGNED NOT NULL COMMENT '块内稳定槽位序号,从1开始',
|
||||
location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID',
|
||||
location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照',
|
||||
shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否落入同仓共享A0',
|
||||
resource_status VARCHAR(20) NOT NULL COMMENT 'RESERVED、OCCUPIED或RELEASED',
|
||||
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 '更新时间',
|
||||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||||
active_normal_slot TINYINT GENERATED ALWAYS AS
|
||||
(CASE WHEN resource_status IN ('RESERVED','OCCUPIED') AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED
|
||||
COMMENT '普通库位活动块槽唯一标记;A0返回NULL',
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE KEY uk_location_block_slot_no (tenant_id, block_id, slot_no),
|
||||
UNIQUE KEY uk_location_block_active_normal (tenant_id, location_id, active_normal_slot),
|
||||
KEY idx_location_block_slot_block (tenant_id, block_id, resource_status),
|
||||
CONSTRAINT fk_location_block_slot_block FOREIGN KEY (block_id) REFERENCES wh_location_block (id),
|
||||
CONSTRAINT fk_location_block_slot_location FOREIGN KEY (location_id) REFERENCES wh_location (id)
|
||||
) ENGINE=InnoDB COMMENT='整票库位块槽位;空槽也由当前入仓码独占';
|
||||
|
||||
-- 头程入库单属于其他数据库,不建立跨库外键。
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
openapi: 3.0.3
|
||||
info:
|
||||
title: Warehouse Internal Location Block API
|
||||
version: 1.0.0
|
||||
paths:
|
||||
/internal/warehouse/v1/pallet-locations/blocks/reservations:
|
||||
post:
|
||||
summary: 原子预占整票库位块
|
||||
security: [{ internalServiceToken: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '#/components/schemas/ReserveRequest' }
|
||||
responses:
|
||||
'200': { $ref: '#/components/responses/BlockResponse' }
|
||||
/internal/warehouse/v1/pallet-locations/blocks/confirm:
|
||||
post:
|
||||
summary: 整段确认占用
|
||||
security: [{ internalServiceToken: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/ConfirmRequest' } } }
|
||||
responses:
|
||||
'200': { $ref: '#/components/responses/BlockResponse' }
|
||||
/internal/warehouse/v1/pallet-locations/blocks/transfer:
|
||||
post:
|
||||
summary: 将整段资源归属转移给余量子入库单
|
||||
security: [{ internalServiceToken: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/TransferRequest' } } }
|
||||
responses:
|
||||
'200': { $ref: '#/components/responses/BlockResponse' }
|
||||
/internal/warehouse/v1/pallet-locations/blocks/release:
|
||||
post:
|
||||
summary: 整段释放
|
||||
description: 仅整票剩余箱数为0、整票作废或显式人工调整可调用;不提供单槽释放接口。
|
||||
security: [{ internalServiceToken: [] }]
|
||||
requestBody:
|
||||
required: true
|
||||
content: { application/json: { schema: { $ref: '#/components/schemas/ReleaseRequest' } } }
|
||||
responses:
|
||||
'200': { $ref: '#/components/responses/BlockResponse' }
|
||||
components:
|
||||
securitySchemes:
|
||||
internalServiceToken:
|
||||
type: apiKey
|
||||
in: header
|
||||
name: X-Internal-Service-Token
|
||||
responses:
|
||||
BlockResponse:
|
||||
description: 统一 ApiResponse,data 为整票块快照
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [code, message, data]
|
||||
properties:
|
||||
code: { type: string }
|
||||
message: { type: string }
|
||||
data: { $ref: '#/components/schemas/BlockResult' }
|
||||
schemas:
|
||||
ReserveRequest:
|
||||
type: object
|
||||
required: [warehouseId, sourceService, businessId, inboundCode, requiredSlotCount, idempotencyKey, operatorId, expiresAt]
|
||||
properties:
|
||||
warehouseId: { type: integer, format: int64, minimum: 1 }
|
||||
sourceService: { type: string, maxLength: 40 }
|
||||
businessId: { type: integer, format: int64, minimum: 1 }
|
||||
inboundCode: { type: string, maxLength: 40 }
|
||||
requiredSlotCount: { type: integer, minimum: 1, maximum: 200 }
|
||||
idempotencyKey: { type: string, maxLength: 128 }
|
||||
operatorId: { type: integer, format: int64, minimum: 1 }
|
||||
expiresAt: { type: string, format: date-time }
|
||||
ConfirmRequest:
|
||||
type: object
|
||||
required: [blockId, businessId, idempotencyKey, operatorId]
|
||||
properties:
|
||||
blockId: { type: integer, format: int64, minimum: 1 }
|
||||
businessId: { type: integer, format: int64, minimum: 1 }
|
||||
idempotencyKey: { type: string, maxLength: 128 }
|
||||
operatorId: { type: integer, format: int64, minimum: 1 }
|
||||
TransferRequest:
|
||||
type: object
|
||||
required: [blockId, sourceBusinessId, targetBusinessId, targetInboundCode, idempotencyKey, operatorId]
|
||||
properties:
|
||||
blockId: { type: integer, format: int64, minimum: 1 }
|
||||
sourceBusinessId: { type: integer, format: int64, minimum: 1 }
|
||||
targetBusinessId: { type: integer, format: int64, minimum: 1 }
|
||||
targetInboundCode: { type: string, maxLength: 40 }
|
||||
idempotencyKey: { type: string, maxLength: 128 }
|
||||
operatorId: { type: integer, format: int64, minimum: 1 }
|
||||
ReleaseRequest:
|
||||
type: object
|
||||
required: [blockId, businessId, idempotencyKey, operatorId, reason]
|
||||
properties:
|
||||
blockId: { type: integer, format: int64, minimum: 1 }
|
||||
businessId: { type: integer, format: int64, minimum: 1 }
|
||||
idempotencyKey: { type: string, maxLength: 128 }
|
||||
operatorId: { type: integer, format: int64, minimum: 1 }
|
||||
reason: { type: string, enum: [ALL_PACKAGES_PICKED, TICKET_VOID, MANUAL_ADJUSTMENT] }
|
||||
BlockResult:
|
||||
type: object
|
||||
required: [blockId, blockStatus, resources]
|
||||
properties:
|
||||
blockId: { type: integer, format: int64 }
|
||||
blockStatus: { type: string, enum: [RESERVED, OCCUPIED, RELEASED] }
|
||||
resources:
|
||||
type: array
|
||||
items: { $ref: '#/components/schemas/Resource' }
|
||||
Resource:
|
||||
type: object
|
||||
required: [blockId, reservationId, locationId, locationCode, slotNo, sharedOverflow, resourceStatus]
|
||||
properties:
|
||||
blockId: { type: integer, format: int64 }
|
||||
reservationId: { type: integer, format: int64 }
|
||||
locationId: { type: integer, format: int64 }
|
||||
locationCode: { type: string }
|
||||
slotNo: { type: integer, minimum: 1 }
|
||||
sharedOverflow: { type: boolean }
|
||||
resourceStatus: { type: string, enum: [RESERVED, OCCUPIED, RELEASED] }
|
||||
Reference in New Issue
Block a user