feat: 订单编辑支持服务商单号并完善操作日志快照
All checks were successful
Build and Deploy / deploy (push) Successful in 1m0s
All checks were successful
Build and Deploy / deploy (push) Successful in 1m0s
开放 DownstreamServiceNo 更新,补充包裹计费相关操作码与字段快照,便于运单详情编辑留痕。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
64737284f3
commit
8df0f37165
@ -25,6 +25,12 @@ public class OrderUpdateInput
|
||||
[StringLength(64)]
|
||||
public string? TrackNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务商单号。
|
||||
/// </summary>
|
||||
[StringLength(64)]
|
||||
public string? DownstreamServiceNo { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 渠道编码。
|
||||
/// </summary>
|
||||
|
||||
@ -37,21 +37,37 @@ public static class OrderOperationLogSnapshot
|
||||
["isPaid"] = "是否已支付",
|
||||
["additionalServices"] = "附加服务",
|
||||
["sender.name"] = "发件人姓名",
|
||||
["sender.company"] = "发件公司",
|
||||
["sender.phone"] = "发件人电话",
|
||||
["sender.telePhone"] = "发件人固话",
|
||||
["sender.email"] = "发件人邮箱",
|
||||
["sender.country"] = "发件国家",
|
||||
["sender.province"] = "发件省/州",
|
||||
["sender.city"] = "发件城市",
|
||||
["sender.zipCode"] = "发件邮编",
|
||||
["sender.address1"] = "发件地址1",
|
||||
["sender.address2"] = "发件地址2",
|
||||
["sender.address3"] = "发件地址3",
|
||||
["sender.houseNumber"] = "发件门牌号",
|
||||
["receiver.name"] = "收件人姓名",
|
||||
["receiver.company"] = "收件公司",
|
||||
["receiver.phone"] = "收件人电话",
|
||||
["receiver.telePhone"] = "收件人固话",
|
||||
["receiver.email"] = "收件人邮箱",
|
||||
["receiver.country"] = "收件国家",
|
||||
["receiver.province"] = "收件省/州",
|
||||
["receiver.city"] = "收件城市",
|
||||
["receiver.zipCode"] = "收件邮编",
|
||||
["receiver.streetNumber"] = "收件街道号",
|
||||
["receiver.address1"] = "收件地址1",
|
||||
["receiver.address2"] = "收件地址2",
|
||||
["receiver.address3"] = "收件地址3",
|
||||
["receiver.taxType"] = "收件税号类型",
|
||||
["receiver.taxNo"] = "收件税号",
|
||||
["receiver.certificateType"] = "收件证件类型",
|
||||
["receiver.certificateNo"] = "收件证件号",
|
||||
["receiver.eori"] = "收件EORI",
|
||||
["receiver.vat"] = "收件VAT",
|
||||
["fee.receivableTotal"] = "应收合计",
|
||||
["fee.payableTotal"] = "应付合计",
|
||||
};
|
||||
@ -94,13 +110,18 @@ public static class OrderOperationLogSnapshot
|
||||
return new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["sender.name"] = Norm(sender.SenderName),
|
||||
["sender.company"] = Norm(sender.Company),
|
||||
["sender.phone"] = Norm(sender.Phone),
|
||||
["sender.telePhone"] = Norm(sender.TelePhone),
|
||||
["sender.email"] = Norm(sender.Email),
|
||||
["sender.country"] = FormatInt(sender.Country),
|
||||
["sender.province"] = Norm(sender.Province),
|
||||
["sender.city"] = Norm(sender.City),
|
||||
["sender.zipCode"] = Norm(sender.ZipCode),
|
||||
["sender.address1"] = Norm(sender.StreetAddress1),
|
||||
["sender.address2"] = Norm(sender.StreetAddress2),
|
||||
["sender.address3"] = Norm(sender.StreetAddress3),
|
||||
["sender.houseNumber"] = Norm(sender.HouseNumber),
|
||||
};
|
||||
}
|
||||
|
||||
@ -114,13 +135,24 @@ public static class OrderOperationLogSnapshot
|
||||
return new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
["receiver.name"] = Norm(recipient.RecipientsName),
|
||||
["receiver.company"] = Norm(recipient.CompanyName),
|
||||
["receiver.phone"] = Norm(recipient.Phone),
|
||||
["receiver.telePhone"] = Norm(recipient.TelePhone),
|
||||
["receiver.email"] = Norm(recipient.Email),
|
||||
["receiver.country"] = FormatInt(recipient.Country),
|
||||
["receiver.province"] = Norm(recipient.Province),
|
||||
["receiver.city"] = Norm(recipient.City),
|
||||
["receiver.zipCode"] = Norm(recipient.ZipCode),
|
||||
["receiver.streetNumber"] = Norm(recipient.StreetNumber),
|
||||
["receiver.address1"] = Norm(recipient.StreetAddress1),
|
||||
["receiver.address2"] = Norm(recipient.StreetAddress2),
|
||||
["receiver.address3"] = Norm(recipient.StreetAddress3),
|
||||
["receiver.taxType"] = FormatInt(recipient.TaxType),
|
||||
["receiver.taxNo"] = Norm(recipient.TaxNo),
|
||||
["receiver.certificateType"] = FormatInt(recipient.CertificateType),
|
||||
["receiver.certificateNo"] = Norm(recipient.CertificateNo),
|
||||
["receiver.eori"] = Norm(recipient.Eori),
|
||||
["receiver.vat"] = Norm(recipient.Vat),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -53,6 +53,13 @@ public partial class OrderService
|
||||
order.TrackNo = string.IsNullOrWhiteSpace(input.TrackNo) ? null : input.TrackNo.Trim();
|
||||
}
|
||||
|
||||
if (input.DownstreamServiceNo != null)
|
||||
{
|
||||
order.DownstreamServiceNo = string.IsNullOrWhiteSpace(input.DownstreamServiceNo)
|
||||
? null
|
||||
: input.DownstreamServiceNo.Trim();
|
||||
}
|
||||
|
||||
if (input.ChannelCode != null)
|
||||
{
|
||||
order.ChannelCode = string.IsNullOrWhiteSpace(input.ChannelCode) ? null : input.ChannelCode.Trim();
|
||||
@ -138,7 +145,9 @@ public partial class OrderService
|
||||
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeParties: true);
|
||||
var remark = input.Items != null ? "申报信息已更新" : null;
|
||||
// 前端保存基本信息时总会带 items;仅在无字段级 diff 时用备注兜底,避免掩盖真实字段变更
|
||||
var fieldChanges = OrderOperationLogSnapshot.Diff(beforeSnap, afterSnap);
|
||||
var remark = input.Items != null && fieldChanges.Count == 0 ? "申报信息已更新" : null;
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.EditBasic,
|
||||
|
||||
@ -2382,6 +2382,7 @@ public partial class OrderService
|
||||
|
||||
try
|
||||
{
|
||||
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeWeights: true);
|
||||
var weights = (await OrderRepository.GetWeightsByOrderIdsAsync([order.Id]))
|
||||
.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
@ -2419,6 +2420,16 @@ public partial class OrderService
|
||||
order.UpdateTime = DateTime.Now;
|
||||
await OrderRepository.UpdateAsync(order);
|
||||
|
||||
// 操作日志同步落库(件重尺已写完);计费/排货仍走 MQ,不把审计塞进队列
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeWeights: true);
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.Inbound,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
FormatMeasuredDimensionsRemark("收货", length!.Value, width!.Value, height!.Value, actualWeight!.Value));
|
||||
|
||||
await EnqueueLifecycleTrackAppendAsync(order, SmallBagTrackLifecycleEvents.InboundTrackCode);
|
||||
await EnqueueInboundBillingAsync(order);
|
||||
}
|
||||
@ -3016,6 +3027,7 @@ public partial class OrderService
|
||||
|
||||
EnsureBillingProductActive(product);
|
||||
|
||||
var beforeSnap = await CaptureOrderAuditSnapshotAsync(order, includeWeights: true);
|
||||
var weights = (await OrderRepository.GetWeightsByOrderIdsAsync([order.Id]))
|
||||
.OrderBy(x => x.Id)
|
||||
.ToList();
|
||||
@ -3038,9 +3050,28 @@ public partial class OrderService
|
||||
order.UpdateTime = now;
|
||||
await OrderRepository.UpdateAsync(order);
|
||||
|
||||
order = await GetOrderOrThrowAsync(order.Id);
|
||||
var afterSnap = await CaptureOrderAuditSnapshotAsync(order, includeWeights: true);
|
||||
await OperationLogWriter.TryWriteAsync(
|
||||
order,
|
||||
OrderOperationActionCodes.Outbound,
|
||||
beforeSnap,
|
||||
afterSnap,
|
||||
FormatMeasuredDimensionsRemark("发货", length!.Value, width!.Value, height!.Value, actualWeight!.Value));
|
||||
|
||||
await EnqueueLifecycleTrackAppendAsync(order, SmallBagTrackLifecycleEvents.OutboundTrackCode);
|
||||
}
|
||||
|
||||
private static string FormatMeasuredDimensionsRemark(
|
||||
string stage,
|
||||
decimal length,
|
||||
decimal width,
|
||||
decimal height,
|
||||
decimal actualWeight)
|
||||
{
|
||||
return $"{stage} 长×宽×高×重:{length:0.####}×{width:0.####}×{height:0.####}×{actualWeight:0.####}";
|
||||
}
|
||||
|
||||
private async Task<OrderParcelCreateOutput> BuildParcelCreateOutputAsync(Order order)
|
||||
{
|
||||
// 预报已成功时,映射/面单/本地存储失败不得回滚订单(常见:容器 /app/wwwroot 不可写)。
|
||||
|
||||
@ -14,6 +14,8 @@ public static class OrderOperationActionCodes
|
||||
public const string PreDeclare = "preDeclare";
|
||||
public const string DownstreamForward = "downstreamForward";
|
||||
public const string Print = "print";
|
||||
public const string Inbound = "inbound";
|
||||
public const string Outbound = "outbound";
|
||||
|
||||
public static string GetActionName(string action) => action switch
|
||||
{
|
||||
@ -29,6 +31,8 @@ public static class OrderOperationActionCodes
|
||||
PreDeclare => "重新预报",
|
||||
DownstreamForward => "预报下游",
|
||||
Print => "打印面单",
|
||||
Inbound => "入库",
|
||||
Outbound => "出库",
|
||||
_ => action
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user