All checks were successful
Build and Deploy / deploy (push) Successful in 1m1s
入库箱唛字段 boxCount;渲染时嵌入 CJK 字体,镜像安装 fonts-noto-cjk。 Co-authored-by: Cursor <cursoragent@cursor.com>
160 lines
5.7 KiB
C#
160 lines
5.7 KiB
C#
using System.Globalization;
|
||
using Oms.Domain.WarehouseAggregate.Entities;
|
||
|
||
namespace Oms.Application.Labeling;
|
||
|
||
/// <summary>
|
||
/// 入库箱唛 PrintData(camelCase,与 hiprint 字段对齐;箱唛为主、SKU 为辅)。
|
||
/// </summary>
|
||
public static class InboundBoxLabelPrintDataBuilder
|
||
{
|
||
public static IReadOnlyDictionary<string, object?> Build(
|
||
CInboundNotice notice,
|
||
CInboundBox box,
|
||
IReadOnlyList<CInboundBoxLine> lines,
|
||
IReadOnlyDictionary<int, CSku> skuMap,
|
||
string? warehouseName = null,
|
||
string? customerName = null,
|
||
string? customerCode = null,
|
||
string? operatorName = null,
|
||
DateTime? printTime = null,
|
||
int pageIndex = 1,
|
||
int pageCount = 1)
|
||
{
|
||
var barcode = ResolveBarcode(notice.NoticeNo, box);
|
||
var skuLines = lines
|
||
.OrderBy(x => x.Id)
|
||
.Select(line =>
|
||
{
|
||
skuMap.TryGetValue(line.SkuId, out var sku);
|
||
var skuCode = FirstNonEmpty(line.SkuCode, sku?.SkuCode) ?? string.Empty;
|
||
var skuName = sku?.SkuName ?? string.Empty;
|
||
return new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||
{
|
||
["skuCode"] = skuCode,
|
||
["skuName"] = skuName,
|
||
["qty"] = line.PlannedQty
|
||
};
|
||
})
|
||
.ToList();
|
||
|
||
var first = skuLines.FirstOrDefault();
|
||
var skuSummary = string.Join(
|
||
"\n",
|
||
skuLines.Select(x =>
|
||
{
|
||
var code = Convert.ToString(x.GetValueOrDefault("skuCode")) ?? string.Empty;
|
||
var name = Convert.ToString(x.GetValueOrDefault("skuName")) ?? string.Empty;
|
||
var qty = Convert.ToString(x.GetValueOrDefault("qty")) ?? "0";
|
||
return string.IsNullOrWhiteSpace(name)
|
||
? $"{code}×{qty}"
|
||
: $"{code} {name}×{qty}";
|
||
}));
|
||
|
||
return new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||
{
|
||
["noticeNo"] = notice.NoticeNo,
|
||
["markReference"] = notice.MarkReference,
|
||
["inboundType"] = notice.InboundType,
|
||
["receiptStatus"] = notice.ReceiptStatus,
|
||
["remark"] = notice.Remark,
|
||
|
||
["boxId"] = box.Id,
|
||
["boxSeqNo"] = box.BoxSeqNo,
|
||
["boxCount"] = pageCount,
|
||
["markBoxNo"] = box.MarkBoxNo,
|
||
["barcode"] = barcode,
|
||
|
||
["warehouseName"] = warehouseName,
|
||
["customerCode"] = customerCode,
|
||
["customerName"] = customerName,
|
||
|
||
["weightG"] = box.WeightG,
|
||
["lengthCm"] = box.LengthCm,
|
||
["widthCm"] = box.WidthCm,
|
||
["heightCm"] = box.HeightCm,
|
||
["weightUnit"] = "G",
|
||
["dimUnit"] = "CM",
|
||
|
||
["skuSummary"] = skuSummary,
|
||
["skuCode"] = first?.GetValueOrDefault("skuCode"),
|
||
["skuName"] = first?.GetValueOrDefault("skuName"),
|
||
["skuQty"] = first?.GetValueOrDefault("qty"),
|
||
["items"] = skuLines,
|
||
|
||
["pageIndex"] = pageIndex,
|
||
["pageCount"] = pageCount,
|
||
["boxIndexText"] = $"{pageIndex}/{pageCount}",
|
||
|
||
["printTime"] = (printTime ?? DateTime.Now).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
|
||
["operatorName"] = operatorName
|
||
};
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设计预览用 Mock PrintData。
|
||
/// </summary>
|
||
public static IReadOnlyDictionary<string, object?> BuildMock() =>
|
||
new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
|
||
{
|
||
["noticeNo"] = "IN202610220001",
|
||
["markReference"] = "SF1234567890",
|
||
["inboundType"] = "normal",
|
||
["receiptStatus"] = "forecasted",
|
||
["remark"] = null,
|
||
["boxId"] = 1,
|
||
["boxSeqNo"] = "1",
|
||
["boxCount"] = 2,
|
||
["markBoxNo"] = "BOX-001",
|
||
["barcode"] = "BOX-001",
|
||
["warehouseName"] = "SZ-01",
|
||
["customerCode"] = "AF0A1",
|
||
["customerName"] = "Demo Customer",
|
||
["weightG"] = 1200m,
|
||
["lengthCm"] = 30m,
|
||
["widthCm"] = 20m,
|
||
["heightCm"] = 15m,
|
||
["weightUnit"] = "G",
|
||
["dimUnit"] = "CM",
|
||
["skuSummary"] = "SKU001 T-Shirt×2\nSKU002 Pants×1",
|
||
["skuCode"] = "SKU001",
|
||
["skuName"] = "T-Shirt",
|
||
["skuQty"] = 2,
|
||
["items"] = new List<Dictionary<string, object?>>
|
||
{
|
||
new()
|
||
{
|
||
["skuCode"] = "SKU001",
|
||
["skuName"] = "T-Shirt",
|
||
["qty"] = 2
|
||
},
|
||
new()
|
||
{
|
||
["skuCode"] = "SKU002",
|
||
["skuName"] = "Pants",
|
||
["qty"] = 1
|
||
}
|
||
},
|
||
["pageIndex"] = 1,
|
||
["pageCount"] = 2,
|
||
["boxIndexText"] = "1/2",
|
||
["printTime"] = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture),
|
||
["operatorName"] = "preview"
|
||
};
|
||
|
||
public static string ResolveBarcode(string noticeNo, CInboundBox box)
|
||
{
|
||
if (!string.IsNullOrWhiteSpace(box.MarkBoxNo))
|
||
{
|
||
return box.MarkBoxNo.Trim();
|
||
}
|
||
|
||
var seq = string.IsNullOrWhiteSpace(box.BoxSeqNo) ? "1" : box.BoxSeqNo.Trim();
|
||
var no = string.IsNullOrWhiteSpace(noticeNo) ? "IN" : noticeNo.Trim();
|
||
return $"{no}-{seq}";
|
||
}
|
||
|
||
private static string? FirstNonEmpty(params string?[] values) =>
|
||
values.FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
|
||
}
|