using System.Globalization;
using Oms.Application.Dtos.Orders;
namespace Oms.Application.Labeling;
///
/// 将订单出参映射为 hiprint PrintData(camelCase)。
///
public static class LabelPrintDataBuilder
{
public static IReadOnlyDictionary Build(
OrderOutput order,
string? operatorName = null,
DateTime? printTime = null)
{
var receiver = order.Receiver;
var sender = order.Sender;
var weight = PickWeight(order.WeightList);
var data = new Dictionary(StringComparer.OrdinalIgnoreCase)
{
["serviceNo"] = order.ServiceNo,
["clientNo"] = order.ClientNo,
["trackNo"] = order.TrackNo,
["requestId"] = order.RequestId,
["productCode"] = order.ProductCode,
["salesProductName"] = order.ProductName,
["channelCode"] = order.ChannelCode,
["channelName"] = order.ChannelName,
["warehouseName"] = order.Warehouse,
["customerCode"] = order.CustomerCode,
["customerName"] = order.CustomerName,
["recipientName"] = receiver?.RecipientsName,
["recipientCompany"] = receiver?.CompanyName,
["recipientPhone"] = FirstNonEmpty(receiver?.Phone, receiver?.TelePhone),
["recipientEmail"] = receiver?.Email,
["recipientZip"] = receiver?.ZipCode,
["recipientCountry"] = order.ConsigneeCountry,
["recipientCountryName"] = order.ConsigneeCountryName,
["recipientProvince"] = receiver?.Province,
["recipientCity"] = receiver?.City,
["recipientStreet1"] = receiver?.StreetAddress1,
["recipientStreet2"] = receiver?.StreetAddress2,
["recipientStreet3"] = receiver?.StreetAddress3,
["recipientAddressFull"] = BuildAddressFull(
receiver?.StreetAddress1,
receiver?.StreetAddress2,
receiver?.StreetAddress3,
receiver?.StreetNumber,
receiver?.City,
receiver?.Province,
receiver?.ZipCode,
order.ConsigneeCountryName ?? order.ConsigneeCountry),
["recipientTaxNo"] = receiver?.TaxNo,
["vatNo"] = receiver?.Vat,
["eori"] = receiver?.Eori,
["senderName"] = sender?.SenderName,
["senderCompany"] = sender?.Company,
["senderPhone"] = FirstNonEmpty(sender?.Phone, sender?.TelePhone),
["senderEmail"] = sender?.Email,
["senderZip"] = sender?.ZipCode,
["senderProvince"] = sender?.Province,
["senderCity"] = sender?.City,
["senderStreet1"] = sender?.StreetAddress1,
["senderStreet2"] = sender?.StreetAddress2,
["senderStreet3"] = sender?.StreetAddress3,
["senderAddressFull"] = BuildAddressFull(
sender?.StreetAddress1,
sender?.StreetAddress2,
sender?.StreetAddress3,
sender?.HouseNumber,
sender?.City,
sender?.Province,
sender?.ZipCode,
null),
["actualWeight"] = weight?.ActualWeight,
["volumetricWeight"] = weight?.VolumetricWeight,
["chargeableWeight"] = order.ChargeableWeight ?? weight?.ChargeableWeight,
["length"] = weight?.Length,
["width"] = weight?.Width,
["height"] = weight?.Height,
["weightUnit"] = "KG",
["dimUnit"] = "CM",
["printTime"] = (printTime ?? DateTime.Now).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
["operatorName"] = operatorName
};
data["items"] = order.Items.Select(x => new Dictionary
{
["skuCode"] = x.Sku,
["skuName"] = FirstNonEmpty(x.CnName, x.EnName),
["qty"] = x.Quantity,
["weight"] = x.Weight ?? x.UnitWeight,
["declareNameEn"] = x.EnName,
["declareValue"] = x.UnitPrice ?? x.Amount
}).ToList();
return data;
}
///
/// 设计预览用的 Mock PrintData。
///
public static IReadOnlyDictionary BuildMock() =>
new Dictionary(StringComparer.OrdinalIgnoreCase)
{
["serviceNo"] = "S202607180001",
["clientNo"] = "C-10086",
["trackNo"] = "YT1234567890",
["requestId"] = "REQ-DEMO",
["productCode"] = "DEMO-PRODUCT",
["salesProductName"] = "专线-普货",
["channelCode"] = "CH-01",
["channelName"] = "Demo Channel",
["warehouseName"] = "SZ-01",
["customerCode"] = "AF0A1",
["customerName"] = "Demo Customer",
["recipientName"] = "John Lee",
["recipientCompany"] = "ACME Inc",
["recipientPhone"] = "+1-555-0100",
["recipientEmail"] = "john@example.com",
["recipientZip"] = "90001",
["recipientCountry"] = "US",
["recipientCountryName"] = "United States",
["recipientProvince"] = "CA",
["recipientCity"] = "Los Angeles",
["recipientStreet1"] = "100 Demo Street",
["recipientStreet2"] = "Suite 8",
["recipientStreet3"] = null,
["recipientAddressFull"] = "100 Demo Street, Suite 8, Los Angeles, CA 90001, United States",
["recipientTaxNo"] = null,
["vatNo"] = null,
["eori"] = null,
["senderName"] = "OMS Warehouse",
["senderCompany"] = "OMS Co",
["senderPhone"] = "+86-755-0000000",
["senderEmail"] = "ops@example.com",
["senderZip"] = "518000",
["senderProvince"] = "Guangdong",
["senderCity"] = "Shenzhen",
["senderStreet1"] = "Warehouse Rd 1",
["senderStreet2"] = null,
["senderStreet3"] = null,
["senderAddressFull"] = "Warehouse Rd 1, Shenzhen, Guangdong 518000",
["actualWeight"] = 1.25m,
["volumetricWeight"] = 1.10m,
["chargeableWeight"] = 1.25m,
["length"] = 30m,
["width"] = 20m,
["height"] = 10m,
["weightUnit"] = "KG",
["dimUnit"] = "CM",
["printTime"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
["operatorName"] = "preview",
["items"] = new List>
{
new()
{
["skuCode"] = "SKU001",
["skuName"] = "T-Shirt",
["qty"] = 2,
["weight"] = 0.2m,
["declareNameEn"] = "T-Shirt",
["declareValue"] = 9.9m
}
}
};
private static OrderWeightOutput? PickWeight(IReadOnlyList list)
{
if (list.Count == 0)
{
return null;
}
return list.FirstOrDefault(x =>
string.Equals(x.Type, "receive", StringComparison.OrdinalIgnoreCase)
|| string.Equals(x.Type, "收货", StringComparison.OrdinalIgnoreCase))
?? list.FirstOrDefault(x =>
string.Equals(x.Type, "forecast", StringComparison.OrdinalIgnoreCase)
|| string.Equals(x.Type, "预报", StringComparison.OrdinalIgnoreCase))
?? list[0];
}
private static string? BuildAddressFull(params string?[] parts)
{
var values = parts
.Where(x => !string.IsNullOrWhiteSpace(x))
.Select(x => x!.Trim())
.ToArray();
return values.Length == 0 ? null : string.Join(", ", values);
}
private static string? FirstNonEmpty(params string?[] values) =>
values.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
}