feat: 揽收方向与地址类型,补充迁移并清理已落地 SQL
All checks were successful
Build and Deploy / deploy (push) Successful in 1m47s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-09-13 23:34:55 +08:00
parent 61d1502148
commit 8d1e3ab17f
26 changed files with 251 additions and 1059 deletions

6
db.sql
View File

@ -233,7 +233,7 @@ CREATE TABLE `t_order_file` (
CREATE TABLE `t_customer_sender_address` (
`Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`CustomerId` INT NOT NULL COMMENT '归属客户 t_customer.Id',
`AddressType` VARCHAR(16) NOT NULL DEFAULT 'sender' COMMENT '地址类型:sender发件/return退件/receiver收件',
`AddressType` VARCHAR(16) NOT NULL DEFAULT 'sender' COMMENT '地址类型:sender国内发件/return国内退件/pickup国内揽收/receiver海外收件',
`AddressName` VARCHAR(64) NULL COMMENT '地址别名',
`SenderName` VARCHAR(50) NOT NULL COMMENT '联系人姓名',
`Company` VARCHAR(255) NULL COMMENT '公司',
@ -1850,7 +1850,8 @@ CREATE TABLE `t_pickup_order` (
`CustomerId` INT NOT NULL COMMENT '客户Id',
`OrganizationId` CHAR(36) NULL COMMENT '数据归属组织',
`SecretLevel` TINYINT NOT NULL DEFAULT 2 COMMENT '数据密级 1-4',
`SenderAddressId` INT NOT NULL COMMENT '发件地址簿Id',
`SenderAddressId` INT NOT NULL COMMENT '客户揽收地址簿Id',
`Direction` VARCHAR(16) NOT NULL DEFAULT 'forward' COMMENT 'forward正向(客户→仓)/reverse逆向(仓→客户)',
`SenderName` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '取件联系人快照',
`SenderCompany` VARCHAR(255) NULL COMMENT '公司快照',
`SenderCountry` INT NULL COMMENT '国家 t_country.Id 快照',
@ -1899,6 +1900,7 @@ CREATE TABLE `t_pickup_order` (
UNIQUE KEY `uk_pickup_no` (`PickupNo`),
UNIQUE KEY `uk_pickup_request_id` (`RequestId`),
KEY `idx_pickup_customer_status` (`CustomerId`, `Status`, `CreateTime`),
KEY `idx_pickup_direction_status` (`Direction`, `Status`, `CreateTime`),
KEY `idx_pickup_warehouse_time` (`WarehouseId`, `ExpectPickupTime`),
KEY `idx_pickup_pay` (`PayStatus`),
KEY `idx_pickup_settle` (`SettlementStatus`),

View File

@ -1,80 +0,0 @@
-- 员工档案「岗位 / 职级」字典初始数据(幂等:已存在同 DictType+DictCode 则跳过)
-- dictType: employee_position / employee_job_level
-- MySQL 5.7+ / 8.0
SET NAMES utf8mb4;
-- ========== 岗位 employee_position ==========
INSERT INTO `t_dict_type` (`DictType`, `Remark`, `TypeSort`, `IsDeleted`, `CreateUserId`)
SELECT 'employee_position', '员工岗位', 0, 0, 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `t_dict_type` WHERE `DictType` = 'employee_position' AND `IsDeleted` = 0
);
INSERT INTO `t_dict` (`DictType`, `DictSort`, `DictCode`, `DictName`, `IsDeleted`, `CreateUserId`)
SELECT v.`DictType`, v.`DictSort`, v.`DictCode`, v.`DictName`, 0, 0
FROM (
SELECT 'employee_position' AS DictType, 1 AS DictSort, 'generalManager' AS DictCode, '总经理' AS DictName
UNION ALL SELECT 'employee_position', 2, 'deputyGeneralManager', '副总经理'
UNION ALL SELECT 'employee_position', 3, 'logisticsAdvisor', '物流顾问'
UNION ALL SELECT 'employee_position', 4, 'csManager', '客服主管'
UNION ALL SELECT 'employee_position', 5, 'csSpecialist', '客服专员'
UNION ALL SELECT 'employee_position', 6, 'opsManager', '运营经理'
UNION ALL SELECT 'employee_position', 7, 'opsSpecialist', '运营专员'
UNION ALL SELECT 'employee_position', 8, 'financeManager', '财务经理'
UNION ALL SELECT 'employee_position', 9, 'financeSpecialist', '财务专员'
UNION ALL SELECT 'employee_position', 10, 'warehouseManager', '仓储主管'
UNION ALL SELECT 'employee_position', 11, 'warehouseClerk', '仓管员'
UNION ALL SELECT 'employee_position', 12, 'customsSpecialist', '关务专员'
UNION ALL SELECT 'employee_position', 13, 'productManager', '产品经理'
UNION ALL SELECT 'employee_position', 14, 'techEngineer', '技术工程师'
UNION ALL SELECT 'employee_position', 15, 'hrAdmin', '人事行政'
UNION ALL SELECT 'employee_position', 16, 'marketingSpecialist', '市场专员'
UNION ALL SELECT 'employee_position', 17, 'dispatcher', '调度员'
) AS v
WHERE NOT EXISTS (
SELECT 1
FROM `t_dict` d
WHERE d.`DictType` = v.`DictType`
AND d.`DictCode` = v.`DictCode`
AND d.`IsDeleted` = 0
);
UPDATE `t_dict`
SET `IsDeleted` = 1,
`UpdateTime` = NOW()
WHERE `DictType` = 'employee_position'
AND `DictCode` IN (
'salesDirector',
'salesManager',
'salesSpecialist',
'logisticsAdvisorDirector',
'logisticsAdvisorManager'
)
AND `IsDeleted` = 0;
-- ========== 职级 employee_job_level(一级~五级) ==========
INSERT INTO `t_dict_type` (`DictType`, `Remark`, `TypeSort`, `IsDeleted`, `CreateUserId`)
SELECT 'employee_job_level', '员工职级', 0, 0, 0
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM `t_dict_type` WHERE `DictType` = 'employee_job_level' AND `IsDeleted` = 0
);
INSERT INTO `t_dict` (`DictType`, `DictSort`, `DictCode`, `DictName`, `IsDeleted`, `CreateUserId`)
SELECT v.`DictType`, v.`DictSort`, v.`DictCode`, v.`DictName`, 0, 0
FROM (
SELECT 'employee_job_level' AS DictType, 1 AS DictSort, '1' AS DictCode, '一级' AS DictName
UNION ALL SELECT 'employee_job_level', 2, '2', '二级'
UNION ALL SELECT 'employee_job_level', 3, '3', '三级'
UNION ALL SELECT 'employee_job_level', 4, '4', '四级'
UNION ALL SELECT 'employee_job_level', 5, '5', '五级'
) AS v
WHERE NOT EXISTS (
SELECT 1
FROM `t_dict` d
WHERE d.`DictType` = v.`DictType`
AND d.`DictCode` = v.`DictCode`
AND d.`IsDeleted` = 0
);

View File

@ -0,0 +1,45 @@
-- 存量库:为问题模板补充处理人字段(与 db.sql / IssueTemplate 实体对齐)
-- 可重复执行;仅在列不存在时 ADD。
-- 目标表:t_issue_template
SET @db := DATABASE();
-- HandlerType
SET @exists := (
SELECT COUNT(1)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_issue_template'
AND COLUMN_NAME = 'HandlerType'
);
SET @sql := IF(
@exists = 0,
'ALTER TABLE `t_issue_template` ADD COLUMN `HandlerType` VARCHAR(16) NULL COMMENT ''处理人类型:customer=订单所属客户,user=指定用户'' AFTER `NotifyMethod`',
'SELECT ''HandlerType already exists'' AS info'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- HandlerUserId
SET @exists := (
SELECT COUNT(1)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_issue_template'
AND COLUMN_NAME = 'HandlerUserId'
);
SET @sql := IF(
@exists = 0,
'ALTER TABLE `t_issue_template` ADD COLUMN `HandlerUserId` INT NULL COMMENT ''指定处理人用户Id(HandlerType=user 时必填)'' AFTER `HandlerType`',
'SELECT ''HandlerUserId already exists'' AS info'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 历史数据默认按「指定用户」语义;无处理人时可在页面再编辑
UPDATE `t_issue_template`
SET `HandlerType` = 'user'
WHERE (`HandlerType` IS NULL OR `HandlerType` = '')
AND `IsDeleted` = 0;

View File

@ -0,0 +1,16 @@
-- 揽收方向 + 客户地址类型扩展(国内揽收)
-- 正向 forward:客户揽收地址 → 仓库
-- 逆向 reverse:仓库 → 客户揽收地址
ALTER TABLE `t_pickup_order`
ADD COLUMN `Direction` VARCHAR(16) NOT NULL DEFAULT 'forward'
COMMENT 'forward正向(客户→仓)/reverse逆向(仓→客户)'
AFTER `SenderAddressId`;
ALTER TABLE `t_pickup_order`
ADD KEY `idx_pickup_direction_status` (`Direction`, `Status`, `CreateTime`);
-- 地址类型注释更新(列已存在,仅说明)
ALTER TABLE `t_customer_sender_address`
MODIFY COLUMN `AddressType` VARCHAR(16) NOT NULL DEFAULT 'sender'
COMMENT 'sender国内发件/return国内退件/pickup国内揽收/receiver海外收件';

View File

@ -1,36 +0,0 @@
-- t_sales_product:官网线路展示排序(幂等;列已存在则跳过)
-- 数值越小越靠前;默认 0
SET @db := DATABASE();
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_sales_product'
AND COLUMN_NAME = 'RouteSort'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_sales_product` ADD COLUMN `RouteSort` INT NOT NULL DEFAULT 0 COMMENT ''官网线路排序,越小越靠前'' AFTER `TradeTerms`',
'SELECT ''skip RouteSort'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @idx := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_sales_product'
AND INDEX_NAME = 'idx_sp_route_sort'
);
SET @sql_idx := IF(
@idx = 0,
'ALTER TABLE `t_sales_product` ADD KEY `idx_sp_route_sort` (`RouteSort`, `IsActive`)',
'SELECT ''skip idx_sp_route_sort'' AS msg'
);
PREPARE stmt_idx FROM @sql_idx;
EXECUTE stmt_idx;
DEALLOCATE PREPARE stmt_idx;

View File

@ -1,81 +0,0 @@
-- 9610 商品明细命名对齐 t_order_declaration(幂等)
-- ItemNo→Sku, ItemName→CnName, Gcode→ExHsCode, Price→UnitPrice, Qty→Quantity,
-- TotalAmount→Amount, DeclareUnit→Unit
-- 海关专属保留:Gmodel / Barcode / DestCountry / ItemCurrency / LegalQty / LegalUnit / Freight / SortNo
SET @db := DATABASE();
-- ItemNo → Sku
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='ItemNo');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Sku');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `ItemNo` `Sku` VARCHAR(32) NOT NULL DEFAULT '''' COMMENT ''SKU(对齐 t_order_declaration.Sku / 上游 itemNo)''',
'SELECT ''skip ItemNo->Sku'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ItemName → CnName
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='ItemName');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='CnName');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `ItemName` `CnName` VARCHAR(250) NOT NULL DEFAULT '''' COMMENT ''中文品名(对齐 t_order_declaration.CnName / 上游 itemName)''',
'SELECT ''skip ItemName->CnName'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Gcode → ExHsCode
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Gcode');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='ExHsCode');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `Gcode` `ExHsCode` VARCHAR(10) NULL COMMENT ''出口海关编码(对齐 t_order_declaration.ExHsCode / 上游 gcode)''',
'SELECT ''skip Gcode->ExHsCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Price → UnitPrice
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Price');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='UnitPrice');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `Price` `UnitPrice` DECIMAL(19,5) NOT NULL DEFAULT 0 COMMENT ''单价(对齐 t_order_declaration.UnitPrice)''',
'SELECT ''skip Price->UnitPrice'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- TotalAmount → Amount(可能尚未存在 TotalAmount)
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='TotalAmount');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Amount');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `TotalAmount` `Amount` DECIMAL(19,5) NULL COMMENT ''总价(对齐 t_order_declaration.Amount / 上游 totalPrice)''',
'SELECT ''skip TotalAmount->Amount'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Amount');
SET @sql := IF(@hasNew=0,
'ALTER TABLE `t_9610_order_item` ADD COLUMN `Amount` DECIMAL(19,5) NULL COMMENT ''总价(对齐 t_order_declaration.Amount)'' AFTER `UnitPrice`',
'SELECT ''skip add Amount'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Qty → Quantity
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Qty');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Quantity');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `Qty` `Quantity` DECIMAL(19,5) NOT NULL DEFAULT 0 COMMENT ''数量(对齐 t_order_declaration.Quantity,精度保留海关小数)''',
'SELECT ''skip Qty->Quantity'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- DeclareUnit → Unit
SET @hasOld := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='DeclareUnit');
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Unit');
SET @sql := IF(@hasOld>0 AND @hasNew=0,
'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `DeclareUnit` `Unit` VARCHAR(3) NULL COMMENT ''计量单位(对齐 t_order_declaration.Unit / 上游 unit)''',
'SELECT ''skip DeclareUnit->Unit'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @hasNew := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Unit');
SET @sql := IF(@hasNew=0,
'ALTER TABLE `t_9610_order_item` ADD COLUMN `Unit` VARCHAR(3) NULL COMMENT ''计量单位(对齐 t_order_declaration.Unit)'' AFTER `LegalQty`',
'SELECT ''skip add Unit'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Gmodel 注释:海关申报要素(由运单 Model/Specifications/Attributes/Material 拼接)
SET @has := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Gmodel');
SET @sql := IF(@has>0,
'ALTER TABLE `t_9610_order_item` MODIFY COLUMN `Gmodel` VARCHAR(255) NULL COMMENT ''申报要素(海关;由运单型号/规格等拼接,上游 gmodel)''',
'SELECT ''skip Gmodel comment'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

View File

@ -1,118 +0,0 @@
-- 9610 单号命名对齐运单 t_order(幂等)
-- ReferenceNo → ClientNo(客户单号)
-- LogisticsNo 并入 ServiceNo(运单号)后删除 LogisticsNo
SET @db := DATABASE();
-- 1) ReferenceNo → ClientNo
SET @hasRef := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ReferenceNo'
);
SET @hasClient := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ClientNo'
);
SET @sql := IF(
@hasRef > 0 AND @hasClient = 0,
'ALTER TABLE `t_9610_order` CHANGE COLUMN `ReferenceNo` `ClientNo` VARCHAR(48) NOT NULL DEFAULT '''' COMMENT ''客户单号(对齐 t_order.ClientNo / 上游 referenceNo)''',
'SELECT ''skip ReferenceNo->ClientNo'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 索引名顺带调整(旧 idx_9610_ref → idx_9610_client_no)
SET @idxRef := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND INDEX_NAME='idx_9610_ref'
);
SET @idxClient := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND INDEX_NAME='idx_9610_client_no'
);
SET @sql := IF(
@idxRef > 0 AND @idxClient = 0,
'ALTER TABLE `t_9610_order` RENAME INDEX `idx_9610_ref` TO `idx_9610_client_no`',
'SELECT ''skip rename idx_9610_ref'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @idxClient := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND INDEX_NAME='idx_9610_client_no'
);
SET @sql := IF(
@idxClient = 0,
'ALTER TABLE `t_9610_order` ADD KEY `idx_9610_client_no` (`ClientNo`)',
'SELECT ''skip add idx_9610_client_no'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 2) LogisticsNo → 回填 ServiceNo,再删列
SET @hasLog := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='LogisticsNo'
);
SET @sql := IF(
@hasLog > 0,
'UPDATE `t_9610_order` SET `ServiceNo` = NULLIF(TRIM(`LogisticsNo`), '''') WHERE (`ServiceNo` IS NULL OR TRIM(`ServiceNo`) = '''') AND `LogisticsNo` IS NOT NULL AND TRIM(`LogisticsNo`) <> ''''',
'SELECT ''skip backfill ServiceNo'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @idxLog := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND INDEX_NAME='idx_9610_logistics'
);
SET @sql := IF(
@idxLog > 0,
'ALTER TABLE `t_9610_order` DROP INDEX `idx_9610_logistics`',
'SELECT ''skip drop idx_9610_logistics'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @hasLog := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='LogisticsNo'
);
SET @sql := IF(
@hasLog > 0,
'ALTER TABLE `t_9610_order` DROP COLUMN `LogisticsNo`',
'SELECT ''skip drop LogisticsNo'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ServiceNo 索引(检索)
SET @idxSvc := (
SELECT COUNT(*) FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND INDEX_NAME='idx_9610_service_no'
);
SET @sql := IF(
@idxSvc = 0,
'ALTER TABLE `t_9610_order` ADD KEY `idx_9610_service_no` (`ServiceNo`)',
'SELECT ''skip idx_9610_service_no'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- OrderNo 注释对齐:海关下游订单编号(非运单 DownstreamServiceNo)
SET @hasOrderNo := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='OrderNo'
);
SET @sql := IF(
@hasOrderNo > 0,
'ALTER TABLE `t_9610_order` MODIFY COLUMN `OrderNo` VARCHAR(32) NULL COMMENT ''海关下游订单编号(申报回写,非 t_order.DownstreamServiceNo)''',
'SELECT ''skip OrderNo comment'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- DownstreamRefNo 注释
SET @hasDr := (
SELECT COUNT(*) FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='DownstreamRefNo'
);
SET @sql := IF(
@hasDr > 0,
'ALTER TABLE `t_9610_order` MODIFY COLUMN `DownstreamRefNo` VARCHAR(32) NULL COMMENT ''申报回写的 referenceNo 快照''',
'SELECT ''skip DownstreamRefNo comment'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

View File

@ -1,170 +0,0 @@
-- 9610:补齐「获取清单数据」回写字段(幂等;列已存在则跳过)
-- 字段名为 OMS 自有命名,与上游 CEB 字段对照见注释
SET @db := DATABASE();
-- ========== t_9610_order ==========
-- EnterpriseBizNo ← copNo 企业唯一编号
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EnterpriseBizNo');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `EnterpriseBizNo` VARCHAR(48) NULL COMMENT ''企业唯一编号(上游 copNo)'' AFTER `DownstreamRefNo`', 'SELECT ''skip EnterpriseBizNo'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ManifestNo ← invtNo 清单编号
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ManifestNo');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `ManifestNo` VARCHAR(48) NULL COMMENT ''清单编号(上游 invtNo)'' AFTER `EnterpriseBizNo`', 'SELECT ''skip ManifestNo'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ClearanceTime ← clearanceTime 结关日期(原文,格式不固定)
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ClearanceTime');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `ClearanceTime` VARCHAR(48) NULL COMMENT ''结关日期原文'' AFTER `ManifestNo`', 'SELECT ''skip ClearanceTime'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- CustomsInboundTime ← warehouseTime 海关入库时间
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='CustomsInboundTime');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `CustomsInboundTime` VARCHAR(48) NULL COMMENT ''海关入库时间原文'' AFTER `ClearanceTime`', 'SELECT ''skip CustomsInboundTime'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- CustomsState ← customsStatus 海关状态
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='CustomsState');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `CustomsState` VARCHAR(4) NULL COMMENT ''海关状态'' AFTER `CustomsInboundTime`', 'SELECT ''skip CustomsState'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- DeclareCustomsCode ← customsCode 申报地海关
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='DeclareCustomsCode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `DeclareCustomsCode` VARCHAR(4) NULL COMMENT ''申报地海关代码'' AFTER `CustomsState`', 'SELECT ''skip DeclareCustomsCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- EbpCode ← ebpCode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EbpCode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `EbpCode` VARCHAR(18) NULL COMMENT ''电商平台代码'' AFTER `DeclareCustomsCode`', 'SELECT ''skip EbpCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- EbpName ← ebpName
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EbpName');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `EbpName` VARCHAR(100) NULL COMMENT ''电商平台名称'' AFTER `EbpCode`', 'SELECT ''skip EbpName'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- LogisticsCorpCode ← logisticsCode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='LogisticsCorpCode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `LogisticsCorpCode` VARCHAR(18) NULL COMMENT ''物流企业代码'' AFTER `EbpName`', 'SELECT ''skip LogisticsCorpCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- LogisticsCorpName ← logisticsName
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='LogisticsCorpName');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `LogisticsCorpName` VARCHAR(100) NULL COMMENT ''物流企业名称'' AFTER `LogisticsCorpCode`', 'SELECT ''skip LogisticsCorpName'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- IeMark ← ieFlag I/E
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='IeMark');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `IeMark` VARCHAR(4) NULL COMMENT ''进出口标记 I/E'' AFTER `LogisticsCorpName`', 'SELECT ''skip IeMark'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ExportPortCode ← portCode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ExportPortCode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `ExportPortCode` VARCHAR(4) NULL COMMENT ''出口口岸代码'' AFTER `IeMark`', 'SELECT ''skip ExportPortCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ExportDate ← ieDate
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ExportDate');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `ExportDate` VARCHAR(32) NULL COMMENT ''出口日期原文'' AFTER `ExportPortCode`', 'SELECT ''skip ExportDate'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- DeclareAgentCode ← agentCode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='DeclareAgentCode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `DeclareAgentCode` VARCHAR(18) NULL COMMENT ''申报企业代码'' AFTER `ExportDate`', 'SELECT ''skip DeclareAgentCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- DeclareAgentName ← agentName
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='DeclareAgentName');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `DeclareAgentName` VARCHAR(100) NULL COMMENT ''申报企业名称'' AFTER `DeclareAgentCode`', 'SELECT ''skip DeclareAgentName'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- TradeModeCode ← tradeMode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='TradeModeCode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `TradeModeCode` VARCHAR(4) NULL COMMENT ''贸易方式代码'' AFTER `DeclareAgentName`', 'SELECT ''skip TradeModeCode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- TransportMode ← trafMode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='TransportMode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `TransportMode` VARCHAR(4) NULL COMMENT ''运输方式代码'' AFTER `TradeModeCode`', 'SELECT ''skip TransportMode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- FreightCurrency ← fCurrency
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='FreightCurrency');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `FreightCurrency` VARCHAR(4) NULL COMMENT ''运费币制'' AFTER `Freight`', 'SELECT ''skip FreightCurrency'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- FreightMark ← fFlag 1率/2单价/3总价
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='FreightMark');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `FreightMark` INT NULL COMMENT ''运费标志 1率2单价3总价'' AFTER `FreightCurrency`', 'SELECT ''skip FreightMark'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- PackageType ← wrapType
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='PackageType');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `PackageType` INT NULL COMMENT ''包装种类代码'' AFTER `FreightMark`', 'SELECT ''skip PackageType'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- PackageQty ← packNo
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='PackageQty');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `PackageQty` INT NULL COMMENT ''件数'' AFTER `PackageType`', 'SELECT ''skip PackageQty'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ManifestSyncTime 最近一次清单回写时间
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ManifestSyncTime');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order` ADD COLUMN `ManifestSyncTime` DATETIME NULL COMMENT ''清单数据最近同步时间'' AFTER `DeclareTime`', 'SELECT ''skip ManifestSyncTime'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- 运费精度对齐上游 DECIMAL(19,5)
SET @colType := (
SELECT COLUMN_TYPE FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='Freight'
);
SET @sql := IF(
@colType IS NOT NULL AND @colType NOT LIKE 'decimal(19,5)%',
'ALTER TABLE `t_9610_order` MODIFY COLUMN `Freight` DECIMAL(19,5) NULL COMMENT ''运费''',
'SELECT ''skip Freight precision'' AS msg'
);
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ManifestNo 索引(幂等)
SET @idx := (SELECT COUNT(*) FROM information_schema.STATISTICS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND INDEX_NAME='idx_9610_manifest');
SET @sql := IF(@idx=0, 'ALTER TABLE `t_9610_order` ADD KEY `idx_9610_manifest` (`ManifestNo`)', 'SELECT ''skip idx_9610_manifest'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ========== t_9610_order_item ==========
-- Barcode ← barCode
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Barcode');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `Barcode` VARCHAR(255) NULL COMMENT ''条形码'' AFTER `Gmodel`', 'SELECT ''skip Barcode'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- DestCountry ← country 目的国
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='DestCountry');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `DestCountry` VARCHAR(255) NULL COMMENT ''目的国(地区)代码'' AFTER `Barcode`', 'SELECT ''skip DestCountry'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- ItemCurrency ← currency
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='ItemCurrency');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `ItemCurrency` VARCHAR(3) NULL COMMENT ''币制'' AFTER `DestCountry`', 'SELECT ''skip ItemCurrency'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- LegalQty ← qty1 法定数量
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='LegalQty');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `LegalQty` DECIMAL(19,5) NULL COMMENT ''法定数量'' AFTER `Quantity`', 'SELECT ''skip LegalQty'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Unit ← unit(对齐运单;旧名 DeclareUnit 由 align_item_fields 迁移)
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Unit');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `Unit` VARCHAR(3) NULL COMMENT ''计量单位'' AFTER `LegalQty`', 'SELECT ''skip Unit'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- LegalUnit ← unit1
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='LegalUnit');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `LegalUnit` VARCHAR(3) NULL COMMENT ''法定计量单位'' AFTER `Unit`', 'SELECT ''skip LegalUnit'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Amount ← totalPrice
SET @col := (SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Amount');
SET @sql := IF(@col=0, 'ALTER TABLE `t_9610_order_item` ADD COLUMN `Amount` DECIMAL(19,5) NULL COMMENT ''总价'' AFTER `UnitPrice`', 'SELECT ''skip Amount'' AS msg');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

View File

@ -1,123 +0,0 @@
-- 9610 汇总申报单(ExportCustomsMode=9610Summary)
-- 幂等:表已存在则跳过
SET @db := DATABASE();
-- t_9610_order
SET @exists := (
SELECT COUNT(*)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 't_9610_order'
);
SET @sql := IF(
@exists = 0,
'CREATE TABLE `t_9610_order` (
`Id` INT NOT NULL AUTO_INCREMENT COMMENT ''主键'',
`OrderId` INT NOT NULL COMMENT ''关联运单 t_order.Id'',
`ServiceNo` VARCHAR(64) NULL COMMENT ''运单号冗余'',
`CustomerId` INT NOT NULL DEFAULT 0 COMMENT ''客户Id'',
`Status` VARCHAR(16) NOT NULL DEFAULT ''pending'' COMMENT ''pending待申报 / declared已申报'',
`PlatformCode` VARCHAR(16) NOT NULL DEFAULT '''' COMMENT ''电商平台'',
`EcomCorpCode` VARCHAR(18) NULL COMMENT ''电商企业代码'',
`EcomCorpName` VARCHAR(100) NULL COMMENT ''电商企业名称'',
`ProducerCode` VARCHAR(18) NULL COMMENT ''生产销售单位代码'',
`ProducerName` VARCHAR(100) NULL COMMENT ''生产销售单位'',
`ClientNo` VARCHAR(48) NOT NULL DEFAULT '''' COMMENT ''客户单号(对齐 t_order.ClientNo)'',
`BusinessType` CHAR(1) NOT NULL DEFAULT ''B'' COMMENT ''业务类型 A简化/B汇总'',
`Region` VARCHAR(10) NULL COMMENT ''区域 SZ/other'',
`AgentDeclare` VARCHAR(2) NULL COMMENT ''是否代理申报 是/否'',
`ActualSellerCode` VARCHAR(18) NULL COMMENT ''实际卖家信用代码'',
`PreRecordFlag` CHAR(1) NULL COMMENT ''汇总预录 0已预录 1未预录'',
`IsSummarySimple` TINYINT NOT NULL DEFAULT 0 COMMENT ''是否汇总简化申报'',
`GrossWeight` DECIMAL(19,5) NOT NULL DEFAULT 0 COMMENT ''毛重KG'',
`Currency` VARCHAR(4) NOT NULL DEFAULT ''CNY'' COMMENT ''币制'',
`DestCountry` VARCHAR(4) NOT NULL DEFAULT '''' COMMENT ''目的国'',
`Freight` DECIMAL(19,5) NULL COMMENT ''运费'',
`FreightCurrency` VARCHAR(4) NULL COMMENT ''运费币制'',
`FreightMark` INT NULL COMMENT ''运费标志 1率2单价3总价'',
`PackageType` INT NULL COMMENT ''包装种类代码'',
`PackageQty` INT NULL COMMENT ''件数'',
`ShipmentNo` VARCHAR(32) NULL COMMENT ''出货单号'',
`CustomsOrderNo` VARCHAR(32) NULL COMMENT ''海关订单号(申报回写)'',
`DownstreamRefNo` VARCHAR(32) NULL COMMENT ''申报回写的 referenceNo 快照'',
`EnterpriseBizNo` VARCHAR(48) NULL COMMENT ''企业唯一编号(上游 copNo)'',
`ManifestNo` VARCHAR(48) NULL COMMENT ''清单编号(上游 invtNo)'',
`ClearanceTime` VARCHAR(48) NULL COMMENT ''结关日期原文'',
`CustomsInboundTime` VARCHAR(48) NULL COMMENT ''海关入库时间原文'',
`CustomsState` VARCHAR(4) NULL COMMENT ''海关状态'',
`DeclareCustomsCode` VARCHAR(4) NULL COMMENT ''申报地海关代码'',
`PlatformCorpCode` VARCHAR(18) NULL COMMENT ''电商平台代码'',
`PlatformName` VARCHAR(100) NULL COMMENT ''电商平台名称'',
`LogisticsCorpCode` VARCHAR(18) NULL COMMENT ''物流企业代码'',
`LogisticsCorpName` VARCHAR(100) NULL COMMENT ''物流企业名称'',
`IeMark` VARCHAR(4) NULL COMMENT ''进出口标记 I/E'',
`ExportPortCode` VARCHAR(4) NULL COMMENT ''出口口岸代码'',
`ExportDate` VARCHAR(32) NULL COMMENT ''出口日期原文'',
`DeclareAgentCode` VARCHAR(18) NULL COMMENT ''申报企业代码'',
`DeclareAgentName` VARCHAR(100) NULL COMMENT ''申报企业名称'',
`TradeModeCode` VARCHAR(4) NULL COMMENT ''贸易方式代码'',
`TransportMode` VARCHAR(4) NULL COMMENT ''运输方式代码'',
`DeclareTime` DATETIME NULL COMMENT ''申报成功时间'',
`ManifestSyncTime` DATETIME NULL COMMENT ''清单数据最近同步时间'',
`FailReason` VARCHAR(512) NULL COMMENT ''最近失败原因'',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT ''软删除'',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '''' COMMENT ''并发戳'',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT ''创建人'',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''创建时间'',
`UpdateUserId` INT NULL COMMENT ''更新人'',
`UpdateTime` DATETIME NULL COMMENT ''更新时间'',
PRIMARY KEY (`Id`),
UNIQUE KEY `uk_9610_order_id` (`OrderId`),
KEY `idx_9610_status_ctime` (`Status`, `CreateTime`),
KEY `idx_9610_service_no` (`ServiceNo`),
KEY `idx_9610_client_no` (`ClientNo`),
KEY `idx_9610_customer` (`CustomerId`, `CreateTime`),
KEY `idx_9610_manifest` (`ManifestNo`)
) COMMENT=''9610汇总申报单''',
'SELECT ''skip t_9610_order'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- t_9610_order_item
SET @exists := (
SELECT COUNT(*)
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = @db AND TABLE_NAME = 't_9610_order_item'
);
SET @sql := IF(
@exists = 0,
'CREATE TABLE `t_9610_order_item` (
`Id` INT NOT NULL AUTO_INCREMENT COMMENT ''主键'',
`Customs9610OrderId` INT NOT NULL COMMENT ''t_9610_order.Id'',
`OrderDeclarationId` INT NULL COMMENT ''溯源 t_order_declaration.Id'',
`Sku` VARCHAR(32) NOT NULL DEFAULT '''' COMMENT ''SKU(对齐 t_order_declaration.Sku)'',
`CnName` VARCHAR(250) NOT NULL DEFAULT '''' COMMENT ''中文品名(对齐 t_order_declaration.CnName)'',
`ExHsCode` VARCHAR(10) NULL COMMENT ''出口海关编码(对齐 t_order_declaration.ExHsCode)'',
`DeclareElement` VARCHAR(255) NULL COMMENT ''申报要素'',
`Barcode` VARCHAR(255) NULL COMMENT ''条形码'',
`DestCountry` VARCHAR(255) NULL COMMENT ''目的国(地区)代码'',
`ItemCurrency` VARCHAR(3) NULL COMMENT ''币制'',
`UnitPrice` DECIMAL(19,5) NOT NULL DEFAULT 0 COMMENT ''单价(对齐 t_order_declaration.UnitPrice)'',
`Amount` DECIMAL(19,5) NULL COMMENT ''总价(对齐 t_order_declaration.Amount)'',
`Quantity` DECIMAL(19,5) NOT NULL DEFAULT 0 COMMENT ''数量(对齐 t_order_declaration.Quantity)'',
`LegalQty` DECIMAL(19,5) NULL COMMENT ''法定数量'',
`Unit` VARCHAR(3) NULL COMMENT ''计量单位(对齐 t_order_declaration.Unit)'',
`LegalUnit` VARCHAR(3) NULL COMMENT ''法定计量单位'',
`Freight` DECIMAL(12,4) NULL COMMENT ''行运费'',
`SortNo` INT NOT NULL DEFAULT 0 COMMENT ''排序'',
`IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT ''软删除'',
`ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '''' COMMENT ''并发戳'',
`CreateUserId` INT NOT NULL DEFAULT 0 COMMENT ''创建人'',
`CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ''创建时间'',
`UpdateUserId` INT NULL COMMENT ''更新人'',
`UpdateTime` DATETIME NULL COMMENT ''更新时间'',
PRIMARY KEY (`Id`),
KEY `idx_9610_item_header` (`Customs9610OrderId`, `IsDeleted`)
) COMMENT=''9610申报商品明细''',
'SELECT ''skip t_9610_order_item'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@ -1,33 +0,0 @@
-- t_9610_order_item 补齐 Fake AggregateRoot 并发戳(幂等)
-- 现象:详情/申报查明细时报 Unknown column 'ConcurrencyStamp' in 'field list'
-- 原因:实体继承 OmsAuditedAggregateRoot → AggregateRoot 含 ConcurrencyStamp,头表有、明细表缺
-- 注意:勿用 DEFAULT (UUID())——Galera/主从会报 Statement is unsafe(副本上 UUID 不一致)
SET @db := DATABASE();
SET @has := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_9610_order_item'
AND COLUMN_NAME = 'ConcurrencyStamp'
);
SET @sql := IF(
@has = 0,
'ALTER TABLE `t_9610_order_item` ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT '''' COMMENT ''并发戳'' AFTER `IsDeleted`',
'SELECT ''skip t_9610_order_item.ConcurrencyStamp'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 已有行补确定性戳(基于主键,主从一致);新写入由 ORM 覆盖
UPDATE `t_9610_order_item`
SET `ConcurrencyStamp` = LOWER(CONCAT(
LPAD(HEX(`Id`), 8, '0'),
'-0000-4000-8000-',
LPAD(HEX(`Id`), 12, '0')
))
WHERE `ConcurrencyStamp` = '' OR `ConcurrencyStamp` IS NULL;

View File

@ -1,90 +0,0 @@
-- 9610 其余字段按业务含义重命名(幂等 CHANGE)
-- 申报头:Ebp→PlatformCode, Ebc*→EcomCorp*, Owner*→Producer*, FormType→BusinessType,
-- IsAgent→AgentDeclare, ActBuyer→ActualSellerCode, SoLabelFlag→PreRecordFlag,
-- IsSimple→IsSummarySimple, Country→DestCountry, BlNo→ShipmentNo,
-- EbpCode/EbpName→PlatformCorpCode/PlatformName, OrderNo→CustomsOrderNo
-- 明细:Gmodel→DeclareElement
SET @db := DATABASE();
-- helper pattern repeated
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='Ebp');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='PlatformCode');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `Ebp` `PlatformCode` VARCHAR(16) NOT NULL DEFAULT '''' COMMENT ''电商平台''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EbcCode');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EcomCorpCode');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `EbcCode` `EcomCorpCode` VARCHAR(18) NULL COMMENT ''电商企业代码''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EbcName');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EcomCorpName');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `EbcName` `EcomCorpName` VARCHAR(100) NULL COMMENT ''电商企业名称''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='OwnerCode');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ProducerCode');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `OwnerCode` `ProducerCode` VARCHAR(18) NULL COMMENT ''生产销售单位代码''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='OwnerName');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ProducerName');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `OwnerName` `ProducerName` VARCHAR(100) NULL COMMENT ''生产销售单位''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='FormType');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='BusinessType');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `FormType` `BusinessType` CHAR(1) NOT NULL DEFAULT ''B'' COMMENT ''业务类型 A简化/B汇总''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='IsAgent');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='AgentDeclare');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `IsAgent` `AgentDeclare` VARCHAR(2) NULL COMMENT ''是否代理申报 是/否''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ActBuyer');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ActualSellerCode');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `ActBuyer` `ActualSellerCode` VARCHAR(18) NULL COMMENT ''实际卖家信用代码''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='SoLabelFlag');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='PreRecordFlag');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `SoLabelFlag` `PreRecordFlag` CHAR(1) NULL COMMENT ''汇总预录 0已预录/1未预录''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='IsSimple');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='IsSummarySimple');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `IsSimple` `IsSummarySimple` TINYINT NOT NULL DEFAULT 0 COMMENT ''是否汇总简化申报''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='Country');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='DestCountry');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `Country` `DestCountry` VARCHAR(4) NOT NULL DEFAULT '''' COMMENT ''目的国''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='BlNo');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='ShipmentNo');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `BlNo` `ShipmentNo` VARCHAR(32) NULL COMMENT ''出货单号''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='OrderNo');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='CustomsOrderNo');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `OrderNo` `CustomsOrderNo` VARCHAR(32) NULL COMMENT ''海关订单号''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EbpCode');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='PlatformCorpCode');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `EbpCode` `PlatformCorpCode` VARCHAR(18) NULL COMMENT ''电商平台代码''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='EbpName');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order' AND COLUMN_NAME='PlatformName');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order` CHANGE COLUMN `EbpName` `PlatformName` VARCHAR(100) NULL COMMENT ''电商平台名称''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;
SET @o:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='Gmodel');
SET @n:=(SELECT COUNT(*) FROM information_schema.COLUMNS WHERE TABLE_SCHEMA=@db AND TABLE_NAME='t_9610_order_item' AND COLUMN_NAME='DeclareElement');
SET @sql:=IF(@o>0 AND @n=0,'ALTER TABLE `t_9610_order_item` CHANGE COLUMN `Gmodel` `DeclareElement` VARCHAR(255) NULL COMMENT ''申报要素''','SELECT 1');
PREPARE s FROM @sql; EXECUTE s; DEALLOCATE PREPARE s;

