This commit is contained in:
2026-08-06 11:49:51 +08:00
parent a11e47fe3b
commit 7dd92f1c84
91 changed files with 6233 additions and 174 deletions
@@ -61,8 +61,8 @@ public class PlatformFirstLegOrderController {
return ApiResponse.success(service.createDraft(scopedTenant, user.userId(), request, idempotencyKey));
}
@BusinessAudit(event = "ORDER_UPDATE", resourceType = "FIRST_LEG_ORDER", resourceId = "#id", description = "平台编辑草稿")
@Operation(summary = "平台编辑草稿", description = "在明确指定的目标租户内编辑草稿或驳回订单。")
@BusinessAudit(event = "ORDER_UPDATE", resourceType = "FIRST_LEG_ORDER", resourceId = "#id", description = "平台编辑订单资料")
@Operation(summary = "平台编辑订单", description = "在待审核阶段编辑订单资料;编辑不会将订单退回草稿状态。")
@ApiResponses({
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "200", description = "编辑成功"),
@io.swagger.v3.oas.annotations.responses.ApiResponse(responseCode = "403", description = "无平台编辑权限"),
@@ -75,7 +75,7 @@ public class PlatformFirstLegOrderController {
@Parameter(description = "订单 ID", required = true) @PathVariable long id,
@Valid @RequestBody OrderRequests.SaveRequest request) {
long scopedTenant = OrderScopeGuard.platform(user, tenantId);
service.updateDraft(scopedTenant, user.userId(), id, request);
service.updateSubmittedOrder(scopedTenant, user.userId(), id, request);
return ApiResponse.success(null);
}
@@ -60,16 +60,37 @@ public class OrderApplicationService {
@Transactional
public void updateDraft(long tenantId, long userId, long id, OrderRequests.SaveRequest request) {
updateOrderData(tenantId, userId, id, request, false);
}
/**
* 平台审核队列中的订单仍允许编辑。编辑只更新订单资料,不回退已提交订单的主状态。
* 商户端继续使用 {@link #updateDraft(long, long, long, OrderRequests.SaveRequest)},
* 因此不会因为该兼容能力意外获得已提交订单的编辑权限。
*/
@Transactional
public void updateSubmittedOrder(long tenantId, long userId, long id, OrderRequests.SaveRequest request) {
updateOrderData(tenantId, userId, id, request, true);
}
private void updateOrderData(long tenantId, long userId, long id, OrderRequests.SaveRequest request,
boolean allowSubmitted) {
OrderEntity order = require(tenantId, id);
validatePrototypeFields(request);
var snapshots = masterDataGuard.validate(tenantId, request);
if (order.getStatus() != OrderStatus.DRAFT && order.getStatus() != OrderStatus.REJECTED) {
throw new BizException("Only draft or rejected orders can be edited");
OrderStatus before = order.getStatus();
if (before != OrderStatus.DRAFT && before != OrderStatus.REJECTED
&& !(allowSubmitted && before == OrderStatus.SUBMITTED)) {
throw new BizException("当前订单状态不允许编辑订单资料");
}
apply(order, request, snapshots); order.setStatus(OrderStatus.DRAFT); order.setUpdatedBy(userId);
if (before == OrderStatus.SUBMITTED) {
order.setStatus(OrderStatus.SUBMITTED);
}
if (repository.saveOrder(tenantId, order) != 1) throw new BizException("Concurrent order update");
repository.replaceDraftChildren(tenantId, id);
saveChildren(tenantId, userId, id, request);
record(tenantId, id, before, order.getStatus(), "UPDATE", null, userId, null);
}
@Transactional
@@ -78,6 +78,48 @@ class OrderApplicationServiceStateTest {
verify(repository).saveOrder(eq(10001L), argThat(saved -> saved.getStatus() == OrderStatus.DRAFT));
}
@Test
void platformCanEditSubmittedOrderWithoutRollingBackReviewStatus() {
OrderRepository repository = mock(OrderRepository.class);
OrderMasterDataGuard masterData = mock(OrderMasterDataGuard.class);
OrderRequests.SaveRequest request = request();
OrderEntity order = new OrderEntity();
order.setId(1L);
order.setTenantId(10001L);
order.setStatus(OrderStatus.SUBMITTED);
when(repository.findOwned(10001L, 1L)).thenReturn(order);
when(masterData.validate(10001L, request)).thenReturn(snapshots());
when(repository.saveOrder(10001L, order)).thenReturn(1);
service(repository, mock(OrderEligibilityGuard.class), masterData)
.updateSubmittedOrder(10001L, 2L, 1L, request);
assertThat(order.getStatus()).isEqualTo(OrderStatus.SUBMITTED);
verify(repository).replaceDraftChildren(10001L, 1L);
verify(repository).insertHistory(argThat(history -> history.getFromStatus() == OrderStatus.SUBMITTED
&& history.getToStatus() == OrderStatus.SUBMITTED
&& "UPDATE".equals(history.getAction())));
}
@Test
void merchantDraftEditorStillCannotEditSubmittedOrder() {
OrderRepository repository = mock(OrderRepository.class);
OrderEntity order = new OrderEntity();
order.setId(1L);
order.setTenantId(10001L);
order.setStatus(OrderStatus.SUBMITTED);
when(repository.findOwned(10001L, 1L)).thenReturn(order);
OrderMasterDataGuard masterData = mock(OrderMasterDataGuard.class);
when(masterData.validate(eq(10001L), any(OrderRequests.SaveRequest.class))).thenReturn(snapshots());
assertThatThrownBy(() -> service(repository, mock(OrderEligibilityGuard.class), masterData)
.updateDraft(10001L, 2L, 1L, request()))
.isInstanceOf(BizException.class)
.hasMessageContaining("不允许编辑");
verify(repository, never()).saveOrder(anyLong(), any());
}
@Test
void unapprovedTenantStillCannotSubmitDraft() {
OrderRepository repository = mock(OrderRepository.class);