feat: persist track upsert response in batch job item resultJson

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zzh 2026-07-23 09:28:34 +08:00
parent 1545bc385f
commit 6314790598
5 changed files with 150 additions and 4 deletions

View File

@ -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) =>

View File

@ -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<OrderBatchActionExecuteResult> ExecuteDownstreamForwardAsync(

View File

@ -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 => "轨迹订单创建成功",
_ => "操作成功",
};

View File

@ -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;
}
}
}

View File

@ -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<bool>("success"));
Assert.Equal(OrderBatchActionCodes.TrackUpsertSmallBag, obj.Value<string>("action"));
Assert.Equal("轨迹订单创建成功", obj.Value<string>("message"));
Assert.Equal(9001, obj.Value<int>("orderId"));
Assert.Equal("IDE001", obj.Value<string>("serviceNo"));
var trackUpsert = obj["trackUpsert"] as JObject;
Assert.NotNull(trackUpsert);
Assert.Equal(200, trackUpsert!.Value<int>("responseStatusCode"));
Assert.Equal(0, trackUpsert["responseBody"]!.Value<int>("code"));
Assert.Equal(1001, trackUpsert["responseBody"]!["data"]!.Value<int>("id"));
}
}