View File

@ -1,27 +0,0 @@
-- t_order_declaration.SkuImage:库内 SKU 选图后写入签名 URL 易超 VARCHAR(255)
-- 后端已改为存 storage key;列宽对齐仓库 SkuImageUrl,兼容外链
SET @db := DATABASE();
SET @need := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_declaration'
AND COLUMN_NAME = 'SkuImage'
AND (
DATA_TYPE <> 'varchar'
OR CHARACTER_MAXIMUM_LENGTH IS NULL
OR CHARACTER_MAXIMUM_LENGTH < 512
)
);
SET @sql := IF(
@need > 0,
'ALTER TABLE `t_order_declaration` MODIFY COLUMN `SkuImage` VARCHAR(512) NULL COMMENT ''图片(存 storage key 或短 URL)''',
'SELECT ''skip t_order_declaration.SkuImage'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@ -1,118 +0,0 @@
-- 订单异常事件表:补齐 Handler* / ConcurrencyStamp(幂等;列已存在则自动跳过)
-- 修复:Unknown column 'HandlerNames' / 'ConcurrencyStamp' in 'field list'
-- MySQL 5.7+ / 8.0
SET @db := DATABASE();
-- HandlerNames
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'HandlerNames'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_order_exception_event` ADD COLUMN `HandlerNames` VARCHAR(256) NULL COMMENT ''处理人快照''',
'SELECT ''skip HandlerNames'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- HandlerType
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'HandlerType'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_order_exception_event` ADD COLUMN `HandlerType` VARCHAR(16) NULL COMMENT ''处理人类型''',
'SELECT ''skip HandlerType'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- HandlerUserId
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'HandlerUserId'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_order_exception_event` ADD COLUMN `HandlerUserId` INT NULL COMMENT ''处理人用户Id(customer 时为订单客户账号)''',
'SELECT ''skip HandlerUserId'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- ConcurrencyStamp(AggregateRoot 并发戳;避免 DEFAULT(UUID()) 触发 1674 复制不安全)
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'ConcurrencyStamp'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_order_exception_event` ADD COLUMN `ConcurrencyStamp` CHAR(36) NULL COMMENT ''并发戳''',
'SELECT ''skip ConcurrencyStamp add'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'ConcurrencyStamp'
);
SET @sql := IF(
@col > 0,
'UPDATE `t_order_exception_event`
SET `ConcurrencyStamp` = LOWER(CONCAT(
LPAD(HEX(`Id`), 8, ''0''),
''-0000-4000-8000-'',
LPAD(HEX(`Id` * 9973), 12, ''0'')
))
WHERE `ConcurrencyStamp` IS NULL OR `ConcurrencyStamp` = ''''',
'SELECT ''skip ConcurrencyStamp backfill'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'ConcurrencyStamp'
);
SET @isNullable := (
SELECT IFNULL(MAX(CASE WHEN IS_NULLABLE = 'YES' THEN 1 ELSE 0 END), 0)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order_exception_event'
AND COLUMN_NAME = 'ConcurrencyStamp'
);
SET @sql := IF(
@col > 0 AND @isNullable = 1,
'ALTER TABLE `t_order_exception_event` MODIFY COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL COMMENT ''并发戳''',
'SELECT ''skip ConcurrencyStamp not null'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@ -1,70 +0,0 @@
-- 代发订单:t_order 履约类型字段(幂等;列/索引已存在则自动跳过)
-- MySQL 5.7+ / 8.0
SET @db := DATABASE();
-- FulfillmentType
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order'
AND COLUMN_NAME = 'FulfillmentType'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_order` ADD COLUMN `FulfillmentType` VARCHAR(16) NULL DEFAULT ''direct'' COMMENT ''履约类型 direct/warehouse'' AFTER `AdditionalServices`',
'SELECT ''skip FulfillmentType'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- FulfillmentSource
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order'
AND COLUMN_NAME = 'FulfillmentSource'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_order` ADD COLUMN `FulfillmentSource` VARCHAR(32) NULL COMMENT ''代发来源 storeFulfill/postBind'' AFTER `FulfillmentType`',
'SELECT ''skip FulfillmentSource'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- idx_ord_fulfillment_customer
SET @idx := (
SELECT COUNT(*)
FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_order'
AND INDEX_NAME = 'idx_ord_fulfillment_customer'
);
SET @sql := IF(
@idx = 0,
'ALTER TABLE `t_order` ADD KEY `idx_ord_fulfillment_customer` (`FulfillmentType`, `CustomerId`, `OrderStatus`)',
'SELECT ''skip idx_ord_fulfillment_customer'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 历史:已有绑定行的订单标记为 warehouse
UPDATE `t_order` o
INNER JOIN (
SELECT DISTINCT b.`OrderId`
FROM `t_order_stock_bind` b
WHERE b.`IsDeleted` = 0
AND b.`Status` IN ('bound', 'deducted')
) x ON x.`OrderId` = o.`Id`
SET o.`FulfillmentType` = 'warehouse';
-- 其余空值兜底为 direct
UPDATE `t_order`
SET `FulfillmentType` = 'direct'
WHERE `FulfillmentType` IS NULL OR `FulfillmentType` = '';

View File

@ -1,49 +0,0 @@
-- 揽收明细:补齐运单号/客户单号快照(幂等;列已存在则跳过)
-- 对应实体 PickupOrderLine.ServiceNo / ClientNo
-- 报错 Unknown column 'ServiceNo' in 'field list' 时执行本脚本
-- MySQL 5.7+ / 8.0
SET @db := DATABASE();
-- ServiceNo
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_pickup_order_line'
AND COLUMN_NAME = 'ServiceNo'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_pickup_order_line` ADD COLUMN `ServiceNo` VARCHAR(64) NULL COMMENT ''运单号快照(便于列表)'' AFTER `OrderId`',
'SELECT ''skip ServiceNo'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- ClientNo
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 't_pickup_order_line'
AND COLUMN_NAME = 'ClientNo'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `t_pickup_order_line` ADD COLUMN `ClientNo` VARCHAR(64) NULL COMMENT ''客户单号快照'' AFTER `ServiceNo`',
'SELECT ''skip ClientNo'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 存量行从订单表回填快照(仅空值)
UPDATE `t_pickup_order_line` pl
INNER JOIN `t_order` o ON o.`Id` = pl.`OrderId`
SET
pl.`ServiceNo` = IFNULL(NULLIF(pl.`ServiceNo`, ''), o.`ServiceNo`),
pl.`ClientNo` = IFNULL(NULLIF(pl.`ClientNo`, ''), o.`ClientNo`)
WHERE pl.`IsDeleted` = 0
AND (pl.`ServiceNo` IS NULL OR pl.`ServiceNo` = '' OR pl.`ClientNo` IS NULL OR pl.`ClientNo` = '');

View File

@ -1,20 +0,0 @@
-- user 表:企业微信客服接入链接(幂等;列已存在则跳过)
-- MySQL 5.7+ / 8.0
SET @db := DATABASE();
SET @col := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @db
AND TABLE_NAME = 'user'
AND COLUMN_NAME = 'WecomKfUrl'
);
SET @sql := IF(
@col = 0,
'ALTER TABLE `user` ADD COLUMN `WecomKfUrl` VARCHAR(512) NULL COMMENT ''企业微信客服接入链接''',
'SELECT ''skip WecomKfUrl'' AS msg'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

View File

@ -187,6 +187,11 @@ public class OrderPickupCreateInput
[Required]
public int SenderAddressId { get; set; }
/// <summary>
/// 揽收方向:forward / reverse。默认正向。
/// </summary>
public string? Direction { get; set; }
[Required]
public DateTime PickupTime { get; set; }

View File

@ -170,6 +170,11 @@ public class OrderParcelCreateInput
/// </summary>
public DateTime? ExpectPickupTime { get; set; }
/// <summary>
/// 揽收方向:forward / reverse(上门揽收挂载揽收单时使用)。
/// </summary>
public string? PickupDirection { get; set; }
/// <summary>
/// 承运商编码(可后补)。
/// </summary>

View File

@ -14,6 +14,11 @@ public class PickupOrderCreateInput
[Required]
public int SenderAddressId { get; set; }
/// <summary>
/// 揽收方向:forward 正向(客户地址→仓库)/ reverse 逆向(仓库→客户地址)。默认正向。
/// </summary>
public string? Direction { get; set; }
[Required]
public int WarehouseId { get; set; }
@ -102,6 +107,11 @@ public class PickupOrderListInput
public int? WarehouseId { get; set; }
/// <summary>
/// 揽收方向:forward / reverse。
/// </summary>
public string? Direction { get; set; }
public DateTime? CreateTimeStart { get; set; }
public DateTime? CreateTimeEnd { get; set; }
@ -208,6 +218,11 @@ public class PickupOrderOutput
public int SenderAddressId { get; set; }
/// <summary>
/// 揽收方向:forward / reverse。
/// </summary>
public string Direction { get; set; } = "forward";
public string SenderName { get; set; } = string.Empty;
public string? SenderPhone { get; set; }

View File

@ -22,7 +22,7 @@ public partial class OrderService
if (input.SenderAddressId <= 0)
{
throw new BusinessException("发件地址不能为空");
throw new BusinessException("揽收地址不能为空");
}
if (string.IsNullOrWhiteSpace(input.ProductCode))
@ -55,15 +55,15 @@ public partial class OrderService
var senderAddress = await CustomerSenderAddressRepository.GetOwnedAsync(input.SenderAddressId, customerId);
if (senderAddress == null)
{
throw new BusinessException("发件地址不存在");
throw new BusinessException("揽收地址不存在");
}
var addressType = string.IsNullOrWhiteSpace(senderAddress.AddressType)
? CustomerAddressTypeCodes.Sender
: senderAddress.AddressType;
if (!string.Equals(addressType, CustomerAddressTypeCodes.Sender, StringComparison.OrdinalIgnoreCase))
if (!CustomerAddressTypeCodes.IsPickupEligible(addressType))
{
throw new BusinessException("揽收订单仅可选择发件地址");
throw new BusinessException("揽收订单请选择「国内揽收」类型地址");
}
var warehouse = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == input.WarehouseId);

