1.06 #10

Merged
zzh merged 18 commits from test into master 2026-10-19 17:03:15 +08:00
10 changed files with 122 additions and 32 deletions
Showing only changes of commit 983dff12c5 - Show all commits

View File

@ -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` 等共享分支会有其他人提交。**推送前必须先拉取远端,再上传**,避免覆盖或漏掉别人的提交。

View File

@ -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`)
- 尽量可重复执行(先判断列/表/字典是否已存在)
- **后续新增脚本一律带日期后缀**;历史未带日期的脚本不强制改名

View File

@ -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;

View File

@ -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; }

View File

@ -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
};

View File

@ -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);

View File

@ -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))
{

View File

@ -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
};

View File

@ -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; }

View File

@ -24,7 +24,5 @@ public class SalesStoreOrderLine : OmsAuditedAggregateRoot
public string? Currency { get; set; }
public bool IsShipExcluded { get; set; }
public int? MappedSkuId { get; set; }
}