All checks were successful
Build and Deploy / deploy (push) Successful in 1m0s
库内 SKU 与 createOrderOne items 对齐 productId/nonStdProductId/stdProductId;无值时仍序列化为 null。 Co-authored-by: Cursor <cursoragent@cursor.com>
596 lines
21 KiB
C#
596 lines
21 KiB
C#
using System.Text.Json;
|
||
using System.Text.Json.Nodes;
|
||
using Fake.Application;
|
||
using Oms.Application.Dtos.Orders;
|
||
using Oms.Application.Dtos.PlatformStore;
|
||
using Oms.Domain.OrdersAggregate.Consts;
|
||
using Oms.Domain.OrdersAggregate.Entities;
|
||
using Oms.Domain.SystemAggregate.Entities;
|
||
using Oms.Domain.WarehouseAggregate.Entities;
|
||
|
||
namespace Oms.Application.Services.Orders;
|
||
|
||
/// <summary>
|
||
/// 将店铺订单转换为小包创建入参。
|
||
/// </summary>
|
||
public static class PlatformStoreOrderParcelBuilder
|
||
{
|
||
private const decimal DefaultLengthCm = 10m;
|
||
private const decimal DefaultWidthCm = 10m;
|
||
private const decimal DefaultHeightCm = 10m;
|
||
private const decimal MinActualWeightKg = 0.01m;
|
||
|
||
public static OrderParcelCreateInput Build(
|
||
SalesStoreOrder storeOrder,
|
||
IReadOnlyCollection<SalesStoreOrderLine> lines,
|
||
IReadOnlyDictionary<int, CSku> skuMap,
|
||
WarehouseAddress warehouse,
|
||
string productCode,
|
||
int warehouseId,
|
||
int customerId,
|
||
OrderParcelReceiverInput? receiverOverride = null,
|
||
string? trackNoOverride = null)
|
||
{
|
||
var receiver = receiverOverride ?? ParseReceiver(storeOrder);
|
||
ValidateReceiver(receiver);
|
||
|
||
var declarationLines = BuildDeclarationLines(lines, skuMap);
|
||
var (length, width, height, actualWeightKg) = ResolveParcelMetrics(declarationLines, lines, skuMap);
|
||
|
||
return new OrderParcelCreateInput
|
||
{
|
||
RequestId = $"platform-store-order:{storeOrder.Id}",
|
||
ClientNo = storeOrder.PlatformOrderNo,
|
||
TrackNo = string.IsNullOrWhiteSpace(trackNoOverride) ? storeOrder.ShippingLabelNo : trackNoOverride.Trim(),
|
||
ProductCode = productCode,
|
||
WarehouseId = warehouseId,
|
||
CustomerId = customerId,
|
||
Length = length,
|
||
Width = width,
|
||
Height = height,
|
||
ActualWeight = actualWeightKg,
|
||
ChargeableWeight = actualWeightKg,
|
||
CargoAttribute = CargoAttributeCodes.General,
|
||
DeclaredCurrency = string.IsNullOrWhiteSpace(storeOrder.Currency) ? "USD" : storeOrder.Currency.Trim(),
|
||
DeclaredSum = storeOrder.TotalAmount,
|
||
Quantity = 1,
|
||
Receiver = receiver,
|
||
Sender = BuildSender(warehouse),
|
||
Items = declarationLines
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将下单页同款「运单基本信息」覆盖到组装好的小包入参。
|
||
/// </summary>
|
||
public static void ApplyParcelBasic(
|
||
OrderParcelCreateInput parcelInput,
|
||
PlatformStoreOrderParcelBasicInput? basic,
|
||
string? clientNoOverride = null)
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(clientNoOverride))
|
||
{
|
||
parcelInput.ClientNo = clientNoOverride.Trim();
|
||
}
|
||
else if (!string.IsNullOrWhiteSpace(basic?.ClientNo))
|
||
{
|
||
parcelInput.ClientNo = basic.ClientNo.Trim();
|
||
}
|
||
|
||
if (basic == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.CargoAttribute))
|
||
{
|
||
parcelInput.CargoAttribute = basic.CargoAttribute.Trim();
|
||
}
|
||
|
||
if (basic.ActualWeight is > 0)
|
||
{
|
||
parcelInput.ActualWeight = basic.ActualWeight;
|
||
parcelInput.ChargeableWeight = basic.ActualWeight;
|
||
}
|
||
|
||
if (basic.Quantity is > 0)
|
||
{
|
||
parcelInput.Quantity = basic.Quantity;
|
||
}
|
||
|
||
if (basic.Length is > 0)
|
||
{
|
||
parcelInput.Length = basic.Length;
|
||
}
|
||
|
||
if (basic.Width is > 0)
|
||
{
|
||
parcelInput.Width = basic.Width;
|
||
}
|
||
|
||
if (basic.Height is > 0)
|
||
{
|
||
parcelInput.Height = basic.Height;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.ExportCustomsMode))
|
||
{
|
||
parcelInput.ExportCustomsMode = basic.ExportCustomsMode.Trim();
|
||
}
|
||
|
||
if (basic.ExportQualificationId is > 0)
|
||
{
|
||
parcelInput.ExportQualificationId = basic.ExportQualificationId;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.PlatformCode))
|
||
{
|
||
parcelInput.PlatformCode = basic.PlatformCode.Trim();
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.InboundMethod))
|
||
{
|
||
parcelInput.InboundMethod = basic.InboundMethod.Trim();
|
||
}
|
||
|
||
if (basic.SenderAddressId is > 0)
|
||
{
|
||
parcelInput.SenderAddressId = basic.SenderAddressId;
|
||
}
|
||
|
||
if (basic.ExpectPickupTime.HasValue && basic.ExpectPickupTime != default)
|
||
{
|
||
parcelInput.ExpectPickupTime = basic.ExpectPickupTime;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.PickupDirection))
|
||
{
|
||
parcelInput.PickupDirection = basic.PickupDirection.Trim();
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.CarrierCode))
|
||
{
|
||
parcelInput.CarrierCode = basic.CarrierCode.Trim();
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(basic.CarrierService))
|
||
{
|
||
parcelInput.CarrierService = basic.CarrierService.Trim();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 按平台商品行组装小包入参(不要求库内 SKU 映射;用于创建物流 / 物流&代发)。
|
||
/// </summary>
|
||
public static OrderParcelCreateInput BuildFromPlatformLines(
|
||
SalesStoreOrder storeOrder,
|
||
IReadOnlyCollection<SalesStoreOrderLine> lines,
|
||
WarehouseAddress? warehouse,
|
||
string productCode,
|
||
int? warehouseId,
|
||
int customerId,
|
||
OrderParcelReceiverInput? receiverOverride = null,
|
||
string? trackNoOverride = null)
|
||
{
|
||
var receiver = receiverOverride ?? ParseReceiver(storeOrder);
|
||
ValidateReceiver(receiver);
|
||
|
||
var declarationLines = BuildDeclarationLinesFromPlatform(lines);
|
||
var totalWeightKg = Math.Max(
|
||
declarationLines.Sum(x => x.Weight ?? 0m),
|
||
MinActualWeightKg);
|
||
|
||
return new OrderParcelCreateInput
|
||
{
|
||
RequestId = $"platform-store-order:{storeOrder.Id}",
|
||
ClientNo = storeOrder.PlatformOrderNo,
|
||
TrackNo = string.IsNullOrWhiteSpace(trackNoOverride) ? storeOrder.ShippingLabelNo : trackNoOverride?.Trim(),
|
||
ProductCode = productCode,
|
||
WarehouseId = warehouseId,
|
||
CustomerId = customerId,
|
||
Length = DefaultLengthCm,
|
||
Width = DefaultWidthCm,
|
||
Height = DefaultHeightCm,
|
||
ActualWeight = totalWeightKg,
|
||
ChargeableWeight = totalWeightKg,
|
||
CargoAttribute = CargoAttributeCodes.General,
|
||
DeclaredCurrency = string.IsNullOrWhiteSpace(storeOrder.Currency) ? "USD" : storeOrder.Currency.Trim(),
|
||
DeclaredSum = storeOrder.TotalAmount,
|
||
Quantity = 1,
|
||
Receiver = receiver,
|
||
Sender = warehouse != null ? BuildSender(warehouse) : BuildFallbackSender(storeOrder),
|
||
Items = declarationLines
|
||
};
|
||
}
|
||
|
||
private static List<OrderParcelItemInput> BuildDeclarationLinesFromPlatform(
|
||
IReadOnlyCollection<SalesStoreOrderLine> lines)
|
||
{
|
||
var items = new List<OrderParcelItemInput>();
|
||
foreach (var line in lines)
|
||
{
|
||
var cnName = string.IsNullOrWhiteSpace(line.ProductName)
|
||
? (string.IsNullOrWhiteSpace(line.PlatformSku) ? "Platform Item" : line.PlatformSku.Trim())
|
||
: line.ProductName.Trim();
|
||
var sku = string.IsNullOrWhiteSpace(line.PlatformSku)
|
||
? (cnName.Length > 64 ? cnName[..64] : cnName)
|
||
: line.PlatformSku.Trim();
|
||
var unitPrice = line.UnitPrice is > 0 ? line.UnitPrice.Value : 1m;
|
||
var qty = Math.Max(1, line.Quantity);
|
||
|
||
items.Add(new OrderParcelItemInput
|
||
{
|
||
CnName = cnName,
|
||
EnName = cnName,
|
||
Sku = sku,
|
||
Unit = "PCS",
|
||
UnitPrice = unitPrice,
|
||
UnitWeight = MinActualWeightKg,
|
||
Quantity = qty,
|
||
Amount = unitPrice * qty,
|
||
Weight = MinActualWeightKg * qty
|
||
});
|
||
}
|
||
|
||
if (items.Count == 0)
|
||
{
|
||
throw new BusinessException("没有可申报的商品行");
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
private static OrderParcelSenderInput BuildFallbackSender(SalesStoreOrder storeOrder)
|
||
{
|
||
return new OrderParcelSenderInput
|
||
{
|
||
SenderName = string.IsNullOrWhiteSpace(storeOrder.PlatformOrderNo)
|
||
? "Platform Seller"
|
||
: $"Store#{storeOrder.StoreId}",
|
||
StreetAddress1 = "TBD",
|
||
CountryCode = storeOrder.OrderCountry
|
||
};
|
||
}
|
||
|
||
private static List<OrderParcelItemInput> BuildDeclarationLines(
|
||
IReadOnlyCollection<SalesStoreOrderLine> lines,
|
||
IReadOnlyDictionary<int, CSku> skuMap)
|
||
{
|
||
var items = new List<OrderParcelItemInput>();
|
||
foreach (var line in lines)
|
||
{
|
||
if (!line.MappedSkuId.HasValue || !skuMap.TryGetValue(line.MappedSkuId.Value, out var sku))
|
||
{
|
||
throw new BusinessException($"申报行「{line.PlatformSku}」缺少库内 SKU 映射");
|
||
}
|
||
|
||
var unitWeightKg = sku.WeightG is > 0 ? Math.Max(sku.WeightG.Value / 1000m, MinActualWeightKg) : MinActualWeightKg;
|
||
var unitPrice = line.UnitPrice is > 0 ? line.UnitPrice.Value : 1m;
|
||
var cnName = string.IsNullOrWhiteSpace(line.ProductName) ? sku.SkuName : line.ProductName.Trim();
|
||
var enName = string.IsNullOrWhiteSpace(sku.SkuNameEn)
|
||
? (string.IsNullOrWhiteSpace(sku.SkuName) ? cnName : sku.SkuName)
|
||
: sku.SkuNameEn.Trim();
|
||
|
||
items.Add(new OrderParcelItemInput
|
||
{
|
||
CnName = cnName,
|
||
EnName = enName,
|
||
Sku = sku.SkuCode,
|
||
Unit = "PCS",
|
||
UnitPrice = unitPrice,
|
||
UnitWeight = unitWeightKg,
|
||
Quantity = line.Quantity,
|
||
Amount = unitPrice * line.Quantity,
|
||
Weight = unitWeightKg * line.Quantity,
|
||
ExHsCode = sku.ExHsCode,
|
||
ImHsCode = sku.ImHsCode,
|
||
DeclareElement = sku.DeclareElement,
|
||
ProductId = sku.ProductId,
|
||
NonStdProductId = sku.NonStdProductId,
|
||
StdProductId = sku.StdProductId,
|
||
});
|
||
}
|
||
|
||
if (items.Count == 0)
|
||
{
|
||
throw new BusinessException("没有可申报的商品行");
|
||
}
|
||
|
||
return items;
|
||
}
|
||
|
||
private static (decimal Length, decimal Width, decimal Height, decimal ActualWeightKg) ResolveParcelMetrics(
|
||
IReadOnlyCollection<OrderParcelItemInput> items,
|
||
IReadOnlyCollection<SalesStoreOrderLine> lines,
|
||
IReadOnlyDictionary<int, CSku> skuMap)
|
||
{
|
||
decimal maxLength = DefaultLengthCm;
|
||
decimal maxWidth = DefaultWidthCm;
|
||
decimal maxHeight = DefaultHeightCm;
|
||
decimal totalWeightKg = 0m;
|
||
|
||
foreach (var line in lines.Where(x => x.MappedSkuId.HasValue))
|
||
{
|
||
if (!skuMap.TryGetValue(line.MappedSkuId!.Value, out var sku))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
if (sku.LengthCm is > 0)
|
||
{
|
||
maxLength = Math.Max(maxLength, sku.LengthCm.Value);
|
||
}
|
||
|
||
if (sku.WidthCm is > 0)
|
||
{
|
||
maxWidth = Math.Max(maxWidth, sku.WidthCm.Value);
|
||
}
|
||
|
||
if (sku.HeightCm is > 0)
|
||
{
|
||
maxHeight = Math.Max(maxHeight, sku.HeightCm.Value);
|
||
}
|
||
|
||
var unitWeightKg = sku.WeightG is > 0 ? sku.WeightG.Value / 1000m : MinActualWeightKg;
|
||
totalWeightKg += unitWeightKg * line.Quantity;
|
||
}
|
||
|
||
if (totalWeightKg <= 0)
|
||
{
|
||
totalWeightKg = Math.Max(items.Sum(x => x.Weight ?? 0m), MinActualWeightKg);
|
||
}
|
||
|
||
return (maxLength, maxWidth, maxHeight, Math.Max(totalWeightKg, MinActualWeightKg));
|
||
}
|
||
|
||
private static OrderParcelSenderInput BuildSender(WarehouseAddress warehouse)
|
||
{
|
||
var senderName = string.IsNullOrWhiteSpace(warehouse.Recipient) ? warehouse.WarehouseName : warehouse.Recipient.Trim();
|
||
return new OrderParcelSenderInput
|
||
{
|
||
SenderName = senderName,
|
||
Phone = warehouse.ContactPhone,
|
||
StreetAddress1 = string.IsNullOrWhiteSpace(warehouse.ShippingAddress) ? warehouse.WarehouseName : warehouse.ShippingAddress.Trim()
|
||
};
|
||
}
|
||
|
||
private static OrderParcelReceiverInput? ParseReceiver(SalesStoreOrder storeOrder)
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(storeOrder.RecipientName)
|
||
&& !string.IsNullOrWhiteSpace(storeOrder.RecipientCountry ?? storeOrder.OrderCountry)
|
||
&& !string.IsNullOrWhiteSpace(storeOrder.RecipientZipCode)
|
||
&& !string.IsNullOrWhiteSpace(storeOrder.RecipientAddress1))
|
||
{
|
||
return new OrderParcelReceiverInput
|
||
{
|
||
RecipientsName = storeOrder.RecipientName.Trim(),
|
||
CompanyName = storeOrder.RecipientCompany,
|
||
Phone = storeOrder.RecipientPhone,
|
||
TelePhone = storeOrder.RecipientTelePhone,
|
||
Email = storeOrder.RecipientEmail,
|
||
CountryCode = (storeOrder.RecipientCountry ?? storeOrder.OrderCountry)!.Trim(),
|
||
Province = storeOrder.RecipientProvince,
|
||
City = storeOrder.RecipientCity,
|
||
StreetAddress1 = storeOrder.RecipientAddress1.Trim(),
|
||
StreetAddress2 = storeOrder.RecipientAddress2,
|
||
ZipCode = storeOrder.RecipientZipCode.Trim()
|
||
};
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(storeOrder.PlatformExtraJson))
|
||
{
|
||
try
|
||
{
|
||
var node = JsonNode.Parse(storeOrder.PlatformExtraJson);
|
||
if (node != null)
|
||
{
|
||
var parsed = ParseReceiverNode(node);
|
||
if (parsed != null)
|
||
{
|
||
return parsed;
|
||
}
|
||
}
|
||
}
|
||
catch (JsonException)
|
||
{
|
||
// 忽略 JSON 解析错误,走兜底
|
||
}
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(storeOrder.OrderCountry))
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return new OrderParcelReceiverInput
|
||
{
|
||
RecipientsName = "Platform Recipient",
|
||
CountryCode = storeOrder.OrderCountry.Trim(),
|
||
ZipCode = "00000",
|
||
StreetAddress1 = "TBD"
|
||
};
|
||
}
|
||
|
||
private static OrderParcelReceiverInput? ParseReceiverNode(JsonNode node)
|
||
{
|
||
var candidates = new List<JsonNode?> { node };
|
||
foreach (var key in new[]
|
||
{
|
||
"recipient_address", "recipientAddress", "recipient", "receiver", "shippingAddress", "address"
|
||
})
|
||
{
|
||
if (node[key] != null)
|
||
{
|
||
candidates.Add(node[key]);
|
||
}
|
||
}
|
||
|
||
foreach (var candidate in candidates)
|
||
{
|
||
if (candidate == null)
|
||
{
|
||
continue;
|
||
}
|
||
|
||
var (province, city, countryFromDistrict) = ParseTiktokDistrictInfo(candidate);
|
||
var name = ReadText(candidate, "recipientsName", "recipientName", "receiverName", "name", "fullName", "first_name");
|
||
var country = ReadText(candidate, "countryCode", "country", "region_code", "region", "orderCountry")
|
||
?? countryFromDistrict
|
||
?? ReadText(node, "orderCountry");
|
||
var zip = ReadText(candidate, "zipCode", "zip", "postal_code", "postalCode", "postcode");
|
||
var address = ReadText(
|
||
candidate,
|
||
"streetAddress1",
|
||
"address_line1",
|
||
"address_detail",
|
||
"address",
|
||
"address1",
|
||
"full_address",
|
||
"fullAddress",
|
||
"detailAddress");
|
||
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(country) || string.IsNullOrWhiteSpace(zip) || string.IsNullOrWhiteSpace(address))
|
||
{
|
||
continue;
|
||
}
|
||
|
||
return new OrderParcelReceiverInput
|
||
{
|
||
RecipientsName = name,
|
||
CompanyName = ReadText(candidate, "companyName", "company"),
|
||
Phone = ReadText(candidate, "phone", "mobile", "phone_number", "phoneNumber"),
|
||
TelePhone = ReadText(candidate, "telePhone", "tel"),
|
||
Email = ReadText(candidate, "email") ?? ReadText(node, "buyer_email"),
|
||
CountryCode = country,
|
||
Province = ReadText(candidate, "province", "state", "regionState") ?? province,
|
||
City = ReadText(candidate, "city") ?? city,
|
||
StreetAddress1 = address,
|
||
StreetAddress2 = ReadText(candidate, "streetAddress2", "address_line2", "address2"),
|
||
ZipCode = zip
|
||
};
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析 TikTok recipient_address.district_info:L0 国家、L1 州省、L3 城市。
|
||
/// </summary>
|
||
private static (string? Province, string? City, string? CountryCode) ParseTiktokDistrictInfo(JsonNode candidate)
|
||
{
|
||
var districts = candidate["district_info"]?.AsArray();
|
||
if (districts == null || districts.Count == 0)
|
||
{
|
||
return (null, null, null);
|
||
}
|
||
|
||
string? province = null;
|
||
string? city = null;
|
||
string? country = null;
|
||
foreach (var district in districts)
|
||
{
|
||
if (district == null) continue;
|
||
var level = district["address_level"]?.ToString();
|
||
var name = district["address_name"]?.ToString()?.Trim();
|
||
var iso = district["iso_code"]?.ToString()?.Trim();
|
||
switch (level)
|
||
{
|
||
case "L0":
|
||
country = !string.IsNullOrWhiteSpace(iso) ? iso : name;
|
||
break;
|
||
case "L1":
|
||
province = name;
|
||
break;
|
||
case "L3":
|
||
city = name;
|
||
break;
|
||
case "L2" when string.IsNullOrWhiteSpace(city):
|
||
city = name;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return (province, city, country);
|
||
}
|
||
|
||
private static string? ReadText(JsonNode node, params string[] keys)
|
||
{
|
||
foreach (var key in keys)
|
||
{
|
||
var value = node[key]?.ToString()?.Trim();
|
||
if (!string.IsNullOrWhiteSpace(value))
|
||
{
|
||
return value;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
private static void ValidateReceiver(OrderParcelReceiverInput? receiver)
|
||
{
|
||
if (receiver == null
|
||
|| string.IsNullOrWhiteSpace(receiver.RecipientsName)
|
||
|| string.IsNullOrWhiteSpace(receiver.CountryCode)
|
||
|| string.IsNullOrWhiteSpace(receiver.ZipCode)
|
||
|| string.IsNullOrWhiteSpace(receiver.StreetAddress1))
|
||
{
|
||
throw new BusinessException("收件人信息不完整,请同步平台订单或在匹配时补充收件人");
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从 PlatformExtraJson / ExtraJson 解析收件人并写入结构化字段(已有值不覆盖)。
|
||
/// </summary>
|
||
public static void TryFillRecipientFields(SalesStoreOrder order, string? extraJson = null)
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(order.RecipientName)
|
||
&& !string.IsNullOrWhiteSpace(order.RecipientAddress1)
|
||
&& !string.IsNullOrWhiteSpace(order.RecipientZipCode)
|
||
&& !string.IsNullOrWhiteSpace(order.RecipientCountry ?? order.OrderCountry))
|
||
{
|
||
return;
|
||
}
|
||
|
||
var json = !string.IsNullOrWhiteSpace(extraJson) ? extraJson : order.PlatformExtraJson;
|
||
if (string.IsNullOrWhiteSpace(json))
|
||
{
|
||
return;
|
||
}
|
||
|
||
try
|
||
{
|
||
var node = JsonNode.Parse(json);
|
||
if (node == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
var parsed = ParseReceiverNode(node);
|
||
if (parsed == null)
|
||
{
|
||
return;
|
||
}
|
||
|
||
order.RecipientName ??= parsed.RecipientsName;
|
||
order.RecipientCompany ??= parsed.CompanyName;
|
||
order.RecipientPhone ??= parsed.Phone;
|
||
order.RecipientTelePhone ??= parsed.TelePhone;
|
||
order.RecipientEmail ??= parsed.Email;
|
||
order.RecipientCountry ??= parsed.CountryCode;
|
||
order.RecipientProvince ??= parsed.Province;
|
||
order.RecipientCity ??= parsed.City;
|
||
order.RecipientZipCode ??= parsed.ZipCode;
|
||
order.RecipientAddress1 ??= parsed.StreetAddress1;
|
||
order.RecipientAddress2 ??= parsed.StreetAddress2;
|
||
if (string.IsNullOrWhiteSpace(order.OrderCountry) && !string.IsNullOrWhiteSpace(parsed.CountryCode))
|
||
{
|
||
order.OrderCountry = parsed.CountryCode;
|
||
}
|
||
}
|
||
catch (JsonException)
|
||
{
|
||
// ignore
|
||
}
|
||
}
|
||
}
|