feat: 店铺订单落库物流商与履约类型,并规范迁移脚本日期命名
All checks were successful
Build and Deploy / deploy (push) Successful in 1m2s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m2s
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
7a611f8cf7
commit
983dff12c5
@ -158,6 +158,8 @@ public async Task<PlatformStoreOrderBatchCreateLogisticsOutput> BatchCreateFulfi
|
||||
|
||||
存量 DDL、字典初始化等脚本放在 `sql/`(说明见 `sql/README.md`),与运行时 ORM 查询分离;**运行时查询与写入必须 ORM**。
|
||||
|
||||
新增增量迁移文件命名:`migrate_<主题>_YYYYMMDD.sql`(日期在末尾,例如 `migrate_xxx_20261016.sql`)。详细约定见 `sql/README.md`。
|
||||
|
||||
### 3. 上传代码前先同步远端
|
||||
|
||||
`test`、`master` 等共享分支会有其他人提交。**推送前必须先拉取远端,再上传**,避免覆盖或漏掉别人的提交。
|
||||
|
||||
@ -14,4 +14,6 @@ OMS / 共用库的建表脚本已统一到仓库根目录 `db.sql`。
|
||||
- 新环境:直接执行 `db.sql`(会 DROP 后重建,勿在有生产数据的库上执行)
|
||||
- 已有库:用 diff 对比 `db.sql` 与现库结构后手工 ALTER;本目录 `migrate_all.sql` 为存量增量迁移合集(可重复执行段已做列/表存在判断;揽收 Direction / FeePush 为裸 ALTER,已执行过请跳过)
|
||||
- 数据权限表(`user_org_perm` 等)若 RBAC 与 OMS 分库,请只在 RBAC 库执行 `db.sql` 末尾对应段落
|
||||
- 单次增量迁移命名:`migrate_<主题>.sql`,尽量可重复执行(先判断列/表/字典是否已存在)
|
||||
- 单次增量迁移命名:`migrate_<主题>_YYYYMMDD.sql`(日期放在文件名**末尾**,如 `migrate_sales_store_order_provider_fulfillment_20261016.sql`)
|
||||
- 尽量可重复执行(先判断列/表/字典是否已存在)
|
||||
- **后续新增脚本一律带日期后缀**;历史未带日期的脚本不强制改名
|
||||
|
||||
@ -0,0 +1,89 @@
|
||||
-- 店铺订单:落库 shipping_provider / fulfillment_type;删除多面单、自定义标签、拒发字段。
|
||||
-- 可重复执行。
|
||||
|
||||
SET @db := DATABASE();
|
||||
|
||||
-- t_sales_store_order.ShippingProvider
|
||||
SET @exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db
|
||||
AND TABLE_NAME = 't_sales_store_order'
|
||||
AND COLUMN_NAME = 'ShippingProvider'
|
||||
);
|
||||
SET @sql := IF(
|
||||
@exists = 0,
|
||||
'ALTER TABLE `t_sales_store_order` ADD COLUMN `ShippingProvider` VARCHAR(128) NULL COMMENT ''平台物流商'' AFTER `ShippingLabelUrl`',
|
||||
'SELECT ''t_sales_store_order.ShippingProvider already exists'' AS info'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- t_sales_store_order.FulfillmentType
|
||||
SET @exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db
|
||||
AND TABLE_NAME = 't_sales_store_order'
|
||||
AND COLUMN_NAME = 'FulfillmentType'
|
||||
);
|
||||
SET @sql := IF(
|
||||
@exists = 0,
|
||||
'ALTER TABLE `t_sales_store_order` ADD COLUMN `FulfillmentType` VARCHAR(64) NULL COMMENT ''平台履约类型'' AFTER `ShippingProvider`',
|
||||
'SELECT ''t_sales_store_order.FulfillmentType already exists'' AS info'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- drop IsMultiLabel
|
||||
SET @exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db
|
||||
AND TABLE_NAME = 't_sales_store_order'
|
||||
AND COLUMN_NAME = 'IsMultiLabel'
|
||||
);
|
||||
SET @sql := IF(
|
||||
@exists > 0,
|
||||
'ALTER TABLE `t_sales_store_order` DROP COLUMN `IsMultiLabel`',
|
||||
'SELECT ''t_sales_store_order.IsMultiLabel already dropped'' AS info'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- drop CustomTags
|
||||
SET @exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db
|
||||
AND TABLE_NAME = 't_sales_store_order'
|
||||
AND COLUMN_NAME = 'CustomTags'
|
||||
);
|
||||
SET @sql := IF(
|
||||
@exists > 0,
|
||||
'ALTER TABLE `t_sales_store_order` DROP COLUMN `CustomTags`',
|
||||
'SELECT ''t_sales_store_order.CustomTags already dropped'' AS info'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- drop line IsShipExcluded
|
||||
SET @exists := (
|
||||
SELECT COUNT(1)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = @db
|
||||
AND TABLE_NAME = 't_sales_store_order_line'
|
||||
AND COLUMN_NAME = 'IsShipExcluded'
|
||||
);
|
||||
SET @sql := IF(
|
||||
@exists > 0,
|
||||
'ALTER TABLE `t_sales_store_order_line` DROP COLUMN `IsShipExcluded`',
|
||||
'SELECT ''t_sales_store_order_line.IsShipExcluded already dropped'' AS info'
|
||||
);
|
||||
PREPARE stmt FROM @sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@ -180,8 +180,6 @@ public class PlatformStoreOrderLineOutput
|
||||
|
||||
public string? Currency { get; set; }
|
||||
|
||||
public bool IsShipExcluded { get; set; }
|
||||
|
||||
public int? MappedSkuId { get; set; }
|
||||
|
||||
public string? MappedSkuCode { get; set; }
|
||||
@ -245,9 +243,11 @@ public class PlatformStoreOrderOutput
|
||||
|
||||
public string? ShippingLabelUrl { get; set; }
|
||||
|
||||
public bool IsMultiLabel { get; set; }
|
||||
/// <summary>平台物流商。</summary>
|
||||
public string? ShippingProvider { get; set; }
|
||||
|
||||
public string? CustomTags { get; set; }
|
||||
/// <summary>平台履约类型。</summary>
|
||||
public string? FulfillmentType { get; set; }
|
||||
|
||||
public bool IsSuspended { get; set; }
|
||||
|
||||
|
||||
@ -99,7 +99,9 @@ public sealed class PlatformShopPulledOrder
|
||||
|
||||
public string? ShippingLabelUrl { get; set; }
|
||||
|
||||
public bool IsMultiLabel { get; set; }
|
||||
public string? ShippingProvider { get; set; }
|
||||
|
||||
public string? FulfillmentType { get; set; }
|
||||
|
||||
public string? ExtraJson { get; set; }
|
||||
|
||||
@ -784,13 +786,10 @@ internal sealed class PlatformShopFulfillmentClient(
|
||||
GetString(recipient, "region"));
|
||||
|
||||
var lines = new List<PlatformShopPulledOrderLine>();
|
||||
var packageIds = new HashSet<string>(StringComparer.Ordinal);
|
||||
if (order.TryGetProperty("line_items", out var lineItems) && lineItems.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var line in lineItems.EnumerateArray())
|
||||
{
|
||||
var packageId = GetString(line, "package_id");
|
||||
if (!string.IsNullOrWhiteSpace(packageId)) packageIds.Add(packageId);
|
||||
lines.Add(new PlatformShopPulledOrderLine
|
||||
{
|
||||
PlatformLineId = GetString(line, "id"),
|
||||
@ -806,15 +805,6 @@ internal sealed class PlatformShopFulfillmentClient(
|
||||
}
|
||||
}
|
||||
|
||||
if (order.TryGetProperty("packages", out var packages) && packages.ValueKind == JsonValueKind.Array)
|
||||
{
|
||||
foreach (var pkg in packages.EnumerateArray())
|
||||
{
|
||||
var packageId = GetString(pkg, "id");
|
||||
if (!string.IsNullOrWhiteSpace(packageId)) packageIds.Add(packageId);
|
||||
}
|
||||
}
|
||||
|
||||
var tracking = GetString(order, "tracking_number");
|
||||
if (string.IsNullOrWhiteSpace(tracking)
|
||||
&& order.TryGetProperty("line_items", out var itemsForTrack)
|
||||
@ -824,6 +814,12 @@ internal sealed class PlatformShopFulfillmentClient(
|
||||
tracking = GetString(itemsForTrack[0], "tracking_number");
|
||||
}
|
||||
|
||||
var shippingProvider = FirstNonEmpty(
|
||||
GetString(order, "shipping_provider"),
|
||||
lineItems.ValueKind == JsonValueKind.Array && lineItems.GetArrayLength() > 0
|
||||
? GetString(lineItems[0], "shipping_provider_name")
|
||||
: null);
|
||||
|
||||
return new PlatformShopPulledOrder
|
||||
{
|
||||
PlatformOrderNo = id,
|
||||
@ -848,7 +844,8 @@ internal sealed class PlatformShopFulfillmentClient(
|
||||
PlatformStatusLabel = status,
|
||||
FulfillStatus = MapTiktokFulfill(status),
|
||||
ShippingLabelNo = tracking,
|
||||
IsMultiLabel = packageIds.Count > 1,
|
||||
ShippingProvider = shippingProvider,
|
||||
FulfillmentType = GetString(order, "fulfillment_type"),
|
||||
ExtraJson = order.ValueKind == JsonValueKind.Undefined ? null : order.GetRawText(),
|
||||
Lines = lines
|
||||
};
|
||||
|
||||
@ -377,7 +377,8 @@ internal sealed class PlatformStoreOrderFulfillmentService(
|
||||
entity.FulfillStatus = pulled.FulfillStatus;
|
||||
entity.ShippingLabelNo = pulled.ShippingLabelNo ?? entity.ShippingLabelNo;
|
||||
entity.ShippingLabelUrl = pulled.ShippingLabelUrl ?? entity.ShippingLabelUrl;
|
||||
entity.IsMultiLabel = pulled.IsMultiLabel || entity.IsMultiLabel;
|
||||
if (!string.IsNullOrWhiteSpace(pulled.ShippingProvider)) entity.ShippingProvider = pulled.ShippingProvider;
|
||||
if (!string.IsNullOrWhiteSpace(pulled.FulfillmentType)) entity.FulfillmentType = pulled.FulfillmentType;
|
||||
entity.PlatformExtraJson = pulled.ExtraJson ?? entity.PlatformExtraJson;
|
||||
entity.LastSyncTime = now;
|
||||
PlatformStoreOrderParcelBuilder.TryFillRecipientFields(entity, pulled.ExtraJson);
|
||||
|
||||
@ -107,7 +107,7 @@ public static class PlatformStoreOrderParcelBuilder
|
||||
IReadOnlyCollection<SalesStoreOrderLine> lines)
|
||||
{
|
||||
var items = new List<OrderParcelItemInput>();
|
||||
foreach (var line in lines.Where(x => !x.IsShipExcluded))
|
||||
foreach (var line in lines)
|
||||
{
|
||||
var cnName = string.IsNullOrWhiteSpace(line.ProductName)
|
||||
? (string.IsNullOrWhiteSpace(line.PlatformSku) ? "Platform Item" : line.PlatformSku.Trim())
|
||||
@ -157,7 +157,7 @@ public static class PlatformStoreOrderParcelBuilder
|
||||
IReadOnlyDictionary<int, CSku> skuMap)
|
||||
{
|
||||
var items = new List<OrderParcelItemInput>();
|
||||
foreach (var line in lines.Where(x => !x.IsShipExcluded))
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (!line.MappedSkuId.HasValue || !skuMap.TryGetValue(line.MappedSkuId.Value, out var sku))
|
||||
{
|
||||
@ -201,7 +201,7 @@ public static class PlatformStoreOrderParcelBuilder
|
||||
decimal maxHeight = DefaultHeightCm;
|
||||
decimal totalWeightKg = 0m;
|
||||
|
||||
foreach (var line in lines.Where(x => !x.IsShipExcluded && x.MappedSkuId.HasValue))
|
||||
foreach (var line in lines.Where(x => x.MappedSkuId.HasValue))
|
||||
{
|
||||
if (!skuMap.TryGetValue(line.MappedSkuId!.Value, out var sku))
|
||||
{
|
||||
|
||||
@ -553,7 +553,7 @@ public class PlatformStoreOrderService : ApplicationService
|
||||
var order = await GetOrderOrThrowAsync(customerId, storeOrderId);
|
||||
await EnsureCanCreateLogisticsAsync(order);
|
||||
|
||||
var lines = await StoreOrderLineRepository.GetListAsync(x => x.StoreOrderId == order.Id && !x.IsShipExcluded);
|
||||
var lines = await StoreOrderLineRepository.GetListAsync(x => x.StoreOrderId == order.Id);
|
||||
if (lines.Count == 0)
|
||||
{
|
||||
throw new BusinessException("没有可发货的商品行");
|
||||
@ -710,7 +710,7 @@ public class PlatformStoreOrderService : ApplicationService
|
||||
var warehouse = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == resolvedWarehouseId.Value)
|
||||
?? throw new BusinessException("仓库不存在");
|
||||
|
||||
var lines = await StoreOrderLineRepository.GetListAsync(x => x.StoreOrderId == order.Id && !x.IsShipExcluded);
|
||||
var lines = await StoreOrderLineRepository.GetListAsync(x => x.StoreOrderId == order.Id);
|
||||
if (lines.Count == 0)
|
||||
{
|
||||
throw new BusinessException("没有可发货的商品行");
|
||||
@ -1103,8 +1103,8 @@ public class PlatformStoreOrderService : ApplicationService
|
||||
PlatformStatusLabel = order.PlatformStatusLabel,
|
||||
ShippingLabelNo = order.ShippingLabelNo,
|
||||
ShippingLabelUrl = order.ShippingLabelUrl,
|
||||
IsMultiLabel = order.IsMultiLabel,
|
||||
CustomTags = order.CustomTags,
|
||||
ShippingProvider = order.ShippingProvider,
|
||||
FulfillmentType = order.FulfillmentType,
|
||||
IsSuspended = order.IsSuspended,
|
||||
WarehouseId = order.WarehouseId,
|
||||
LinkedOrderId = order.LinkedOrderId,
|
||||
@ -1129,7 +1129,6 @@ public class PlatformStoreOrderService : ApplicationService
|
||||
UnitPrice = line.UnitPrice,
|
||||
Quantity = line.Quantity,
|
||||
Currency = line.Currency,
|
||||
IsShipExcluded = line.IsShipExcluded,
|
||||
MappedSkuId = line.MappedSkuId,
|
||||
MappedSkuCode = mappedSkuCode
|
||||
};
|
||||
|
||||
@ -56,9 +56,11 @@ public class SalesStoreOrder : OmsAuditedAggregateRoot
|
||||
|
||||
public string? ShippingLabelUrl { get; set; }
|
||||
|
||||
public bool IsMultiLabel { get; set; }
|
||||
/// <summary>平台物流商,如 TikTok shipping_provider。</summary>
|
||||
public string? ShippingProvider { get; set; }
|
||||
|
||||
public string? CustomTags { get; set; }
|
||||
/// <summary>平台履约类型,如 TikTok fulfillment_type。</summary>
|
||||
public string? FulfillmentType { get; set; }
|
||||
|
||||
public bool IsSuspended { get; set; }
|
||||
|
||||
|
||||
@ -24,7 +24,5 @@ public class SalesStoreOrderLine : OmsAuditedAggregateRoot
|
||||
|
||||
public string? Currency { get; set; }
|
||||
|
||||
public bool IsShipExcluded { get; set; }
|
||||
|
||||
public int? MappedSkuId { get; set; }
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user