diff --git a/db.sql b/db.sql index 91ca9b1..b0ff82d 100644 --- a/db.sql +++ b/db.sql @@ -29,6 +29,11 @@ DROP TABLE IF EXISTS `role_data_scope`; DROP TABLE IF EXISTS `role_org_perm`; DROP TABLE IF EXISTS `user_org_perm`; DROP TABLE IF EXISTS `t_xhs_media`; +DROP TABLE IF EXISTS `t_kb_article`; +DROP TABLE IF EXISTS `t_kb_category`; +DROP TABLE IF EXISTS `t_mcp_tool`; +DROP TABLE IF EXISTS `t_pickup_order_line`; +DROP TABLE IF EXISTS `t_pickup_order`; DROP TABLE IF EXISTS `t_ai_skill`; DROP TABLE IF EXISTS `t_ai_provider`; DROP TABLE IF EXISTS `t_xhs_ai_provider`; @@ -119,6 +124,9 @@ CREATE TABLE `t_order` ( `ExportCustomsMode` VARCHAR(32) NULL COMMENT '出口报关方式', `PredeclareFailReason` VARCHAR(512) NULL COMMENT '预报失败原因', `AllocationPendingReason` VARCHAR(512) NULL COMMENT '待排货原因(排货或渠道买价未匹配)', + `AllocationScheme` VARCHAR(32) NULL COMMENT '最近一次排货方案 costLowest/timeFastest/overallBest/designated', + `AllocationTraceJson` JSON NULL COMMENT '最近一次排货过程快照 JSON', + `AllocationTraceTime` DATETIME NULL COMMENT '排货快照写入时间', `SalesProductRulesVersion` VARCHAR(64) NULL COMMENT '销售产品规则快照版本', `SalesProductPriceVersion` VARCHAR(64) NULL COMMENT '销售产品价格快照版本', `OrderStatus` VARCHAR(32) NOT NULL COMMENT '订单状态', @@ -137,9 +145,20 @@ CREATE TABLE `t_order` ( `PreviousOrderStatus` VARCHAR(32) NULL COMMENT '进入异常状态前的订单状态', `WarehouseId` INT NULL COMMENT '仓库ID', `CustomerId` INT NULL COMMENT '客户ID', + `MemberLevelId` INT NULL COMMENT '下单时会员等级Id快照', + `PriceTierKey` VARCHAR(64) NULL COMMENT '下单时价区键快照', + `ReceivableSubtotal` DECIMAL(18,4) NULL COMMENT '应收小计(折扣前)', + `ForecastReceivableAmount` DECIMAL(18,4) NULL COMMENT '预报应收快照(创建预报后固化,入库不覆盖)', + `ForecastPayableAmount` DECIMAL(18,4) NULL COMMENT '预报应付快照(创建预报后固化,入库不覆盖)', + `LevelDiscountAmount` DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '会员等级折扣金额', + `CouponInstanceId` INT NULL COMMENT '使用的优惠券实例Id', + `CouponDiscountAmount` DECIMAL(18,4) NOT NULL DEFAULT 0 COMMENT '优惠券抵扣金额', + `PayableAmount` DECIMAL(18,4) NULL COMMENT '应付金额(对客应收)', `OrderSource` VARCHAR(32) NULL COMMENT '订单来源:manual/pickup/upload/batch/platform', `PickupTime` DATETIME NULL COMMENT '预约揽收时间', `CustomerSenderAddressId` INT NULL COMMENT '发件地址簿 Id', + `InboundMethod` VARCHAR(16) NULL COMMENT '到仓方式 selfShip/doorPickup', + `PickupOrderId` INT NULL COMMENT '关联揽收单Id(冗余)', `OrganizationId` CHAR(36) NULL COMMENT '数据归属组织', `SecretLevel` TINYINT NOT NULL DEFAULT 2 COMMENT '数据密级 1-4', `SenderId` INT NULL COMMENT '发件人ID', @@ -158,6 +177,7 @@ CREATE TABLE `t_order` ( `Quantity` INT NULL COMMENT '包裹数量', `IsIntercept` TINYINT NOT NULL DEFAULT 0 COMMENT '是否拦截:0-否,1-是', `IsRemote` TINYINT NOT NULL DEFAULT 0 COMMENT '是否偏远:0-否,1-是', + `AdditionalServices` VARCHAR(512) NULL COMMENT '客户勾选附加服务字典code JSON数组', `LabelTemplateId` INT NULL COMMENT '出单标签模板Id', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳', @@ -177,7 +197,9 @@ CREATE TABLE `t_order` ( KEY `idx_ord_recipient` (`RecipientId`), KEY `idx_ord_declaration` (`DeclarationId`), KEY `idx_ord_org_secret_ctime` (`OrganizationId`, `SecretLevel`, `CreateTime`), - KEY `idx_ord_source_ctime` (`OrderSource`, `CreateTime`) + KEY `idx_ord_source_ctime` (`OrderSource`, `CreateTime`), + KEY `idx_order_pickup` (`PickupOrderId`), + KEY `idx_order_inbound_method` (`InboundMethod`) ) COMMENT='订单表'; CREATE TABLE `t_order_file` ( @@ -454,6 +476,9 @@ CREATE TABLE `t_order_exception_event` ( `Content` TEXT NULL COMMENT '内容快照', `IssueTemplateId` INT NULL COMMENT '模板Id', `NotifyMethod` VARCHAR(64) NULL COMMENT '通知方式快照', + `HandlerNames` VARCHAR(256) NULL COMMENT '处理人快照', + `HandlerType` VARCHAR(16) NULL COMMENT '处理人类型', + `HandlerUserId` INT NULL COMMENT '处理人用户Id(customer 时为订单客户账号)', `ClaimType` VARCHAR(32) NULL COMMENT '理赔类型', `ClaimAmount` DECIMAL(18,4) NULL COMMENT '索赔金额', `ClaimCurrency` VARCHAR(16) NULL COMMENT '索赔币种', @@ -475,6 +500,8 @@ CREATE TABLE `t_sales_product` ( `ProductGroup` VARCHAR(32) NULL COMMENT '分组(专线/快递/邮政)', `MinTimeliness` INT NULL COMMENT '最小时效(天)', `MaxTimeliness` INT NULL COMMENT '最大时效(天)', + `TradeTerms` VARCHAR(16) NULL COMMENT '贸易条款:DDP/DDU', + `AdditionalServices` VARCHAR(512) NULL COMMENT '可选附加服务字典code JSON数组', `CustomerWaybill` VARCHAR(32) NULL COMMENT '系统面单/客户面单', `BlacklistAreaId` INT NULL COMMENT '黑名单区ID', `RemoteAreaId` INT NULL COMMENT '偏远分区ID', @@ -578,6 +605,7 @@ CREATE TABLE `t_sales_product_publish_record` ( `PublishUser` VARCHAR(64) NOT NULL COMMENT '发布人', `PublishTime` DATETIME NOT NULL COMMENT '发布时间', `Description` VARCHAR(512) NULL COMMENT '版本备注', + `AiAnalysisReport` MEDIUMTEXT NULL COMMENT '价格发布AI风险分析报告', `Content` JSON NULL COMMENT '发布内容JSON快照', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', @@ -615,6 +643,7 @@ CREATE TABLE `t_service_channel` ( `ForecastType` VARCHAR(32) NULL COMMENT '预报单号类型(customer/waybill/tracking)', `ForecastCode` VARCHAR(128) NULL COMMENT '预报单号', `Description` TEXT COMMENT '描述', + `RemoteAreaId` INT NULL COMMENT '偏远分区KPI AreaId', `PreScript` TEXT COMMENT '入库前脚本', `IsActive` TINYINT NOT NULL DEFAULT 2 COMMENT 'EnableStatus:0=None未设置,1=Disabled禁用,2=Enabled启用', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', @@ -825,6 +854,8 @@ CREATE TABLE `t_issue_template` ( `Title` VARCHAR(128) NOT NULL COMMENT '问题标题', `Content` TEXT NOT NULL COMMENT '问题内容', `NotifyMethod` VARCHAR(64) NOT NULL COMMENT '通知方式,逗号分隔', + `HandlerType` VARCHAR(16) NULL COMMENT '处理人类型:customer=订单所属客户 user=指定用户', + `HandlerUserId` INT NULL COMMENT '指定处理人用户Id(HandlerType=user 时必填)', `Status` TINYINT NOT NULL DEFAULT 2 COMMENT 'EnableStatus:0=None未设置,1=Disabled禁用,2=Enabled启用', `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳', @@ -934,6 +965,8 @@ CREATE TABLE `t_customer` ( `WechatNickname` VARCHAR(64) NULL COMMENT '微信昵称', `Email` VARCHAR(64) NULL COMMENT '邮箱,用于登录/找回密码', `Phone` VARCHAR(16) NULL COMMENT '手机号,用于联系;可空,唯一(NULL 可多条)', + `MemberLevelId` INT NULL COMMENT '会员等级Id', + `PriceTierKey` VARCHAR(64) NULL COMMENT '价区键(卖价 CustomerGroupValues JSON 键)', `Balance` DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '账户余额', `TotalQuota` DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '总额度', `UsedQuota` DECIMAL(18,2) NOT NULL DEFAULT 0.00 COMMENT '已用额度', @@ -1777,6 +1810,151 @@ CREATE TABLE `t_ai_skill` ( KEY `idx_ai_skill_scene` (`Scene`, `Enabled`, `SortOrder`) ) COMMENT='平台级 AI Skill(提示词/规范)'; +CREATE TABLE `t_mcp_tool` ( + `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', + `ToolKey` VARCHAR(64) NOT NULL COMMENT '工具编码,如 oms.price_check', + `DisplayName` VARCHAR(128) NOT NULL COMMENT '显示名称', + `Description` VARCHAR(1000) NOT NULL COMMENT '给 AI 的工具描述', + `Enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是', + `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '排序,越小越靠前', + `Remark` VARCHAR(512) NULL COMMENT '备注', + `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', + `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_mcp_tool_key` (`ToolKey`), + KEY `idx_mcp_tool_enabled` (`Enabled`, `SortOrder`, `Id`) +) COMMENT='MCP 工具配置表'; + +CREATE TABLE `t_pickup_order` ( + `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', + `PickupNo` VARCHAR(32) NOT NULL COMMENT '揽收单号', + `RequestId` VARCHAR(64) NULL COMMENT '请求幂等ID', + `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', + `SenderName` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '取件联系人快照', + `SenderCompany` VARCHAR(255) NULL COMMENT '公司快照', + `SenderCountry` INT NULL COMMENT '国家 t_country.Id 快照', + `SenderCountryCode` VARCHAR(8) NULL COMMENT '国家码快照', + `SenderProvince` VARCHAR(50) NULL COMMENT '省快照', + `SenderCity` VARCHAR(50) NULL COMMENT '市快照', + `SenderZipCode` VARCHAR(50) NULL COMMENT '邮编快照', + `SenderStreetAddress1` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '地址1快照', + `SenderStreetAddress2` VARCHAR(500) NULL COMMENT '地址2快照', + `SenderStreetAddress3` VARCHAR(500) NULL COMMENT '地址3快照', + `SenderHouseNumber` VARCHAR(50) NULL COMMENT '门牌号快照', + `SenderPhone` VARCHAR(50) NULL COMMENT '手机快照', + `SenderTelePhone` VARCHAR(50) NULL COMMENT '电话快照', + `SenderEmail` VARCHAR(60) NULL COMMENT '邮箱快照', + `WarehouseId` INT NOT NULL COMMENT '送到仓库Id', + `CarrierCode` VARCHAR(64) NULL COMMENT '承运商编码(draft可空)', + `CarrierService` VARCHAR(64) NULL COMMENT '承运服务(draft可空)', + `CarrierWaybillNo` VARCHAR(64) NULL COMMENT '承运商回执单号', + `ExpectPickupTime` DATETIME NOT NULL COMMENT '期望揽收时间', + `PickupWindowStart` DATETIME NULL COMMENT '时间窗起', + `PickupWindowEnd` DATETIME NULL COMMENT '时间窗止', + `ActualPickupTime` DATETIME NULL COMMENT '实际取件时间', + `Status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT 'draft/scheduled/dispatched/picked/inbound/cancelled/failed', + `ParcelCount` INT NOT NULL DEFAULT 0 COMMENT '关联票数', + `TotalActualWeight` DECIMAL(18,3) NULL COMMENT '汇总实重', + `ChargeableWeight` DECIMAL(18,3) NULL COMMENT '计费重', + `Currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '币种', + `FreightAmount` DECIMAL(18,2) NULL COMMENT '对客揽收运费', + `OtherFeeAmount` DECIMAL(18,2) NULL COMMENT '对客其他费', + `ReceivableAmount` DECIMAL(18,2) NULL COMMENT '对客应收合计', + `PayStatus` VARCHAR(16) NOT NULL DEFAULT 'unpaid' COMMENT 'unpaid/paid', + `PayTime` DATETIME NULL COMMENT '支付时间', + `PayMode` VARCHAR(16) NOT NULL DEFAULT 'prepaid' COMMENT 'prepaid/collect', + `CarrierPayableAmount` DECIMAL(18,2) NULL COMMENT '应付承运商', + `SettlementStatus` VARCHAR(16) NOT NULL DEFAULT 'none' COMMENT 'none/pending/settled', + `SettlementBatchNo` VARCHAR(64) NULL COMMENT '结算批次号', + `SettledAt` DATETIME NULL COMMENT '结算时间', + `Remark` VARCHAR(512) NULL COMMENT '备注', + `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', + `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_pickup_no` (`PickupNo`), + UNIQUE KEY `uk_pickup_request_id` (`RequestId`), + KEY `idx_pickup_customer_status` (`CustomerId`, `Status`, `CreateTime`), + KEY `idx_pickup_warehouse_time` (`WarehouseId`, `ExpectPickupTime`), + KEY `idx_pickup_pay` (`PayStatus`), + KEY `idx_pickup_settle` (`SettlementStatus`), + KEY `idx_pickup_org_secret_ctime` (`OrganizationId`, `SecretLevel`, `CreateTime`) +) COMMENT='揽收单(上门取件履约+对客收款+承运结算)'; + +CREATE TABLE `t_pickup_order_line` ( + `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', + `PickupOrderId` INT NOT NULL COMMENT '揽收单Id', + `OrderId` INT NOT NULL COMMENT '物流订单Id', + `ServiceNo` VARCHAR(64) NULL COMMENT '运单号快照(便于列表)', + `ClientNo` VARCHAR(64) NULL COMMENT '客户单号快照', + `SortNo` INT NOT NULL DEFAULT 0 COMMENT '展示序', + `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', + `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_pickup_line_order` (`OrderId`), + UNIQUE KEY `uk_pickup_line_pair` (`PickupOrderId`, `OrderId`), + KEY `idx_pickup_line_header` (`PickupOrderId`, `IsDeleted`) +) COMMENT='揽收单关联物流订单(1揽收:N物流)'; + +CREATE TABLE `t_kb_category` ( + `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键', + `Code` VARCHAR(64) NOT NULL COMMENT '稳定键,如 pricing', + `Name` VARCHAR(128) NOT NULL COMMENT '展示名(中文)', + `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '排序,越小越前', + `Enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是', + `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', + `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_kb_category_code` (`Code`), + KEY `idx_kb_category_enabled_sort` (`Enabled`, `SortOrder`) +) COMMENT='知识库分类'; + +CREATE TABLE `t_kb_article` ( + `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键', + `CategoryId` INT NOT NULL COMMENT '分类 Id', + `Title` VARCHAR(200) NOT NULL COMMENT '标题(中文)', + `Summary` VARCHAR(500) NULL COMMENT '列表摘要', + `Content` LONGTEXT NOT NULL COMMENT 'Markdown 正文(中文)', + `Audience` VARCHAR(16) NOT NULL DEFAULT 'customer' COMMENT '受众 customer/internal', + `Status` VARCHAR(16) NOT NULL DEFAULT 'draft' COMMENT 'draft/published/offline', + `Tags` VARCHAR(256) NULL COMMENT '逗号分隔标签', + `RelatedPath` VARCHAR(256) NULL COMMENT '站内关联 path', + `RelatedLabel` VARCHAR(64) NULL COMMENT '关联按钮文案', + `IsPinned` TINYINT NOT NULL DEFAULT 0 COMMENT '置顶:0-否,1-是', + `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '同类排序', + `PublishTime` DATETIME NULL COMMENT '发布时间', + `ExpireTime` DATETIME NULL COMMENT '过期时间', + `ViewCount` INT NOT NULL DEFAULT 0 COMMENT '浏览次数', + `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', + `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_kb_article_list` (`Status`, `Audience`, `CategoryId`, `IsPinned`, `SortOrder`), + KEY `idx_kb_article_publish` (`Status`, `Audience`, `PublishTime`), + KEY `idx_kb_article_hot` (`Status`, `Audience`, `IsPinned`, `ViewCount`) +) COMMENT='知识库文章'; + CREATE TABLE `t_xhs_media` ( `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键', `CustomerId` INT NOT NULL COMMENT '客户ID', diff --git a/sql/20260727_customer_phone_nullable.sql b/sql/20260727_customer_phone_nullable.sql deleted file mode 100644 index 1788f35..0000000 --- a/sql/20260727_customer_phone_nullable.sql +++ /dev/null @@ -1,5 +0,0 @@ --- 微信注册简化:客户手机号改为可空(空值请用 NULL,勿存空字符串) --- 执行环境:生产库先备份;与 docs/微信注册简化与联系方式补全方案.md 一致 - -ALTER TABLE `t_customer` - MODIFY COLUMN `Phone` VARCHAR(16) NULL COMMENT '手机号,用于联系;可空,唯一(NULL 可多条)'; diff --git a/sql/20260728_auto_trigger_merge_forecast_to_order_create.sql b/sql/20260728_auto_trigger_merge_forecast_to_order_create.sql deleted file mode 100644 index c3532bf..0000000 --- a/sql/20260728_auto_trigger_merge_forecast_to_order_create.sql +++ /dev/null @@ -1,6 +0,0 @@ --- 自动触发时机:预报 并入 下单 -UPDATE t_auto_trigger -SET TriggerTiming = N'下单' -WHERE TriggerTiming IN (N'预报', N'forecast', N'order_create', N'OrderCreate') - OR TriggerTiming LIKE N'%预报%' - OR LOWER(TriggerTiming) LIKE N'%forecast%'; diff --git a/sql/20260728_order_downstream_service_no.sql b/sql/20260728_order_downstream_service_no.sql deleted file mode 100644 index 691807f..0000000 --- a/sql/20260728_order_downstream_service_no.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Add DownstreamServiceNo to t_order (provider service no from createOrderOne Data.serviceNo) --- Backup production DB before running. - -ALTER TABLE `t_order` - ADD COLUMN `DownstreamServiceNo` VARCHAR(64) NULL COMMENT 'Downstream provider service no' AFTER `TrackNo`; diff --git a/sql/20260728_order_file.sql b/sql/20260728_order_file.sql deleted file mode 100644 index 1e94b5f..0000000 --- a/sql/20260728_order_file.sql +++ /dev/null @@ -1,50 +0,0 @@ --- 订单附件表;将原 LabelUrl 迁移为 systemLabel 后删除订单旧面单字段。 --- 在 MySQL 执行前请先备份。 - -CREATE TABLE IF NOT EXISTS `t_order_file` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', - `OrderId` INT NOT NULL COMMENT '订单Id', - `FileType` VARCHAR(32) NOT NULL COMMENT '附件类型:tradeProof交易证明/systemLabel系统面单/downstreamLabel下游面单/lastMileLabel末端面单/infraredImage红外图片', - `FileName` VARCHAR(255) NULL COMMENT '原始文件名', - `FileUrl` VARCHAR(512) NOT NULL COMMENT '文件地址(相对路径或外链)', - `ContentType` VARCHAR(128) NULL COMMENT '文件MIME类型', - `FileSize` BIGINT NULL COMMENT '文件大小(字节)', - `Sort` INT NOT NULL DEFAULT 0 COMMENT '同类型内排序', - `Source` VARCHAR(32) NOT NULL DEFAULT 'upload' COMMENT '来源:upload上传/systemGenerate系统生成/downstream下游回传/migrate迁移', - `Remark` VARCHAR(512) NULL COMMENT '备注', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_ord_file_order_type` (`OrderId`, `FileType`, `IsDeleted`) -) COMMENT='订单附件表'; - --- 迁移已有系统面单地址(若 LabelUrl 列已删除可跳过本段) -INSERT INTO `t_order_file` (`OrderId`, `FileType`, `FileName`, `FileUrl`, `ContentType`, `Sort`, `Source`, `CreateUserId`, `CreateTime`) -SELECT - `Id`, - 'systemLabel', - SUBSTRING_INDEX(`LabelUrl`, '/', -1), - `LabelUrl`, - 'application/pdf', - 0, - 'migrate', - 0, - NOW() -FROM `t_order` -WHERE `LabelUrl` IS NOT NULL - AND TRIM(`LabelUrl`) <> '' - AND NOT EXISTS ( - SELECT 1 FROM `t_order_file` f - WHERE f.`OrderId` = `t_order`.`Id` - AND f.`FileType` = 'systemLabel' - AND f.`IsDeleted` = 0 - ); - -ALTER TABLE `t_order` - DROP COLUMN `LabelUrl`, - DROP COLUMN `LabelGenerateStatus`, - DROP COLUMN `LabelGenerateError`; diff --git a/sql/20260728_order_file_comments.sql b/sql/20260728_order_file_comments.sql deleted file mode 100644 index 1934c3c..0000000 --- a/sql/20260728_order_file_comments.sql +++ /dev/null @@ -1,20 +0,0 @@ --- 若 t_order_file 已按英文注释建表,执行本脚本改为中文注释(不改结构)。 - -ALTER TABLE `t_order_file` - MODIFY COLUMN `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', - MODIFY COLUMN `OrderId` INT NOT NULL COMMENT '订单Id', - MODIFY COLUMN `FileType` VARCHAR(32) NOT NULL COMMENT '附件类型:tradeProof交易证明/systemLabel系统面单/downstreamLabel下游面单/lastMileLabel末端面单/infraredImage红外图片', - MODIFY COLUMN `FileName` VARCHAR(255) NULL COMMENT '原始文件名', - MODIFY COLUMN `FileUrl` VARCHAR(512) NOT NULL COMMENT '文件地址(相对路径或外链)', - MODIFY COLUMN `ContentType` VARCHAR(128) NULL COMMENT '文件MIME类型', - MODIFY COLUMN `FileSize` BIGINT NULL COMMENT '文件大小(字节)', - MODIFY COLUMN `Sort` INT NOT NULL DEFAULT 0 COMMENT '同类型内排序', - MODIFY COLUMN `Source` VARCHAR(32) NOT NULL DEFAULT 'upload' COMMENT '来源:upload上传/systemGenerate系统生成/downstream下游回传/migrate迁移', - MODIFY COLUMN `Remark` VARCHAR(512) NULL COMMENT '备注', - MODIFY COLUMN `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - MODIFY COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳', - MODIFY COLUMN `CreateUserId` INT NOT NULL DEFAULT 0 COMMENT '创建人', - MODIFY COLUMN `CreateTime` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', - MODIFY COLUMN `UpdateUserId` INT NULL COMMENT '更新人', - MODIFY COLUMN `UpdateTime` DATETIME NULL COMMENT '更新时间', - COMMENT='订单附件表'; diff --git a/sql/20260729_fix_user_empty_email.sql b/sql/20260729_fix_user_empty_email.sql deleted file mode 100644 index 3485f95..0000000 --- a/sql/20260729_fix_user_empty_email.sql +++ /dev/null @@ -1,12 +0,0 @@ --- 修复:微信注册无邮箱时曾写入 user.Email='',撞 uk_user_email 导致后续注册提示「邮箱已被占用」 --- 将空邮箱改为「客户编号@noemail.local」占位(与 CustomerContactHelper.ResolveRbacEmailOrPlaceholder 一致) - -UPDATE `user` u -INNER JOIN `t_customer` c ON c.`UserId` = u.`userid` -SET u.`Email` = CONCAT(LOWER(TRIM(c.`CustomerCode`)), '@noemail.local') -WHERE u.`Email` IS NULL OR TRIM(u.`Email`) = ''; - --- 无客户关联的残留空邮箱 -UPDATE `user` -SET `Email` = CONCAT('u', `userid`, '@noemail.local') -WHERE `Email` IS NULL OR TRIM(`Email`) = ''; diff --git a/sql/20260729_mcp_tool.sql b/sql/20260729_mcp_tool.sql deleted file mode 100644 index ebb0a69..0000000 --- a/sql/20260729_mcp_tool.sql +++ /dev/null @@ -1,32 +0,0 @@ --- MCP 工具配置(启用/描述覆盖),与代码内置目录合并 --- 对齐 t_system_other_config / t_order_file 等配置表结构习惯 - -CREATE TABLE IF NOT EXISTS `t_mcp_tool` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', - `ToolKey` VARCHAR(64) NOT NULL COMMENT '工具编码,如 oms.price_check', - `DisplayName` VARCHAR(128) NOT NULL COMMENT '显示名称', - `Description` VARCHAR(1000) NOT NULL COMMENT '给 AI 的工具描述', - `Enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是', - `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '排序,越小越靠前', - `Remark` VARCHAR(512) NULL COMMENT '备注', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_mcp_tool_key` (`ToolKey`), - KEY `idx_mcp_tool_enabled` (`Enabled`, `SortOrder`, `Id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='MCP 工具配置表'; - -INSERT INTO `t_mcp_tool` (`ToolKey`, `DisplayName`, `Description`, `Enabled`, `SortOrder`, `Remark`) -VALUES - ('oms.price_check', '查价格', '根据目的国、重量等查询运费报价,返回可用渠道与价格摘要。', 1, 10, '内置:封装 /order/price-check'), - ('oms.channel_guide', '查渠道对客说明', '按销售产品代码/名称查询对客说明(禁运、可寄品名等),判断客户品名是否可承运。', 1, 20, '内置:读销售产品 CustomerGuideMarkdown'), - ('oms.track_query', '查轨迹', '根据运单号/客户单号查询物流轨迹时间轴摘要。', 1, 30, '内置:轨迹中心 GetDetailTimeline') -ON DUPLICATE KEY UPDATE - `DisplayName` = VALUES(`DisplayName`), - `Description` = VALUES(`Description`), - `SortOrder` = VALUES(`SortOrder`), - `Remark` = VALUES(`Remark`); diff --git a/sql/20260729_mcp_tool_alter_align.sql b/sql/20260729_mcp_tool_alter_align.sql deleted file mode 100644 index 501ee94..0000000 --- a/sql/20260729_mcp_tool_alter_align.sql +++ /dev/null @@ -1,38 +0,0 @@ --- 若已按旧版建过 t_mcp_tool,执行本脚本补齐字段(幂等) - -ALTER TABLE `t_mcp_tool` - ADD COLUMN IF NOT EXISTS `Remark` VARCHAR(512) NULL COMMENT '备注' AFTER `SortOrder`; - --- MySQL 8.0.12 前无 IF NOT EXISTS 时,可改用下面手工判断;8.0.29+ 支持 ADD COLUMN IF NOT EXISTS --- 并发戳:已存在则跳过 -SET @col_exists := ( - SELECT COUNT(*) FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 't_mcp_tool' - AND COLUMN_NAME = 'ConcurrencyStamp' -); -SET @sql := IF( - @col_exists = 0, - 'ALTER TABLE `t_mcp_tool` ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT ''并发戳'' AFTER `IsDeleted`', - 'SELECT 1' -); -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - -SET @idx_exists := ( - SELECT COUNT(*) FROM information_schema.STATISTICS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 't_mcp_tool' - AND INDEX_NAME = 'idx_mcp_tool_enabled' -); -SET @sql := IF( - @idx_exists = 0, - 'ALTER TABLE `t_mcp_tool` ADD KEY `idx_mcp_tool_enabled` (`Enabled`, `SortOrder`, `Id`)', - 'SELECT 1' -); -PREPARE stmt FROM @sql; -EXECUTE stmt; -DEALLOCATE PREPARE stmt; - -ALTER TABLE `t_mcp_tool` COMMENT = 'MCP 工具配置表'; diff --git a/sql/20260730_customer_price_tier_key.sql b/sql/20260730_customer_price_tier_key.sql deleted file mode 100644 index cbc9b9f..0000000 --- a/sql/20260730_customer_price_tier_key.sql +++ /dev/null @@ -1,46 +0,0 @@ --- 价区键迁到客户:与会员等级解耦 --- 新注册默认价区键/会员等级均为「普通会员」;计价时空键回落「普通客户」 - --- 1) 客户表增加价区键 -ALTER TABLE `t_customer` - ADD COLUMN `PriceTierKey` VARCHAR(64) NULL COMMENT '价区键(卖价 CustomerGroupValues JSON 键)' AFTER `MemberLevelId`; - --- 2) 从原会员等级价区键回填(依赖本脚本执行前 t_member_level 仍有 PriceTierKey) -UPDATE `t_customer` c -INNER JOIN `t_member_level` ml ON ml.`Id` = c.`MemberLevelId` AND ml.`IsDeleted` = 0 -SET c.`PriceTierKey` = NULLIF(TRIM(ml.`PriceTierKey`), '') -WHERE c.`IsDeleted` = 0 - AND (c.`PriceTierKey` IS NULL OR TRIM(c.`PriceTierKey`) = '') - AND ml.`PriceTierKey` IS NOT NULL - AND TRIM(ml.`PriceTierKey`) <> ''; - --- 3) 仍为空的主客户:默认「普通会员」(与新注册一致) -UPDATE `t_customer` -SET `PriceTierKey` = '普通会员' -WHERE `IsDeleted` = 0 - AND (`ParentCustomerId` IS NULL OR `ParentCustomerId` = 0) - AND (`PriceTierKey` IS NULL OR TRIM(`PriceTierKey`) = ''); - --- 4) 子客户跟随主客户价区 -UPDATE `t_customer` sub -INNER JOIN `t_customer` main ON main.`Id` = sub.`ParentCustomerId` AND main.`IsDeleted` = 0 -SET sub.`PriceTierKey` = main.`PriceTierKey` -WHERE sub.`IsDeleted` = 0 - AND sub.`ParentCustomerId` IS NOT NULL - AND sub.`ParentCustomerId` <> 0; - --- 5) 删除会员等级上的价区键列(须在插入默认等级前执行,避免 NOT NULL 约束) -ALTER TABLE `t_member_level` DROP COLUMN `PriceTierKey`; - --- 6) 确保存在启用的「普通会员」等级(供新注册默认挂靠) -INSERT INTO `t_member_level` ( - `LevelCode`, `LevelName`, `MinPoints`, `ExtraDiscountRate`, `Sort`, - `Status`, `IsDeleted`, `CreateTime` -) -SELECT '普通会员', '普通会员', 0, 0, 0, 2, 0, NOW() -FROM DUAL -WHERE NOT EXISTS ( - SELECT 1 FROM `t_member_level` - WHERE `IsDeleted` = 0 - AND (`LevelName` = '普通会员' OR `LevelCode` = '普通会员') -); diff --git a/sql/20260730_sales_product_trade_terms.sql b/sql/20260730_sales_product_trade_terms.sql deleted file mode 100644 index 9817317..0000000 --- a/sql/20260730_sales_product_trade_terms.sql +++ /dev/null @@ -1,3 +0,0 @@ --- 销售产品:贸易条款 DDP / DDU(查价线路返回并展示于价卡) -ALTER TABLE `t_sales_product` - ADD COLUMN `TradeTerms` VARCHAR(16) NULL COMMENT '贸易条款:DDP/DDU' AFTER `MaxTimeliness`; diff --git a/sql/20260801_ai_skill.sql b/sql/20260801_ai_skill.sql deleted file mode 100644 index 1ea238a..0000000 --- a/sql/20260801_ai_skill.sql +++ /dev/null @@ -1,26 +0,0 @@ --- 平台级 AI Skill 表(全局一份,系统页维护) -CREATE TABLE IF NOT EXISTS `t_ai_skill` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键', - `SkillKey` VARCHAR(64) NOT NULL COMMENT '稳定键', - `Scene` VARCHAR(32) NOT NULL COMMENT '场景 pricePublish/autoTriggerFormula/receiverAddressParse/itfxPrefixScript', - `Name` VARCHAR(128) NOT NULL COMMENT '展示名', - `Description` VARCHAR(512) NULL COMMENT '简介', - `Content` LONGTEXT NOT NULL COMMENT '发给模型的正文', - `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '排序', - `Enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_ai_skill_key` (`SkillKey`), - KEY `idx_ai_skill_scene` (`Scene`, `Enabled`, `SortOrder`) -) COMMENT='平台级 AI Skill(提示词/规范)'; - --- 若表已按旧脚本建好(无 ConcurrencyStamp),执行: --- ALTER TABLE `t_ai_skill` --- ADD COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) COMMENT '并发戳' AFTER `IsDeleted`; - --- 种子数据由应用首次调用 /ai/skill/list|get 时幂等写入(避免 LONGTEXT 转义问题)。 diff --git a/sql/20260801_billing_additional_services.sql b/sql/20260801_billing_additional_services.sql deleted file mode 100644 index 4076bc9..0000000 --- a/sql/20260801_billing_additional_services.sql +++ /dev/null @@ -1,11 +0,0 @@ --- 附加服务 / 渠道偏远分区 --- 字典种子由前端 dict-batch-import 同步;AI Skill 由应用首次 list/get 幂等写入。 - -ALTER TABLE `t_sales_product` - ADD COLUMN `AdditionalServices` VARCHAR(512) NULL COMMENT '可选附加服务字典code JSON数组' AFTER `TradeTerms`; - -ALTER TABLE `t_order` - ADD COLUMN `AdditionalServices` VARCHAR(512) NULL COMMENT '客户勾选附加服务字典code JSON数组' AFTER `IsRemote`; - -ALTER TABLE `t_service_channel` - ADD COLUMN `RemoteAreaId` INT NULL COMMENT '偏远分区KPI AreaId' AFTER `Description`; diff --git a/sql/20260801_billing_phase2.sql b/sql/20260801_billing_phase2.sql deleted file mode 100644 index ae7b2d9..0000000 --- a/sql/20260801_billing_phase2.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Phase-2:预报应收/应付快照(预报→入库差额对比) - -ALTER TABLE `t_order` - ADD COLUMN `ForecastReceivableAmount` DECIMAL(18,4) NULL COMMENT '预报应收快照(创建预报后固化,入库不覆盖)' AFTER `ReceivableSubtotal`, - ADD COLUMN `ForecastPayableAmount` DECIMAL(18,4) NULL COMMENT '预报应付快照(创建预报后固化,入库不覆盖)' AFTER `ForecastReceivableAmount`; diff --git a/sql/20260801_global_ai_provider.sql b/sql/20260801_global_ai_provider.sql deleted file mode 100644 index 33788ab..0000000 --- a/sql/20260801_global_ai_provider.sql +++ /dev/null @@ -1,16 +0,0 @@ --- 全局 AI 提供商:从小红书域表迁出(未上线环境可直接改名) --- 若表尚不存在则跳过;若已是 t_ai_provider 则无需执行。 - -RENAME TABLE `t_xhs_ai_provider` TO `t_ai_provider`; - -ALTER TABLE `t_ai_provider` - COMMENT = '全局 AI 提供商配置表(CustomerId=0 表示平台级)'; - --- 索引名顺带规范化(可选,失败可忽略) -ALTER TABLE `t_ai_provider` - DROP INDEX `uk_xhs_ai_provider`, - ADD UNIQUE KEY `uk_ai_provider` (`CustomerId`, `ProviderKey`); - -ALTER TABLE `t_ai_provider` - DROP INDEX `idx_xhs_ai_customer`, - ADD KEY `idx_ai_customer` (`CustomerId`, `Enabled`); diff --git a/sql/20260801_order_allocation_trace.sql b/sql/20260801_order_allocation_trace.sql deleted file mode 100644 index 2f89baf..0000000 --- a/sql/20260801_order_allocation_trace.sql +++ /dev/null @@ -1,6 +0,0 @@ --- 订单排货过程快照(方案 + 候选指标,供详情「查看排货过程」) - -ALTER TABLE `t_order` - ADD COLUMN `AllocationScheme` VARCHAR(32) NULL COMMENT '最近一次排货方案 costLowest/timeFastest/overallBest/designated' AFTER `AllocationPendingReason`, - ADD COLUMN `AllocationTraceJson` JSON NULL COMMENT '最近一次排货过程快照 JSON' AFTER `AllocationScheme`, - ADD COLUMN `AllocationTraceTime` DATETIME NULL COMMENT '排货快照写入时间' AFTER `AllocationTraceJson`; diff --git a/sql/20260801_sales_product_publish_ai_report.sql b/sql/20260801_sales_product_publish_ai_report.sql deleted file mode 100644 index d2fd354..0000000 --- a/sql/20260801_sales_product_publish_ai_report.sql +++ /dev/null @@ -1,3 +0,0 @@ --- 销售产品价格发布记录:保存 AI 风险分析报告 -ALTER TABLE `t_sales_product_publish_record` - ADD COLUMN `AiAnalysisReport` MEDIUMTEXT NULL COMMENT '价格发布AI风险分析报告' AFTER `Description`; diff --git a/sql/20260803_pickup_order.sql b/sql/20260803_pickup_order.sql deleted file mode 100644 index 62d1cbe..0000000 --- a/sql/20260803_pickup_order.sql +++ /dev/null @@ -1,95 +0,0 @@ --- 揽收单(独立履约/结算)+ 与物流单 1:N 关联;物流单冗余到仓方式与揽收 FK。 --- 对齐现表公共字段:ConcurrencyStamp / OrganizationId / SecretLevel;发件快照对齐 t_order_sender。 --- 文档:前端 docs/揽收单与物流单串联方案.md --- 执行前请备份。 --- 若表已按旧版脚本建好,请改跑 sql/20260803_pickup_order_align_fields.sql - -CREATE TABLE IF NOT EXISTS `t_pickup_order` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', - `PickupNo` VARCHAR(32) NOT NULL COMMENT '揽收单号', - `RequestId` VARCHAR(64) NULL COMMENT '请求幂等ID', - `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', - `SenderName` VARCHAR(50) NOT NULL DEFAULT '' COMMENT '取件联系人快照', - `SenderCompany` VARCHAR(255) NULL COMMENT '公司快照', - `SenderCountry` INT NULL COMMENT '国家 t_country.Id 快照', - `SenderCountryCode` VARCHAR(8) NULL COMMENT '国家码快照', - `SenderProvince` VARCHAR(50) NULL COMMENT '省快照', - `SenderCity` VARCHAR(50) NULL COMMENT '市快照', - `SenderZipCode` VARCHAR(50) NULL COMMENT '邮编快照', - `SenderStreetAddress1` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '地址1快照', - `SenderStreetAddress2` VARCHAR(500) NULL COMMENT '地址2快照', - `SenderStreetAddress3` VARCHAR(500) NULL COMMENT '地址3快照', - `SenderHouseNumber` VARCHAR(50) NULL COMMENT '门牌号快照', - `SenderPhone` VARCHAR(50) NULL COMMENT '手机快照', - `SenderTelePhone` VARCHAR(50) NULL COMMENT '电话快照', - `SenderEmail` VARCHAR(60) NULL COMMENT '邮箱快照', - `WarehouseId` INT NOT NULL COMMENT '送到仓库Id', - `CarrierCode` VARCHAR(64) NULL COMMENT '承运商编码(draft可空)', - `CarrierService` VARCHAR(64) NULL COMMENT '承运服务(draft可空)', - `CarrierWaybillNo` VARCHAR(64) NULL COMMENT '承运商回执单号', - `ExpectPickupTime` DATETIME NOT NULL COMMENT '期望揽收时间', - `PickupWindowStart` DATETIME NULL COMMENT '时间窗起', - `PickupWindowEnd` DATETIME NULL COMMENT '时间窗止', - `ActualPickupTime` DATETIME NULL COMMENT '实际取件时间', - `Status` VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT 'draft/scheduled/dispatched/picked/inbound/cancelled/failed', - `ParcelCount` INT NOT NULL DEFAULT 0 COMMENT '关联票数', - `TotalActualWeight` DECIMAL(18,3) NULL COMMENT '汇总实重', - `ChargeableWeight` DECIMAL(18,3) NULL COMMENT '计费重', - `Currency` VARCHAR(8) NOT NULL DEFAULT 'CNY' COMMENT '币种', - `FreightAmount` DECIMAL(18,2) NULL COMMENT '对客揽收运费', - `OtherFeeAmount` DECIMAL(18,2) NULL COMMENT '对客其他费', - `ReceivableAmount` DECIMAL(18,2) NULL COMMENT '对客应收合计', - `PayStatus` VARCHAR(16) NOT NULL DEFAULT 'unpaid' COMMENT 'unpaid/paid', - `PayTime` DATETIME NULL COMMENT '支付时间', - `PayMode` VARCHAR(16) NOT NULL DEFAULT 'prepaid' COMMENT 'prepaid/collect', - `CarrierPayableAmount` DECIMAL(18,2) NULL COMMENT '应付承运商', - `SettlementStatus` VARCHAR(16) NOT NULL DEFAULT 'none' COMMENT 'none/pending/settled', - `SettlementBatchNo` VARCHAR(64) NULL COMMENT '结算批次号', - `SettledAt` DATETIME NULL COMMENT '结算时间', - `Remark` VARCHAR(512) NULL COMMENT '备注', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - -- CREATE 可用 DEFAULT (UUID());若环境同样禁非确定默认值,可去掉 DEFAULT,由应用写入 - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_pickup_no` (`PickupNo`), - UNIQUE KEY `uk_pickup_request_id` (`RequestId`), - KEY `idx_pickup_customer_status` (`CustomerId`, `Status`, `CreateTime`), - KEY `idx_pickup_warehouse_time` (`WarehouseId`, `ExpectPickupTime`), - KEY `idx_pickup_pay` (`PayStatus`), - KEY `idx_pickup_settle` (`SettlementStatus`), - KEY `idx_pickup_org_secret_ctime` (`OrganizationId`, `SecretLevel`, `CreateTime`) -) COMMENT='揽收单(上门取件履约+对客收款+承运结算)'; - -CREATE TABLE IF NOT EXISTS `t_pickup_order_line` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键,自增', - `PickupOrderId` INT NOT NULL COMMENT '揽收单Id', - `OrderId` INT NOT NULL COMMENT '物流订单Id', - `ServiceNo` VARCHAR(64) NULL COMMENT '运单号快照(便于列表)', - `ClientNo` VARCHAR(64) NULL COMMENT '客户单号快照', - `SortNo` INT NOT NULL DEFAULT 0 COMMENT '展示序', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_pickup_line_order` (`OrderId`), - UNIQUE KEY `uk_pickup_line_pair` (`PickupOrderId`, `OrderId`), - KEY `idx_pickup_line_header` (`PickupOrderId`, `IsDeleted`) -) COMMENT='揽收单关联物流订单(1揽收:N物流)'; - -ALTER TABLE `t_order` - ADD COLUMN `InboundMethod` VARCHAR(16) NULL COMMENT '到仓方式 selfShip/doorPickup' AFTER `CustomerSenderAddressId`, - ADD COLUMN `PickupOrderId` INT NULL COMMENT '关联揽收单Id(冗余)' AFTER `InboundMethod`; - -ALTER TABLE `t_order` - ADD KEY `idx_order_pickup` (`PickupOrderId`), - ADD KEY `idx_order_inbound_method` (`InboundMethod`); diff --git a/sql/20260803_pickup_order_align_fields.sql b/sql/20260803_pickup_order_align_fields.sql deleted file mode 100644 index 638fce1..0000000 --- a/sql/20260803_pickup_order_align_fields.sql +++ /dev/null @@ -1,53 +0,0 @@ --- 对齐已创建的 t_pickup_order / t_pickup_order_line 与现表公共字段。 --- 适用于已执行旧版 20260803_pickup_order.sql 的环境;列已存在时对应语句会报错,可跳过。 --- 执行前请备份。 --- --- 注意:ConcurrencyStamp 勿写 DEFAULT (UUID()),在开启复制/GTID 时 ALTER 会报 1674。 --- 正确做法:先可空列 → UPDATE 回填 → 再改为 NOT NULL。 - --- ===== t_pickup_order ===== -ALTER TABLE `t_pickup_order` - ADD COLUMN `RequestId` VARCHAR(64) NULL COMMENT '请求幂等ID' AFTER `PickupNo`, - ADD COLUMN `OrganizationId` CHAR(36) NULL COMMENT '数据归属组织' AFTER `CustomerId`, - ADD COLUMN `SecretLevel` TINYINT NOT NULL DEFAULT 2 COMMENT '数据密级 1-4' AFTER `OrganizationId`; - -ALTER TABLE `t_pickup_order` - ADD COLUMN `SenderCountry` INT NULL COMMENT '国家 t_country.Id 快照' AFTER `SenderCompany`, - ADD COLUMN `SenderStreetAddress3` VARCHAR(500) NULL COMMENT '地址3快照' AFTER `SenderStreetAddress2`, - ADD COLUMN `SenderHouseNumber` VARCHAR(50) NULL COMMENT '门牌号快照' AFTER `SenderStreetAddress3`, - ADD COLUMN `SenderTelePhone` VARCHAR(50) NULL COMMENT '电话快照' AFTER `SenderPhone`, - ADD COLUMN `SenderEmail` VARCHAR(60) NULL COMMENT '邮箱快照' AFTER `SenderTelePhone`; - --- 手机字段长度与现表对齐(若已是 50 可忽略报错) -ALTER TABLE `t_pickup_order` - MODIFY COLUMN `SenderPhone` VARCHAR(50) NULL COMMENT '手机快照'; - --- ConcurrencyStamp(复制安全写法) -ALTER TABLE `t_pickup_order` - ADD COLUMN `ConcurrencyStamp` CHAR(36) NULL COMMENT '并发戳' AFTER `IsDeleted`; - -UPDATE `t_pickup_order` -SET `ConcurrencyStamp` = UUID() -WHERE `ConcurrencyStamp` IS NULL OR `ConcurrencyStamp` = ''; - -ALTER TABLE `t_pickup_order` - MODIFY COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL COMMENT '并发戳'; - -ALTER TABLE `t_pickup_order` - ADD UNIQUE KEY `uk_pickup_request_id` (`RequestId`), - ADD KEY `idx_pickup_org_secret_ctime` (`OrganizationId`, `SecretLevel`, `CreateTime`); - --- ===== t_pickup_order_line ===== -ALTER TABLE `t_pickup_order_line` - ADD COLUMN `ServiceNo` VARCHAR(64) NULL COMMENT '运单号快照(便于列表)' AFTER `OrderId`, - ADD COLUMN `ClientNo` VARCHAR(64) NULL COMMENT '客户单号快照' AFTER `ServiceNo`; - -ALTER TABLE `t_pickup_order_line` - ADD COLUMN `ConcurrencyStamp` CHAR(36) NULL COMMENT '并发戳' AFTER `IsDeleted`; - -UPDATE `t_pickup_order_line` -SET `ConcurrencyStamp` = UUID() -WHERE `ConcurrencyStamp` IS NULL OR `ConcurrencyStamp` = ''; - -ALTER TABLE `t_pickup_order_line` - MODIFY COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL COMMENT '并发戳'; diff --git a/sql/20260803_pickup_order_concurrency_stamp.sql b/sql/20260803_pickup_order_concurrency_stamp.sql deleted file mode 100644 index 06e2d44..0000000 --- a/sql/20260803_pickup_order_concurrency_stamp.sql +++ /dev/null @@ -1,53 +0,0 @@ --- 幂等补 ConcurrencyStamp:已存在则跳过 ADD,只做回填/NOT NULL。 --- 执行前请备份。 - --- 先看现状(可选) -SELECT TABLE_NAME, COLUMN_NAME, IS_NULLABLE, COLUMN_TYPE -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME IN ('t_pickup_order', 't_pickup_order_line') - AND COLUMN_NAME = 'ConcurrencyStamp'; - --- ===== t_pickup_order ===== -SET @sql := ( - SELECT IF( - EXISTS( - SELECT 1 FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 't_pickup_order' - AND COLUMN_NAME = 'ConcurrencyStamp' - ), - 'SELECT ''t_pickup_order.ConcurrencyStamp already exists'' AS info', - 'ALTER TABLE `t_pickup_order` ADD COLUMN `ConcurrencyStamp` CHAR(36) NULL COMMENT ''并发戳'' AFTER `IsDeleted`' - ) -); -PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -UPDATE `t_pickup_order` -SET `ConcurrencyStamp` = UUID() -WHERE `ConcurrencyStamp` IS NULL OR `ConcurrencyStamp` = ''; - -ALTER TABLE `t_pickup_order` - MODIFY COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL COMMENT '并发戳'; - --- ===== t_pickup_order_line ===== -SET @sql := ( - SELECT IF( - EXISTS( - SELECT 1 FROM information_schema.COLUMNS - WHERE TABLE_SCHEMA = DATABASE() - AND TABLE_NAME = 't_pickup_order_line' - AND COLUMN_NAME = 'ConcurrencyStamp' - ), - 'SELECT ''t_pickup_order_line.ConcurrencyStamp already exists'' AS info', - 'ALTER TABLE `t_pickup_order_line` ADD COLUMN `ConcurrencyStamp` CHAR(36) NULL COMMENT ''并发戳'' AFTER `IsDeleted`' - ) -); -PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; - -UPDATE `t_pickup_order_line` -SET `ConcurrencyStamp` = UUID() -WHERE `ConcurrencyStamp` IS NULL OR `ConcurrencyStamp` = ''; - -ALTER TABLE `t_pickup_order_line` - MODIFY COLUMN `ConcurrencyStamp` CHAR(36) NOT NULL COMMENT '并发戳'; diff --git a/sql/20260804_issue_template_handler.sql b/sql/20260804_issue_template_handler.sql deleted file mode 100644 index 624bf3a..0000000 --- a/sql/20260804_issue_template_handler.sql +++ /dev/null @@ -1,9 +0,0 @@ --- 问题模板:处理人类型 + 指定用户 -ALTER TABLE `t_issue_template` - ADD COLUMN `HandlerType` VARCHAR(16) NULL COMMENT '处理人类型:customer=订单所属客户 user=指定用户' AFTER `NotifyMethod`, - ADD COLUMN `HandlerUserId` INT NULL COMMENT '指定处理人用户Id(HandlerType=user 时必填)' AFTER `HandlerType`; - --- 问题事件:处理人快照(运行时解析) -ALTER TABLE `t_order_exception_event` - ADD COLUMN `HandlerType` VARCHAR(16) NULL COMMENT '处理人类型' AFTER `HandlerNames`, - ADD COLUMN `HandlerUserId` INT NULL COMMENT '处理人用户Id(customer 时为订单客户账号)' AFTER `HandlerType`; diff --git a/sql/20260804_kb_knowledge.sql b/sql/20260804_kb_knowledge.sql deleted file mode 100644 index 2077eca..0000000 --- a/sql/20260804_kb_knowledge.sql +++ /dev/null @@ -1,144 +0,0 @@ --- 物流业务知识库 M1:分类 + 文章 --- 执行库:OMS 业务库 - -CREATE TABLE IF NOT EXISTS `t_kb_category` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键', - `Code` VARCHAR(64) NOT NULL COMMENT '稳定键,如 pricing', - `Name` VARCHAR(128) NOT NULL COMMENT '展示名(中文)', - `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '排序,越小越前', - `Enabled` TINYINT NOT NULL DEFAULT 1 COMMENT '是否启用:0-否,1-是', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_kb_category_code` (`Code`), - KEY `idx_kb_category_enabled_sort` (`Enabled`, `SortOrder`) -) COMMENT='知识库分类'; - -CREATE TABLE IF NOT EXISTS `t_kb_article` ( - `Id` INT NOT NULL AUTO_INCREMENT COMMENT '主键', - `CategoryId` INT NOT NULL COMMENT '分类 Id', - `Title` VARCHAR(200) NOT NULL COMMENT '标题(中文)', - `Summary` VARCHAR(500) NULL COMMENT '列表摘要', - `Content` LONGTEXT NOT NULL COMMENT 'Markdown 正文(中文)', - `Audience` VARCHAR(16) NOT NULL DEFAULT 'customer' COMMENT '受众 customer/internal', - `Status` VARCHAR(16) NOT NULL DEFAULT 'draft' COMMENT 'draft/published/offline', - `Tags` VARCHAR(256) NULL COMMENT '逗号分隔标签', - `RelatedPath` VARCHAR(256) NULL COMMENT '站内关联 path', - `RelatedLabel` VARCHAR(64) NULL COMMENT '关联按钮文案', - `IsPinned` TINYINT NOT NULL DEFAULT 0 COMMENT '置顶:0-否,1-是', - `SortOrder` INT NOT NULL DEFAULT 0 COMMENT '同类排序', - `PublishTime` DATETIME NULL COMMENT '发布时间', - `ExpireTime` DATETIME NULL COMMENT '过期时间', - `ViewCount` INT NOT NULL DEFAULT 0 COMMENT '浏览次数', - `IsDeleted` TINYINT NOT NULL DEFAULT 0 COMMENT '软删除:0-否,1-是', - `ConcurrencyStamp` CHAR(36) NOT NULL DEFAULT (UUID()) 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_kb_article_list` (`Status`, `Audience`, `CategoryId`, `IsPinned`, `SortOrder`), - KEY `idx_kb_article_publish` (`Status`, `Audience`, `PublishTime`), - KEY `idx_kb_article_hot` (`Status`, `Audience`, `IsPinned`, `ViewCount`) -) COMMENT='知识库文章'; - --- 种子分类(幂等:Code 唯一) -INSERT INTO `t_kb_category` (`Code`, `Name`, `SortOrder`, `Enabled`) -SELECT 'pricing', '查价与计费', 10, 1 FROM DUAL -WHERE NOT EXISTS (SELECT 1 FROM `t_kb_category` WHERE `Code` = 'pricing' AND `IsDeleted` = 0); - -INSERT INTO `t_kb_category` (`Code`, `Name`, `SortOrder`, `Enabled`) -SELECT 'order', '下单与轨迹', 20, 1 FROM DUAL -WHERE NOT EXISTS (SELECT 1 FROM `t_kb_category` WHERE `Code` = 'order' AND `IsDeleted` = 0); - -INSERT INTO `t_kb_category` (`Code`, `Name`, `SortOrder`, `Enabled`) -SELECT 'exception', '问题件与售后', 30, 1 FROM DUAL -WHERE NOT EXISTS (SELECT 1 FROM `t_kb_category` WHERE `Code` = 'exception' AND `IsDeleted` = 0); - -INSERT INTO `t_kb_category` (`Code`, `Name`, `SortOrder`, `Enabled`) -SELECT 'customs', '禁限运与清关', 40, 1 FROM DUAL -WHERE NOT EXISTS (SELECT 1 FROM `t_kb_category` WHERE `Code` = 'customs' AND `IsDeleted` = 0); - -INSERT INTO `t_kb_category` (`Code`, `Name`, `SortOrder`, `Enabled`) -SELECT 'account', '账户与充值', 50, 1 FROM DUAL -WHERE NOT EXISTS (SELECT 1 FROM `t_kb_category` WHERE `Code` = 'account' AND `IsDeleted` = 0); - -INSERT INTO `t_kb_category` (`Code`, `Name`, `SortOrder`, `Enabled`) -SELECT 'dropship', '代发与店铺', 60, 1 FROM DUAL -WHERE NOT EXISTS (SELECT 1 FROM `t_kb_category` WHERE `Code` = 'dropship' AND `IsDeleted` = 0); - --- 种子 FAQ(幂等:按 Title + Category Code) -INSERT INTO `t_kb_article` -(`CategoryId`, `Title`, `Summary`, `Content`, `Audience`, `Status`, `Tags`, `RelatedPath`, `RelatedLabel`, `IsPinned`, `SortOrder`, `PublishTime`, `ViewCount`) -SELECT c.`Id`, - '如何查价?计费重量怎么算?', - '说明计费重、体积重与卖价取整规则。', - '## 查价入口\n\n工作台或菜单进入「查价」,填写目的国、重量与尺寸即可预估运费。\n\n## 计费重量\n\n系统按 **实重** 与 **体积重** 取较大者作为计费重。体积重公式以销售产品配置为准。\n\n## 提示\n\n查价结果为预估,实际以出库计费为准。', - 'customer', 'published', '查价,计费', '/order/priceCheck', '去查价', 1, 10, NOW(), 0 -FROM `t_kb_category` c -WHERE c.`Code` = 'pricing' AND c.`IsDeleted` = 0 - AND NOT EXISTS ( - SELECT 1 FROM `t_kb_article` a - WHERE a.`Title` = '如何查价?计费重量怎么算?' AND a.`CategoryId` = c.`Id` AND a.`IsDeleted` = 0 - ); - -INSERT INTO `t_kb_article` -(`CategoryId`, `Title`, `Summary`, `Content`, `Audience`, `Status`, `Tags`, `RelatedPath`, `RelatedLabel`, `IsPinned`, `SortOrder`, `PublishTime`, `ViewCount`) -SELECT c.`Id`, - '下单后如何查看轨迹?', - '订单列表与轨迹查询入口说明。', - '## 查看轨迹\n\n1. 进入「我的订单」,找到目标运单。\n2. 点击轨迹图标或进入详情查看最新节点。\n\n上网后才会出现承运商轨迹;未上网前可能仅有内部操作节点。', - 'customer', 'published', '轨迹,订单', NULL, NULL, 1, 10, NOW(), 0 -FROM `t_kb_category` c -WHERE c.`Code` = 'order' AND c.`IsDeleted` = 0 - AND NOT EXISTS ( - SELECT 1 FROM `t_kb_article` a - WHERE a.`Title` = '下单后如何查看轨迹?' AND a.`CategoryId` = c.`Id` AND a.`IsDeleted` = 0 - ); - -INSERT INTO `t_kb_article` -(`CategoryId`, `Title`, `Summary`, `Content`, `Audience`, `Status`, `Tags`, `RelatedPath`, `RelatedLabel`, `IsPinned`, `SortOrder`, `PublishTime`, `ViewCount`) -SELECT c.`Id`, - '什么是问题件?如何处理?', - '问题件常见原因与处理路径。', - '## 什么是问题件\n\n因地址不全、禁限运、欠费、清关资料缺失等原因,包裹无法继续流转时会标记为问题件。\n\n## 怎么处理\n\n在订单列表筛选「问题件」,按提示补全资料或联系客服。处理完成后会重新放行。', - 'customer', 'published', '问题件,售后', NULL, NULL, 0, 20, NOW(), 0 -FROM `t_kb_category` c -WHERE c.`Code` = 'exception' AND c.`IsDeleted` = 0 - AND NOT EXISTS ( - SELECT 1 FROM `t_kb_article` a - WHERE a.`Title` = '什么是问题件?如何处理?' AND a.`CategoryId` = c.`Id` AND a.`IsDeleted` = 0 - ); - -INSERT INTO `t_kb_article` -(`CategoryId`, `Title`, `Summary`, `Content`, `Audience`, `Status`, `Tags`, `RelatedPath`, `RelatedLabel`, `IsPinned`, `SortOrder`, `PublishTime`, `ViewCount`) -SELECT c.`Id`, - '账户余额不足怎么办?', - '充值入口与余额扣费说明。', - '## 充值\n\n工作台余额卡片或财务菜单可发起充值。到账后余额可用于下单扣费。\n\n## 注意\n\n子账号余额归属主客户;扣费失败时订单可能无法提交或出库。', - 'customer', 'published', '充值,余额', NULL, NULL, 0, 10, NOW(), 0 -FROM `t_kb_category` c -WHERE c.`Code` = 'account' AND c.`IsDeleted` = 0 - AND NOT EXISTS ( - SELECT 1 FROM `t_kb_article` a - WHERE a.`Title` = '账户余额不足怎么办?' AND a.`CategoryId` = c.`Id` AND a.`IsDeleted` = 0 - ); - -INSERT INTO `t_kb_article` -(`CategoryId`, `Title`, `Summary`, `Content`, `Audience`, `Status`, `Tags`, `RelatedPath`, `RelatedLabel`, `IsPinned`, `SortOrder`, `PublishTime`, `ViewCount`) -SELECT c.`Id`, - '禁限运物品有哪些?', - '常见禁限运与申报注意点。', - '## 常见禁限运\n\n电池、液体、粉末、管制刀具、仿牌等通常受限或禁运,以承运商与目的国法规为准。\n\n## 申报建议\n\n如实填写品名与货值,避免笼统描述(如 gifts)。不确定时可先咨询客服。', - 'customer', 'published', '禁运,清关', NULL, NULL, 0, 10, NOW(), 0 -FROM `t_kb_category` c -WHERE c.`Code` = 'customs' AND c.`IsDeleted` = 0 - AND NOT EXISTS ( - SELECT 1 FROM `t_kb_article` a - WHERE a.`Title` = '禁限运物品有哪些?' AND a.`CategoryId` = c.`Id` AND a.`IsDeleted` = 0 - ); - diff --git a/sql/20260804_kb_menu_notes.sql b/sql/20260804_kb_menu_notes.sql deleted file mode 100644 index 64e6747..0000000 --- a/sql/20260804_kb_menu_notes.sql +++ /dev/null @@ -1,8 +0,0 @@ --- 知识库 M1 菜单挂载说明 --- 一级:知识库 route=/kb permissionCode=Knowledge --- 在菜单管理对该一级点「同步子菜单及按钮」,将自动创建: --- 分类管理 /kb/category permissionCode=Knowledge.Category --- 三级:Knowledge.Category.Query / Knowledge.Category.Edit --- 文章管理 /kb/article permissionCode=Knowledge.Article --- 三级:Knowledge.Article.Query / Knowledge.Article.Edit / Knowledge.Article.Publish --- Admin 角色启动时可自动合并上述权限(见 XhsRolePermissionSeedContributor.AdminKbPermissions) diff --git a/sql/20260804_order_exception_event_handler.sql b/sql/20260804_order_exception_event_handler.sql deleted file mode 100644 index 48ee74a..0000000 --- a/sql/20260804_order_exception_event_handler.sql +++ /dev/null @@ -1,3 +0,0 @@ --- 问题处理:事件级处理人快照(订单可有多条问题记录) -ALTER TABLE `t_order_exception_event` - ADD COLUMN `HandlerNames` VARCHAR(256) NULL COMMENT '处理人快照' AFTER `NotifyMethod`; diff --git a/sql/20260804_order_status_drop_received.sql b/sql/20260804_order_status_drop_received.sql deleted file mode 100644 index 4b875b3..0000000 --- a/sql/20260804_order_status_drop_received.sql +++ /dev/null @@ -1,14 +0,0 @@ --- 废弃订单状态 received(已收货):入库后直接进 pendingAllocation / pendingPayment,不再停留 received --- 历史数据:已入库的归待排货;若已有应付且未支付则归待支付 - -UPDATE `t_order` -SET - `OrderStatus` = CASE - WHEN IFNULL(`IsPaid`, 0) > 0 THEN 'pendingShip' - WHEN IFNULL(`PayableAmount`, 0) > 0 - AND (`AllocationPendingReason` IS NULL OR TRIM(`AllocationPendingReason`) = '') - THEN 'pendingPayment' - ELSE 'pendingAllocation' - END, - `UpdateTime` = NOW() -WHERE `OrderStatus` = 'received'; diff --git a/src/Oms.Application/Dtos/Orders/OrderWorkplaceStatsOutput.cs b/src/Oms.Application/Dtos/Orders/OrderWorkplaceStatsOutput.cs index 1d345af..014da04 100644 --- a/src/Oms.Application/Dtos/Orders/OrderWorkplaceStatsOutput.cs +++ b/src/Oms.Application/Dtos/Orders/OrderWorkplaceStatsOutput.cs @@ -41,9 +41,9 @@ public class OrderWorkplaceStatsOutput public int Shipped { get; set; } /// - /// 待上网数量。 + /// 待支付数量。 /// - public int PendingOnline { get; set; } + public int PendingPayment { get; set; } /// /// 问题件数量。 diff --git a/src/Oms.Application/Services/Orders/OrderService.Workplace.cs b/src/Oms.Application/Services/Orders/OrderService.Workplace.cs index 191ba62..66ec360 100644 --- a/src/Oms.Application/Services/Orders/OrderService.Workplace.cs +++ b/src/Oms.Application/Services/Orders/OrderService.Workplace.cs @@ -74,7 +74,7 @@ public partial class OrderService DayOverDayGrowthPercent = growth, PendingShip = GetCount(OrderStatusCodes.PendingShip), Shipped = shipped, - PendingOnline = GetCount(OrderStatusCodes.PendingOnline), + PendingPayment = GetCount(OrderStatusCodes.PendingPayment), Problematic = GetCount(OrderStatusCodes.Problematic), StoreCount = storeCount, StoreOrderPending = storeOrderPending, diff --git a/tools/SwaggerDiag/Program.cs b/tools/SwaggerDiag/Program.cs new file mode 100644 index 0000000..539c73d --- /dev/null +++ b/tools/SwaggerDiag/Program.cs @@ -0,0 +1,47 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.OpenApi.Models; +using Oms.Application.Dtos.Orders; +using Swashbuckle.AspNetCore.SwaggerGen; +using System.Reflection; + +var services = new ServiceCollection(); +services.AddSwaggerGen(c => +{ + c.SwaggerDoc("OMS-Order", new OpenApiInfo { Title = "OMS-Order", Version = "v1" }); + c.CustomSchemaIds(t => t.FullName?.Replace("+", ".") ?? t.Name); +}); +var sp = services.BuildServiceProvider(); +var gen = sp.GetRequiredService(); +var repo = new SchemaRepository("OMS-Order"); + +void Try(string name, Type t) +{ + try + { + gen.GenerateSchema(t, repo); + Console.WriteLine($"OK {name}"); + } + catch (Exception ex) + { + Console.WriteLine($"FAIL {name}: {ex.GetType().Name}: {ex.Message}"); + if (ex.InnerException != null) Console.WriteLine($" inner: {ex.InnerException.Message}"); + } +} + +Try(nameof(OrderParcelBatchCreateInput), typeof(OrderParcelBatchCreateInput)); +Try(nameof(OrderParcelCreateInput), typeof(OrderParcelCreateInput)); +Try(nameof(OrderPriceCheckResultOutput), typeof(OrderPriceCheckResultOutput)); +Try(nameof(OrderPriceCheckOutput), typeof(OrderPriceCheckOutput)); +Try(nameof(OrderUploadInput), typeof(OrderUploadInput)); +Try(nameof(OrderTemplateCustomDetailOutput), typeof(OrderTemplateCustomDetailOutput)); +Try(nameof(OrderOutput), typeof(OrderOutput)); +Try(nameof(OrderPaginatedOutput), typeof(OrderPaginatedOutput)); + +// Also generate for all public types in Orders Dtos +var asm = typeof(OrderOutput).Assembly; +foreach (var t in asm.GetTypes().Where(x => x.IsPublic && x.Namespace == "Oms.Application.Dtos.Orders").OrderBy(x => x.Name)) +{ + Try(t.Name, t); +} + +Console.WriteLine($"Schemas generated: {repo.Schemas.Count}"); diff --git a/tools/SwaggerDiag/SwaggerDiag.csproj b/tools/SwaggerDiag/SwaggerDiag.csproj new file mode 100644 index 0000000..6617412 --- /dev/null +++ b/tools/SwaggerDiag/SwaggerDiag.csproj @@ -0,0 +1,13 @@ + + + Exe + net8.0 + enable + enable + + + + + + + diff --git a/tools/_chk.py b/tools/_chk.py new file mode 100644 index 0000000..18c6313 --- /dev/null +++ b/tools/_chk.py @@ -0,0 +1,10 @@ +from pathlib import Path +db = Path(r"c:\Users\wilso\Desktop\oms0414-back\db.sql").read_text(encoding="utf-8") +names = [ + "t_member_level", "t_mcp_tool", "t_pickup_order", "t_coupon_template", + "MemberLevelId", "PriceTierKey", "PayableAmount", "ReceivableSubtotal", + "TradeTerms", "AdditionalServices", "AiAnalysisReport", "HandlerNames", +] +for n in names: + needle = f"`{n}`" if not n.startswith("t_") else f"CREATE TABLE `{n}`" + print(n, needle in db or f"`{n}`" in db) diff --git a/tools/_cmp_sql_db.ps1 b/tools/_cmp_sql_db.ps1 new file mode 100644 index 0000000..8066c15 --- /dev/null +++ b/tools/_cmp_sql_db.ps1 @@ -0,0 +1,79 @@ +# Compare sql/*.sql migrations against db.sql +$dbPath = "c:\Users\wilso\Desktop\oms0414-back\db.sql" +$sqlDir = "c:\Users\wilso\Desktop\oms0414-back\sql" +$db = [IO.File]::ReadAllText($dbPath) + +function HasCol([string]$name) { + return $db.Contains("`$name`".Replace('$name', $name)) -or $db.Contains("``$name``") +} + +# simpler: look for `ColName` +function ColInDb([string]$name) { + return $db.IndexOf("`" + $name + "`" ) -ge 0 -or $db.IndexOf("``$name``") -ge 0 +} + +function ColInDb2([string]$name) { + $needle = [char]96 + $name + [char]96 # backtick Col backtick + return $db.Contains($needle) +} + +function TableInDb([string]$name) { + $needle = "CREATE TABLE " + [char]96 + $name + [char]96 + return $db.Contains($needle) +} + +$files = Get-ChildItem "$sqlDir\*.sql" | Where-Object { $_.Name -notmatch 'menu_notes' } | Sort-Object Name +$missing = @() + +foreach ($f in $files) { + $content = [IO.File]::ReadAllText($f.FullName) + $createMatches = [regex]::Matches($content, 'CREATE TABLE(?: IF NOT EXISTS)?\s+`([^`]+)`', 'IgnoreCase') + $addMatches = [regex]::Matches($content, 'ADD COLUMN(?: IF NOT EXISTS)?\s+`([^`]+)`', 'IgnoreCase') + $dropMatches = [regex]::Matches($content, 'DROP COLUMN\s+`([^`]+)`', 'IgnoreCase') + $modMatches = [regex]::Matches($content, 'MODIFY COLUMN\s+`([^`]+)`', 'IgnoreCase') + + $section = @() + foreach ($m in $createMatches) { + $t = $m.Groups[1].Value + if (-not (TableInDb $t)) { + $section += "MISSING TABLE: $t" + $missing += "$($f.Name) -> TABLE $t" + } else { + $section += "OK TABLE: $t" + } + } + foreach ($m in $addMatches) { + $c = $m.Groups[1].Value + if (-not (ColInDb2 $c)) { + $section += "MISSING COL (ADD): $c" + $missing += "$($f.Name) -> ADD $c" + } else { + $section += "OK COL (ADD): $c" + } + } + foreach ($m in $dropMatches) { + $c = $m.Groups[1].Value + if (ColInDb2 $c) { + $section += "STILL IN db (DROP intended): $c" + $missing += "$($f.Name) -> DROP not applied in db.sql: $c" + } else { + $section += "OK DROPPED: $c" + } + } + foreach ($m in $modMatches) { + $c = $m.Groups[1].Value + if (-not (ColInDb2 $c)) { + $section += "MISSING COL (MODIFY): $c" + $missing += "$($f.Name) -> MODIFY $c (col absent)" + } + } + + if ($section.Count -gt 0) { + Write-Output "==== $($f.Name) ====" + $section | ForEach-Object { Write-Output " $_" } + } +} + +Write-Output "" +Write-Output "==== SUMMARY MISSING ====" +if ($missing.Count -eq 0) { Write-Output "(none)" } else { $missing | ForEach-Object { Write-Output $_ } } diff --git a/tools/_cmp_sql_db.py b/tools/_cmp_sql_db.py new file mode 100644 index 0000000..a2beae0 --- /dev/null +++ b/tools/_cmp_sql_db.py @@ -0,0 +1,75 @@ +import re +from pathlib import Path + +db = Path(r"c:\Users\wilso\Desktop\oms0414-back\db.sql").read_text(encoding="utf-8") +sql_dir = Path(r"c:\Users\wilso\Desktop\oms0414-back\sql") +missing = [] + +# Extract CREATE TABLE blocks from db.sql for per-table column checks +table_cols = {} +for m in re.finditer(r"CREATE TABLE `([^`]+)`\s*\((.*?)\)\s*(?:ENGINE|COMMENT|=|;)", db, re.S | re.I): + name = m.group(1) + body = m.group(2) + cols = re.findall(r"`([^`]+)`", body) + # filter index-only mentions roughly: keep all backtick names in body + table_cols[name] = set(cols) + +for f in sorted(sql_dir.glob("*.sql")): + if "menu_notes" in f.name: + continue + text = f.read_text(encoding="utf-8") + creates = re.findall(r"CREATE TABLE(?: IF NOT EXISTS)?\s+`([^`]+)`", text, re.I) + # ALTER TABLE `x` ... ADD COLUMN `c` + alter_adds = re.findall( + r"ALTER TABLE\s+`([^`]+)`[\s\S]*?(?=ALTER TABLE|CREATE TABLE|\Z)", + text, + re.I, + ) + # Better: find each ADD COLUMN with preceding table via scanning + lines_out = [] + for t in creates: + ok = f"CREATE TABLE `{t}`" in db + lines_out.append(("OK" if ok else "MISS", "TABLE", t, None)) + if not ok: + missing.append(f"{f.name}: TABLE `{t}`") + + # Parse ADD COLUMN with associated table + pos = 0 + current_table = None + for m in re.finditer( + r"ALTER TABLE\s+`([^`]+)`|ADD COLUMN(?: IF NOT EXISTS)?\s+`([^`]+)`|DROP COLUMN\s+`([^`]+)`|MODIFY COLUMN\s+`([^`]+)`", + text, + re.I, + ): + if m.group(1): + current_table = m.group(1) + elif m.group(2): + col = m.group(2) + in_db = f"`{col}`" in db + in_table = current_table and col in table_cols.get(current_table, set()) + ok = bool(in_table) if current_table in table_cols else in_db + lines_out.append(("OK" if ok else "MISS", "ADD", col, current_table)) + if not ok: + missing.append(f"{f.name}: ADD `{current_table}`.`{col}`") + elif m.group(3): + col = m.group(3) + still = current_table and col in table_cols.get(current_table, set()) + lines_out.append(("STILL" if still else "OK", "DROP", col, current_table)) + if still: + missing.append(f"{f.name}: DROP `{current_table}`.`{col}` still in db.sql") + elif m.group(4): + col = m.group(4) + ok = current_table and col in table_cols.get(current_table, set()) + # For MODIFY we just check presence; nullability needs manual review + lines_out.append(("OK" if ok else "MISS", "MODIFY", col, current_table)) + if not ok: + missing.append(f"{f.name}: MODIFY `{current_table}`.`{col}` absent") + + if lines_out: + print(f"==== {f.name} ====") + for st, kind, name, tbl in lines_out: + loc = f"{tbl}." if tbl else "" + print(f" [{st}] {kind} {loc}{name}") + +print("\n==== SUMMARY (needs db.sql sync) ====") +print("\n".join(missing) if missing else "(none)")