feat: 打印面单扫码核对 lookup(运单/客户单/跟踪号/包裹/SKU)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
fd9f57bac1
commit
9957b79b19
109
src/Oms.Application/Dtos/Operations/PrintLabelLookupOutput.cs
Normal file
109
src/Oms.Application/Dtos/Operations/PrintLabelLookupOutput.cs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
namespace Oms.Application.Dtos.Operations;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打印标签扫码查单入参(Query)。
|
||||||
|
/// </summary>
|
||||||
|
public class PrintLabelLookupInput
|
||||||
|
{
|
||||||
|
/// <summary>扫描号码。</summary>
|
||||||
|
public string Number { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 号码类型:auto / waybill / customerOrder / tracking / other / parcel / sku。
|
||||||
|
/// 空视为 auto。
|
||||||
|
/// </summary>
|
||||||
|
public string? NumberType { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打印标签查单结果:订单头 + 绑定明细,供操作员核对后打印。
|
||||||
|
/// </summary>
|
||||||
|
public class PrintLabelLookupOutput
|
||||||
|
{
|
||||||
|
/// <summary>是否唯一命中订单。</summary>
|
||||||
|
public bool Matched { get; set; }
|
||||||
|
|
||||||
|
/// <summary>实际命中的号码类型。</summary>
|
||||||
|
public string? MatchedNumberType { get; set; }
|
||||||
|
|
||||||
|
/// <summary>告警:noneBind / multiMatch / alreadyPrinted 等。</summary>
|
||||||
|
public List<string> Warnings { get; set; } = [];
|
||||||
|
|
||||||
|
public int? OrderId { get; set; }
|
||||||
|
|
||||||
|
public string? ServiceNo { get; set; }
|
||||||
|
|
||||||
|
public string? ClientNo { get; set; }
|
||||||
|
|
||||||
|
public string? TrackNo { get; set; }
|
||||||
|
|
||||||
|
public string? ProductCode { get; set; }
|
||||||
|
|
||||||
|
public string? SalesProductName { get; set; }
|
||||||
|
|
||||||
|
public string? DestinationCountry { get; set; }
|
||||||
|
|
||||||
|
public string? DestinationCountryName { get; set; }
|
||||||
|
|
||||||
|
public string? OrderStatus { get; set; }
|
||||||
|
|
||||||
|
public string? OrderStatusName { get; set; }
|
||||||
|
|
||||||
|
public int? WarehouseId { get; set; }
|
||||||
|
|
||||||
|
public string? WarehouseName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>none / bound / deducted / released</summary>
|
||||||
|
public string BindStatus { get; set; } = "none";
|
||||||
|
|
||||||
|
/// <summary>绑定件数合计。</summary>
|
||||||
|
public int BindQtyTotal { get; set; }
|
||||||
|
|
||||||
|
/// <summary>绑定行数。</summary>
|
||||||
|
public int BindLineCount { get; set; }
|
||||||
|
|
||||||
|
public List<PrintLabelBindItemOutput> BindItems { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>SKU/模糊扫到多单时的候选列表。</summary>
|
||||||
|
public List<PrintLabelLookupCandidateOutput> Candidates { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrintLabelBindItemOutput
|
||||||
|
{
|
||||||
|
public string BindType { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public string? SkuCode { get; set; }
|
||||||
|
|
||||||
|
public string? SkuName { get; set; }
|
||||||
|
|
||||||
|
public string? TrackingNo { get; set; }
|
||||||
|
|
||||||
|
public string? ProductName { get; set; }
|
||||||
|
|
||||||
|
public string? AttributeText { get; set; }
|
||||||
|
|
||||||
|
public string? ImageUrl { get; set; }
|
||||||
|
|
||||||
|
public string? BinCode { get; set; }
|
||||||
|
|
||||||
|
public int BindQty { get; set; }
|
||||||
|
|
||||||
|
public string Status { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PrintLabelLookupCandidateOutput
|
||||||
|
{
|
||||||
|
public int OrderId { get; set; }
|
||||||
|
|
||||||
|
public string? ServiceNo { get; set; }
|
||||||
|
|
||||||
|
public string? ClientNo { get; set; }
|
||||||
|
|
||||||
|
public string? TrackNo { get; set; }
|
||||||
|
|
||||||
|
public string? OrderStatusName { get; set; }
|
||||||
|
|
||||||
|
public int BindQtyTotal { get; set; }
|
||||||
|
|
||||||
|
public string? MatchedHint { get; set; }
|
||||||
|
}
|
||||||
@ -2,11 +2,17 @@ using Fake.Application;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Oms.Application.Dtos.Operations;
|
using Oms.Application.Dtos.Operations;
|
||||||
using Oms.Application.Dtos.Shared;
|
using Oms.Application.Dtos.Shared;
|
||||||
|
using Oms.Application.Shared;
|
||||||
using Oms.Domain.ChannelsAggregate.Entities;
|
using Oms.Domain.ChannelsAggregate.Entities;
|
||||||
using Oms.Domain.ChannelsAggregate.Repositories;
|
using Oms.Domain.ChannelsAggregate.Repositories;
|
||||||
using Oms.Domain.OperationsAggregate.Entities;
|
using Oms.Domain.OperationsAggregate.Entities;
|
||||||
using Oms.Domain.OperationsAggregate.Repositories;
|
using Oms.Domain.OperationsAggregate.Repositories;
|
||||||
|
using Oms.Domain.OrdersAggregate.Consts;
|
||||||
|
using Oms.Domain.OrdersAggregate.Entities;
|
||||||
|
using Oms.Domain.OrdersAggregate.Repositories;
|
||||||
using Oms.Domain.Shared.Enums;
|
using Oms.Domain.Shared.Enums;
|
||||||
|
using Oms.Domain.SystemAggregate.Repositories;
|
||||||
|
using Oms.Domain.WarehouseAggregate.Repositories;
|
||||||
|
|
||||||
namespace Oms.Application.Services.Operations;
|
namespace Oms.Application.Services.Operations;
|
||||||
|
|
||||||
@ -18,12 +24,70 @@ public class LabelPrintService : ApplicationService
|
|||||||
{
|
{
|
||||||
private ILabelPrintRecordRepository LabelPrintRecordRepository => LazyServiceProvider.GetRequiredService<ILabelPrintRecordRepository>();
|
private ILabelPrintRecordRepository LabelPrintRecordRepository => LazyServiceProvider.GetRequiredService<ILabelPrintRecordRepository>();
|
||||||
private ILabelTemplateRepository LabelTemplateRepository => LazyServiceProvider.GetRequiredService<ILabelTemplateRepository>();
|
private ILabelTemplateRepository LabelTemplateRepository => LazyServiceProvider.GetRequiredService<ILabelTemplateRepository>();
|
||||||
|
private IOrderRepository OrderRepository => LazyServiceProvider.GetRequiredService<IOrderRepository>();
|
||||||
|
private IOrderStockBindRepository OrderStockBindRepository => LazyServiceProvider.GetRequiredService<IOrderStockBindRepository>();
|
||||||
|
private ICParcelRepository ParcelRepository => LazyServiceProvider.GetRequiredService<ICParcelRepository>();
|
||||||
|
private ICSkuRepository SkuRepository => LazyServiceProvider.GetRequiredService<ICSkuRepository>();
|
||||||
|
private ISalesProductRepository SalesProductRepository => LazyServiceProvider.GetRequiredService<ISalesProductRepository>();
|
||||||
|
private ICountryRepository CountryRepository => LazyServiceProvider.GetRequiredService<ICountryRepository>();
|
||||||
|
private IWarehouseAddressRepository WarehouseAddressRepository => LazyServiceProvider.GetRequiredService<IWarehouseAddressRepository>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 扫码查单:运单/客户单/跟踪号/其他单号/包裹快递单号/SKU → 订单 + 绑定明细。
|
||||||
|
/// </summary>
|
||||||
|
[HttpGet("/operation/print-label/lookup")]
|
||||||
|
public async Task<PrintLabelLookupOutput> LookupAsync(
|
||||||
|
[FromQuery] string number,
|
||||||
|
[FromQuery] string? numberType = null)
|
||||||
|
{
|
||||||
|
var raw = number?.Trim() ?? string.Empty;
|
||||||
|
if (string.IsNullOrWhiteSpace(raw))
|
||||||
|
{
|
||||||
|
throw new BusinessException("请扫描或输入单号");
|
||||||
|
}
|
||||||
|
|
||||||
|
var type = NormalizeNumberType(numberType);
|
||||||
|
Order? order = null;
|
||||||
|
string? matchedType = null;
|
||||||
|
List<PrintLabelLookupCandidateOutput>? candidates = null;
|
||||||
|
|
||||||
|
if (type is "auto" or "")
|
||||||
|
{
|
||||||
|
(order, matchedType, candidates) = await ResolveAutoAsync(raw);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(order, matchedType, candidates) = await ResolveByTypeAsync(raw, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (candidates is { Count: > 1 })
|
||||||
|
{
|
||||||
|
return new PrintLabelLookupOutput
|
||||||
|
{
|
||||||
|
Matched = false,
|
||||||
|
MatchedNumberType = matchedType,
|
||||||
|
Warnings = ["multiMatch"],
|
||||||
|
Candidates = candidates
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order == null && candidates is { Count: 1 })
|
||||||
|
{
|
||||||
|
order = await OrderRepository.FirstOrDefaultAsync(x => x.Id == candidates[0].OrderId);
|
||||||
|
matchedType ??= "sku";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (order == null)
|
||||||
|
{
|
||||||
|
throw new BusinessException("未找到对应订单,请检查号码或类型");
|
||||||
|
}
|
||||||
|
|
||||||
|
return await BuildLookupOutputAsync(order, matchedType ?? type);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行面单打印。
|
/// 执行面单打印。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">入参:面单打印参数。</param>
|
|
||||||
/// <returns>面单打印记录。</returns>
|
|
||||||
[HttpPost("/operation/print-label/print")]
|
[HttpPost("/operation/print-label/print")]
|
||||||
public async Task<LabelPrintRecordOutput> PrintAsync(PrintLabelInput input)
|
public async Task<LabelPrintRecordOutput> PrintAsync(PrintLabelInput input)
|
||||||
{
|
{
|
||||||
@ -89,11 +153,10 @@ public class LabelPrintService : ApplicationService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询最近面单打印记录列表。
|
/// 查询最近面单打印记录列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="limit">入参:返回记录条数上限。</param>
|
|
||||||
/// <param name="labelTemplateId">入参:标签模板主键,可选。</param>
|
|
||||||
/// <returns>面单打印记录列表结果。</returns>
|
|
||||||
[HttpGet("/operation/print-label/recent-list")]
|
[HttpGet("/operation/print-label/recent-list")]
|
||||||
public async Task<OmsItemsResult<LabelPrintRecordOutput>> GetRecentListAsync([FromQuery] int limit = 20, [FromQuery] int? labelTemplateId = null)
|
public async Task<OmsItemsResult<LabelPrintRecordOutput>> GetRecentListAsync(
|
||||||
|
[FromQuery] int limit = 20,
|
||||||
|
[FromQuery] int? labelTemplateId = null)
|
||||||
{
|
{
|
||||||
var hasTemplateFilter = labelTemplateId.HasValue;
|
var hasTemplateFilter = labelTemplateId.HasValue;
|
||||||
var labelTemplateIdValue = labelTemplateId.GetValueOrDefault();
|
var labelTemplateIdValue = labelTemplateId.GetValueOrDefault();
|
||||||
@ -127,10 +190,9 @@ public class LabelPrintService : ApplicationService
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询标签模板列表。
|
/// 查询标签模板列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="templateType">入参:模板类型,可选。</param>
|
|
||||||
/// <returns>标签模板列表结果。</returns>
|
|
||||||
[HttpGet("/operation/print-label/template-list")]
|
[HttpGet("/operation/print-label/template-list")]
|
||||||
public async Task<OmsItemsResult<LabelTemplateDropdownOutput>> GetTemplateDropdownListAsync([FromQuery] string? templateType = null)
|
public async Task<OmsItemsResult<LabelTemplateDropdownOutput>> GetTemplateDropdownListAsync(
|
||||||
|
[FromQuery] string? templateType = null)
|
||||||
{
|
{
|
||||||
var entities = await LabelTemplateRepository.GetListAsync(
|
var entities = await LabelTemplateRepository.GetListAsync(
|
||||||
x => string.IsNullOrWhiteSpace(templateType) || x.TemplateType == templateType);
|
x => string.IsNullOrWhiteSpace(templateType) || x.TemplateType == templateType);
|
||||||
@ -140,4 +202,244 @@ public class LabelPrintService : ApplicationService
|
|||||||
.ToList();
|
.ToList();
|
||||||
return new OmsItemsResult<LabelTemplateDropdownOutput> { Items = items };
|
return new OmsItemsResult<LabelTemplateDropdownOutput> { Items = items };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string NormalizeNumberType(string? numberType)
|
||||||
|
{
|
||||||
|
var value = numberType?.Trim().ToLowerInvariant() ?? "auto";
|
||||||
|
return value switch
|
||||||
|
{
|
||||||
|
"customerorderno" or "customer-order" or "client" or "clientno" => "customerorder",
|
||||||
|
"track" or "trackno" => "tracking",
|
||||||
|
"parceltracking" or "parcelno" or "express" => "parcel",
|
||||||
|
"skucode" => "sku",
|
||||||
|
"" or "all" => "auto",
|
||||||
|
_ => value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Order? Order, string? MatchedType, List<PrintLabelLookupCandidateOutput>? Candidates)>
|
||||||
|
ResolveAutoAsync(string number)
|
||||||
|
{
|
||||||
|
var order = await OrderRepository.GetByWaybillNoAsync(number);
|
||||||
|
if (order != null)
|
||||||
|
{
|
||||||
|
var matched =
|
||||||
|
string.Equals(order.ServiceNo, number, StringComparison.OrdinalIgnoreCase) ? "waybill"
|
||||||
|
: string.Equals(order.TrackNo, number, StringComparison.OrdinalIgnoreCase) ? "tracking"
|
||||||
|
: string.Equals(order.ClientNo, number, StringComparison.OrdinalIgnoreCase) ? "customerorder"
|
||||||
|
: "waybill";
|
||||||
|
return (order, matched, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var byParcel = await ResolveByParcelTrackingAsync(number);
|
||||||
|
if (byParcel.Order != null || byParcel.Candidates is { Count: > 0 })
|
||||||
|
{
|
||||||
|
return byParcel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await ResolveBySkuAsync(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Order? Order, string? MatchedType, List<PrintLabelLookupCandidateOutput>? Candidates)>
|
||||||
|
ResolveByTypeAsync(string number, string type)
|
||||||
|
{
|
||||||
|
return type switch
|
||||||
|
{
|
||||||
|
"waybill" => (await OrderRepository.GetByServiceNoAsync(number)
|
||||||
|
?? await OrderRepository.GetByWaybillNoAsync(number), "waybill", null),
|
||||||
|
"customerorder" => (
|
||||||
|
await OrderRepository.FirstOrDefaultAsync(x => x.ClientNo == number),
|
||||||
|
"customerorder",
|
||||||
|
null),
|
||||||
|
"tracking" => (
|
||||||
|
await OrderRepository.GetByTrackNoAsync(number),
|
||||||
|
"tracking",
|
||||||
|
null),
|
||||||
|
"other" => (
|
||||||
|
await OrderRepository.FirstOrDefaultAsync(x => x.RequestId == number || x.ClientNo == number)
|
||||||
|
?? await OrderRepository.GetByWaybillNoAsync(number),
|
||||||
|
"other",
|
||||||
|
null),
|
||||||
|
"parcel" => await ResolveByParcelTrackingAsync(number),
|
||||||
|
"sku" => await ResolveBySkuAsync(number),
|
||||||
|
_ => await ResolveAutoAsync(number)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Order? Order, string? MatchedType, List<PrintLabelLookupCandidateOutput>? Candidates)>
|
||||||
|
ResolveByParcelTrackingAsync(string trackingNo)
|
||||||
|
{
|
||||||
|
var parcels = await ParcelRepository.GetListAsync(x => x.TrackingNo == trackingNo);
|
||||||
|
if (parcels.Count == 0)
|
||||||
|
{
|
||||||
|
return (null, "parcel", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var parcelIds = parcels.Select(x => x.Id).ToArray();
|
||||||
|
var binds = await OrderStockBindRepository.GetListAsync(x =>
|
||||||
|
x.ParcelId.HasValue
|
||||||
|
&& parcelIds.Contains(x.ParcelId.Value)
|
||||||
|
&& (x.Status == OrderStockBindStatusCodes.Bound || x.Status == OrderStockBindStatusCodes.Deducted));
|
||||||
|
|
||||||
|
var orderIds = binds.Select(x => x.OrderId).Distinct().ToArray();
|
||||||
|
if (orderIds.Length == 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException("找到包裹但未绑定到任何订单,请先绑定包裹/库存");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderIds.Length == 1)
|
||||||
|
{
|
||||||
|
var order = await OrderRepository.FirstOrDefaultAsync(x => x.Id == orderIds[0]);
|
||||||
|
return (order, "parcel", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var candidates = await BuildCandidatesAsync(orderIds, "包裹快递单号命中多笔订单");
|
||||||
|
return (null, "parcel", candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(Order? Order, string? MatchedType, List<PrintLabelLookupCandidateOutput>? Candidates)>
|
||||||
|
ResolveBySkuAsync(string skuCode)
|
||||||
|
{
|
||||||
|
var skus = await SkuRepository.GetListAsync(x => x.SkuCode == skuCode);
|
||||||
|
if (skus.Count == 0)
|
||||||
|
{
|
||||||
|
return (null, "sku", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var skuIds = skus.Select(x => x.Id).ToArray();
|
||||||
|
var binds = await OrderStockBindRepository.GetListAsync(x =>
|
||||||
|
x.SkuId.HasValue
|
||||||
|
&& skuIds.Contains(x.SkuId.Value)
|
||||||
|
&& (x.Status == OrderStockBindStatusCodes.Bound || x.Status == OrderStockBindStatusCodes.Deducted));
|
||||||
|
|
||||||
|
var orderIds = binds.Select(x => x.OrderId).Distinct().ToArray();
|
||||||
|
if (orderIds.Length == 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException("找到 SKU 但没有绑定中的订单,请确认是否已绑定");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orderIds.Length == 1)
|
||||||
|
{
|
||||||
|
var order = await OrderRepository.FirstOrDefaultAsync(x => x.Id == orderIds[0]);
|
||||||
|
return (order, "sku", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
var candidates = await BuildCandidatesAsync(orderIds, $"SKU {skuCode} 命中多笔订单,请选择");
|
||||||
|
return (null, "sku", candidates);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<List<PrintLabelLookupCandidateOutput>> BuildCandidatesAsync(int[] orderIds, string hint)
|
||||||
|
{
|
||||||
|
var orders = await OrderRepository.GetListAsync(x => orderIds.Contains(x.Id));
|
||||||
|
var binds = await OrderStockBindRepository.GetListAsync(x =>
|
||||||
|
orderIds.Contains(x.OrderId)
|
||||||
|
&& (x.Status == OrderStockBindStatusCodes.Bound || x.Status == OrderStockBindStatusCodes.Deducted));
|
||||||
|
var qtyMap = binds.GroupBy(x => x.OrderId).ToDictionary(g => g.Key, g => g.Sum(x => x.BindQty));
|
||||||
|
|
||||||
|
return orders
|
||||||
|
.OrderByDescending(x => x.UpdateTime)
|
||||||
|
.Select(o => new PrintLabelLookupCandidateOutput
|
||||||
|
{
|
||||||
|
OrderId = o.Id,
|
||||||
|
ServiceNo = o.ServiceNo,
|
||||||
|
ClientNo = o.ClientNo,
|
||||||
|
TrackNo = o.TrackNo,
|
||||||
|
OrderStatusName = OmsDocHelper.GetOrderStatusName(o.OrderStatus),
|
||||||
|
BindQtyTotal = qtyMap.GetValueOrDefault(o.Id),
|
||||||
|
MatchedHint = hint
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<PrintLabelLookupOutput> BuildLookupOutputAsync(Order order, string matchedType)
|
||||||
|
{
|
||||||
|
var binds = await OrderStockBindRepository.GetListAsync(x =>
|
||||||
|
x.OrderId == order.Id
|
||||||
|
&& (x.Status == OrderStockBindStatusCodes.Bound || x.Status == OrderStockBindStatusCodes.Deducted));
|
||||||
|
binds = binds.OrderBy(x => x.Id).ToList();
|
||||||
|
|
||||||
|
var warehouseId = order.WarehouseId ?? binds.FirstOrDefault()?.WarehouseId;
|
||||||
|
string? warehouseName = null;
|
||||||
|
if (warehouseId is > 0)
|
||||||
|
{
|
||||||
|
var warehouse = await WarehouseAddressRepository.FirstOrDefaultAsync(x => x.Id == warehouseId.Value);
|
||||||
|
warehouseName = warehouse?.WarehouseName;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? salesProductName = null;
|
||||||
|
if (!string.IsNullOrWhiteSpace(order.ProductCode))
|
||||||
|
{
|
||||||
|
var product = await SalesProductRepository.GetByProductCodeAsync(order.ProductCode.Trim());
|
||||||
|
salesProductName = product?.ProductName;
|
||||||
|
}
|
||||||
|
|
||||||
|
string? countryName = order.ConsigneeCountry;
|
||||||
|
if (!string.IsNullOrWhiteSpace(order.ConsigneeCountry))
|
||||||
|
{
|
||||||
|
var country = await CountryRepository.FirstOrDefaultAsync(x => x.CountryCode == order.ConsigneeCountry);
|
||||||
|
countryName = country?.ChineseName ?? country?.EnglishName ?? order.ConsigneeCountry;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bindStatus = "none";
|
||||||
|
if (binds.Any(x => x.Status == OrderStockBindStatusCodes.Deducted))
|
||||||
|
{
|
||||||
|
bindStatus = OrderStockBindStatusCodes.Deducted;
|
||||||
|
}
|
||||||
|
else if (binds.Any(x => x.Status == OrderStockBindStatusCodes.Bound))
|
||||||
|
{
|
||||||
|
bindStatus = OrderStockBindStatusCodes.Bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
var warnings = new List<string>();
|
||||||
|
if (binds.Count == 0)
|
||||||
|
{
|
||||||
|
warnings.Add("noneBind");
|
||||||
|
}
|
||||||
|
|
||||||
|
var binIds = binds.Where(x => x.BinLocationId.HasValue).Select(x => x.BinLocationId!.Value).Distinct().ToArray();
|
||||||
|
var binMap = new Dictionary<int, string>();
|
||||||
|
if (binIds.Length > 0)
|
||||||
|
{
|
||||||
|
var binRepo = LazyServiceProvider.GetRequiredService<ICBinLocationRepository>();
|
||||||
|
var bins = await binRepo.GetListAsync(x => binIds.Contains(x.Id));
|
||||||
|
binMap = bins.ToDictionary(x => x.Id, x => x.BinCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var bindItems = binds.Select(b => new PrintLabelBindItemOutput
|
||||||
|
{
|
||||||
|
BindType = b.BindType,
|
||||||
|
SkuCode = b.SkuCode,
|
||||||
|
SkuName = b.SkuName,
|
||||||
|
TrackingNo = b.TrackingNo,
|
||||||
|
ProductName = b.ProductName,
|
||||||
|
AttributeText = b.AttributeText,
|
||||||
|
ImageUrl = b.ImageUrl,
|
||||||
|
BinCode = b.BinLocationId is > 0 && binMap.TryGetValue(b.BinLocationId.Value, out var code) ? code : null,
|
||||||
|
BindQty = b.BindQty,
|
||||||
|
Status = b.Status
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
return new PrintLabelLookupOutput
|
||||||
|
{
|
||||||
|
Matched = true,
|
||||||
|
MatchedNumberType = matchedType,
|
||||||
|
Warnings = warnings,
|
||||||
|
OrderId = order.Id,
|
||||||
|
ServiceNo = order.ServiceNo,
|
||||||
|
ClientNo = order.ClientNo,
|
||||||
|
TrackNo = order.TrackNo,
|
||||||
|
ProductCode = order.ProductCode,
|
||||||
|
SalesProductName = salesProductName,
|
||||||
|
DestinationCountry = order.ConsigneeCountry,
|
||||||
|
DestinationCountryName = countryName,
|
||||||
|
OrderStatus = order.OrderStatus,
|
||||||
|
OrderStatusName = OmsDocHelper.GetOrderStatusName(order.OrderStatus),
|
||||||
|
WarehouseId = warehouseId,
|
||||||
|
WarehouseName = warehouseName,
|
||||||
|
BindStatus = bindStatus,
|
||||||
|
BindQtyTotal = binds.Sum(x => x.BindQty),
|
||||||
|
BindLineCount = binds.Count,
|
||||||
|
BindItems = bindItems
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user