From 631479059860ae27d9e04c3e5431b901b40a585e Mon Sep 17 00:00:00 2001 From: zzh <1368735060@qq.com> Date: Thu, 23 Jul 2026 09:28:34 +0800 Subject: [PATCH] feat: persist track upsert response in batch job item resultJson Co-authored-by: Cursor --- .../Orders/Batch/IOrderBatchActionExecutor.cs | 6 +- .../Orders/Batch/OrderBatchActionExecutor.cs | 37 +++++++++- .../Orders/Batch/OrderBatchJobItemFeedback.cs | 5 +- .../OrderBatchTrackUpsertResultBuilder.cs | 67 +++++++++++++++++++ ...OrderBatchTrackUpsertResultBuilderTests.cs | 39 +++++++++++ 5 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 src/Oms.Application/Services/Orders/Batch/OrderBatchTrackUpsertResultBuilder.cs create mode 100644 src/Oms.Tests/OrderBatchTrackUpsertResultBuilderTests.cs diff --git a/src/Oms.Application/Services/Orders/Batch/IOrderBatchActionExecutor.cs b/src/Oms.Application/Services/Orders/Batch/IOrderBatchActionExecutor.cs index ca96f39..07b157d 100644 --- a/src/Oms.Application/Services/Orders/Batch/IOrderBatchActionExecutor.cs +++ b/src/Oms.Application/Services/Orders/Batch/IOrderBatchActionExecutor.cs @@ -47,13 +47,17 @@ public sealed class OrderBatchActionExecuteResult ResultJson = resultJson, }; - public static OrderBatchActionExecuteResult BusinessFail(string reason, int? createdOrderId = null) => + public static OrderBatchActionExecuteResult BusinessFail( + string reason, + int? createdOrderId = null, + string? resultJson = null) => new() { Success = false, IsBusinessFailure = true, FailReason = reason, CreatedOrderId = createdOrderId, + ResultJson = resultJson, }; public static OrderBatchActionExecuteResult SystemFail(string reason) => diff --git a/src/Oms.Application/Services/Orders/Batch/OrderBatchActionExecutor.cs b/src/Oms.Application/Services/Orders/Batch/OrderBatchActionExecutor.cs index 66dd698..acb9cfb 100644 --- a/src/Oms.Application/Services/Orders/Batch/OrderBatchActionExecutor.cs +++ b/src/Oms.Application/Services/Orders/Batch/OrderBatchActionExecutor.cs @@ -83,8 +83,41 @@ public sealed class OrderBatchActionExecutor( request = await smallBagTrackUpsertRequestBuilder.BuildAsync(order, cancellationToken: cancellationToken); } - await smallBagTrackOrderClient.UpsertAsync(request, cancellationToken); - return OrderBatchActionExecuteResult.Ok(); + var trackResult = await smallBagTrackOrderClient.UpsertDebugAsync(request, cancellationToken); + var serviceNo = request.OrderNo?.Trim(); + + if (trackResult.Skipped) + { + var reason = string.IsNullOrWhiteSpace(trackResult.SkipReason) + ? "轨迹服务未启用或配置不完整" + : trackResult.SkipReason.Trim(); + return OrderBatchActionExecuteResult.BusinessFail( + reason, + resultJson: OrderBatchTrackUpsertResultBuilder.BuildFailure( + trackResult, + message.OrderId, + serviceNo, + reason)); + } + + if (!trackResult.Success) + { + var reason = $"轨迹订单创建失败: HTTP {trackResult.StatusCode}"; + return OrderBatchActionExecuteResult.BusinessFail( + reason, + resultJson: OrderBatchTrackUpsertResultBuilder.BuildFailure( + trackResult, + message.OrderId, + serviceNo, + reason)); + } + + return OrderBatchActionExecuteResult.Ok( + serviceNo: serviceNo, + resultJson: OrderBatchTrackUpsertResultBuilder.BuildSuccess( + trackResult, + message.OrderId, + serviceNo)); } private async Task ExecuteDownstreamForwardAsync( diff --git a/src/Oms.Application/Services/Orders/Batch/OrderBatchJobItemFeedback.cs b/src/Oms.Application/Services/Orders/Batch/OrderBatchJobItemFeedback.cs index 34d277c..f54422f 100644 --- a/src/Oms.Application/Services/Orders/Batch/OrderBatchJobItemFeedback.cs +++ b/src/Oms.Application/Services/Orders/Batch/OrderBatchJobItemFeedback.cs @@ -132,7 +132,9 @@ public static class OrderBatchJobItemFeedback item.OrderId = result.CreatedOrderId.Value; } - item.ResultJson = BuildFailureResultJson(item, action, item.FailReason, retryCount: item.RetryCount); + item.ResultJson = !string.IsNullOrWhiteSpace(result.ResultJson) + ? result.ResultJson + : BuildFailureResultJson(item, action, item.FailReason, retryCount: item.RetryCount); } public static void ApplySystemRetry( @@ -270,6 +272,7 @@ public static class OrderBatchJobItemFeedback OrderBatchActionCodes.MarkClaimed => "理赔件创建成功", OrderBatchActionCodes.HandleStatusUpdate => "处理状态更新成功", OrderBatchActionCodes.DownstreamForwardCreateOne => "下游预报成功", + OrderBatchActionCodes.TrackUpsertSmallBag => "轨迹订单创建成功", _ => "操作成功", }; diff --git a/src/Oms.Application/Services/Orders/Batch/OrderBatchTrackUpsertResultBuilder.cs b/src/Oms.Application/Services/Orders/Batch/OrderBatchTrackUpsertResultBuilder.cs new file mode 100644 index 0000000..0485cc9 --- /dev/null +++ b/src/Oms.Application/Services/Orders/Batch/OrderBatchTrackUpsertResultBuilder.cs @@ -0,0 +1,67 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Oms.Application.Integrations.SmallBagTrack; +using Oms.Domain.OrdersAggregate.Consts; + +namespace Oms.Application.Services.Orders.Batch; + +internal static class OrderBatchTrackUpsertResultBuilder +{ + public static string BuildSuccess( + SmallBagTrackUpsertResult trackResult, + int orderId, + string? serviceNo) => + JsonConvert.SerializeObject(new + { + success = true, + action = OrderBatchActionCodes.TrackUpsertSmallBag, + message = "轨迹订单创建成功", + orderId = orderId > 0 ? orderId : (int?)null, + serviceNo, + trackUpsert = MapTrackUpsert(trackResult), + }); + + public static string BuildFailure( + SmallBagTrackUpsertResult trackResult, + int orderId, + string? serviceNo, + string reason) => + JsonConvert.SerializeObject(new + { + success = false, + action = OrderBatchActionCodes.TrackUpsertSmallBag, + message = reason, + orderId = orderId > 0 ? orderId : (int?)null, + serviceNo, + trackUpsert = MapTrackUpsert(trackResult), + }); + + private static object MapTrackUpsert(SmallBagTrackUpsertResult result) => + new + { + skipped = result.Skipped, + skipReason = result.SkipReason, + requestUrl = result.Url, + requestBody = TryParseJson(result.RequestJson), + responseStatusCode = result.StatusCode, + responseBody = TryParseJson(result.ResponseBody), + responseBodyRaw = TryParseJson(result.ResponseBody) == null ? result.ResponseBody : null, + }; + + private static object? TryParseJson(string? json) + { + if (string.IsNullOrWhiteSpace(json)) + { + return null; + } + + try + { + return JToken.Parse(json); + } + catch + { + return null; + } + } +} diff --git a/src/Oms.Tests/OrderBatchTrackUpsertResultBuilderTests.cs b/src/Oms.Tests/OrderBatchTrackUpsertResultBuilderTests.cs new file mode 100644 index 0000000..7489149 --- /dev/null +++ b/src/Oms.Tests/OrderBatchTrackUpsertResultBuilderTests.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json.Linq; +using Oms.Application.Integrations.SmallBagTrack; +using Oms.Application.Services.Orders.Batch; +using Oms.Domain.OrdersAggregate.Consts; +using Xunit; + +namespace Oms.Tests; + +public class OrderBatchTrackUpsertResultBuilderTests +{ + [Fact] + public void BuildSuccess_IncludesTrackResponseBody() + { + var trackResult = new SmallBagTrackUpsertResult + { + Skipped = false, + Success = true, + Url = "http://track/OrderV2/UpsertSmallBag", + RequestJson = "{\"orderNo\":\"IDE001\"}", + StatusCode = 200, + ResponseBody = "{\"code\":0,\"data\":{\"id\":1001}}" + }; + + var json = OrderBatchTrackUpsertResultBuilder.BuildSuccess(trackResult, 9001, "IDE001"); + var obj = JObject.Parse(json); + + Assert.True(obj.Value("success")); + Assert.Equal(OrderBatchActionCodes.TrackUpsertSmallBag, obj.Value("action")); + Assert.Equal("轨迹订单创建成功", obj.Value("message")); + Assert.Equal(9001, obj.Value("orderId")); + Assert.Equal("IDE001", obj.Value("serviceNo")); + + var trackUpsert = obj["trackUpsert"] as JObject; + Assert.NotNull(trackUpsert); + Assert.Equal(200, trackUpsert!.Value("responseStatusCode")); + Assert.Equal(0, trackUpsert["responseBody"]!.Value("code")); + Assert.Equal(1001, trackUpsert["responseBody"]!["data"]!.Value("id")); + } +}