admin/src/Oms.Application/Services/Orders/OrderService.BatchJob.cs
zzh c02cb21049 feat: add pickup-order model and door-pickup linking
Support 1 pickup to N logistics orders with create/pay/schedule APIs, parcel inboundMethod auto-attach, plus allocation-trace and inbound-billing updates already in tree.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-03 12:22:30 +08:00

220 lines
7.9 KiB
C#

using Fake.Application;
using Fake.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Oms.Application.Dtos.Orders;
using Oms.Application.Dtos.Shared;
using Oms.Application.Services.Orders.Batch;
using Oms.Application.Messaging;
using Oms.Application.Shared;
using Oms.Domain.CustomersAggregate.Repositories;
using Oms.Domain.OrdersAggregate.Consts;
namespace Oms.Application.Services.Orders;
public partial class OrderService
{
private OrderBatchJobCoordinator BatchJobCoordinator =>
LazyServiceProvider.GetRequiredService<OrderBatchJobCoordinator>();
/// <summary>
/// 创建订单批量异步任务并入队 RabbitMQ。
/// </summary>
[HttpPost("/order/batch/jobs")]
public Task<OrderBatchJobOutput> CreateBatchJobAsync([FromBody] OrderBatchJobCreateInput input)
{
return BatchJobCoordinator.CreateAndEnqueueAsync(input, CurrentUser.GetId<int>());
}
/// <summary>
/// 查询批量任务进度。
/// </summary>
[HttpGet("/order/batch/jobs/{id:int}")]
public async Task<OrderBatchJobOutput> GetBatchJobAsync([FromRoute] int id)
{
var job = await BatchJobCoordinator.GetJobAsync(id);
if (job == null)
{
throw new BusinessException("批量任务不存在");
}
return job;
}
/// <summary>
/// 分页查询批量任务列表。
/// </summary>
[HttpGet("/order/batch/jobs")]
public async Task<OmsPageResult<OrderBatchJobOutput>> GetBatchJobListAsync([FromQuery] OrderBatchJobListInput input)
{
var customerId = await OmsSessionHelper.ResolveListCustomerIdAsync(
LazyServiceProvider.GetRequiredService<ICustomerRepository>(),
CurrentUser,
null);
return await BatchJobCoordinator.GetJobListAsync(input, customerId);
}
/// <summary>
/// 查询批量任务子项明细。
/// </summary>
[HttpGet("/order/batch/jobs/{id:int}/items")]
public async Task<List<OrderBatchJobItemOutput>> GetBatchJobItemsAsync([FromRoute] int id)
{
var job = await BatchJobCoordinator.GetJobEntityAsync(id);
if (job == null)
{
throw new BusinessException("批量任务不存在");
}
return await BatchJobCoordinator.GetJobItemsAsync(id);
}
/// <summary>
/// 异步批量创建轨迹订单(替代前端逐条调用)。
/// </summary>
[HttpPost("/order/batch/track-upsert")]
public Task<OrderBatchJobOutput> BatchTrackUpsertAsync([FromBody] OrderBatchJobCreateInput input)
{
input.Action = OrderBatchActionCodes.TrackUpsertSmallBag;
var authorization = LazyServiceProvider
.GetRequiredService<IHttpContextAccessor>()
.HttpContext?
.Request
.Headers
.Authorization
.ToString();
return BatchJobCoordinator.CreateAndEnqueueAsync(
input,
CurrentUser.GetId<int>(),
string.IsNullOrWhiteSpace(authorization) ? null : authorization);
}
/// <summary>
/// 异步批量预报下游订单。
/// </summary>
[HttpPost("/order/batch/downstream-forward")]
public Task<OrderBatchJobOutput> BatchDownstreamForwardAsync([FromBody] OrderBatchJobCreateInput input)
{
input.Action = OrderBatchActionCodes.DownstreamForwardCreateOne;
var authorization = LazyServiceProvider
.GetRequiredService<IHttpContextAccessor>()
.HttpContext?
.Request
.Headers
.Authorization
.ToString();
return BatchJobCoordinator.CreateAndEnqueueAsync(
input,
CurrentUser.GetId<int>(),
string.IsNullOrWhiteSpace(authorization) ? null : authorization);
}
private Task<OrderBatchJobOutput> EnqueueOrderBatchAsync(string action, OrderBatchJobCreateInput input)
{
input.Action = action;
return BatchJobCoordinator.CreateAndEnqueueAsync(input, CurrentUser.GetId<int>());
}
/// <summary>
/// 异步批量支付订单。
/// </summary>
[HttpPost("/order/batch/pay")]
public Task<OrderBatchJobOutput> BatchPayAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.Pay, input);
/// <summary>
/// 异步批量预报订单。
/// </summary>
[HttpPost("/order/batch/pre-declare")]
public Task<OrderBatchJobOutput> BatchPreDeclareAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.PreDeclare, input);
/// <summary>
/// 异步批量拦截订单。
/// </summary>
[HttpPost("/order/batch/intercept")]
public Task<OrderBatchJobOutput> BatchInterceptAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.Intercept, input);
/// <summary>
/// 异步批量取消拦截。
/// </summary>
[HttpPost("/order/batch/cancel-intercept")]
public Task<OrderBatchJobOutput> BatchCancelInterceptAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.CancelIntercept, input);
/// <summary>
/// 异步批量删除订单。
/// </summary>
[HttpPost("/order/batch/delete")]
public Task<OrderBatchJobOutput> BatchDeleteAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.Delete, input);
/// <summary>
/// 异步批量打印面单。
/// </summary>
[HttpPost("/order/batch/print")]
public Task<OrderBatchJobOutput> BatchPrintAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.Print, input);
/// <summary>
/// 异步批量标记问题件。
/// </summary>
[HttpPost("/order/batch/mark-problematic")]
public Task<OrderBatchJobOutput> BatchMarkProblematicAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.MarkProblematic, input);
/// <summary>
/// 异步批量重新排货。
/// </summary>
[HttpPost("/order/batch/reallocate")]
public Task<OrderBatchJobOutput> BatchReallocateAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.Reallocate, input);
/// <summary>
/// 异步批量标记已认领。
/// </summary>
[HttpPost("/order/batch/mark-claimed")]
public Task<OrderBatchJobOutput> BatchMarkClaimedAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.MarkClaimed, input);
/// <summary>
/// 异步批量更新处理状态。
/// </summary>
[HttpPost("/order/batch/handle-status-update")]
public Task<OrderBatchJobOutput> BatchHandleStatusUpdateAsync([FromBody] OrderBatchJobCreateInput input) =>
EnqueueOrderBatchAsync(OrderBatchActionCodes.HandleStatusUpdate, input);
/// <summary>
/// 查询 RabbitMQ 队列与 DLX 堆积情况。
/// </summary>
[HttpGet("/order/batch/dlx/stats")]
public Task<OrderBatchDlxStatsOutput> GetBatchDlxStatsAsync()
{
var inspector = LazyServiceProvider.GetRequiredService<IOrderBatchQueueInspector>();
return inspector.GetStatsAsync();
}
/// <summary>
/// 重新投递失败子项。
/// </summary>
[HttpPost("/order/batch/jobs/{id:int}/retry-failed")]
public Task<OrderBatchJobManageOutput> RetryFailedBatchJobAsync(
[FromRoute] int id,
[FromBody] OrderBatchJobRetryFailedInput? input)
{
return BatchJobCoordinator.RetryFailedAsync(id, input, CurrentUser.GetId<int>());
}
/// <summary>
/// 取消尚未执行的 pending 子项。
/// </summary>
[HttpPost("/order/batch/jobs/{id:int}/cancel")]
public Task<OrderBatchJobManageOutput> CancelBatchJobAsync([FromRoute] int id)
{
return BatchJobCoordinator.CancelPendingAsync(id, CurrentUser.GetId<int>());
}
}