diff --git a/deploy/sql/README.md b/deploy/sql/README.md index ddfc62a86..f5855fbff 100644 --- a/deploy/sql/README.md +++ b/deploy/sql/README.md @@ -155,3 +155,5 @@ node --test scripts/admin-test-env-modules/initialization-baseline-contract.test `migrations/overseas/baiyue_lastleg/V24__cargo_discard_photos.sql` 仅新增废弃照片关联表,按客户、申请和托盘关联文件及提交时间。与 Lastleg、File 和三端照片功能共同发布;不回填历史废弃单,不修改库存。脚本存在不表示目标环境已执行。 自营库存周转后端导出权限见 `selfop-turnover-export-permission.sql`,仅新增 `platform:self-operated-analytics:export` 并授予平台管理员;同步 IAM 自营权限源及国内统一基线。配套部署 Lastleg、File、Admin,File 注册 `SELFOP_INVENTORY_TURNOVER`(Nacos同名配置同步);无业务建表及采集配置变更。执行前须逐项授权。 + +货物废弃通用库存与散箱字段迁移:`migrations/overseas/baiyue_lastleg/V25__cargo_discard_generic_inventory.sql`。新增库存仓位关联及箱唛快照,须先迁移再部署 Lastleg;不回填历史废弃单。 diff --git a/deploy/sql/migrations/cn/baiyue_iam/V6__cargo_discard_customer_confirmation_permission.sql b/deploy/sql/migrations/cn/baiyue_iam/V6__cargo_discard_customer_confirmation_permission.sql new file mode 100644 index 000000000..b4952fe4f --- /dev/null +++ b/deploy/sql/migrations/cn/baiyue_iam/V6__cargo_discard_customer_confirmation_permission.sql @@ -0,0 +1,21 @@ +-- 仅 baiyue_iam,新增客户废弃确认按钮权限并授权默认客户管理员。 +-- 自定义客户角色由管理员按需分配;不自动扩大其权限。 +-- 可重复执行;授权和持久化安全版本在同一事务提交。 +START TRANSACTION; +INSERT INTO iam_permission(id,tenant_id,app_code,permission_type,parent_id,permission_code,permission_name,route_path,http_method,sort_no,status,built_in,deleted) +VALUES (5306183,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:confirm','确认废弃完成',NULL,'POST',30,'ACTIVE',1,0) +ON DUPLICATE KEY UPDATE permission_name=VALUES(permission_name),status='ACTIVE',deleted=0; +INSERT IGNORE INTO iam_role_permission(tenant_id,role_id,permission_id,created_at) +SELECT 0,r.id,p.id,NOW(3) FROM iam_role r JOIN iam_permission p + ON p.tenant_id=0 AND p.app_code='MERCHANT' AND p.permission_code='merchant:overseas-warehouse:discard:confirm' +WHERE r.tenant_id=0 AND r.app_code='MERCHANT' AND r.role_code='MERCHANT_OWNER' AND r.status='ACTIVE' AND r.deleted=0; +INSERT INTO iam_security_subject_version(auth_user_id,permission_version) +SELECT DISTINCT u.auth_user_id,1 FROM iam_user u +JOIN iam_membership m ON m.user_id=u.id +JOIN iam_membership_role mr ON mr.membership_id=m.id AND mr.tenant_id=m.tenant_id +JOIN iam_role r ON r.id=mr.role_id +WHERE u.auth_user_id IS NOT NULL AND u.status='ACTIVE' AND u.deleted=0 + AND m.status='ACTIVE' AND m.deleted=0 AND r.tenant_id=0 AND r.app_code='MERCHANT' + AND r.role_code='MERCHANT_OWNER' AND r.status='ACTIVE' AND r.deleted=0 +ON DUPLICATE KEY UPDATE permission_version=permission_version+1; +COMMIT; diff --git a/deploy/sql/migrations/overseas/baiyue_lastleg/V25__cargo_discard_generic_inventory.sql b/deploy/sql/migrations/overseas/baiyue_lastleg/V25__cargo_discard_generic_inventory.sql new file mode 100644 index 000000000..4e79aa929 --- /dev/null +++ b/deploy/sql/migrations/overseas/baiyue_lastleg/V25__cargo_discard_generic_inventory.sql @@ -0,0 +1,24 @@ +-- 货物废弃支持所有入库来源及散箱全量作业;不回填或修改历史单据。 +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND column_name='inventory_position_id'), + 'ALTER TABLE ll_cargo_discard_item ADD COLUMN inventory_position_id BIGINT NULL COMMENT ''废弃来源库存仓位ID''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND column_name='carton_marks_json'), + 'ALTER TABLE ll_cargo_discard_item ADD COLUMN carton_marks_json TEXT NULL COMMENT ''本次废弃所选真实箱唛快照JSON数组''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND index_name='uk_ll_discard_position_sku'), + 'ALTER TABLE ll_cargo_discard_item ADD UNIQUE KEY uk_ll_discard_position_sku(application_id,inventory_position_id,sku_code)', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +ALTER TABLE ll_cargo_discard_item MODIFY COLUMN source_type VARCHAR(32) NOT NULL DEFAULT 'DROPSHIP' COMMENT '库存来源:一件代发DROPSHIP、退货箱RETURN_CARTON、通用库存INVENTORY'; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND column_name='carton_scan_required'), + 'ALTER TABLE ll_cargo_discard_item ADD COLUMN carton_scan_required TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否需要逐箱核对本次所选箱子''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; +ALTER TABLE ll_cargo_discard_item MODIFY COLUMN carton_marks_json TEXT NULL COMMENT '本次废弃所选真实箱唛快照JSON数组'; +ALTER TABLE ll_inbound_plan_carton MODIFY COLUMN status VARCHAR(32) NOT NULL COMMENT '箱唛状态:未绑定UNASSIGNED、已绑托ON_PALLET、整票收货BULK_RECEIVED、可用AVAILABLE、待废弃DISCARD_PENDING、已废弃DISCARDED'; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_carton' AND column_name='source_type'), + 'ALTER TABLE ll_cargo_discard_carton ADD COLUMN source_type VARCHAR(32) NOT NULL DEFAULT ''DROPSHIP'' COMMENT ''箱子来源:一件代发DROPSHIP、入仓箱INBOUND、转运箱TRANSFER''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; diff --git a/deploy/sql/migrations/overseas/baiyue_lastleg/V26__allow_zero_return_carton_item_quantity.sql b/deploy/sql/migrations/overseas/baiyue_lastleg/V26__allow_zero_return_carton_item_quantity.sql new file mode 100644 index 000000000..7f5a22c6b --- /dev/null +++ b/deploy/sql/migrations/overseas/baiyue_lastleg/V26__allow_zero_return_carton_item_quantity.sql @@ -0,0 +1,13 @@ +-- 整箱废弃后保留SKU明细,剩余数量允许归零,仍禁止负库存。 +-- 原子替换约束,可重复执行;不修改业务记录。 +SET @ddl = IF(EXISTS ( + SELECT 1 FROM information_schema.table_constraints + WHERE constraint_schema=DATABASE() AND table_name='ll_return_inventory_carton_item' + AND constraint_name='chk_ll_return_inventory_carton_item_quantity' +), + 'ALTER TABLE ll_return_inventory_carton_item DROP CHECK chk_ll_return_inventory_carton_item_quantity, ADD CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK(quantity>=0)', + 'ALTER TABLE ll_return_inventory_carton_item ADD CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK(quantity>=0)' +); +PREPARE stmt FROM @ddl; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/deploy/sql/migrations/overseas/baiyue_lastleg/V27__cargo_discard_customer_confirmation.sql b/deploy/sql/migrations/overseas/baiyue_lastleg/V27__cargo_discard_customer_confirmation.sql new file mode 100644 index 000000000..c8109e3c2 --- /dev/null +++ b/deploy/sql/migrations/overseas/baiyue_lastleg/V27__cargo_discard_customer_confirmation.sql @@ -0,0 +1,3 @@ +-- 客户确认废弃完结时间,可重复执行;仅结构变更。 +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_application' AND column_name='customer_confirmed_at'), 'ALTER TABLE ll_cargo_discard_application ADD COLUMN customer_confirmed_at DATETIME(3) NULL COMMENT ''客户确认废弃完结时间''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index e70fee62f..d58001da3 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -7142,7 +7142,9 @@ INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306172,0,CURRENT_TIMESTAMP(3)); INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306180,0,CURRENT_TIMESTAMP(3)); INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306181,0,CURRENT_TIMESTAMP(3)); +INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306183,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:confirm','确认废弃完成',NULL,'POST',30,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0); INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306182,0,CURRENT_TIMESTAMP(3)); +INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306183,0,CURRENT_TIMESTAMP(3)); INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306190,0,CURRENT_TIMESTAMP(3)); INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306191,0,CURRENT_TIMESTAMP(3)); INSERT INTO iam_role_permission (role_id, permission_id, tenant_id, created_at) VALUES (4000100,5306192,0,CURRENT_TIMESTAMP(3)); diff --git a/deploy/sql/海外区域统一增量-MySQL8.sql b/deploy/sql/海外区域统一增量-MySQL8.sql index 1dd8baf47..1867ced47 100644 --- a/deploy/sql/海外区域统一增量-MySQL8.sql +++ b/deploy/sql/海外区域统一增量-MySQL8.sql @@ -48,6 +48,7 @@ CREATE TABLE ll_cargo_discard_carton ( customer_id varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户租户ID', carton_id bigint NOT NULL COMMENT '箱唛记录ID', carton_mark varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '箱唛', + source_type VARCHAR(32) NOT NULL DEFAULT 'DROPSHIP' COMMENT '箱子来源:一件代发DROPSHIP、入仓箱INBOUND、转运箱TRANSFER', created_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY (id), UNIQUE KEY uk_ll_cargo_discard_carton (application_id,carton_id), @@ -60,13 +61,16 @@ CREATE TABLE ll_cargo_discard_item ( application_id bigint NOT NULL COMMENT '申请单ID', customer_id varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户租户ID', order_id bigint DEFAULT NULL COMMENT '一件代发订单ID', - source_type varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'DROPSHIP' COMMENT '库存来源:一件代发DROPSHIP、退货箱RETURN_CARTON', + source_type varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'DROPSHIP' COMMENT '库存来源:一件代发DROPSHIP、退货箱RETURN_CARTON、通用库存INVENTORY', return_carton_id bigint DEFAULT NULL COMMENT '退货库存箱ID', inbound_code varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '入仓单号快照', profile_id bigint DEFAULT NULL COMMENT '托盘档案ID', sku_inventory_id bigint DEFAULT NULL COMMENT 'SKU库存记录ID', sku_code varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'SKU编码', product_name varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '产品名称', + inventory_position_id BIGINT NULL COMMENT '废弃来源库存仓位ID', + carton_marks_json TEXT NULL COMMENT '本次废弃所选真实箱唛快照JSON数组', + carton_scan_required TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否需要逐箱核对本次所选箱子', available_packages_snapshot int NOT NULL COMMENT '可用箱数快照', discard_packages int NOT NULL COMMENT '申请废弃箱数', completion_photo_file_ids text COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'PDA完工照片文件ID JSON数组', @@ -77,6 +81,7 @@ CREATE TABLE ll_cargo_discard_item ( created_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', PRIMARY KEY (id), UNIQUE KEY uk_ll_cargo_discard_item (application_id,profile_id,sku_code), + UNIQUE KEY uk_ll_discard_position_sku(application_id,inventory_position_id,sku_code), KEY idx_ll_cargo_discard_item_list (customer_id,application_id), KEY idx_ll_cargo_discard_item_inbound (customer_id,inbound_code,sku_code) ,KEY idx_ll_cargo_discard_return_carton (customer_id,return_carton_id) @@ -1098,7 +1103,7 @@ CREATE TABLE ll_inbound_plan_carton ( warehouse_pallet_id bigint DEFAULT NULL COMMENT '海外实物托盘ID', warehouse_location_id bigint DEFAULT NULL COMMENT '海外库位ID', pda_task_id bigint DEFAULT NULL COMMENT '首次扫码PDA任务ID', - status varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '箱唛状态:UNASSIGNED、ON_PALLET、BULK_RECEIVED、AVAILABLE', + status varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '箱唛状态:未绑定UNASSIGNED、已绑托ON_PALLET、整票收货BULK_RECEIVED、可用AVAILABLE、待废弃DISCARD_PENDING、已废弃DISCARDED', version int NOT NULL DEFAULT '0' COMMENT '乐观锁版本', bound_at datetime(3) DEFAULT NULL COMMENT '绑定托盘时间', received_at datetime(3) DEFAULT NULL COMMENT '完成入库时间', @@ -2494,7 +2499,7 @@ CREATE TABLE ll_return_inventory_carton_item ( PRIMARY KEY (id), UNIQUE KEY uk_ll_return_inventory_carton_item (carton_id,sku_code), KEY idx_ll_return_inventory_carton_item_customer (customer_id,sku_code), - CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK ((quantity > 0)), + CONSTRAINT chk_ll_return_inventory_carton_item_quantity CHECK ((quantity >= 0)), packing_reserved_quantity BIGINT NOT NULL DEFAULT 0 COMMENT '合箱计划预占件数' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='退货库存箱内SKU和数量'; @@ -4347,6 +4352,31 @@ CREATE TABLE IF NOT EXISTS ll_cargo_discard_photo ( KEY idx_cargo_discard_photo_application (customer_id, application_id, pallet_no) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +-- 货物废弃支持所有入库来源及散箱全量作业;不回填或修改历史单据。 +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND column_name='inventory_position_id'), + 'ALTER TABLE ll_cargo_discard_item ADD COLUMN inventory_position_id BIGINT NULL COMMENT ''废弃来源库存仓位ID''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND column_name='carton_marks_json'), + 'ALTER TABLE ll_cargo_discard_item ADD COLUMN carton_marks_json TEXT NULL COMMENT ''本次废弃所选真实箱唛快照JSON数组''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.statistics WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND index_name='uk_ll_discard_position_sku'), + 'ALTER TABLE ll_cargo_discard_item ADD UNIQUE KEY uk_ll_discard_position_sku(application_id,inventory_position_id,sku_code)', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +ALTER TABLE ll_cargo_discard_item MODIFY COLUMN source_type VARCHAR(32) NOT NULL DEFAULT 'DROPSHIP' COMMENT '库存来源:一件代发DROPSHIP、退货箱RETURN_CARTON、通用库存INVENTORY'; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_item' AND column_name='carton_scan_required'), + 'ALTER TABLE ll_cargo_discard_item ADD COLUMN carton_scan_required TINYINT(1) NOT NULL DEFAULT 0 COMMENT ''是否需要逐箱核对本次所选箱子''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; +ALTER TABLE ll_cargo_discard_item MODIFY COLUMN carton_marks_json TEXT NULL COMMENT '本次废弃所选真实箱唛快照JSON数组'; +ALTER TABLE ll_inbound_plan_carton MODIFY COLUMN status VARCHAR(32) NOT NULL COMMENT '箱唛状态:未绑定UNASSIGNED、已绑托ON_PALLET、整票收货BULK_RECEIVED、可用AVAILABLE、待废弃DISCARD_PENDING、已废弃DISCARDED'; + +SET @ddl = IF(NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_cargo_discard_carton' AND column_name='source_type'), + 'ALTER TABLE ll_cargo_discard_carton ADD COLUMN source_type VARCHAR(32) NOT NULL DEFAULT ''DROPSHIP'' COMMENT ''箱子来源:一件代发DROPSHIP、入仓箱INBOUND、转运箱TRANSFER''', 'SELECT 1'); +PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; + CREATE TABLE ll_selfop_owner ( id BIGINT NOT NULL COMMENT '主键', run_id BIGINT NOT NULL COMMENT '完整资料采集版本', @@ -4382,6 +4412,37 @@ CREATE TABLE ll_selfop_product ( ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自营领星商品资料版本'; +-- 仓储转运逐箱测量与清点;仅增加字段,不修改业务数据。 +USE baiyue_lastleg; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='length_cm'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN length_cm DECIMAL(12,2) NULL COMMENT ''箱子实测长度厘米''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='width_cm'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN width_cm DECIMAL(12,2) NULL COMMENT ''箱子实测宽度厘米''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='height_cm'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN height_cm DECIMAL(12,2) NULL COMMENT ''箱子实测高度厘米''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='gross_weight_kg'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN gross_weight_kg DECIMAL(12,2) NULL COMMENT ''箱子实测重量千克''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='counted_quantity'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN counted_quantity BIGINT NULL COMMENT ''箱内SKU实点件数''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='count_idempotency_key'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN count_idempotency_key VARCHAR(255) NULL COMMENT ''箱内清点幂等键''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='count_request_hash'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN count_request_hash VARCHAR(64) NULL COMMENT ''箱内清点请求摘要''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='counted_by'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN counted_by VARCHAR(128) NULL COMMENT ''箱内清点操作人''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='counted_at'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN counted_at DATETIME(3) NULL COMMENT ''箱内清点完成时间''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; + +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='discrepancy_reason'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN discrepancy_reason VARCHAR(1000) NULL COMMENT ''实收与预报箱数差异原因''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; + +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_carton' AND column_name='transfer_pallet_id'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_carton ADD COLUMN transfer_pallet_id BIGINT NULL COMMENT ''签收箱所属转运托盘事实ID''')); +PREPARE transfer_count_stmt FROM @ddl; EXECUTE transfer_count_stmt; DEALLOCATE PREPARE transfer_count_stmt; + +-- SKU 申报件数独立于预计箱数;历史未申报件数保持 NULL,实收以 PDA 清点为准。 +SET @ddl = (SELECT IF(EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema=DATABASE() AND table_name='ll_warehouse_transfer_item' AND column_name='declared_quantity'), 'SELECT 1', 'ALTER TABLE ll_warehouse_transfer_item ADD COLUMN declared_quantity BIGINT NULL COMMENT ''SKU申报件数,非预计或实收箱数''')); +PREPARE transfer_quantity_stmt FROM @ddl; EXECUTE transfer_quantity_stmt; DEALLOCATE PREPARE transfer_quantity_stmt; + USE baiyue_lastleg; -- 历史库存基线;执行前必须取得指定环境的建表授权。 diff --git a/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/controller/TerminalDrayageOpenApiContractTest.java b/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/controller/TerminalDrayageOpenApiContractTest.java index fdc975777..c7baa1099 100644 --- a/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/controller/TerminalDrayageOpenApiContractTest.java +++ b/firstleg/src/test/java/com/baiyue/firstleg/terminaldrayage/controller/TerminalDrayageOpenApiContractTest.java @@ -51,7 +51,8 @@ class TerminalDrayageOpenApiContractTest { "emptyReturnWarning", "actualFacts", "deadlineAt", "overdueHours", "overdueDays", "船节点跟踪任务尚未建立也返回WAITING_FOR_ARRIVAL空详情", "允许读取空邮件列表,不以船节点跟踪任务是否已经建立作为货柜存在性条件"); - assertThat(yaml).contains("description: 卸柜完成时间加72小时"); + assertThat(yaml).contains("原海外仓卸柜时间加72小时", "直送按最晚真实卸货Instant加72小时", + "直送72小时按绝对时长计算", "不比较不同地点的当地钟面值"); assertThat(yaml).doesNotContain("/api/platform/v1/terminal-drayages/{containerBookingId}/pickup:", "platform:firstleg:terminal-drayage:pickup:confirm", "RECORD_PICKUP"); } diff --git a/iam/src/main/resources/db/lastleg-permissions.sql b/iam/src/main/resources/db/lastleg-permissions.sql index 6b4c39d13..cb9388409 100644 --- a/iam/src/main/resources/db/lastleg-permissions.sql +++ b/iam/src/main/resources/db/lastleg-permissions.sql @@ -142,6 +142,7 @@ VALUES (5306180,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:discard:list','货物废弃','/overseas-warehouse/cargo-disposal','GET',130,'ACTIVE',1,0), (5306181,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:create','创建货物废弃申请',NULL,'POST',10,'ACTIVE',1,0), (5306182,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请',NULL,'POST',20,'ACTIVE',1,0), + (5306183,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:confirm','确认废弃完成',NULL,'POST',30,'ACTIVE',1,0), (5306190,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:return-order:list','退货换标','/overseas-warehouse/return-relabel','GET',140,'ACTIVE',1,0), (5306191,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:create','创建退货预报',NULL,'POST',10,'ACTIVE',1,0), (5306192,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:relabel','退货转换标申请',NULL,'POST',20,'ACTIVE',1,0) @@ -336,6 +337,7 @@ JOIN iam_permission permission ON permission.tenant_id=0 AND permission.app_code 'merchant:overseas-warehouse:discard:list', 'merchant:overseas-warehouse:discard:create', 'merchant:overseas-warehouse:discard:cancel', + 'merchant:overseas-warehouse:discard:confirm', 'merchant:overseas-warehouse:return-order:list', 'merchant:overseas-warehouse:return-order:create', 'merchant:overseas-warehouse:return-order:relabel' @@ -371,9 +373,10 @@ BEGIN 'merchant:overseas-warehouse:discard:list', 'merchant:overseas-warehouse:discard:create', 'merchant:overseas-warehouse:discard:cancel', + 'merchant:overseas-warehouse:discard:confirm', 'merchant:overseas-warehouse:return-order:list', 'merchant:overseas-warehouse:return-order:create', - 'merchant:overseas-warehouse:return-order:relabel')) <> 24 THEN + 'merchant:overseas-warehouse:return-order:relabel')) <> 25 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='海外客户权限初始化失败:权限资源不完整'; END IF; IF (SELECT COUNT(*) FROM iam_role_permission grant_row @@ -405,9 +408,10 @@ BEGIN 'merchant:overseas-warehouse:discard:list', 'merchant:overseas-warehouse:discard:create', 'merchant:overseas-warehouse:discard:cancel', + 'merchant:overseas-warehouse:discard:confirm', 'merchant:overseas-warehouse:return-order:list', 'merchant:overseas-warehouse:return-order:create', - 'merchant:overseas-warehouse:return-order:relabel')) <> 24 THEN + 'merchant:overseas-warehouse:return-order:relabel')) <> 25 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT='海外客户权限初始化失败:客户默认管理员授权不完整'; END IF; END$$ diff --git a/iam/src/test/java/com/baiyue/iam/repository/MerchantReturnInventoryPermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/MerchantReturnInventoryPermissionSqlContractTest.java index d7deb63ea..6768e66bd 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/MerchantReturnInventoryPermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/MerchantReturnInventoryPermissionSqlContractTest.java @@ -20,7 +20,7 @@ class MerchantReturnInventoryPermissionSqlContractTest { assertThat(sql).contains( "(5306140,0,'MERCHANT','MENU',0,'" + PERMISSION + "','退货库存'", "role.role_code='MERCHANT_OWNER'", - ")) <> 24 THEN", + ")) <> 25 THEN", "客户默认管理员授权不完整"); int grantStart = sql.indexOf("-- 客户默认管理员获得当前客户海外业务入口"); diff --git a/iam/src/test/java/com/baiyue/iam/repository/OverseasCustomerPermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/OverseasCustomerPermissionSqlContractTest.java index ba27c34e8..3bf4205bb 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/OverseasCustomerPermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/OverseasCustomerPermissionSqlContractTest.java @@ -36,6 +36,7 @@ class OverseasCustomerPermissionSqlContractTest { "merchant:overseas-warehouse:discard:list", "merchant:overseas-warehouse:discard:create", "merchant:overseas-warehouse:discard:cancel", + "merchant:overseas-warehouse:discard:confirm", "merchant:overseas-warehouse:return-order:list", "merchant:overseas-warehouse:return-order:create", "merchant:overseas-warehouse:return-order:relabel"); @@ -85,7 +86,7 @@ class OverseasCustomerPermissionSqlContractTest { "海外客户权限初始化失败:客户默认管理员授权不完整", "permission.app_code='MERCHANT'", "role.role_code='MERCHANT_OWNER'", - ")) <> 24 THEN"); + ")) <> 25 THEN"); } @Test diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java index 6f68db6d1..6abe4ce17 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/service/DeliveryTransferService.java @@ -1158,6 +1158,7 @@ public class DeliveryTransferService { required(request == null ? null : request.reason(), "取消原因不能为空"); OutboundOrder observed = outboundOrders.findGlobalByNo(trim(outboundNo)); if (observed == null) throw notFound("Outbound order not found"); + if ("DISCARD_OUTBOUND".equals(observed.getOutboundType())) throw conflict("请通过废弃单取消,废弃出库单随申请同步取消"); // Match dispatch picking and relabel confirmation lock order before locking outbound. DispatchOrder dispatch = observed.getDispatchOrderId() == null ? null : dispatchOrders.lockById(observed.getCustomerId(), observed.getDispatchOrderId()); @@ -1425,6 +1426,7 @@ public class DeliveryTransferService { new LambdaQueryWrapper().eq(StringUtils.hasText(customerId), OutboundOrder::getCustomerId, customerId) .like(StringUtils.hasText(query.documentNo()), OutboundOrder::getOutboundNo, query.documentNo()) .like(StringUtils.hasText(query.lxCode()), OutboundOrder::getLxCodes, query.lxCode()) + .ne(StringUtils.hasText(query.lxCode()), OutboundOrder::getOutboundType, "DISCARD_OUTBOUND") .eq(StringUtils.hasText(query.warehouseId()), OutboundOrder::getOverseasWarehouseId, query.warehouseId()) .eq(StringUtils.hasText(query.status()), OutboundOrder::getStatus, query.status()) .eq(StringUtils.hasText(query.outboundType()), OutboundOrder::getOutboundType, query.outboundType()) @@ -1610,7 +1612,7 @@ public class DeliveryTransferService { d.getDeliveryNo(), d.getStatus(), d.getDestinationWarehouseId(), d.getDestinationWarehouseCode(), d.getDestinationWarehouseName(), value(d.getPalletCount()), value(d.getPackageCount()))).toList(), replayed); } - private DeliveryResponses.OutboundRow outboundRow(OutboundOrder o) { return new DeliveryResponses.OutboundRow(o.getId(), o.getOutboundNo(), o.getDispatchNo(), o.getOverseasWarehouseId(), o.getLxCodes(), o.getStatus(), o.getPalletCount(), o.getPackageCount(), o.getGrossWeightKg(), o.getVolumeWeightKg(), o.getVolumeCbm(), o.getCreatedAt(), o.getOutboundType()); } + private DeliveryResponses.OutboundRow outboundRow(OutboundOrder o) { return new DeliveryResponses.OutboundRow(o.getId(), o.getOutboundNo(), o.getDispatchNo(), o.getOverseasWarehouseId(), "DISCARD_OUTBOUND".equals(o.getOutboundType()) ? null : o.getLxCodes(), o.getStatus(), o.getPalletCount(), o.getPackageCount(), o.getGrossWeightKg(), o.getVolumeWeightKg(), o.getVolumeCbm(), o.getCreatedAt(), o.getOutboundType()); } private DeliveryResponses.OutboundPalletRow outboundPalletRow(OutboundPalletItem item) { return new DeliveryResponses.OutboundPalletRow(item.getId(), item.getPalletNo(), item.getCartonMarks(), item.getInboundCode(), item.getDestinationWarehouseCode(), item.getDestinationWarehouseName(), diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/CargoDiscardController.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/CargoDiscardController.java index e63473c3f..560138fe0 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/CargoDiscardController.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/CargoDiscardController.java @@ -77,13 +77,6 @@ public class CargoDiscardController { return ApiResponse.success(service.cancel(scope(user, customerId), discardNo, operator(user), true)); } - @PostMapping("/{discardNo}/complete") - public ApiResponse complete(@AuthenticationPrincipal AuthenticatedUser user, - @RequestParam(required = false) String customerId, @PathVariable String discardNo) { - requireApprovalPermission(user); - return ApiResponse.success(service.complete(scope(user, customerId), discardNo, operator(user))); - } - private String scope(AuthenticatedUser user, String requested) { if (user == null || user.tenantId() == null) throw new ResponseStatusException(HttpStatus.UNAUTHORIZED); if ("PLATFORM".equals(user.appCode()) && user.tenantId() == 0L) { diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/MerchantCargoDiscardController.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/MerchantCargoDiscardController.java index d69a705d7..300108ecc 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/MerchantCargoDiscardController.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/controller/MerchantCargoDiscardController.java @@ -46,6 +46,12 @@ public class MerchantCargoDiscardController { org.springframework.http.ContentDisposition.inline().filename(file.fileName(), java.nio.charset.StandardCharsets.UTF_8).build().toString()) .contentType(org.springframework.http.MediaType.parseMediaType(file.contentType())).body(file.content()); } + @PostMapping("/{discardNo}/confirm-completion") + @PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_DISCARD_CONFIRM + "')") + public ApiResponse confirmCompletion(@AuthenticationPrincipal AuthenticatedUser user, + @PathVariable String discardNo) { + return ApiResponse.success(service.confirmCompletion(customer(user), discardNo, operator(user))); + } @PostMapping("/{discardNo}/cancel") @PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_DISCARD_CANCEL + "')") public ApiResponse cancel(@AuthenticationPrincipal AuthenticatedUser user, diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardRequests.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardRequests.java index f368e7224..8cbac94b8 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardRequests.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardRequests.java @@ -20,7 +20,14 @@ public final class CargoDiscardRequests { @Size(max = 1000) String remark) {} public record Item(Long orderId, Long returnCartonId, @NotBlank @Size(max = 128) String skuCode, - @Positive int discardPackages) {} + @Positive int discardPackages, Long inventoryPositionId, @Size(max = 5000) List<@NotNull @Positive Long> cartonIds) { + public Item(Long orderId, Long returnCartonId, String skuCode, int discardPackages, Long inventoryPositionId) { + this(orderId, returnCartonId, skuCode, discardPackages, inventoryPositionId, null); + } + public Item(Long orderId, Long returnCartonId, String skuCode, int discardPackages) { + this(orderId, returnCartonId, skuCode, discardPackages, null, null); + } + } public record Review(@NotBlank String decision, @Size(max = 1000) String remark) {} diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardResponses.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardResponses.java index 168140564..efde17c22 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardResponses.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/dto/CargoDiscardResponses.java @@ -11,16 +11,37 @@ public final class CargoDiscardResponses { String inboundCode, String inboundOrderNo, String overseasWarehouseId, String overseasWarehouseName, LocalDateTime inboundCreatedAt, long availablePackages, - List skus) {} + List skus, Long inventoryPositionId, String palletNo, List cartons, boolean cartonSelectionSupported, String cartonSelectionBlockReason) { + public Candidate(Long orderId, String sourceType, Long returnCartonId, String cartonMark, + String inboundCode, String inboundOrderNo, String overseasWarehouseId, + String overseasWarehouseName, LocalDateTime inboundCreatedAt, long availablePackages, + List skus, Long inventoryPositionId, String palletNo) { + this(orderId, sourceType, returnCartonId, cartonMark, inboundCode, inboundOrderNo, + overseasWarehouseId, overseasWarehouseName, inboundCreatedAt, availablePackages, skus, + inventoryPositionId, palletNo, List.of(), false, "当前库存缺少可核对的箱级记录,可按全部库存废弃"); + } + public Candidate(Long orderId, String sourceType, Long returnCartonId, String cartonMark, + String inboundCode, String inboundOrderNo, String overseasWarehouseId, + String overseasWarehouseName, LocalDateTime inboundCreatedAt, long availablePackages, + List skus) { + this(orderId, sourceType, returnCartonId, cartonMark, inboundCode, inboundOrderNo, + overseasWarehouseId, overseasWarehouseName, inboundCreatedAt, availablePackages, skus, null, null); + } + } + public record Box(Long cartonId, String cartonMark, String palletNo, List skus) {} public record CandidateSku(String skuCode, String productName, long availablePackages) {} public record Summary(Long id, String customerId, String discardNo, String inboundCodes, String overseasWarehouseId, String overseasWarehouseName, int totalPackages, BigDecimal totalFee, String currency, String status, - String createdBy, LocalDateTime createdAt, LocalDateTime reviewedAt) {} + String createdBy, LocalDateTime createdAt, LocalDateTime reviewedAt, String outboundNo, LocalDateTime customerConfirmedAt) {} public record Item(Long id, Long orderId, String inboundCode, String skuCode, - String productName, int availablePackagesSnapshot, int discardPackages) {} + String productName, int availablePackagesSnapshot, int discardPackages, List cartonMarks) { + public Item(Long id, Long orderId, String inboundCode, String skuCode, String productName, int availablePackagesSnapshot, int discardPackages) { + this(id, orderId, inboundCode, skuCode, productName, availablePackagesSnapshot, discardPackages, List.of()); + } + } public record History(String fromStatus, String toStatus, String operatorId, String remark, LocalDateTime createdAt) {} diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardApplication.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardApplication.java index 369ece1f4..0997f55a0 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardApplication.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardApplication.java @@ -28,6 +28,7 @@ public class CargoDiscardApplication { private String createdBy; private String reviewedBy; private String reviewRemark; + private LocalDateTime customerConfirmedAt; private LocalDateTime reviewedAt; private LocalDateTime createdAt; private LocalDateTime updatedAt; diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardCarton.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardCarton.java index b8319c505..2e4f89bbb 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardCarton.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardCarton.java @@ -15,6 +15,7 @@ public class CargoDiscardCarton { private Long itemId; private String customerId; private Long cartonId; + private String sourceType; private String cartonMark; private LocalDateTime createdAt; } diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardItem.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardItem.java index bd21d4164..eb89faa2f 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardItem.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/entity/CargoDiscardItem.java @@ -16,6 +16,9 @@ public class CargoDiscardItem { private Long orderId; private String sourceType; private Long returnCartonId; + private Long inventoryPositionId; + private String cartonMarksJson; + private Boolean cartonScanRequired; private String inboundCode; private Long profileId; private Long skuInventoryId; diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/mapper/CargoDiscardInventoryMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/mapper/CargoDiscardInventoryMapper.java index 6b642d1da..67cad5b89 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/discard/mapper/CargoDiscardInventoryMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/discard/mapper/CargoDiscardInventoryMapper.java @@ -12,6 +12,66 @@ import java.util.List; @Mapper public interface CargoDiscardInventoryMapper { + + @Select("SELECT p.* FROM ll_inventory_position p WHERE p.customer_id=#{customerId} AND p.id=#{positionId} FOR UPDATE") + com.baiyue.lastleg.inventory.entity.InventoryPosition lockGenericPosition(@Param("customerId") String customerId, @Param("positionId") Long positionId); + + @Select(""" + SELECT c.id,c.carton_mark,c.sku_code,'INBOUND' source_type + FROM ll_inbound_plan_carton c + JOIN ll_inventory_balance b ON b.customer_id=c.customer_id AND b.inbound_order_id=c.order_id + JOIN ll_inventory_position p ON p.customer_id=b.customer_id AND p.balance_id=b.id AND p.pallet_id=c.warehouse_pallet_id + WHERE p.customer_id=#{customerId} AND p.id=#{positionId} AND c.status='AVAILABLE' AND c.received_at IS NOT NULL + AND COALESCE(b.destination_warehouse_code,'')=COALESCE(c.destination_warehouse_code,'') + UNION ALL + SELECT c.id,c.carton_mark,i.sku_code,'TRANSFER' source_type + FROM ll_inventory_position p + JOIN ll_inventory_balance b ON b.customer_id=p.customer_id AND b.id=p.balance_id + JOIN ll_warehouse_transfer_order t ON t.customer_id=p.customer_id AND t.inbound_order_id=b.inbound_order_id + AND t.transfer_no=p.batch_no AND t.operating_warehouse_id=p.overseas_warehouse_id + JOIN ll_warehouse_transfer_carton c ON c.customer_id=t.customer_id AND c.transfer_order_id=t.id AND c.status='EXPECTED' + JOIN ll_warehouse_transfer_item i ON i.customer_id=c.customer_id AND i.id=c.transfer_item_id + WHERE p.customer_id=#{customerId} AND p.id=#{positionId} + AND (SELECT COUNT(*) FROM ll_inventory_position current_position + WHERE current_position.customer_id=p.customer_id AND current_position.balance_id=p.balance_id + AND current_position.batch_no=p.batch_no AND current_position.overseas_warehouse_id=p.overseas_warehouse_id + AND current_position.available_packages+current_position.hold_packages+current_position.allocated_packages+current_position.picked_packages>0)=1 + ORDER BY id + """) + List genericCartons(@Param("customerId") String customerId, @Param("positionId") Long positionId); + + @Update("UPDATE ll_warehouse_transfer_carton SET status=#{toStatus},updated_at=NOW(3) " + + "WHERE customer_id=#{customerId} AND id=#{cartonId} AND status=#{fromStatus}") + int changeTransferCartonStatus(@Param("customerId") String customerId, @Param("cartonId") Long cartonId, + @Param("fromStatus") String fromStatus, @Param("toStatus") String toStatus); + + @Update("UPDATE ll_inbound_plan_carton SET status=#{toStatus},version=version+1,updated_at=NOW(3) " + + "WHERE customer_id=#{customerId} AND id=#{cartonId} AND status=#{fromStatus}") + int changeGenericCartonStatus(@Param("customerId") String customerId, @Param("cartonId") Long cartonId, + @Param("fromStatus") String fromStatus, @Param("toStatus") String toStatus); + + @Select("SELECT c.* FROM ll_dropship_carton c WHERE c.customer_id=#{customerId} AND c.order_id=#{orderId} AND c.status='AVAILABLE' ORDER BY c.profile_id,c.id") + List availableOrderCartons(@Param("customerId") String customerId, @Param("orderId") Long orderId); + + @Select("") + List lockSelected(@Param("customerId") String customerId, @Param("orderId") Long orderId, + @Param("skuCode") String skuCode, @Param("cartonIds") List cartonIds); + + @Select("") + List genericPositions(@Param("customerId") String customerId, @Param("keyword") String keyword); + + @Select("SELECT COUNT(*) FROM ll_dropship_order_profile WHERE customer_id=#{customerId} AND inventory_position_id=#{positionId}") + long isDropshipPosition(@Param("customerId") String customerId, @Param("positionId") Long positionId); + + @Select("SELECT DISTINCT carton_mark FROM ll_inventory_ledger WHERE customer_id=#{customerId} AND position_id=#{positionId} " + + "AND business_type IN ('STOCK_IN','RETURN_STOCK_IN') AND carton_mark IS NOT NULL AND carton_mark<>'' ORDER BY carton_mark") + List looseCartonMarks(@Param("customerId") String customerId, @Param("positionId") Long positionId); @Select("