订单批量审核提交

This commit is contained in:
2026-08-07 14:52:21 +08:00
parent 0dc60d835b
commit 77dc32a69a
5 changed files with 131 additions and 0 deletions
@@ -3,7 +3,9 @@ package com.baiyue.order.controller;
import com.baiyue.common.audit.BusinessAudit;
import com.baiyue.common.core.api.ApiResponse;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.common.core.exception.BizException;
import com.baiyue.common.security.AuthenticatedUser;
import com.baiyue.order.dto.BatchOrderReviewResponse;
import com.baiyue.order.dto.OrderDetailResponse;
import com.baiyue.order.dto.OrderRequests;
import com.baiyue.order.dto.TenantOrderCountResponse;
@@ -28,6 +30,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.PutMapping;
import java.util.ArrayList;
import java.util.List;
/**
@@ -155,6 +158,18 @@ public class PlatformFirstLegOrderController {
return transit(user, tenantId, id, OrderStatus.APPROVED, null);
}
@BusinessAudit(event = "ORDER_BATCH_APPROVE", resourceType = "FIRST_LEG_ORDER_BATCH",
resourceId = "#request.orderIds", tenantId = "#tenantId", description = "批量审核通过订单")
@Operation(summary = "批量审核通过订单", description = "单租户模式下逐单独立审核,返回成功和失败明细。")
@PostMapping("/batch-approve")
@PreAuthorize("hasAuthority('platform:order:approve')")
public ApiResponse<BatchOrderReviewResponse> batchApprove(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam long tenantId,
@Valid @RequestBody OrderRequests.BatchReviewRequest request) {
return batchTransit(user, tenantId, request.orderIds(), OrderStatus.APPROVED, null);
}
@BusinessAudit(event = "ORDER_ASSIGN_CARRIER", resourceType = "FIRST_LEG_ORDER", resourceId = "#id", description = "指派订单承运商")
@Operation(summary = "指派承运商", description = "可选地为待审核订单选择启用的公共承运商,名称快照由服务端主数据回填;该动作不是审核前置条件。")
@PutMapping("/{id}/carrier")
@@ -179,6 +194,18 @@ public class PlatformFirstLegOrderController {
return transit(user, tenantId, id, OrderStatus.REJECTED, request.reason());
}
@BusinessAudit(event = "ORDER_BATCH_REJECT", resourceType = "FIRST_LEG_ORDER_BATCH",
resourceId = "#request.orderIds", tenantId = "#tenantId", description = "批量驳回订单")
@Operation(summary = "批量驳回订单", description = "单租户模式下使用统一原因逐单独立驳回,返回成功和失败明细。")
@PostMapping("/batch-reject")
@PreAuthorize("hasAuthority('platform:order:reject')")
public ApiResponse<BatchOrderReviewResponse> batchReject(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam long tenantId,
@Valid @RequestBody OrderRequests.BatchRejectRequest request) {
return batchTransit(user, tenantId, request.orderIds(), OrderStatus.REJECTED, request.reason());
}
@BusinessAudit(event = "ORDER_ACCEPT", resourceType = "FIRST_LEG_ORDER", resourceId = "#id", description = "Accept order / 受理订单")
@Operation(summary = "Accept / 受理订单", description = "Accepts an approved order for fulfillment processing. / 受理已审核通过的订单,进入履约处理。")
@PostMapping("/{id}/accept")
@@ -255,4 +282,22 @@ public class PlatformFirstLegOrderController {
);
return ApiResponse.success(null);
}
private ApiResponse<BatchOrderReviewResponse> batchTransit(
AuthenticatedUser user, long tenantId, List<Long> orderIds, OrderStatus target, String reason) {
long scopedTenantId = OrderScopeGuard.platform(user, tenantId);
List<Long> successOrderIds = new ArrayList<>();
List<BatchOrderReviewResponse.FailedOrder> failedOrders = new ArrayList<>();
for (Long orderId : orderIds) {
try {
service.transit(scopedTenantId, user.userId(), user.username(), orderId, target, reason);
successOrderIds.add(orderId);
} catch (BizException exception) {
failedOrders.add(new BatchOrderReviewResponse.FailedOrder(
orderId, exception.getResultCode().code(), exception.getMessage()));
}
}
return ApiResponse.success(new BatchOrderReviewResponse(orderIds.size(), successOrderIds.size(),
failedOrders.size(), List.copyOf(successOrderIds), List.copyOf(failedOrders)));
}
}
@@ -0,0 +1,23 @@
package com.baiyue.order.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
/** 单租户订单批量审核结果。 */
@Schema(description = "订单批量审核结果")
public record BatchOrderReviewResponse(
@Schema(description = "请求订单总数") int total,
@Schema(description = "成功数量") int successCount,
@Schema(description = "失败数量") int failureCount,
@Schema(description = "成功订单 ID") List<Long> successOrderIds,
@Schema(description = "失败订单及原因") List<FailedOrder> failedOrders
) {
@Schema(description = "单笔失败结果")
public record FailedOrder(
@Schema(description = "订单 ID") long orderId,
@Schema(description = "业务错误码") String code,
@Schema(description = "失败原因") String message
) {
}
}
@@ -166,6 +166,30 @@ public final class OrderRequests {
) {
}
@Schema(name = "FirstLegOrderBatchReviewRequest", description = "单租户订单批量审核请求")
public record BatchReviewRequest(
@Schema(description = "订单 ID 列表,单次最多 100 条", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty @Size(max = 100) List<@NotNull @Min(1) Long> orderIds
) {
@AssertTrue(message = "订单 ID 不能重复")
public boolean hasDistinctOrderIds() {
return orderIds == null || orderIds.size() == orderIds.stream().distinct().count();
}
}
@Schema(name = "FirstLegOrderBatchRejectRequest", description = "单租户订单批量驳回请求")
public record BatchRejectRequest(
@Schema(description = "订单 ID 列表,单次最多 100 条", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty @Size(max = 100) List<@NotNull @Min(1) Long> orderIds,
@Schema(description = "统一驳回原因", maxLength = 500, requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank @Size(max = 500) String reason
) {
@AssertTrue(message = "订单 ID 不能重复")
public boolean hasDistinctOrderIds() {
return orderIds == null || orderIds.size() == orderIds.stream().distinct().count();
}
}
@Schema(name = "OrderInternalNoteRequest", description = "Platform internal order note / 平台内部订单备注")
public record NoteRequest(
@Schema(description = "Internal note content / 内部备注内容", example = "Customer confirmed the shipping schedule / 客户已确认船期", maxLength = 2000, requiredMode = Schema.RequiredMode.REQUIRED)