| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- package com.ruoyi.app.user;
- import com.ruoyi.app.user.dto.MerchantSubaccountCreateRequest;
- import com.ruoyi.app.user.dto.StoreAccountsView;
- import com.ruoyi.common.exception.ServiceException;
- import com.ruoyi.common.utils.MessageUtils;
- import com.ruoyi.system.domain.InfoUser;
- import com.ruoyi.system.domain.PosStore;
- import com.ruoyi.system.mapper.PosStoreMapper;
- import com.ruoyi.system.service.IInfoUserService;
- import com.ruoyi.system.service.IMerchantSubaccountStoreService;
- import com.ruoyi.system.service.MerchantStoreAccessService;
- import org.junit.jupiter.api.Test;
- import org.mockito.ArgumentCaptor;
- import org.mockito.MockedStatic;
- import java.util.List;
- import java.util.Set;
- 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.any;
- import static org.mockito.ArgumentMatchers.anyString;
- import static org.mockito.Mockito.doAnswer;
- import static org.mockito.Mockito.mock;
- import static org.mockito.Mockito.mockStatic;
- import static org.mockito.Mockito.verify;
- import static org.mockito.Mockito.when;
- class MerchantSubaccountApplicationServiceTest {
- @Test
- void newSubaccountUsesTelPhoneAsTheBusinessPhoneField() {
- IInfoUserService infoUserService = mock(IInfoUserService.class);
- IMerchantSubaccountStoreService relationService = mock(IMerchantSubaccountStoreService.class);
- MerchantStoreAccessService accessService = mock(MerchantStoreAccessService.class);
- PosStoreMapper posStoreMapper = mock(PosStoreMapper.class);
- MerchantTokenSessionService tokenSessionService = mock(MerchantTokenSessionService.class);
- BusinessPhoneService businessPhoneService = mock(BusinessPhoneService.class);
- MerchantSubaccountApplicationService service = new MerchantSubaccountApplicationService(
- infoUserService, relationService, accessService, posStoreMapper,
- tokenSessionService, businessPhoneService);
- when(accessService.getAccessibleStoreIds(10L)).thenReturn(Set.of(7L));
- when(infoUserService.getinfouserName("0912345678")).thenReturn(null);
- doAnswer(invocation -> {
- InfoUser user = invocation.getArgument(0);
- user.setUserId(20L);
- return 1;
- }).when(infoUserService).insertInfoUser(any(InfoUser.class));
- when(relationService.selectStoreIdsBySubaccountUserId(20L)).thenReturn(List.of());
- MerchantSubaccountCreateRequest request = new MerchantSubaccountCreateRequest();
- request.setPhone("0912345678");
- request.setUserName("store_staff");
- request.setName("分店账号");
- request.setPassword("password");
- request.setStoreIds(List.of(7L));
- var created = service.create(10L, request);
- assertEquals("store_staff", created.getUserName());
- ArgumentCaptor<InfoUser> captor = ArgumentCaptor.forClass(InfoUser.class);
- verify(infoUserService).insertInfoUser(captor.capture());
- assertEquals("store_staff", captor.getValue().getUserName());
- assertEquals("0912345678", captor.getValue().getTelPhone());
- assertNull(captor.getValue().getPhone());
- verify(businessPhoneService).ensureUnique("0912345678", null);
- }
- @Test
- void listStoreAccountsRejectsMissingOrDeletedStore() {
- PosStoreMapper posStoreMapper = mock(PosStoreMapper.class);
- MerchantSubaccountApplicationService service = newService(posStoreMapper);
- when(posStoreMapper.selectPosStoreById(7L)).thenReturn(null);
- PosStore deleted = new PosStore();
- deleted.setDelFlag("1");
- when(posStoreMapper.selectPosStoreById(8L)).thenReturn(deleted);
- try (MockedStatic<MessageUtils> messages = mockStatic(MessageUtils.class)) {
- messages.when(() -> MessageUtils.message(anyString()))
- .thenAnswer(invocation -> invocation.getArgument(0));
- ServiceException missing = assertThrows(ServiceException.class,
- () -> service.listStoreAccounts(7L));
- assertEquals("merchant.store.not.found", missing.getMessage());
- ServiceException deletedStore = assertThrows(ServiceException.class,
- () -> service.listStoreAccounts(8L));
- assertEquals("merchant.store.not.found", deletedStore.getMessage());
- }
- }
- @Test
- void listStoreAccountsReturnsOwnerAndEligibleSubaccountsWithContactFields() {
- IInfoUserService infoUserService = mock(IInfoUserService.class);
- IMerchantSubaccountStoreService relationService = mock(IMerchantSubaccountStoreService.class);
- PosStoreMapper posStoreMapper = mock(PosStoreMapper.class);
- MerchantSubaccountApplicationService service = newService(infoUserService, relationService, posStoreMapper);
- PosStore store = new PosStore();
- store.setDelFlag("0");
- store.setUserId(10L);
- when(posStoreMapper.selectPosStoreById(7L)).thenReturn(store);
- when(infoUserService.selectInfoUserByUserId(10L)).thenReturn(contactUser(10L, "1", "0"));
- when(relationService.selectEligibleSubaccountsByStoreId(7L))
- .thenReturn(List.of(contactUser(20L, "5", "0")));
- StoreAccountsView view = service.listStoreAccounts(7L);
- assertEquals(10L, view.getOwner().getUserId());
- assertEquals("1", view.getOwner().getUserType());
- assertEquals("nick-10", view.getOwner().getNickName());
- assertEquals("tel-10", view.getOwner().getPhone());
- assertEquals("avatar-10", view.getOwner().getAvatar());
- assertEquals("imKey-10", view.getOwner().getImApiKey());
- assertEquals("900010", view.getOwner().getImUserId());
- assertEquals("cid-10", view.getOwner().getCid());
- assertEquals("ios", view.getOwner().getCidType());
- assertEquals("device-10", view.getOwner().getDeviceToken());
- assertEquals("voip-10", view.getOwner().getVoIPToken());
- assertEquals(1, view.getSubaccounts().size());
- assertEquals(20L, view.getSubaccounts().get(0).getUserId());
- assertEquals("5", view.getSubaccounts().get(0).getUserType());
- assertEquals("nick-20", view.getSubaccounts().get(0).getNickName());
- }
- @Test
- void listStoreAccountsOmitsUnavailableOwner() {
- IInfoUserService infoUserService = mock(IInfoUserService.class);
- IMerchantSubaccountStoreService relationService = mock(IMerchantSubaccountStoreService.class);
- PosStoreMapper posStoreMapper = mock(PosStoreMapper.class);
- MerchantSubaccountApplicationService service = newService(infoUserService, relationService, posStoreMapper);
- PosStore store = new PosStore();
- store.setDelFlag("0");
- store.setUserId(10L);
- when(posStoreMapper.selectPosStoreById(7L)).thenReturn(store);
- when(infoUserService.selectInfoUserByUserId(10L)).thenReturn(contactUser(10L, "1", "1"));
- when(relationService.selectEligibleSubaccountsByStoreId(7L)).thenReturn(List.of());
- StoreAccountsView view = service.listStoreAccounts(7L);
- assertNull(view.getOwner());
- assertEquals(List.of(), view.getSubaccounts());
- }
- private MerchantSubaccountApplicationService newService(PosStoreMapper posStoreMapper) {
- return newService(mock(IInfoUserService.class), mock(IMerchantSubaccountStoreService.class), posStoreMapper);
- }
- private MerchantSubaccountApplicationService newService(IInfoUserService infoUserService,
- IMerchantSubaccountStoreService relationService,
- PosStoreMapper posStoreMapper) {
- return new MerchantSubaccountApplicationService(infoUserService, relationService,
- mock(MerchantStoreAccessService.class), posStoreMapper,
- mock(MerchantTokenSessionService.class), mock(BusinessPhoneService.class));
- }
- private InfoUser contactUser(Long userId, String userType, String status) {
- InfoUser user = new InfoUser();
- user.setUserId(userId);
- user.setUserType(userType);
- user.setStatus(status);
- user.setDelFlag("0");
- user.setNickName("nick-" + userId);
- user.setTelPhone("tel-" + userId);
- user.setAvatar("avatar-" + userId);
- user.setImApiKey("imKey-" + userId);
- user.setImUserId(900000L + userId);
- user.setCid("cid-" + userId);
- user.setCidType("ios");
- user.setDeviceToken("device-" + userId);
- user.setVoIPToken("voip-" + userId);
- return user;
- }
- @Test
- void missingUsernameDoesNotFallBackToPhone() {
- var fixture = new UsernameFixture();
- fixture.request.setUserName(" ");
- try (MockedStatic<MessageUtils> messages = mockStatic(MessageUtils.class)) {
- messages.when(() -> MessageUtils.message(anyString())).thenAnswer(i -> i.getArgument(0));
- assertEquals("merchant.subaccount.username.required", assertThrows(ServiceException.class,
- () -> fixture.service.create(10L, fixture.request)).getMessage());
- }
- org.mockito.Mockito.verify(fixture.users, org.mockito.Mockito.never()).insertInfoUser(any());
- }
- @Test
- void usernameCannotCollideWithAnotherAccount() {
- var fixture = new UsernameFixture();
- InfoUser other = new InfoUser(); other.setUserId(99L);
- when(fixture.users.getinfouserName("staff")).thenReturn(other);
- try (MockedStatic<MessageUtils> messages = mockStatic(MessageUtils.class)) {
- messages.when(() -> MessageUtils.message(anyString())).thenAnswer(i -> i.getArgument(0));
- assertEquals("merchant.subaccount.username.exists", assertThrows(ServiceException.class,
- () -> fixture.service.create(10L, fixture.request)).getMessage());
- }
- }
- @Test
- void renameExistingSubaccountPreservesContactAndRevokesSessions() {
- var fixture = new UsernameFixture();
- var request = new com.ruoyi.app.user.dto.MerchantSubaccountUpdateRequest();
- request.setUserName(" new_staff "); request.setStoreIds(List.of(7L));
- var view = fixture.service.update(10L, 20L, request);
- assertEquals("new_staff", view.getUserName());
- assertEquals("0912345678", view.getPhone());
- ArgumentCaptor<InfoUser> update = ArgumentCaptor.forClass(InfoUser.class);
- verify(fixture.users).updateInfoUser(update.capture());
- assertEquals("new_staff", update.getValue().getUserName());
- assertNull(update.getValue().getTelPhone());
- verify(fixture.sessions).revokeAll(20L);
- }
- @Test
- void unchangedUsernameCanBelongToSelfWithoutRevokingSessions() {
- var fixture = new UsernameFixture();
- when(fixture.users.getinfouserName("0912345678")).thenReturn(fixture.target);
- var request = new com.ruoyi.app.user.dto.MerchantSubaccountUpdateRequest();
- request.setUserName("0912345678"); request.setStoreIds(List.of(7L));
- assertEquals("0912345678", fixture.service.update(10L, 20L, request).getUserName());
- org.mockito.Mockito.verify(fixture.sessions, org.mockito.Mockito.never()).revokeAll(20L);
- }
- private static class UsernameFixture {
- final IInfoUserService users = mock(IInfoUserService.class);
- final MerchantTokenSessionService sessions = mock(MerchantTokenSessionService.class);
- final InfoUser target = new InfoUser();
- final MerchantSubaccountCreateRequest request = new MerchantSubaccountCreateRequest();
- final MerchantSubaccountApplicationService service;
- UsernameFixture() {
- var access = mock(MerchantStoreAccessService.class);
- var relations = mock(IMerchantSubaccountStoreService.class);
- service = new MerchantSubaccountApplicationService(users, relations, access,
- mock(PosStoreMapper.class), sessions, mock(BusinessPhoneService.class));
- when(access.getAccessibleStoreIds(10L)).thenReturn(Set.of(7L));
- target.setUserId(20L); target.setUserType("5"); target.setDelFlag("0");
- target.setMerchantOwnerId(10L); target.setUserName("0912345678"); target.setTelPhone("0912345678");
- when(users.selectInfoUserByUserId(20L)).thenReturn(target);
- when(users.updateInfoUser(any())).thenReturn(1);
- request.setUserName("staff"); request.setPhone("0912345678");
- request.setPassword("encrypted-password"); request.setStoreIds(List.of(7L));
- }
- }
- }
|