feat(order): 新增管理端完成订单能力(店员端触发)
Some checks failed
Build and Push Backend / docker (push) Failing after 6s

- OrderConstant 新增角色 GROUP_LEADER、触发源 WX_CLERK_MGMT;补充映射
- IPlayOrderInfoService 新增 completeOrderByManagement 方法
- PlayOrderInfoServiceImpl:校验权限(仅运营/组长,组长仅限本组);ACCEPTED 自动切换为 IN_PROGRESS 后完成;抽取 completeOrderInternal;完善 GROUP_LEADER 的 Actor/Source 映射
- WxClerkController 新增 POST /wx/clerk/order/complete 接口,支持备注参数
- 新增请求体 PlayOrderCompleteVo
- 新增单测 PlayOrderInfoServiceImplTest 覆盖核心流程与边界
This commit is contained in:
irving
2025-11-01 15:07:59 -04:00
parent 16ea9b9d48
commit b1fd515fb3
7 changed files with 331 additions and 26 deletions

View File

@@ -0,0 +1,144 @@
package com.starry.admin.modules.order.service.impl;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.starry.admin.common.exception.CustomException;
import com.starry.admin.modules.clerk.module.entity.PlayClerkUserInfoEntity;
import com.starry.admin.modules.clerk.service.IPlayClerkUserInfoService;
import com.starry.admin.modules.order.mapper.PlayOrderInfoMapper;
import com.starry.admin.modules.order.module.constant.OrderConstant.OperatorType;
import com.starry.admin.modules.order.module.constant.OrderConstant.OrderActor;
import com.starry.admin.modules.order.module.constant.OrderConstant.OrderStatus;
import com.starry.admin.modules.order.module.constant.OrderConstant.OrderTriggerSource;
import com.starry.admin.modules.order.module.dto.OrderCompletionContext;
import com.starry.admin.modules.order.module.entity.PlayOrderInfoEntity;
import com.starry.admin.modules.order.service.IOrderLifecycleService;
import com.starry.admin.modules.personnel.module.entity.PlayPersonnelGroupInfoEntity;
import com.starry.admin.modules.personnel.service.IPlayPersonnelGroupInfoService;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class PlayOrderInfoServiceImplTest {
@InjectMocks
private PlayOrderInfoServiceImpl service;
@Mock
private PlayOrderInfoMapper baseMapper;
@Mock
private IPlayClerkUserInfoService playClerkUserInfoService;
@Mock
private IPlayPersonnelGroupInfoService playClerkGroupInfoService;
@Mock
private IOrderLifecycleService orderLifecycleService;
@Test
void completeOrderByManagement_allowsAdmin() {
PlayOrderInfoEntity order = new PlayOrderInfoEntity();
order.setId("order-1");
order.setOrderStatus(OrderStatus.IN_PROGRESS.getCode());
when(baseMapper.selectById("order-1")).thenReturn(order);
String remark = "人工完成";
service.completeOrderByManagement(OperatorType.ADMIN.getCode(), "sys-admin", order.getId(), remark);
ArgumentCaptor<OrderCompletionContext> captor = ArgumentCaptor.forClass(OrderCompletionContext.class);
verify(orderLifecycleService).completeOrder(eq(order.getId()), captor.capture());
OrderCompletionContext context = captor.getValue();
assertEquals(OrderActor.ADMIN, context.getOperatorActor());
assertEquals("sys-admin", context.getOperatorId());
assertEquals(OrderTriggerSource.WX_CLERK_MGMT, context.getTriggerSource());
assertEquals(remark, context.getComment());
}
@Test
void completeOrderByManagement_deniesLeaderOutsideGroup() {
PlayOrderInfoEntity order = new PlayOrderInfoEntity();
order.setId("order-2");
order.setOrderStatus(OrderStatus.IN_PROGRESS.getCode());
order.setGroupId("group-A");
when(baseMapper.selectById("order-2")).thenReturn(order);
PlayClerkUserInfoEntity leader = new PlayClerkUserInfoEntity();
leader.setId("leader-clerk");
leader.setSysUserId("leader-sys");
when(playClerkUserInfoService.getById("leader-clerk")).thenReturn(leader);
PlayPersonnelGroupInfoEntity leaderGroup = new PlayPersonnelGroupInfoEntity();
leaderGroup.setId("group-B");
when(playClerkGroupInfoService.selectByUserId("leader-sys")).thenReturn(leaderGroup);
assertThrows(
CustomException.class,
() -> service.completeOrderByManagement(
OperatorType.GROUP_LEADER.getCode(), "leader-clerk", order.getId(), null));
verify(orderLifecycleService, never()).completeOrder(eq(order.getId()), any());
}
@Test
void completeOrderByManagement_allowsLeaderInGroup() {
PlayOrderInfoEntity order = new PlayOrderInfoEntity();
order.setId("order-3");
order.setOrderStatus(OrderStatus.IN_PROGRESS.getCode());
order.setGroupId("group-C");
order.setAcceptBy("clerk-accepted");
when(baseMapper.selectById("order-3")).thenReturn(order);
PlayClerkUserInfoEntity leader = new PlayClerkUserInfoEntity();
leader.setId("leader-clerk");
leader.setSysUserId("leader-sys");
when(playClerkUserInfoService.getById("leader-clerk")).thenReturn(leader);
PlayPersonnelGroupInfoEntity leaderGroup = new PlayPersonnelGroupInfoEntity();
leaderGroup.setId("group-C");
when(playClerkGroupInfoService.selectByUserId("leader-sys")).thenReturn(leaderGroup);
service.completeOrderByManagement(
OperatorType.GROUP_LEADER.getCode(), "leader-clerk", order.getId(), null);
ArgumentCaptor<OrderCompletionContext> captor = ArgumentCaptor.forClass(OrderCompletionContext.class);
verify(orderLifecycleService).completeOrder(eq(order.getId()), captor.capture());
OrderCompletionContext context = captor.getValue();
assertEquals(OrderActor.GROUP_LEADER, context.getOperatorActor());
assertEquals("leader-clerk", context.getOperatorId());
assertEquals(OrderTriggerSource.WX_CLERK_MGMT, context.getTriggerSource());
assertNull(context.getComment());
}
@Test
void completeOrderByManagement_promotesAcceptedToInProgress() {
PlayOrderInfoEntity accepted = new PlayOrderInfoEntity();
accepted.setId("order-4");
accepted.setOrderStatus(OrderStatus.ACCEPTED.getCode());
PlayOrderInfoEntity inProgress = new PlayOrderInfoEntity();
inProgress.setId("order-4");
inProgress.setOrderStatus(OrderStatus.IN_PROGRESS.getCode());
when(baseMapper.selectById("order-4")).thenReturn(accepted, inProgress);
service.completeOrderByManagement(OperatorType.ADMIN.getCode(), "sys-admin", accepted.getId(), null);
ArgumentCaptor<PlayOrderInfoEntity> updateCaptor = ArgumentCaptor.forClass(PlayOrderInfoEntity.class);
verify(baseMapper).updateById(updateCaptor.capture());
PlayOrderInfoEntity updateEntity = updateCaptor.getValue();
assertEquals(OrderStatus.IN_PROGRESS.getCode(), updateEntity.getOrderStatus());
ArgumentCaptor<OrderCompletionContext> completionCaptor = ArgumentCaptor.forClass(OrderCompletionContext.class);
verify(orderLifecycleService).completeOrder(eq(accepted.getId()), completionCaptor.capture());
assertEquals(OrderTriggerSource.WX_CLERK_MGMT, completionCaptor.getValue().getTriggerSource());
}
}