feat: 运单操作日志改为列表摘要,补齐费用/支付/预报/打印埋点
All checks were successful
Build and Deploy / deploy (push) Successful in 1m3s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m3s
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
dcd985bca4
commit
64737284f3
@ -17,7 +17,7 @@ SET @sql := IF(
|
||||
`Id` INT NOT NULL AUTO_INCREMENT COMMENT ''主键'',
|
||||
`OrderId` INT NOT NULL COMMENT ''运单Id'',
|
||||
`ServiceNo` VARCHAR(64) NULL COMMENT ''运单号冗余'',
|
||||
`Action` VARCHAR(32) NOT NULL COMMENT ''动作码 editBasic/editWeight/recalcReceivable/recalcPayable/reallocate'',
|
||||
`Action` VARCHAR(32) NOT NULL COMMENT ''动作码 editBasic/editWeight/recalcReceivable/recalcPayable/reallocate/bindSnapshotVersions/updateAdditionalServices/addFee/pay/preDeclare/downstreamForward/print'',
|
||||
`ActionName` VARCHAR(64) NOT NULL COMMENT ''动作中文名'',
|
||||
`OperatorId` INT NOT NULL DEFAULT 0 COMMENT ''操作人用户Id'',
|
||||
`OperatorName` VARCHAR(64) NULL COMMENT ''操作人展示名'',
|
||||
|
||||
@ -35,6 +35,11 @@ public class OrderOperationLogOutput
|
||||
|
||||
public string? Remark { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 列表「内容」列:由备注 + 字段变更摘要拼装。
|
||||
/// </summary>
|
||||
public string Summary { get; set; } = string.Empty;
|
||||
|
||||
public DateTime CreateTime { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ public sealed class OrderBatchActionExecutor(
|
||||
OrderDownstreamCredentialResolver downstreamCredentialResolver,
|
||||
IItfxForwardClient itfxForwardClient,
|
||||
OrderFileManager orderFileManager,
|
||||
OrderOperationLogWriter operationLogWriter,
|
||||
OrderBatchCreateActionHandler createActionHandler,
|
||||
OrderBatchOrderActionHandler orderActionHandler) : IOrderBatchActionExecutor, IScopedDependency
|
||||
{
|
||||
@ -225,6 +226,8 @@ public sealed class OrderBatchActionExecutor(
|
||||
businessMessage));
|
||||
}
|
||||
|
||||
var beforeSnap = OrderOperationLogSnapshot.CaptureOrder(order);
|
||||
|
||||
if (ItfxCreateOrderOneDataParser.TryParse(forward.ResponseBody, out var data)
|
||||
&& data != null)
|
||||
{
|
||||
@ -243,6 +246,29 @@ public sealed class OrderBatchActionExecutor(
|
||||
}
|
||||
}
|
||||
|
||||
var afterSnap = OrderOperationLogSnapshot.CaptureOrder(order);
|
||||
var remarkParts = new List<string> { $"供应商 {creds.SupplierCode}" };
|
||||
if (!string.IsNullOrWhiteSpace(order.DownstreamServiceNo))
|
||||
{
|
||||
remarkParts.Add($"服务商单号 {order.DownstreamServiceNo}");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(order.TrackNo))
|
||||
{
|
||||
remarkParts.Add($"跟踪号 {order.TrackNo}");
|
||||
}
|
||||
|
||||
await operationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.DownstreamForward,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
string.Join(";", remarkParts),
|
||||
message.OperatorUserId > 0 ? message.OperatorUserId : null,
|
||||
operatorName: null,
|
||||
operatorType: "staff",
|
||||
source: "job");
|
||||
|
||||
return OrderBatchActionExecuteResult.Ok(
|
||||
serviceNo: order.ServiceNo,
|
||||
trackNo: order.TrackNo,
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
using System.Globalization;
|
||||
using Newtonsoft.Json;
|
||||
using Oms.Application.Shared;
|
||||
using Oms.Domain.OrdersAggregate.Consts;
|
||||
using Oms.Domain.OrdersAggregate.Entities;
|
||||
|
||||
@ -9,6 +11,8 @@ namespace Oms.Application.Services.Orders;
|
||||
/// </summary>
|
||||
public static class OrderOperationLogSnapshot
|
||||
{
|
||||
public const int SummaryMaxChangeItems = 5;
|
||||
|
||||
private static readonly Dictionary<string, string> Labels = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["orderStatus"] = "订单状态",
|
||||
@ -31,6 +35,7 @@ public static class OrderOperationLogSnapshot
|
||||
["salesProductRulesVersion"] = "规则版本",
|
||||
["salesProductPriceVersion"] = "价格版本",
|
||||
["isPaid"] = "是否已支付",
|
||||
["additionalServices"] = "附加服务",
|
||||
["sender.name"] = "发件人姓名",
|
||||
["sender.phone"] = "发件人电话",
|
||||
["sender.country"] = "发件国家",
|
||||
@ -75,6 +80,7 @@ public static class OrderOperationLogSnapshot
|
||||
["salesProductRulesVersion"] = Norm(order.SalesProductRulesVersion),
|
||||
["salesProductPriceVersion"] = Norm(order.SalesProductPriceVersion),
|
||||
["isPaid"] = FormatByte(order.IsPaid),
|
||||
["additionalServices"] = FormatAdditionalServices(order.AdditionalServices),
|
||||
};
|
||||
}
|
||||
|
||||
@ -225,6 +231,89 @@ public static class OrderOperationLogSnapshot
|
||||
return path;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 拼装列表「内容」列:备注优先,再跟最多 N 条字段变更。
|
||||
/// </summary>
|
||||
public static string BuildSummary(
|
||||
IReadOnlyList<OrderOperationLogChangeView> changes,
|
||||
string? remark,
|
||||
int maxItems = SummaryMaxChangeItems)
|
||||
{
|
||||
var parts = new List<string>();
|
||||
if (!string.IsNullOrWhiteSpace(remark))
|
||||
{
|
||||
parts.Add(remark.Trim());
|
||||
}
|
||||
|
||||
if (changes.Count > 0)
|
||||
{
|
||||
var take = Math.Max(0, maxItems);
|
||||
foreach (var change in changes.Take(take))
|
||||
{
|
||||
var label = string.IsNullOrWhiteSpace(change.Label) ? change.Path : change.Label;
|
||||
parts.Add($"{label}:{DisplayValue(change.Path, change.Before)}→{DisplayValue(change.Path, change.After)}");
|
||||
}
|
||||
|
||||
if (changes.Count > take)
|
||||
{
|
||||
parts.Add($"等{changes.Count}项变更");
|
||||
}
|
||||
}
|
||||
|
||||
return parts.Count == 0 ? "—" : string.Join(";", parts);
|
||||
}
|
||||
|
||||
public readonly record struct OrderOperationLogChangeView(
|
||||
string Path,
|
||||
string Label,
|
||||
string? Before,
|
||||
string? After);
|
||||
|
||||
private static string DisplayValue(string path, string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return "空";
|
||||
}
|
||||
|
||||
if (string.Equals(path, "isPaid", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(path, "isCod", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return value == "1" ? "是" : "否";
|
||||
}
|
||||
|
||||
if (string.Equals(path, "orderStatus", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return OmsDocHelper.GetOrderStatusName(value) ?? value;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static string? FormatAdditionalServices(string? json)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var list = JsonConvert.DeserializeObject<List<string>>(json) ?? [];
|
||||
var codes = list
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.Select(x => x.Trim())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
return codes.Count == 0 ? null : string.Join("、", codes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return Norm(json);
|
||||
}
|
||||
}
|
||||
|
||||
private static string? Norm(string? value)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
|
||||
@ -33,23 +33,29 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task TryWriteAsync(
|
||||
public Task TryWriteAsync(
|
||||
Order order,
|
||||
string action,
|
||||
IReadOnlyDictionary<string, string?> before,
|
||||
IReadOnlyDictionary<string, string?> after,
|
||||
string? remark = null)
|
||||
=> TryWriteAsync(order, action, before, after, remark, operatorId: null, operatorName: null);
|
||||
|
||||
public async Task TryWriteAsync(
|
||||
Order order,
|
||||
string action,
|
||||
IReadOnlyDictionary<string, string?> before,
|
||||
IReadOnlyDictionary<string, string?> after,
|
||||
string? remark,
|
||||
int? operatorId,
|
||||
string? operatorName,
|
||||
string operatorType = "staff",
|
||||
string source = "pc")
|
||||
{
|
||||
try
|
||||
{
|
||||
var changes = OrderOperationLogSnapshot.Diff(before, after);
|
||||
var operatorId = 0;
|
||||
string? operatorName = null;
|
||||
if (_currentUser.IsAuthenticated)
|
||||
{
|
||||
operatorId = _currentUser.GetId<int>();
|
||||
operatorName = await _userDisplayNameResolver.ResolveAsync(operatorId);
|
||||
}
|
||||
var (resolvedId, resolvedName) = await ResolveOperatorAsync(operatorId, operatorName);
|
||||
|
||||
var entity = new OrderOperationLog
|
||||
{
|
||||
@ -57,10 +63,10 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
ServiceNo = order.ServiceNo,
|
||||
Action = action,
|
||||
ActionName = OrderOperationActionCodes.GetActionName(action),
|
||||
OperatorId = operatorId,
|
||||
OperatorName = operatorName,
|
||||
OperatorType = "staff",
|
||||
Source = "pc",
|
||||
OperatorId = resolvedId,
|
||||
OperatorName = resolvedName,
|
||||
OperatorType = string.IsNullOrWhiteSpace(operatorType) ? "staff" : operatorType.Trim(),
|
||||
Source = string.IsNullOrWhiteSpace(source) ? "pc" : source.Trim(),
|
||||
ChangesJson = JsonConvert.SerializeObject(
|
||||
changes.Select(x => new OrderOperationLogChangeItem
|
||||
{
|
||||
@ -70,7 +76,7 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
After = x.After
|
||||
}).ToList()),
|
||||
Remark = string.IsNullOrWhiteSpace(remark) ? null : remark.Trim(),
|
||||
CreateUserId = operatorId,
|
||||
CreateUserId = resolvedId,
|
||||
CreateTime = DateTime.Now
|
||||
};
|
||||
|
||||
@ -86,6 +92,28 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 无字段 diff 时写入叙事日志(打印、下游预报成功等)。
|
||||
/// </summary>
|
||||
public Task TryWriteSimpleAsync(
|
||||
Order order,
|
||||
string action,
|
||||
string? remark,
|
||||
int? operatorId = null,
|
||||
string? operatorName = null,
|
||||
string operatorType = "staff",
|
||||
string source = "pc")
|
||||
=> TryWriteAsync(
|
||||
order,
|
||||
action,
|
||||
new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase),
|
||||
new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase),
|
||||
remark,
|
||||
operatorId,
|
||||
operatorName,
|
||||
operatorType,
|
||||
source);
|
||||
|
||||
public async Task<OrderOperationLogListOutput> ListByOrderIdAsync(int orderId)
|
||||
{
|
||||
var rows = await _repository.GetListAsync(x => x.OrderId == orderId);
|
||||
@ -97,6 +125,30 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
return new OrderOperationLogListOutput { Items = items };
|
||||
}
|
||||
|
||||
private async Task<(int OperatorId, string? OperatorName)> ResolveOperatorAsync(
|
||||
int? operatorId,
|
||||
string? operatorName)
|
||||
{
|
||||
if (operatorId is > 0)
|
||||
{
|
||||
var name = string.IsNullOrWhiteSpace(operatorName)
|
||||
? await _userDisplayNameResolver.ResolveAsync(operatorId.Value)
|
||||
: operatorName.Trim();
|
||||
return (operatorId.Value, name);
|
||||
}
|
||||
|
||||
if (_currentUser.IsAuthenticated)
|
||||
{
|
||||
var id = _currentUser.GetId<int>();
|
||||
var name = string.IsNullOrWhiteSpace(operatorName)
|
||||
? await _userDisplayNameResolver.ResolveAsync(id)
|
||||
: operatorName.Trim();
|
||||
return (id, name);
|
||||
}
|
||||
|
||||
return (0, string.IsNullOrWhiteSpace(operatorName) ? null : operatorName.Trim());
|
||||
}
|
||||
|
||||
private static OrderOperationLogOutput MapOutput(OrderOperationLog row)
|
||||
{
|
||||
var changes = new List<OrderOperationLogChangeItem>();
|
||||
@ -113,6 +165,14 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
}
|
||||
}
|
||||
|
||||
var views = changes
|
||||
.Select(x => new OrderOperationLogSnapshot.OrderOperationLogChangeView(
|
||||
x.Path,
|
||||
x.Label,
|
||||
x.Before,
|
||||
x.After))
|
||||
.ToList();
|
||||
|
||||
return new OrderOperationLogOutput
|
||||
{
|
||||
Id = row.Id,
|
||||
@ -126,6 +186,7 @@ public class OrderOperationLogWriter : IScopedDependency
|
||||
Source = row.Source,
|
||||
Changes = changes,
|
||||
Remark = row.Remark,
|
||||
Summary = OrderOperationLogSnapshot.BuildSummary(views, row.Remark),
|
||||
CreateTime = row.CreateTime
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using Fake.Application;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Newtonsoft.Json;
|
||||
@ -323,7 +324,7 @@ public partial class OrderService
|
||||
"规则");
|
||||
if (!string.Equals(order.SalesProductRulesVersion, resolved, StringComparison.Ordinal))
|
||||
{
|
||||
remarkParts.Add($"rules:{order.SalesProductRulesVersion ?? "-"}→{resolved}");
|
||||
remarkParts.Add($"规则版本 {order.SalesProductRulesVersion ?? "-"}→{resolved}");
|
||||
order.SalesProductRulesVersion = resolved;
|
||||
}
|
||||
}
|
||||
@ -337,7 +338,7 @@ public partial class OrderService
|
||||
"价格");
|
||||
if (!string.Equals(order.SalesProductPriceVersion, resolved, StringComparison.Ordinal))
|
||||
{
|
||||
remarkParts.Add($"price:{order.SalesProductPriceVersion ?? "-"}→{resolved}");
|
||||
remarkParts.Add($"价格版本 {order.SalesProductPriceVersion ?? "-"}→{resolved}");
|
||||
order.SalesProductPriceVersion = resolved;
|
||||
}
|
||||
}
|
||||
@ -354,11 +355,13 @@ public partial class OrderService
|
||||
{
|
||||
EnsureReceivableMutable(order);
|
||||
await RecalculateReceivableCoreAsync(order);
|
||||
remarkParts.Add("并重算应收");
|
||||
}
|
||||
|
||||
if (input.RecalculatePayable)
|
||||
{
|
||||
await RecalculatePayableCoreAsync(order);
|
||||
remarkParts.Add("并重算应付");
|
||||
}
|
||||
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
@ -368,7 +371,7 @@ public partial class OrderService
|
||||
OrderOperationActionCodes.BindSnapshotVersions,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
remarkParts.Count == 0 ? null : string.Join(';', remarkParts));
|
||||
remarkParts.Count == 0 ? null : string.Join(';', remarkParts));
|
||||
return (await MapOrderOutputsAsync([order])).First();
|
||||
}
|
||||
|
||||
@ -785,6 +788,7 @@ public partial class OrderService
|
||||
{
|
||||
var order = await GetOrderOrThrowAsync(input.Id);
|
||||
EnsureReceivableMutable(order);
|
||||
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(order.ProductCode))
|
||||
{
|
||||
@ -803,6 +807,15 @@ public partial class OrderService
|
||||
|
||||
order.UpdateTime = DateTime.Now;
|
||||
await OrderRepository.UpdateAsync(order);
|
||||
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.UpdateAdditionalServices,
|
||||
beforeSnap,
|
||||
afterSnap);
|
||||
|
||||
return (await MapOrderOutputsAsync([order])).First();
|
||||
}
|
||||
|
||||
@ -892,6 +905,8 @@ public partial class OrderService
|
||||
throw new BusinessException("计费阶段无效");
|
||||
}
|
||||
|
||||
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
|
||||
|
||||
var fee = new OrderFee
|
||||
{
|
||||
Type = type,
|
||||
@ -912,6 +927,17 @@ public partial class OrderService
|
||||
order.UpdateTime = DateTime.Now;
|
||||
await OrderRepository.UpdateAsync(order);
|
||||
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true);
|
||||
var typeName = type == OrderFeeTypeCodes.Receivable ? "应收" : "应付";
|
||||
var amountText = input.Amount.ToString("0.####", CultureInfo.InvariantCulture);
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.AddFee,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
$"新增{typeName}「{costItem}」{currency} {amountText}");
|
||||
|
||||
return (await MapOrderOutputsAsync([order])).First();
|
||||
}
|
||||
|
||||
|
||||
@ -2623,6 +2623,8 @@ public partial class OrderService
|
||||
return;
|
||||
}
|
||||
|
||||
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true, includeWeights: true);
|
||||
|
||||
int? couponInstanceId = order.CouponInstanceId;
|
||||
if (!string.IsNullOrWhiteSpace(payloadJson))
|
||||
{
|
||||
@ -2765,6 +2767,18 @@ public partial class OrderService
|
||||
order.UpdateTime = DateTime.Now;
|
||||
await OrderRepository.UpdateAsync(order);
|
||||
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeFees: true, includeWeights: true);
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.PreDeclare,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
"预报计费/排货完成",
|
||||
operatorUserId > 0 ? operatorUserId : null,
|
||||
operatorName: null,
|
||||
operatorType: "staff",
|
||||
source: "job");
|
||||
|
||||
var customer = order.CustomerId.HasValue
|
||||
? await CustomerRepository.FirstOrDefaultAsync(x => x.Id == order.CustomerId.Value)
|
||||
: null;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using Fake.Application;
|
||||
using Fake.Domain.Exceptions;
|
||||
using Fake.ObjectStorage;
|
||||
@ -147,6 +148,7 @@ public partial class OrderService : ApplicationService
|
||||
throw new BusinessException("订单未关联客户,无法支付");
|
||||
}
|
||||
|
||||
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order);
|
||||
var fees = await OrderRepository.GetFeesByOrderIdsAsync([order.Id]);
|
||||
var payAmount = order.PayableAmount ?? fees
|
||||
.Where(x => x.Type == OrderFeeTypeCodes.Receivable)
|
||||
@ -189,6 +191,16 @@ public partial class OrderService : ApplicationService
|
||||
order.IsPaid = 1;
|
||||
order.OrderStatus = OrderStatusCodes.PendingShip;
|
||||
await UpdateOrderAsync(order);
|
||||
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order);
|
||||
var amountText = payAmount.ToString("0.####", CultureInfo.InvariantCulture);
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.Pay,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
$"支付金额 {amountText}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -346,6 +358,10 @@ public partial class OrderService : ApplicationService
|
||||
var existingUrl = await OrderFileManager.GetSystemLabelUrlAsync(order.Id);
|
||||
if (!string.IsNullOrWhiteSpace(existingUrl))
|
||||
{
|
||||
await OperationLogWriter.TryWriteSimpleAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.Print,
|
||||
"打印面单(使用已有文件)");
|
||||
return new OrderPrintOutput
|
||||
{
|
||||
PrintUrl = existingUrl!,
|
||||
@ -365,6 +381,10 @@ public partial class OrderService : ApplicationService
|
||||
{
|
||||
// 兼容回落:仍无模板时给 HTML stub,避免彻底不可打
|
||||
var fallbackUrl = await CreateOrderPrintFileAsync(mapped);
|
||||
await OperationLogWriter.TryWriteSimpleAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.Print,
|
||||
"打印面单(回落 HTML)");
|
||||
return new OrderPrintOutput
|
||||
{
|
||||
PrintUrl = fallbackUrl,
|
||||
@ -373,6 +393,10 @@ public partial class OrderService : ApplicationService
|
||||
};
|
||||
}
|
||||
|
||||
await OperationLogWriter.TryWriteSimpleAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.Print,
|
||||
"打印面单");
|
||||
return new OrderPrintOutput
|
||||
{
|
||||
PrintUrl = result.LabelUrl!,
|
||||
@ -420,6 +444,21 @@ public partial class OrderService : ApplicationService
|
||||
PrintUrl = url,
|
||||
LabelGenerateStatus = LabelGenerateStatusCodes.Ready
|
||||
});
|
||||
try
|
||||
{
|
||||
var existingOrder = await OrderRepository.FirstOrDefaultAsync(x => x.Id == orderId);
|
||||
if (existingOrder != null)
|
||||
{
|
||||
await OperationLogWriter.TryWriteSimpleAsync(
|
||||
existingOrder,
|
||||
OrderOperationActionCodes.Print,
|
||||
"批量打印(使用已有文件)");
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// 日志失败不影响打印
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -8,6 +8,12 @@ public static class OrderOperationActionCodes
|
||||
public const string RecalcPayable = "recalcPayable";
|
||||
public const string Reallocate = "reallocate";
|
||||
public const string BindSnapshotVersions = "bindSnapshotVersions";
|
||||
public const string UpdateAdditionalServices = "updateAdditionalServices";
|
||||
public const string AddFee = "addFee";
|
||||
public const string Pay = "pay";
|
||||
public const string PreDeclare = "preDeclare";
|
||||
public const string DownstreamForward = "downstreamForward";
|
||||
public const string Print = "print";
|
||||
|
||||
public static string GetActionName(string action) => action switch
|
||||
{
|
||||
@ -17,6 +23,12 @@ public static class OrderOperationActionCodes
|
||||
RecalcPayable => "重算应付",
|
||||
Reallocate => "重新排货",
|
||||
BindSnapshotVersions => "切换价格/规则版本",
|
||||
UpdateAdditionalServices => "更新附加服务",
|
||||
AddFee => "添加费用",
|
||||
Pay => "支付",
|
||||
PreDeclare => "重新预报",
|
||||
DownstreamForward => "预报下游",
|
||||
Print => "打印面单",
|
||||
_ => action
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user