606 lines
23 KiB
C#
606 lines
23 KiB
C#
using System.Linq.Expressions;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using Fake.Application;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using MiniExcelLibs;
|
|
using Oms.Application.Dtos.Orders;
|
|
using Oms.Application.Dtos.Shared;
|
|
using Oms.Application.Shared;
|
|
using Oms.Domain.OrdersAggregate.Consts;
|
|
using Oms.Domain.OrdersAggregate.Entities;
|
|
|
|
namespace Oms.Application.Services.Orders;
|
|
|
|
public partial class OrderService
|
|
{
|
|
private async Task<List<OrderOutput>> MapOrderOutputsAsync(IReadOnlyCollection<Order> orders)
|
|
{
|
|
if (orders.Count == 0)
|
|
{
|
|
return [];
|
|
}
|
|
|
|
var orderIds = orders.Select(x => x.Id).ToArray();
|
|
var warehouseIds = orders.Where(x => x.WarehouseId.HasValue).Select(x => x.WarehouseId!.Value).Distinct().ToArray();
|
|
var senders = await OrderRepository.GetSendersByOrderIdsAsync(orderIds);
|
|
var recipients = await OrderRepository.GetRecipientsByOrderIdsAsync(orderIds);
|
|
var declarations = await OrderRepository.GetDeclarationsByOrderIdsAsync(orderIds);
|
|
var weights = await OrderRepository.GetWeightsByOrderIdsAsync(orderIds);
|
|
var warehouses = warehouseIds.Length == 0
|
|
? []
|
|
: await WarehouseAddressRepository.GetListAsync(x => warehouseIds.Contains(x.Id));
|
|
|
|
var senderMap = senders.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.First());
|
|
var recipientMap = recipients.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.First());
|
|
var declarationMap = declarations.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.ToList());
|
|
var weightMap = weights.GroupBy(x => x.OrderId).ToDictionary(x => x.Key, x => x.ToList());
|
|
var warehouseMap = warehouses.ToDictionary(x => x.Id);
|
|
|
|
return orders.Select(order =>
|
|
{
|
|
senderMap.TryGetValue(order.Id, out var sender);
|
|
recipientMap.TryGetValue(order.Id, out var recipient);
|
|
declarationMap.TryGetValue(order.Id, out var items);
|
|
weightMap.TryGetValue(order.Id, out var orderWeights);
|
|
return new OrderOutput
|
|
{
|
|
Id = order.Id,
|
|
ClientNo = order.ClientNo,
|
|
TrackNo = order.TrackNo,
|
|
ServiceNo = order.ServiceNo,
|
|
ProductCode = order.ProductCode,
|
|
ChannelCode = order.ChannelCode,
|
|
CargoAttribute = order.CargoAttribute,
|
|
WarehouseId = order.WarehouseId,
|
|
Warehouse = order.WarehouseId.HasValue && warehouseMap.TryGetValue(order.WarehouseId.Value, out var warehouse)
|
|
? warehouse.WarehouseName
|
|
: null,
|
|
CustomerId = order.CustomerId,
|
|
IsCod = order.IsCod > 0,
|
|
CodCurrency = order.CodCurrency,
|
|
CodSum = order.CodSum,
|
|
OrderStatus = OmsDocHelper.GetOrderStatusName(order.OrderStatus),
|
|
Status = order.OrderStatus,
|
|
ReceiveTime = order.ReceiveTime,
|
|
ShipTime = order.ShipTime,
|
|
PayTime = order.PayTime,
|
|
SignTime = order.SignTime,
|
|
IsIntercept = order.IsIntercept > 0,
|
|
IsRemote = order.IsRemote > 0,
|
|
CreateTime = order.CreateTime,
|
|
CreateBy = order.CreateUserId <= 0 ? null : order.CreateUserId.ToString(),
|
|
UpdateTime = OmsDocHelper.NullIfDefault(order.UpdateTime),
|
|
UpdateBy = order.UpdateUserId <= 0 ? null : order.UpdateUserId.ToString(),
|
|
Sender = MapSender(sender),
|
|
Receiver = MapReceiver(recipient),
|
|
Items = (items ?? []).Select(MapDeclaration).ToList(),
|
|
WeightList = (orderWeights ?? []).Select(MapWeight).ToList()
|
|
};
|
|
}).ToList();
|
|
}
|
|
|
|
private async Task<List<object>> BuildOrderExportRowsAsync(IReadOnlyCollection<Order> orders)
|
|
{
|
|
var mapped = await MapOrderOutputsAsync(orders);
|
|
return mapped.Select(x => (object)new
|
|
{
|
|
x.Id,
|
|
x.ClientNo,
|
|
x.TrackNo,
|
|
x.ServiceNo,
|
|
x.ProductCode,
|
|
x.ChannelCode,
|
|
x.CargoAttribute,
|
|
x.WarehouseId,
|
|
x.Warehouse,
|
|
x.CustomerId,
|
|
x.Status,
|
|
x.OrderStatus,
|
|
x.ReceiveTime,
|
|
x.ShipTime,
|
|
x.PayTime,
|
|
x.SignTime,
|
|
x.IsCod,
|
|
x.CodCurrency,
|
|
x.CodSum,
|
|
x.IsIntercept,
|
|
x.IsRemote,
|
|
x.CreateTime,
|
|
x.UpdateTime
|
|
}).ToList();
|
|
}
|
|
|
|
private async Task<OmsPageResult<OrderTemplateOutput>> GetTemplateOutputsAsync(OrderTemplateListInput input)
|
|
{
|
|
var page = OmsDocHelper.NormalizePage(input.Page);
|
|
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
|
var keyword = input.Keyword?.Trim();
|
|
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
|
|
CustomerRepository,
|
|
CurrentUser,
|
|
null);
|
|
var hasCustomerFilter = customerId.HasValue;
|
|
var customerIdValue = customerId.GetValueOrDefault();
|
|
var predicate = (Expression<Func<OrderTemplate, bool>>)(x =>
|
|
(string.IsNullOrWhiteSpace(input.Type) || x.Type == input.Type) &&
|
|
(string.IsNullOrWhiteSpace(keyword) || x.Name.Contains(keyword) || (x.TemplateKey ?? string.Empty).Contains(keyword)) &&
|
|
(!hasCustomerFilter || x.Type == "standard" || x.CustomerId == customerIdValue));
|
|
|
|
var templates = await OrderTemplateRepository.GetPagedListAsync(
|
|
predicate,
|
|
page,
|
|
pageSize,
|
|
new Dictionary<string, bool> { [nameof(OrderTemplate.UpdateTime)] = false, [nameof(OrderTemplate.Id)] = false });
|
|
var total = await OrderTemplateRepository.CountAsync(predicate);
|
|
|
|
return new OmsPageResult<OrderTemplateOutput>
|
|
{
|
|
Items = templates.Select(x => new OrderTemplateOutput
|
|
{
|
|
Id = x.Id,
|
|
Name = x.Name,
|
|
Type = x.Type,
|
|
TemplateKey = x.TemplateKey,
|
|
CustomerId = x.CustomerId,
|
|
CreateTime = x.CreateTime,
|
|
UpdateTime = OmsDocHelper.NullIfDefault(x.UpdateTime)
|
|
}).ToList(),
|
|
Total = total
|
|
};
|
|
}
|
|
|
|
private async Task<FileContentResult> BuildTemplateDownloadAsync(int templateId)
|
|
{
|
|
var template = await OrderTemplateRepository.FirstOrDefaultAsync(x => x.Id == templateId);
|
|
if (template == null)
|
|
{
|
|
throw new BusinessException("模板不存在");
|
|
}
|
|
|
|
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
|
|
CustomerRepository,
|
|
CurrentUser,
|
|
null);
|
|
if (customerId.HasValue)
|
|
{
|
|
EnsureTemplateAccessible(template, customerId.Value);
|
|
}
|
|
|
|
var rows = new[]
|
|
{
|
|
new Dictionary<string, object?>
|
|
{
|
|
["ClientNo"] = "",
|
|
["TrackNo"] = "",
|
|
["ServiceNo"] = "",
|
|
["ProductCode"] = "",
|
|
["ChannelCode"] = "",
|
|
["CargoAttribute"] = CargoAttributeCodes.General,
|
|
["WarehouseId"] = "",
|
|
["CustomerId"] = customerId ?? template.CustomerId,
|
|
["Length"] = "",
|
|
["Width"] = "",
|
|
["Height"] = "",
|
|
["ActualWeight"] = "",
|
|
["VolumetricWeight"] = "",
|
|
["ChargeableWeight"] = "",
|
|
["Cubic"] = "",
|
|
["IsCod"] = "",
|
|
["CodCurrency"] = "",
|
|
["CodSum"] = "",
|
|
["DeclaredCurrency"] = "",
|
|
["DeclaredSum"] = "",
|
|
["Quantity"] = ""
|
|
}
|
|
};
|
|
|
|
await using var stream = new MemoryStream();
|
|
await MiniExcel.SaveAsAsync(stream, rows);
|
|
stream.Position = 0;
|
|
return new FileContentResult(stream.ToArray(),
|
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
|
|
{
|
|
FileDownloadName = $"{template.Name}-{DateTime.Now:yyyyMMddHHmmss}.xlsx"
|
|
};
|
|
}
|
|
|
|
private async Task<OrderUploadOutput> ImportOrdersAsync(OrderUploadInput input)
|
|
{
|
|
if (input.File == null || input.File.Length == 0)
|
|
{
|
|
throw new BusinessException("上传文件不能为空");
|
|
}
|
|
|
|
var template = await OrderTemplateRepository.FirstOrDefaultAsync(x => x.Id == input.TemplateId);
|
|
if (template == null)
|
|
{
|
|
throw new BusinessException("模板不存在");
|
|
}
|
|
|
|
var effectiveCustomer = await ResolveEffectiveCustomerAsync();
|
|
EnsureTemplateAccessible(template, effectiveCustomer.Id);
|
|
|
|
var task = await OrderTaskRepository.InsertAsync(new OrderTask
|
|
{
|
|
TaskName = $"批量下单_{DateTime.Now:yyyyMMddHHmmss}",
|
|
Quantity = 0,
|
|
SuccessCount = 0,
|
|
FailCount = 0,
|
|
Status = "processing",
|
|
TemplateId = template.Id,
|
|
CustomerId = effectiveCustomer.Id
|
|
});
|
|
|
|
var quantity = 0;
|
|
var successCount = 0;
|
|
var failCount = 0;
|
|
var rowNumber = 1;
|
|
var failList = new List<OrderTaskFail>();
|
|
|
|
var rows = await MiniExcel.QueryAsync(input.File.OpenReadStream(), useHeaderRow: true);
|
|
foreach (var row in rows)
|
|
{
|
|
rowNumber++;
|
|
quantity++;
|
|
if (row is not IDictionary<string, object> rowDict)
|
|
{
|
|
failCount++;
|
|
failList.Add(BuildTaskFail(task.Id, rowNumber, "无法解析Excel行数据", row));
|
|
continue;
|
|
}
|
|
|
|
try
|
|
{
|
|
await CreateImportOrderAsync(rowDict, effectiveCustomer.Id);
|
|
successCount++;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
failCount++;
|
|
failList.Add(BuildTaskFail(task.Id, rowNumber, ex.Message, rowDict));
|
|
}
|
|
}
|
|
|
|
if (failList.Count > 0)
|
|
{
|
|
await OrderTaskRepository.InsertFailListAsync(failList);
|
|
}
|
|
|
|
task.Quantity = quantity;
|
|
task.SuccessCount = successCount;
|
|
task.FailCount = failCount;
|
|
task.Status = "completed";
|
|
await OrderTaskRepository.UpdateAsync(task);
|
|
return new OrderUploadOutput { TaskId = task.Id };
|
|
}
|
|
|
|
private async Task CreateImportOrderAsync(IDictionary<string, object> rowDict, int effectiveCustomerId)
|
|
{
|
|
var rowCustomerId = GetIntCell(rowDict, "CustomerId");
|
|
if (rowCustomerId is > 0 && rowCustomerId.Value != effectiveCustomerId)
|
|
{
|
|
throw new BusinessException("客户ID非法");
|
|
}
|
|
|
|
var serviceNo = GetStringCell(rowDict, "ServiceNo");
|
|
var resolvedServiceNo = await ResolveServiceNoAsync(serviceNo);
|
|
|
|
var order = await OrderRepository.InsertAsync(new Order
|
|
{
|
|
ServiceNo = resolvedServiceNo,
|
|
ClientNo = GetStringCell(rowDict, "ClientNo"),
|
|
TrackNo = string.IsNullOrWhiteSpace(GetStringCell(rowDict, "TrackNo"))
|
|
? null
|
|
: GetStringCell(rowDict, "TrackNo"),
|
|
ProductCode = GetStringCell(rowDict, "ProductCode"),
|
|
ChannelCode = GetStringCell(rowDict, "ChannelCode"),
|
|
CargoAttribute = GetStringCell(rowDict, "CargoAttribute") ?? CargoAttributeCodes.General,
|
|
WarehouseId = GetIntCell(rowDict, "WarehouseId"),
|
|
CustomerId = effectiveCustomerId,
|
|
CodCurrency = GetStringCell(rowDict, "CodCurrency"),
|
|
CodSum = GetDecimalCell(rowDict, "CodSum"),
|
|
DeclaredCurrency = GetStringCell(rowDict, "DeclaredCurrency"),
|
|
DeclaredSum = GetDecimalCell(rowDict, "DeclaredSum"),
|
|
Quantity = GetIntCell(rowDict, "Quantity"),
|
|
IsCod = GetBoolCell(rowDict, "IsCod") ? (byte)1 : (byte)0,
|
|
IsIntercept = 0,
|
|
IsRemote = 0,
|
|
OrderStatus = OrderStatusCodes.PendingPayment
|
|
});
|
|
|
|
var weight = BuildForecastWeight(order.Id, rowDict);
|
|
if (weight != null)
|
|
{
|
|
await OrderRepository.InsertWeightsAsync([weight]);
|
|
}
|
|
}
|
|
|
|
private async Task<OmsPageResult<OrderTaskOutput>> GetTaskOutputsAsync(OrderTaskListInput input)
|
|
{
|
|
var page = OmsDocHelper.NormalizePage(input.Page);
|
|
var pageSize = OmsDocHelper.NormalizePageSize(input.PageSize);
|
|
var keyword = input.Keyword?.Trim();
|
|
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
|
|
CustomerRepository,
|
|
CurrentUser,
|
|
null);
|
|
var hasCustomerFilter = customerId.HasValue;
|
|
var customerIdValue = customerId.GetValueOrDefault();
|
|
var predicate = (Expression<Func<OrderTask, bool>>)(x =>
|
|
(string.IsNullOrWhiteSpace(input.Status) || x.Status == input.Status) &&
|
|
(string.IsNullOrWhiteSpace(keyword) || x.TaskName.Contains(keyword)) &&
|
|
(!hasCustomerFilter || x.CustomerId == customerIdValue));
|
|
var tasks = await OrderTaskRepository.GetPagedListAsync(
|
|
predicate,
|
|
page,
|
|
pageSize,
|
|
new Dictionary<string, bool> { [nameof(OrderTask.UpdateTime)] = false, [nameof(OrderTask.Id)] = false });
|
|
var total = await OrderTaskRepository.CountAsync(predicate);
|
|
|
|
return new OmsPageResult<OrderTaskOutput>
|
|
{
|
|
Items = tasks.Select(x => new OrderTaskOutput
|
|
{
|
|
Id = x.Id,
|
|
TaskName = x.TaskName,
|
|
Quantity = x.Quantity,
|
|
Status = x.Status,
|
|
TemplateId = x.TemplateId,
|
|
CreateTime = x.CreateTime,
|
|
UpdateTime = OmsDocHelper.NullIfDefault(x.UpdateTime)
|
|
}).ToList(),
|
|
Total = total
|
|
};
|
|
}
|
|
|
|
private async Task<OrderTaskDetailOutput> GetTaskDetailCoreAsync(int taskId)
|
|
{
|
|
var task = await OrderTaskRepository.FirstOrDefaultAsync(x => x.Id == taskId);
|
|
if (task == null)
|
|
{
|
|
throw new BusinessException("任务不存在");
|
|
}
|
|
|
|
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
|
|
CustomerRepository,
|
|
CurrentUser,
|
|
null);
|
|
if (customerId.HasValue && task.CustomerId != customerId.Value)
|
|
{
|
|
throw new BusinessException("任务不存在");
|
|
}
|
|
|
|
var failList = await OrderTaskRepository.GetFailListAsync(task.Id);
|
|
return new OrderTaskDetailOutput
|
|
{
|
|
Id = task.Id,
|
|
TaskName = task.TaskName,
|
|
Quantity = task.Quantity,
|
|
SuccessCount = task.SuccessCount,
|
|
FailCount = task.FailCount,
|
|
Status = task.Status,
|
|
TemplateId = task.TemplateId,
|
|
CreateTime = task.CreateTime,
|
|
UpdateTime = OmsDocHelper.NullIfDefault(task.UpdateTime),
|
|
FailList = failList.Select(x => new OrderTaskFailOutput
|
|
{
|
|
Id = x.Id,
|
|
TaskId = x.TaskId,
|
|
RowNumber = x.RowNumber,
|
|
Reason = x.Reason,
|
|
RawDataJson = OmsDocHelper.DeserializeJsonObject(x.RawDataJson)
|
|
}).ToList()
|
|
};
|
|
}
|
|
|
|
private async Task<string> CreateOrderPrintFileAsync(OrderOutput order)
|
|
{
|
|
var directory = Path.Combine(GetWebRootDirectory(), "uploads", "prints", "orders");
|
|
Directory.CreateDirectory(directory);
|
|
var fileName = $"{order.ServiceNo}-{DateTime.Now:yyyyMMddHHmmss}.html";
|
|
var html = $"""
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head><meta charset="utf-8"><title>{order.ServiceNo}</title></head>
|
|
<body>
|
|
<h2>Order Label</h2>
|
|
<p>ServiceNo: {order.ServiceNo}</p>
|
|
<p>ClientNo: {order.ClientNo}</p>
|
|
<p>TrackNo: {order.TrackNo}</p>
|
|
<p>Warehouse: {order.Warehouse}</p>
|
|
</body>
|
|
</html>
|
|
""";
|
|
await File.WriteAllTextAsync(Path.Combine(directory, fileName), html, Encoding.UTF8);
|
|
return $"/uploads/prints/orders/{fileName}";
|
|
}
|
|
|
|
private string GetOrderExportDirectory() => Path.Combine(GetWebRootDirectory(), "uploads", "exports", "orders");
|
|
|
|
private string GetWebRootDirectory()
|
|
{
|
|
var webRoot = string.IsNullOrWhiteSpace(WebHostEnvironment.WebRootPath)
|
|
? Path.Combine(WebHostEnvironment.ContentRootPath, "wwwroot")
|
|
: WebHostEnvironment.WebRootPath;
|
|
Directory.CreateDirectory(webRoot);
|
|
return webRoot;
|
|
}
|
|
|
|
private async Task CleanupExpiredFilesAsync(string directory)
|
|
{
|
|
if (!Directory.Exists(directory))
|
|
{
|
|
return;
|
|
}
|
|
|
|
await Task.Run(() =>
|
|
{
|
|
foreach (var file in Directory.GetFiles(directory))
|
|
{
|
|
if (File.GetCreationTime(file) <= DateTime.Now.AddHours(-24))
|
|
{
|
|
File.Delete(file);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static OrderSenderOutput? MapSender(OrderSender? sender)
|
|
{
|
|
return sender == null
|
|
? null
|
|
: new OrderSenderOutput
|
|
{
|
|
SenderName = sender.SenderName,
|
|
Company = sender.Company,
|
|
Phone = sender.Phone,
|
|
TelePhone = sender.TelePhone,
|
|
Email = sender.Email,
|
|
CountryCode = sender.Country,
|
|
Province = sender.Province,
|
|
City = sender.City,
|
|
ZipCode = sender.ZipCode,
|
|
StreetAddress1 = sender.StreetAddress1,
|
|
StreetAddress2 = sender.StreetAddress2,
|
|
StreetAddress3 = sender.StreetAddress3,
|
|
HouseNumber = sender.HouseNumber
|
|
};
|
|
}
|
|
|
|
private static OrderReceiverOutput? MapReceiver(OrderRecipient? recipient)
|
|
{
|
|
return recipient == null
|
|
? null
|
|
: new OrderReceiverOutput
|
|
{
|
|
RecipientsName = recipient.RecipientsName,
|
|
CompanyName = recipient.CompanyName,
|
|
Phone = recipient.Phone,
|
|
TelePhone = recipient.TelePhone,
|
|
Email = recipient.Email,
|
|
CountryCode = recipient.Country,
|
|
Province = recipient.Province,
|
|
City = recipient.City,
|
|
StreetNumber = recipient.StreetNumber,
|
|
StreetAddress1 = recipient.StreetAddress1,
|
|
StreetAddress2 = recipient.StreetAddress2,
|
|
StreetAddress3 = recipient.StreetAddress3,
|
|
ZipCode = recipient.ZipCode,
|
|
TaxType = recipient.TaxType,
|
|
TaxNo = recipient.TaxNo,
|
|
CertificateType = recipient.CertificateType,
|
|
CertificateNo = recipient.CertificateNo,
|
|
Eori = recipient.Eori,
|
|
Vat = recipient.Vat
|
|
};
|
|
}
|
|
|
|
private static OrderItemOutput MapDeclaration(OrderDeclaration x)
|
|
{
|
|
return new OrderItemOutput
|
|
{
|
|
CnName = x.CnName,
|
|
EnName = x.EnName,
|
|
Sku = x.Sku,
|
|
Unit = x.Unit,
|
|
UnitPrice = x.UnitPrice,
|
|
UnitWeight = x.UnitWeight,
|
|
Quantity = x.Quantity,
|
|
Amount = x.Amount,
|
|
Weight = x.Weight,
|
|
HsCode = x.ExHsCode ?? x.ImHsCode ?? x.HsCode,
|
|
SkuImage = x.SkuImage,
|
|
Category = x.Category,
|
|
Brand = x.Brand,
|
|
BrandType = x.BrandType,
|
|
IsMagnetic = x.IsMagnetic > 0,
|
|
Distribution = x.Distribution,
|
|
Material = x.Material,
|
|
EnMaterial = x.EnMaterial,
|
|
Purpose = x.Purpose,
|
|
Attributes = x.Attributes,
|
|
OriginCountry = x.OriginCountry,
|
|
SalesLink = x.SalesLink,
|
|
Model = x.Model,
|
|
Specifications = x.Specifications,
|
|
Comment = x.Comment
|
|
};
|
|
}
|
|
|
|
private static OrderWeightOutput MapWeight(OrderWeight x)
|
|
{
|
|
return new OrderWeightOutput
|
|
{
|
|
Type = x.Type,
|
|
Length = x.Length,
|
|
Width = x.Width,
|
|
Height = x.Height,
|
|
ActualWeight = x.ActualWeight,
|
|
VolumetricWeight = x.VolumetricWeight,
|
|
ChargeableWeight = x.ChargeableWeight,
|
|
Cubic = x.Cubic
|
|
};
|
|
}
|
|
|
|
private static OrderTaskFail BuildTaskFail(int taskId, int rowNumber, string reason, object rawData)
|
|
{
|
|
return new OrderTaskFail
|
|
{
|
|
TaskId = taskId,
|
|
RowNumber = rowNumber,
|
|
Reason = reason,
|
|
RawDataJson = JsonSerializer.Serialize(rawData),
|
|
CreateUserId = 0,
|
|
CreateTime = DateTime.Now
|
|
};
|
|
}
|
|
|
|
private static string? GetStringCell(IDictionary<string, object> row, string key) => row.TryGetValue(key, out var value) ? value?.ToString() : null;
|
|
private static int? GetintCell(IDictionary<string, object> row, string key) => int.TryParse(GetStringCell(row, key), out var value) ? value : null;
|
|
private static int? GetIntCell(IDictionary<string, object> row, string key) => int.TryParse(GetStringCell(row, key), out var value) ? value : null;
|
|
private static decimal? GetDecimalCell(IDictionary<string, object> row, string key) => decimal.TryParse(GetStringCell(row, key), out var value) ? value : null;
|
|
private static bool GetBoolCell(IDictionary<string, object> row, string key) => GetStringCell(row, key) is "1" or "true" or "True" or "TRUE" or "是";
|
|
|
|
private static void EnsureTemplateAccessible(OrderTemplate template, int effectiveCustomerId)
|
|
{
|
|
if (string.Equals(template.Type, "standard", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (template.CustomerId != effectiveCustomerId)
|
|
{
|
|
throw new BusinessException("模板不存在");
|
|
}
|
|
}
|
|
|
|
private OrderWeight? BuildForecastWeight(int orderId, IDictionary<string, object> row)
|
|
{
|
|
var length = GetDecimalCell(row, "Length");
|
|
var width = GetDecimalCell(row, "Width");
|
|
var height = GetDecimalCell(row, "Height");
|
|
var actualWeight = GetDecimalCell(row, "ActualWeight");
|
|
var volumetricWeight = GetDecimalCell(row, "VolumetricWeight");
|
|
var chargeableWeight = GetDecimalCell(row, "ChargeableWeight");
|
|
var cubic = GetDecimalCell(row, "Cubic");
|
|
if (!length.HasValue && !width.HasValue && !height.HasValue && !actualWeight.HasValue && !volumetricWeight.HasValue && !chargeableWeight.HasValue && !cubic.HasValue)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
return new OrderWeight
|
|
{
|
|
OrderId = orderId,
|
|
Type = OrderWeightTypeCodes.Forecast,
|
|
Length = length,
|
|
Width = width,
|
|
Height = height,
|
|
ActualWeight = actualWeight,
|
|
VolumetricWeight = volumetricWeight,
|
|
ChargeableWeight = chargeableWeight,
|
|
Cubic = cubic
|
|
};
|
|
}
|
|
}
|