1.06 #10
@ -158,6 +158,8 @@ public async Task<PlatformStoreOrderBatchCreateLogisticsOutput> BatchCreateFulfi
|
|||||||
|
|
||||||
存量 DDL、字典初始化等脚本放在 `sql/`(说明见 `sql/README.md`),与运行时 ORM 查询分离;**运行时查询与写入必须 ORM**。
|
存量 DDL、字典初始化等脚本放在 `sql/`(说明见 `sql/README.md`),与运行时 ORM 查询分离;**运行时查询与写入必须 ORM**。
|
||||||
|
|
||||||
|
新增增量迁移文件命名:`migrate_<主题>_YYYYMMDD.sql`(日期在末尾,例如 `migrate_xxx_20261016.sql`)。详细约定见 `sql/README.md`。
|
||||||
|
|
||||||
### 3. 上传代码前先同步远端
|
### 3. 上传代码前先同步远端
|
||||||
|
|
||||||
`test`、`master` 等共享分支会有其他人提交。**推送前必须先拉取远端,再上传**,避免覆盖或漏掉别人的提交。
|
`test`、`master` 等共享分支会有其他人提交。**推送前必须先拉取远端,再上传**,避免覆盖或漏掉别人的提交。
|
||||||
|
|||||||
@ -14,4 +14,6 @@ OMS / 共用库的建表脚本已统一到仓库根目录 `db.sql`。
|
|||||||
- 新环境:直接执行 `db.sql`(会 DROP 后重建,勿在有生产数据的库上执行)
|
- 新环境:直接执行 `db.sql`(会 DROP 后重建,勿在有生产数据的库上执行)
|
||||||
- 已有库:用 diff 对比 `db.sql` 与现库结构后手工 ALTER;本目录 `migrate_all.sql` 为存量增量迁移合集(可重复执行段已做列/表存在判断;揽收 Direction / FeePush 为裸 ALTER,已执行过请跳过)
|
- 已有库:用 diff 对比 `db.sql` 与现库结构后手工 ALTER;本目录 `migrate_all.sql` 为存量增量迁移合集(可重复执行段已做列/表存在判断;揽收 Direction / FeePush 为裸 ALTER,已执行过请跳过)
|
||||||
- 数据权限表(`user_org_perm` 等)若 RBAC 与 OMS 分库,请只在 RBAC 库执行 `db.sql` 末尾对应段落
|
- 数据权限表(`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 string? Currency { get; set; }
|
||||||
|
|
||||||
public bool IsShipExcluded { get; set; }
|
|
||||||
|
|
||||||
public int? MappedSkuId { get; set; }
|
public int? MappedSkuId { get; set; }
|
||||||
|
|
||||||
public string? MappedSkuCode { get; set; }
|
public string? MappedSkuCode { get; set; }
|
||||||
@ -245,9 +243,11 @@ public class PlatformStoreOrderOutput
|
|||||||
|
|
||||||
public string? ShippingLabelUrl { get; set; }
|
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; }
|
public bool IsSuspended { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -99,7 +99,9 @@ public sealed class PlatformShopPulledOrder
|
|||||||
|
|
||||||
public string? ShippingLabelUrl { get; set; }
|
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; }
|
public string? ExtraJson { get; set; }
|
||||||
|
|
||||||
@ -784,13 +786,10 @@ internal sealed class PlatformShopFulfillmentClient(
|
|||||||
GetString(recipient, "region"));
|
GetString(recipient, "region"));
|
||||||
|
|
||||||
var lines = new List<PlatformShopPulledOrderLine>();
|
var lines = new List<PlatformShopPulledOrderLine>();
|
||||||
var packageIds = new HashSet<string>(StringComparer.Ordinal);
|
|
||||||
if (order.TryGetProperty("line_items", out var lineItems) && lineItems.ValueKind == JsonValueKind.Array)
|
if (order.TryGetProperty("line_items", out var lineItems) && lineItems.ValueKind == JsonValueKind.Array)
|
||||||
{
|
{
|
||||||
foreach (var line in lineItems.EnumerateArray())
|
foreach (var line in lineItems.EnumerateArray())
|
||||||
{
|
{
|
||||||
var packageId = GetString(line, "package_id");
|
|
||||||
if (!string.IsNullOrWhiteSpace(packageId)) packageIds.Add(packageId);
|
|
||||||
lines.Add(new PlatformShopPulledOrderLine
|
lines.Add(new PlatformShopPulledOrderLine
|
||||||
{
|
{
|
||||||
PlatformLineId = GetString(line, "id"),
|
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");
|
var tracking = GetString(order, "tracking_number");
|
||||||
if (string.IsNullOrWhiteSpace(tracking)
|
if (string.IsNullOrWhiteSpace(tracking)
|
||||||
&& order.TryGetProperty("line_items", out var itemsForTrack)
|
&& order.TryGetProperty("line_items", out var itemsForTrack)
|
||||||
@ -824,6 +814,12 @@ internal sealed class PlatformShopFulfillmentClient(
|
|||||||
tracking = GetString(itemsForTrack[0], "tracking_number");
|
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
|
return new PlatformShopPulledOrder
|
||||||
{
|
{
|
||||||
PlatformOrderNo = id,
|
PlatformOrderNo = id,
|
||||||
@ -848,7 +844,8 @@ internal sealed class PlatformShopFulfillmentClient(
|
|||||||
PlatformStatusLabel = status,
|
PlatformStatusLabel = status,
|
||||||
FulfillStatus = MapTiktokFulfill(status),
|
FulfillStatus = MapTiktokFulfill(status),
|
||||||
ShippingLabelNo = tracking,
|
ShippingLabelNo = tracking,
|
||||||
IsMultiLabel = packageIds.Count > 1,
|
ShippingProvider = shippingProvider,
|
||||||
|
FulfillmentType = GetString(order, "fulfillment_type"),
|
||||||
ExtraJson = order.ValueKind == JsonValueKind.Undefined ? null : order.GetRawText(),
|
ExtraJson = order.ValueKind == JsonValueKind.Undefined ? null : order.GetRawText(),
|
||||||
Lines = lines
|
Lines = lines
|
||||||
};
|
};
|
||||||
|
|||||||
@ -377,7 +377,8 @@ internal sealed class PlatformStoreOrderFulfillmentService(
|
|||||||
entity.FulfillStatus = pulled.FulfillStatus;
|
entity.FulfillStatus = pulled.FulfillStatus;
|
||||||
entity.ShippingLabelNo = pulled.ShippingLabelNo ?? entity.ShippingLabelNo;
|
entity.ShippingLabelNo = pulled.ShippingLabelNo ?? entity.ShippingLabelNo;
|
||||||
entity.ShippingLabelUrl = pulled.ShippingLabelUrl ?? entity.ShippingLabelUrl;
|
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.PlatformExtraJson = pulled.ExtraJson ?? entity.PlatformExtraJson;
|
||||||
entity.LastSyncTime = now;
|
entity.LastSyncTime = now;
|
||||||
PlatformStoreOrderParcelBuilder.TryFillRecipientFields(entity, pulled.ExtraJson);
|
PlatformStoreOrderParcelBuilder.TryFillRecipientFields(entity, pulled.ExtraJson);
|
||||||
|
|||||||
@ -107,7 +107,7 @@ public static class PlatformStoreOrderParcelBuilder
|
|||||||
IReadOnlyCollection<SalesStoreOrderLine> lines)
|
IReadOnlyCollection<SalesStoreOrderLine> lines)
|
||||||
{
|
{
|
||||||
var items = new List<OrderParcelItemInput>();
|
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)
|
var cnName = string.IsNullOrWhiteSpace(line.ProductName)
|
||||||
? (string.IsNullOrWhiteSpace(line.PlatformSku) ? "Platform Item" : line.PlatformSku.Trim())
|
? (string.IsNullOrWhiteSpace(line.PlatformSku) ? "Platform Item" : line.PlatformSku.Trim())
|
||||||
@ -157,7 +157,7 @@ public static class PlatformStoreOrderParcelBuilder
|
|||||||
IReadOnlyDictionary<int, CSku> skuMap)
|
IReadOnlyDictionary<int, CSku> skuMap)
|
||||||
{
|
{
|
||||||
var items = new List<OrderParcelItemInput>();
|
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))
|
if (!line.MappedSkuId.HasValue || !skuMap.TryGetValue(line.MappedSkuId.Value, out var sku))
|
||||||
{
|
{
|
||||||
@ -201,7 +201,7 @@ public static class PlatformStoreOrderParcelBuilder
|
|||||||
decimal maxHeight = DefaultHeightCm;
|
decimal maxHeight = DefaultHeightCm;
|
||||||
decimal totalWeightKg = 0m;
|
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))
|
if (!skuMap.TryGetValue(line.MappedSkuId!.Value, out var sku))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -553,7 +553,7 @@ public class PlatformStoreOrderService : ApplicationService
|
|||||||
var order = await GetOrderOrThrowAsync(customerId, storeOrderId);
|
var order = await GetOrderOrThrowAsync(customerId, storeOrderId);
|
||||||
await EnsureCanCreateLogisticsAsync(order);
|
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)
|
if (lines.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("没有可发货的商品行");
|
throw new BusinessException("没有可发货的商品行");
|
||||||
@ -710,7 +710,7 @@ public class PlatformStoreOrderService : ApplicationService
|
|||||||
var warehouse = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == resolvedWarehouseId.Value)
|
var warehouse = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == resolvedWarehouseId.Value)
|
||||||
?? throw new BusinessException("仓库不存在");
|
?? 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)
|
if (lines.Count == 0)
|
||||||
{
|
{
|
||||||
throw new BusinessException("没有可发货的商品行");
|
throw new BusinessException("没有可发货的商品行");
|
||||||
@ -1103,8 +1103,8 @@ public class PlatformStoreOrderService : ApplicationService
|
|||||||
PlatformStatusLabel = order.PlatformStatusLabel,
|
PlatformStatusLabel = order.PlatformStatusLabel,
|
||||||
ShippingLabelNo = order.ShippingLabelNo,
|
ShippingLabelNo = order.ShippingLabelNo,
|
||||||
ShippingLabelUrl = order.ShippingLabelUrl,
|
ShippingLabelUrl = order.ShippingLabelUrl,
|
||||||
IsMultiLabel = order.IsMultiLabel,
|
ShippingProvider = order.ShippingProvider,
|
||||||
CustomTags = order.CustomTags,
|
FulfillmentType = order.FulfillmentType,
|
||||||
IsSuspended = order.IsSuspended,
|
IsSuspended = order.IsSuspended,
|
||||||
WarehouseId = order.WarehouseId,
|
WarehouseId = order.WarehouseId,
|
||||||
LinkedOrderId = order.LinkedOrderId,
|
LinkedOrderId = order.LinkedOrderId,
|
||||||
@ -1129,7 +1129,6 @@ public class PlatformStoreOrderService : ApplicationService
|
|||||||
UnitPrice = line.UnitPrice,
|
UnitPrice = line.UnitPrice,
|
||||||
Quantity = line.Quantity,
|
Quantity = line.Quantity,
|
||||||
Currency = line.Currency,
|
Currency = line.Currency,
|
||||||
IsShipExcluded = line.IsShipExcluded,
|
|
||||||
MappedSkuId = line.MappedSkuId,
|
MappedSkuId = line.MappedSkuId,
|
||||||
MappedSkuCode = mappedSkuCode
|
MappedSkuCode = mappedSkuCode
|
||||||
};
|
};
|
||||||
|
|||||||
@ -56,9 +56,11 @@ public class SalesStoreOrder : OmsAuditedAggregateRoot
|
|||||||
|
|
||||||
public string? ShippingLabelUrl { get; set; }
|
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; }
|
public bool IsSuspended { get; set; }
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,5 @@ public class SalesStoreOrderLine : OmsAuditedAggregateRoot
|
|||||||
|
|
||||||
public string? Currency { get; set; }
|
public string? Currency { get; set; }
|
||||||
|
|
||||||
public bool IsShipExcluded { get; set; }
|
|
||||||
|
|
||||||
public int? MappedSkuId { get; set; }
|
public int? MappedSkuId { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user