View File

@ -541,7 +541,7 @@ public partial class OrderService : ApplicationService
if (input.SenderAddressId is not > 0)
{
output.PickupCreateError = "上门揽收需选择发件地址";
output.PickupCreateError = "上门揽收需选择揽收地址";
return;
}
@ -564,6 +564,7 @@ public partial class OrderService : ApplicationService
{
CustomerId = input.CustomerId,
SenderAddressId = input.SenderAddressId.Value,
Direction = PickupDirectionCodes.NormalizeOrDefault(input.PickupDirection),
WarehouseId = input.WarehouseId.Value,
CarrierCode = input.CarrierCode,
CarrierService = input.CarrierService,

View File

@ -23,13 +23,71 @@ public static class PickupOrderParcelBuilder
? $"PK{DateTime.Now:yyyyMMddHHmmss}{Random.Shared.Next(1000, 9999)}"
: input.ClientNo.Trim();
var receiverName = string.IsNullOrWhiteSpace(warehouse.Recipient)
var warehouseContact = string.IsNullOrWhiteSpace(warehouse.Recipient)
? warehouse.WarehouseName
: warehouse.Recipient!.Trim();
var street = string.IsNullOrWhiteSpace(warehouse.ShippingAddress)
var warehouseStreet = string.IsNullOrWhiteSpace(warehouse.ShippingAddress)
? warehouse.WarehouseName
: warehouse.ShippingAddress!.Trim();
var isReverse = string.Equals(
PickupDirectionCodes.NormalizeOrDefault(input.Direction),
PickupDirectionCodes.Reverse,
StringComparison.OrdinalIgnoreCase);
// 正向:客户揽收地址 → 仓库;逆向:仓库 → 客户揽收地址
var sender = isReverse
? new OrderParcelSenderInput
{
SenderName = warehouseContact,
Phone = warehouse.ContactPhone,
CountryCode = "CN",
StreetAddress1 = warehouseStreet,
ZipCode = "000000"
}
: new OrderParcelSenderInput
{
SenderName = senderAddress.SenderName,
Company = senderAddress.Company,
Phone = senderAddress.Phone,
TelePhone = senderAddress.TelePhone,
Email = senderAddress.Email,
CountryCode = senderCountryCode ?? "CN",
Province = senderAddress.Province,
City = senderAddress.City,
ZipCode = senderAddress.ZipCode,
StreetAddress1 = senderAddress.StreetAddress1,
StreetAddress2 = senderAddress.StreetAddress2,
StreetAddress3 = senderAddress.StreetAddress3,
HouseNumber = senderAddress.HouseNumber
};
var receiver = isReverse
? new OrderParcelReceiverInput
{
RecipientsName = senderAddress.SenderName,
CompanyName = senderAddress.Company,
Phone = senderAddress.Phone,
TelePhone = senderAddress.TelePhone,
Email = senderAddress.Email,
CountryCode = senderCountryCode ?? "CN",
Province = senderAddress.Province,
City = senderAddress.City,
ZipCode = senderAddress.ZipCode ?? "000000",
StreetAddress1 = senderAddress.StreetAddress1,
StreetAddress2 = senderAddress.StreetAddress2,
StreetAddress3 = senderAddress.StreetAddress3,
StreetNumber = senderAddress.HouseNumber
}
: new OrderParcelReceiverInput
{
RecipientsName = warehouseContact,
Phone = warehouse.ContactPhone,
CountryCode = "CN",
ZipCode = "000000",
StreetAddress1 = warehouseStreet
};
return new OrderParcelCreateInput
{
RequestId = string.IsNullOrWhiteSpace(input.RequestId) ? null : input.RequestId.Trim(),
@ -47,30 +105,12 @@ public static class PickupOrderParcelBuilder
DeclaredCurrency = "CNY",
DeclaredSum = 1,
Quantity = 1,
Sender = new OrderParcelSenderInput
{
SenderName = senderAddress.SenderName,
Company = senderAddress.Company,
Phone = senderAddress.Phone,
TelePhone = senderAddress.TelePhone,
Email = senderAddress.Email,
CountryCode = senderCountryCode ?? "CN",
Province = senderAddress.Province,
City = senderAddress.City,
ZipCode = senderAddress.ZipCode,
StreetAddress1 = senderAddress.StreetAddress1,
StreetAddress2 = senderAddress.StreetAddress2,
StreetAddress3 = senderAddress.StreetAddress3,
HouseNumber = senderAddress.HouseNumber
},
Receiver = new OrderParcelReceiverInput
{
RecipientsName = receiverName,
Phone = warehouse.ContactPhone,
CountryCode = "CN",
ZipCode = "000000",
StreetAddress1 = street
},
InboundMethod = OrderInboundMethodCodes.DoorPickup,
SenderAddressId = input.SenderAddressId,
ExpectPickupTime = input.PickupTime,
PickupDirection = PickupDirectionCodes.NormalizeOrDefault(input.Direction),
Sender = sender,
Receiver = receiver,
Items =
[
new OrderParcelItemInput

View File

@ -63,7 +63,7 @@ public class PickupOrderService : ApplicationService
if (input.SenderAddressId <= 0)
{
throw new BusinessException("发件地址不能为空");
throw new BusinessException("揽收地址不能为空");
}
if (input.WarehouseId <= 0)
@ -76,6 +76,8 @@ public class PickupOrderService : ApplicationService
throw new BusinessException("期望揽收时间不能为空");
}
var direction = PickupDirectionCodes.NormalizeOrDefault(input.Direction);
var orderIds = (input.OrderIds ?? []).Where(x => x > 0).Distinct().ToList();
if (orderIds.Count == 0)
{
@ -85,15 +87,15 @@ public class PickupOrderService : ApplicationService
var senderAddress = await CustomerSenderAddressRepository.GetOwnedAsync(input.SenderAddressId, customerId);
if (senderAddress == null)
{
throw new BusinessException("发件地址不存在");
throw new BusinessException("揽收地址不存在");
}
var addressType = string.IsNullOrWhiteSpace(senderAddress.AddressType)
? CustomerAddressTypeCodes.Sender
: senderAddress.AddressType;
if (!string.Equals(addressType, CustomerAddressTypeCodes.Sender, StringComparison.OrdinalIgnoreCase))
if (!CustomerAddressTypeCodes.IsPickupEligible(addressType))
{
throw new BusinessException("揽收单仅可选择发件地址");
throw new BusinessException("揽收单请选择「国内揽收」类型地址");
}
var warehouse = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == input.WarehouseId);
@ -198,6 +200,7 @@ public class PickupOrderService : ApplicationService
OrganizationId = orgId,
SecretLevel = secretLevel,
SenderAddressId = senderAddress.Id,
Direction = direction,
SenderName = senderAddress.SenderName ?? string.Empty,
SenderCompany = senderAddress.Company,
SenderCountry = senderAddress.Country,
@ -408,9 +411,13 @@ public class PickupOrderService : ApplicationService
var keyword = NormalizeOptional(input.Keyword);
var status = NormalizeOptional(input.Status);
var payStatus = NormalizeOptional(input.PayStatus);
var direction = string.IsNullOrWhiteSpace(input.Direction)
? null
: PickupDirectionCodes.NormalizeOrDefault(input.Direction);
var all = await PickupOrderRepository.GetListAsync(x =>
(customerId == null || x.CustomerId == customerId.Value) &&
(direction == null || x.Direction == direction) &&
(status == null || x.Status == status) &&
(payStatus == null || x.PayStatus == payStatus) &&
(input.WarehouseId == null || input.WarehouseId <= 0 || x.WarehouseId == input.WarehouseId.Value) &&
@ -438,15 +445,22 @@ public class PickupOrderService : ApplicationService
/// 揽收单状态计数(Tab 徽章)。
/// </summary>
[HttpGet("/order/pickup-order/status-counts")]
public async Task<PickupOrderStatusCountsOutput> GetStatusCountsAsync([FromQuery] int? customerId)
public async Task<PickupOrderStatusCountsOutput> GetStatusCountsAsync(
[FromQuery] int? customerId,
[FromQuery] string? direction = null)
{
var resolvedCustomerId = await WarehouseCustomerHelper.ResolveListCustomerIdAsync(
CustomerRepository,
CurrentUser,
customerId);
var directionFilter = string.IsNullOrWhiteSpace(direction)
? null
: PickupDirectionCodes.NormalizeOrDefault(direction);
var all = await PickupOrderRepository.GetListAsync(x =>
resolvedCustomerId == null || x.CustomerId == resolvedCustomerId.Value);
(resolvedCustomerId == null || x.CustomerId == resolvedCustomerId.Value) &&
(directionFilter == null || x.Direction == directionFilter));
var terminal = new[] { PickupOrderStatusCodes.Cancelled, PickupOrderStatusCodes.Failed };
var pendingPayment = all.Count(x =>
@ -929,6 +943,7 @@ public class PickupOrderService : ApplicationService
OrganizationId = entity.OrganizationId,
SecretLevel = entity.SecretLevel,
SenderAddressId = entity.SenderAddressId,
Direction = PickupDirectionCodes.NormalizeOrDefault(entity.Direction),
SenderName = entity.SenderName,
SenderPhone = entity.SenderPhone,
SenderTelePhone = entity.SenderTelePhone,

View File

@ -1,18 +1,27 @@
namespace Oms.Domain.OrdersAggregate.Consts;
/// <summary>
/// 客户地址类型:发件 / 退件 / 收件。
/// 客户地址类型:国内发件 / 国内退件 / 国内揽收 / 海外收件。
/// </summary>
public static class CustomerAddressTypeCodes
{
/// <summary>国内发件(国际件发件人地址)</summary>
public const string Sender = "sender";
/// <summary>国内退件</summary>
public const string Return = "return";
/// <summary>国内揽收(上门取件地址)</summary>
public const string Pickup = "pickup";
/// <summary>海外收件</summary>
public const string Receiver = "receiver";
public static readonly HashSet<string> All = new(StringComparer.OrdinalIgnoreCase)
{
Sender,
Return,
Pickup,
Receiver
};
@ -21,7 +30,7 @@ public static class CustomerAddressTypeCodes
var code = string.IsNullOrWhiteSpace(addressType) ? Sender : addressType.Trim();
if (!All.Contains(code))
{
throw new ArgumentException("地址类型不合法,仅支持 sender/return/receiver");
throw new ArgumentException("地址类型不合法,仅支持 sender/return/pickup/receiver");
}
return All.First(x => string.Equals(x, code, StringComparison.OrdinalIgnoreCase));
@ -31,10 +40,19 @@ public static class CustomerAddressTypeCodes
{
return addressType?.Trim().ToLowerInvariant() switch
{
Sender => "发件",
Return => "退件",
Receiver => "收件",
Sender => "国内发件",
Return => "国内退件",
Pickup => "国内揽收",
Receiver => "海外收件",
_ => addressType ?? string.Empty
};
}
/// <summary>是否可作为揽收单客户地址(国内揽收;兼容历史发件地址)。</summary>
public static bool IsPickupEligible(string? addressType)
{
var code = string.IsNullOrWhiteSpace(addressType) ? Sender : addressType.Trim();
return string.Equals(code, Pickup, StringComparison.OrdinalIgnoreCase)
|| string.Equals(code, Sender, StringComparison.OrdinalIgnoreCase);
}
}

View File

@ -0,0 +1,39 @@
namespace Oms.Domain.OrdersAggregate.Consts;
/// <summary>
/// 揽收方向:正向(客户地址→仓库)/ 逆向(仓库→客户地址)。
/// </summary>
public static class PickupDirectionCodes
{
/// <summary>正向:客户揽收地址 → 仓库</summary>
public const string Forward = "forward";
/// <summary>逆向:仓库 → 客户揽收地址</summary>
public const string Reverse = "reverse";
public static readonly HashSet<string> All = new(StringComparer.OrdinalIgnoreCase)
{
Forward,
Reverse
};
public static string NormalizeOrDefault(string? direction)
{
var code = string.IsNullOrWhiteSpace(direction) ? Forward : direction.Trim();
if (!All.Contains(code))
{
return Forward;
}
return All.First(x => string.Equals(x, code, StringComparison.OrdinalIgnoreCase));
}
public static string GetDisplayName(string? direction)
{
return NormalizeOrDefault(direction) switch
{
Reverse => "逆向",
_ => "正向"
};
}
}

View File

@ -24,6 +24,12 @@ public class PickupOrder : OmsAuditedAggregateRoot
public int SenderAddressId { get; set; }
/// <summary>
/// 揽收方向:forward 正向(客户→仓)/ reverse 逆向(仓→客户)。
/// </summary>
[SugarColumn(Length = 16)]
public string Direction { get; set; } = "forward";
[SugarColumn(Length = 50)]
public string SenderName { get; set; } = string.Empty;