package com.ruoyi.account.service.impl;
|
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
import com.ruoyi.account.api.dto.AppUserWhitelistAllocateDTO;
|
import com.ruoyi.account.api.dto.AppUserWhitelistAllocateItemDTO;
|
import com.ruoyi.account.api.dto.AppUserWhitelistStatusDTO;
|
import com.ruoyi.account.api.model.TAppUser;
|
import com.ruoyi.account.api.model.TAppUserWhitelist;
|
import com.ruoyi.account.api.model.TCompanyAllocateRecord;
|
import com.ruoyi.account.api.vo.AppUserWhitelistAllocateVO;
|
import com.ruoyi.account.api.vo.AppUserWhitelistImportResultVO;
|
import com.ruoyi.account.api.vo.AppUserWhitelistMatchVO;
|
import com.ruoyi.account.mapper.TAppUserWhitelistMapper;
|
import com.ruoyi.account.service.PartnerAppUserAccessService;
|
import com.ruoyi.account.service.TAppUserService;
|
import com.ruoyi.account.service.TAppUserWhitelistSiteService;
|
import com.ruoyi.account.service.TCompanyAllocateRecordService;
|
import com.ruoyi.chargingPile.api.feignClient.PartnerClient;
|
import com.ruoyi.chargingPile.api.feignClient.SiteClient;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.exception.ServiceException;
|
import com.ruoyi.common.security.service.TokenService;
|
import com.ruoyi.other.api.domain.TGroupCompany;
|
import com.ruoyi.other.api.feignClient.GroupCompanyClient;
|
import com.ruoyi.system.api.feignClient.SysUserClient;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.mockito.ArgumentCaptor;
|
import org.mockito.Mock;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.redisson.api.RLock;
|
import org.redisson.api.RedissonClient;
|
import org.springframework.mock.web.MockMultipartFile;
|
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.TransactionStatus;
|
|
import java.io.ByteArrayOutputStream;
|
import java.math.BigDecimal;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.atomic.AtomicLong;
|
|
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.junit.jupiter.api.Assertions.assertTrue;
|
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.anyCollection;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.isNull;
|
import static org.mockito.Mockito.doAnswer;
|
import static org.mockito.Mockito.doThrow;
|
import static org.mockito.Mockito.lenient;
|
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.when;
|
|
@ExtendWith(MockitoExtension.class)
|
class TAppUserWhitelistServiceImplTest {
|
@Mock private TAppUserWhitelistMapper mapper;
|
@Mock private TAppUserWhitelistSiteService whitelistSiteService;
|
@Mock private TAppUserService appUserService;
|
@Mock private SiteClient siteClient;
|
@Mock private PartnerClient partnerClient;
|
@Mock private TokenService tokenService;
|
@Mock private SysUserClient sysUserClient;
|
@Mock private PlatformTransactionManager transactionManager;
|
@Mock private GroupCompanyClient groupCompanyClient;
|
@Mock private RedissonClient redissonClient;
|
@Mock private TCompanyAllocateRecordService companyAllocateRecordService;
|
@Mock private PartnerAppUserAccessService partnerAppUserAccessService;
|
|
private TAppUserWhitelistServiceImpl service;
|
|
@BeforeAll
|
static void initTableInfo() {
|
// MP 的 lambdaUpdate 会通过 TableInfoHelper.getTableInfo 取表元数据,
|
// 单元测试不启动 Spring,需要手动初始化 TableInfo,否则抛 MybatisPlusException
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), TAppUserWhitelist.class);
|
}
|
|
@BeforeEach
|
void setUp() {
|
service = new TAppUserWhitelistServiceImpl();
|
ReflectionTestUtils.setField(service, "baseMapper", mapper);
|
ReflectionTestUtils.setField(service, "whitelistSiteService", whitelistSiteService);
|
ReflectionTestUtils.setField(service, "appUserService", appUserService);
|
ReflectionTestUtils.setField(service, "siteClient", siteClient);
|
ReflectionTestUtils.setField(service, "partnerClient", partnerClient);
|
ReflectionTestUtils.setField(service, "tokenService", tokenService);
|
ReflectionTestUtils.setField(service, "sysUserClient", sysUserClient);
|
ReflectionTestUtils.setField(service, "transactionManager", transactionManager);
|
ReflectionTestUtils.setField(service, "groupCompanyClient", groupCompanyClient);
|
ReflectionTestUtils.setField(service, "redissonClient", redissonClient);
|
ReflectionTestUtils.setField(service, "companyAllocateRecordService", companyAllocateRecordService);
|
ReflectionTestUtils.setField(service, "partnerAppUserAccessService", partnerAppUserAccessService);
|
// 默认透传(模拟非公司账号),公司账号隔离场景由具体用例覆盖打桩
|
lenient().when(partnerAppUserAccessService.resolveCompanyFilter(any())).thenAnswer(invocation -> invocation.getArgument(0));
|
lenient().when(partnerAppUserAccessService.getCurrentCompanyId()).thenReturn(null);
|
RLock lock = mock(RLock.class);
|
// 并发锁仅在额度相关场景使用,宽松桩避免严格模式下未使用即报错
|
lenient().when(redissonClient.getLock(any())).thenReturn(lock);
|
try {
|
lenient().when(lock.tryLock(anyLong(), anyLong(), any(TimeUnit.class))).thenReturn(true);
|
} catch (InterruptedException exception) {
|
throw new IllegalStateException(exception);
|
}
|
}
|
|
@Test
|
void importsValidRowsAndReturnsOnlyInvalidRows() throws Exception {
|
when(mapper.selectValidByPhone(any())).thenReturn(null);
|
TransactionStatus transactionStatus = mock(TransactionStatus.class);
|
when(transactionManager.getTransaction(any())).thenReturn(transactionStatus);
|
LambdaQueryChainWrapper<TAppUser> appUserQuery = mock(LambdaQueryChainWrapper.class);
|
when(appUserService.lambdaQuery()).thenReturn(appUserQuery);
|
when(appUserQuery.eq(any(), any())).thenReturn(appUserQuery);
|
when(appUserQuery.last(any())).thenReturn(appUserQuery);
|
when(appUserQuery.one()).thenReturn(null);
|
AtomicLong ids = new AtomicLong(1L);
|
doAnswer(invocation -> {
|
TAppUserWhitelist whitelist = invocation.getArgument(0);
|
whitelist.setId(ids.getAndIncrement());
|
return 1;
|
}).when(mapper).insert(any(TAppUserWhitelist.class));
|
|
AppUserWhitelistImportResultVO result = service.importWhitelist(importFile());
|
|
assertEquals(4, result.getTotalCount());
|
assertEquals(3, result.getSuccessCount());
|
assertEquals(1, result.getErrorCount());
|
assertEquals("1234", result.getErrorMessage().get(0).getPhone());
|
org.mockito.ArgumentCaptor<TAppUserWhitelist> captor = org.mockito.ArgumentCaptor.forClass(TAppUserWhitelist.class);
|
verify(mapper, org.mockito.Mockito.times(3)).insert(captor.capture());
|
for (TAppUserWhitelist saved : captor.getAllValues()) {
|
// 导入统一按默认值写入:全部电站 + 启用;白名单权益已下线,不再写入享受权益,忽略模板中的享受权益/白名单电站列
|
assertEquals(null, saved.getBenefitType());
|
assertEquals(1, saved.getScopeType().intValue());
|
assertEquals(1, saved.getStatus().intValue());
|
}
|
}
|
|
// ---------------- unbindFleet ----------------
|
|
@Test
|
void unbindFleetRejectsNullOrEmptyIds() {
|
ServiceException nullEx = assertThrows(ServiceException.class, () -> service.unbindFleet(null));
|
assertEquals("请选择需要解绑车队的白名单用户", nullEx.getMessage());
|
|
ServiceException emptyEx = assertThrows(ServiceException.class, () -> service.unbindFleet(Collections.emptyList()));
|
assertEquals("请选择需要解绑车队的白名单用户", emptyEx.getMessage());
|
}
|
|
@Test
|
void unbindFleetRejectsMissingRecords() {
|
TAppUserWhitelist existing = new TAppUserWhitelist();
|
existing.setId(1L);
|
when(mapper.selectBatchIds(anyCollection())).thenReturn(Collections.singletonList(existing));
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.unbindFleet(Arrays.asList(1L, 2L)));
|
|
assertEquals("部分白名单用户不存在或已删除", exception.getMessage());
|
verify(mapper, never()).update(isNull(), any(Wrapper.class));
|
}
|
|
@Test
|
void unbindFleetClearsFleetIdAndIgnoresUnboundRecords() {
|
TAppUserWhitelist bound = new TAppUserWhitelist();
|
bound.setId(1L);
|
bound.setFleetId(5);
|
TAppUserWhitelist unbound = new TAppUserWhitelist();
|
unbound.setId(2L);
|
when(mapper.selectBatchIds(anyCollection())).thenReturn(Arrays.asList(bound, unbound));
|
when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(1);
|
|
int result = service.unbindFleet(Arrays.asList(1L, 2L, 2L, null));
|
|
assertEquals(1, result);
|
ArgumentCaptor<Wrapper> wrapperCaptor = ArgumentCaptor.forClass(Wrapper.class);
|
verify(mapper).update(isNull(), wrapperCaptor.capture());
|
String sqlSet = wrapperCaptor.getValue().getSqlSet();
|
assertTrue(sqlSet.contains("fleet_id="));
|
assertTrue(sqlSet.contains("update_by="));
|
// 实现使用 setSql("update_time = now()"),SQL 片段不带列名与等号紧邻的写法
|
assertTrue(sqlSet.contains("update_time = now()"));
|
}
|
|
@Test
|
void unbindFleetReturnsZeroWhenAllUnbound() {
|
TAppUserWhitelist unbound = new TAppUserWhitelist();
|
unbound.setId(1L);
|
when(mapper.selectBatchIds(anyCollection())).thenReturn(Collections.singletonList(unbound));
|
|
int result = service.unbindFleet(Collections.singletonList(1L));
|
|
assertEquals(0, result);
|
verify(mapper, never()).update(isNull(), any(Wrapper.class));
|
}
|
|
// ---------------- 白名单匹配(含公司/车队归属) ----------------
|
|
@Test
|
void matchWhitelistReturnsCompanyAndFleetOwnership() {
|
TAppUser appUser = new TAppUser();
|
appUser.setId(100L);
|
appUser.setPhone("13540211236");
|
when(appUserService.getById(100L)).thenReturn(appUser);
|
|
TAppUserWhitelist whitelist = new TAppUserWhitelist();
|
whitelist.setId(88L);
|
whitelist.setPhone("13540211236");
|
whitelist.setStatus(1);
|
whitelist.setBenefitType(1);
|
whitelist.setScopeType(1);
|
whitelist.setCompanyId(12);
|
whitelist.setFleetId(3);
|
when(mapper.selectOne(any(Wrapper.class))).thenReturn(whitelist);
|
|
AppUserWhitelistMatchVO result = service.matchWhitelist(100L, 2001);
|
|
assertTrue(result.getMatched());
|
assertEquals(12, result.getCompanyId());
|
assertEquals(3, result.getFleetId());
|
// 白名单权益已下线:历史数据的享受权益不再回传给调用方,充电完全按企业优惠结算
|
assertEquals(null, result.getBenefitType());
|
assertEquals(null, result.getBenefitName());
|
}
|
|
@Test
|
void matchWhitelistReturnsNullOwnershipWhenUnassigned() {
|
TAppUser appUser = new TAppUser();
|
appUser.setId(100L);
|
appUser.setPhone("13540211236");
|
when(appUserService.getById(100L)).thenReturn(appUser);
|
|
TAppUserWhitelist whitelist = new TAppUserWhitelist();
|
whitelist.setId(88L);
|
whitelist.setPhone("13540211236");
|
whitelist.setStatus(1);
|
whitelist.setBenefitType(2);
|
whitelist.setScopeType(1);
|
when(mapper.selectOne(any(Wrapper.class))).thenReturn(whitelist);
|
|
AppUserWhitelistMatchVO result = service.matchWhitelist(100L, 2001);
|
|
assertTrue(result.getMatched());
|
assertEquals(null, result.getCompanyId());
|
assertEquals(null, result.getFleetId());
|
}
|
|
// ---------------- 白名单账户可用余额解析(充电页余额显示) ----------------
|
|
@Test
|
void resolveWhitelistAccountBalanceReturnsCompanyBalanceForSharedMode() {
|
TGroupCompany company = new TGroupCompany();
|
company.setAccountMode(1);
|
company.setAvailableBalance(new BigDecimal("500.50"));
|
when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company));
|
|
AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
|
match.setMatched(true);
|
match.setCompanyId(12);
|
match.setBalance(new BigDecimal("100.00"));
|
|
BigDecimal result = service.resolveWhitelistAccountBalance(match);
|
|
assertEquals(new BigDecimal("500.50"), result);
|
}
|
|
@Test
|
void resolveWhitelistAccountBalanceReturnsWhitelistBalanceForAllocationMode() {
|
TGroupCompany company = new TGroupCompany();
|
company.setAccountMode(2);
|
company.setAvailableBalance(new BigDecimal("500.50"));
|
when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company));
|
|
AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
|
match.setMatched(true);
|
match.setCompanyId(12);
|
match.setBalance(new BigDecimal("100.00"));
|
|
BigDecimal result = service.resolveWhitelistAccountBalance(match);
|
|
assertEquals(new BigDecimal("100.00"), result);
|
}
|
|
@Test
|
void resolveWhitelistAccountBalanceTreatsNullAccountModeAsShared() {
|
TGroupCompany company = new TGroupCompany();
|
company.setAccountMode(null);
|
company.setAvailableBalance(new BigDecimal("500.50"));
|
when(groupCompanyClient.getCompanyById(12)).thenReturn(R.ok(company));
|
|
AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
|
match.setMatched(true);
|
match.setCompanyId(12);
|
match.setBalance(new BigDecimal("100.00"));
|
|
BigDecimal result = service.resolveWhitelistAccountBalance(match);
|
|
assertEquals(new BigDecimal("500.50"), result);
|
}
|
|
@Test
|
void resolveWhitelistAccountBalanceReturnsNullWhenCompanyQueryFails() {
|
when(groupCompanyClient.getCompanyById(12)).thenReturn(R.fail("公司信息查询失败"));
|
|
AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
|
match.setMatched(true);
|
match.setCompanyId(12);
|
match.setBalance(new BigDecimal("100.00"));
|
|
BigDecimal result = service.resolveWhitelistAccountBalance(match);
|
|
assertNull(result);
|
}
|
|
@Test
|
void resolveWhitelistAccountBalanceReturnsNullWhenNotMatched() {
|
AppUserWhitelistMatchVO match = new AppUserWhitelistMatchVO();
|
match.setMatched(false);
|
|
BigDecimal result = service.resolveWhitelistAccountBalance(match);
|
|
assertNull(result);
|
}
|
|
// ---------------- 额度分配 ----------------
|
|
@Test
|
void getAllocateOverviewNormalizesAmounts() {
|
TGroupCompany company = allocationCompany(9, "测试公司");
|
company.setAvailableBalance(new BigDecimal("8420.5"));
|
company.setTotalRechargeAmount(null);
|
when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(company));
|
|
AppUserWhitelistAllocateVO overview = service.getAllocateOverview(9);
|
|
assertEquals(Integer.valueOf(9), overview.getCompanyId());
|
assertEquals("测试公司", overview.getCompanyName());
|
assertEquals(Integer.valueOf(2), overview.getAccountMode());
|
assertEquals(new BigDecimal("8420.50"), overview.getAvailableBalance());
|
assertEquals(new BigDecimal("0.00"), overview.getTotalRechargeAmount());
|
}
|
|
@Test
|
void getAllocateOverviewRejectsMissingCompanyId() {
|
ServiceException exception = assertThrows(ServiceException.class, () -> service.getAllocateOverview(null));
|
assertEquals("请选择公司", exception.getMessage());
|
}
|
|
@Test
|
void allocateQuotaAddsWhitelistBalanceAndDeductsCompanyBalance() {
|
when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司")));
|
when(mapper.selectBatchIds(anyCollection())).thenReturn(Arrays.asList(
|
allocateWhitelist(1L, 9, "13540211236", "10.00"),
|
allocateWhitelist(2L, 9, "13540211237", "20.00")));
|
when(mapper.addBalance(anyLong(), any(BigDecimal.class), any())).thenReturn(1);
|
when(groupCompanyClient.deductBalance(9, new BigDecimal("30.00"))).thenReturn(R.ok(new BigDecimal("970.00")));
|
|
AppUserWhitelistAllocateVO overview = service.allocateQuota(allocateDto(9,
|
allocateItem(1L, "10.00"), allocateItem(2L, "20.00")));
|
|
assertEquals(new BigDecimal("970.00"), overview.getAvailableBalance());
|
assertEquals("测试公司", overview.getCompanyName());
|
verify(redissonClient).getLock("APP_USER_WHITELIST_QUOTA:COMPANY:9");
|
verify(groupCompanyClient).deductBalance(9, new BigDecimal("30.00"));
|
verify(mapper).addBalance(eq(1L), eq(new BigDecimal("10.00")), any());
|
verify(mapper).addBalance(eq(2L), eq(new BigDecimal("20.00")), any());
|
verify(companyAllocateRecordService).recordAllocate(TCompanyAllocateRecord.USER_TYPE_WHITELIST,
|
"13540211236", null, 9, TCompanyAllocateRecord.SOURCE_ALLOCATE,
|
new BigDecimal("10.00"), new BigDecimal("10.00"), "额度分配(公司:测试公司)");
|
}
|
|
@Test
|
void allocateQuotaRejectsSharedModeCompany() {
|
TGroupCompany shared = allocationCompany(9, "共享公司");
|
shared.setAccountMode(1);
|
when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(shared));
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.allocateQuota(allocateDto(9, allocateItem(1L, "10.00"))));
|
|
assertEquals("该公司为共享模式,不支持额度分配", exception.getMessage());
|
verify(groupCompanyClient, never()).deductBalance(any(Integer.class), any(BigDecimal.class));
|
}
|
|
@Test
|
void allocateQuotaRejectsWhitelistOfAnotherCompany() {
|
when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司")));
|
when(mapper.selectBatchIds(anyCollection()))
|
.thenReturn(Collections.singletonList(allocateWhitelist(1L, 8, "13540211236", "10.00")));
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.allocateQuota(allocateDto(9, allocateItem(1L, "10.00"))));
|
|
assertTrue(exception.getMessage().contains("不属于所选公司"));
|
verify(groupCompanyClient, never()).deductBalance(any(Integer.class), any(BigDecimal.class));
|
}
|
|
@Test
|
void allocateQuotaRejectsDisabledWhitelist() {
|
when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司")));
|
TAppUserWhitelist disabled = allocateWhitelist(1L, 9, "13540211236", "10.00");
|
disabled.setStatus(2);
|
when(mapper.selectBatchIds(anyCollection())).thenReturn(Collections.singletonList(disabled));
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.allocateQuota(allocateDto(9, allocateItem(1L, "10.00"))));
|
|
assertTrue(exception.getMessage().contains("已停用"));
|
verify(groupCompanyClient, never()).deductBalance(any(Integer.class), any(BigDecimal.class));
|
}
|
|
@Test
|
void allocateQuotaRefundsCompanyBalanceWhenWhitelistUpdateFails() {
|
when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司")));
|
when(mapper.selectBatchIds(anyCollection()))
|
.thenReturn(Collections.singletonList(allocateWhitelist(1L, 9, "13540211236", "0")));
|
when(mapper.addBalance(anyLong(), any(BigDecimal.class), any())).thenReturn(0);
|
when(groupCompanyClient.deductBalance(9, new BigDecimal("10.00"))).thenReturn(R.ok(new BigDecimal("990.00")));
|
when(groupCompanyClient.refundBalance(9, new BigDecimal("10.00"))).thenReturn(R.ok(new BigDecimal("1000.00")));
|
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.allocateQuota(allocateDto(9, allocateItem(1L, "10.00"))));
|
|
assertTrue(exception.getMessage().contains("额度分配失败"));
|
verify(groupCompanyClient).refundBalance(9, new BigDecimal("10.00"));
|
}
|
|
@Test
|
void allocateQuotaRejectsAmountExceedingLimit() {
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.allocateQuota(allocateDto(9, allocateItem(1L, "999999999.00"))));
|
|
assertTrue(exception.getMessage().contains("不能超过"));
|
verify(groupCompanyClient, never()).getCompanyById(any(Integer.class));
|
}
|
|
@Test
|
void allocateQuotaRejectsDuplicateWhitelistItems() {
|
ServiceException exception = assertThrows(ServiceException.class,
|
() -> service.allocateQuota(allocateDto(9, allocateItem(1L, "10.00"), allocateItem(1L, "5.00"))));
|
|
assertEquals("分配明细中存在重复白名单用户", exception.getMessage());
|
}
|
|
// ---------------- updateStatus ----------------
|
|
@Test
|
void updateStatusRejectsInvalidParams() {
|
assertThrows(ServiceException.class, () -> service.updateStatus(null));
|
AppUserWhitelistStatusDTO noId = new AppUserWhitelistStatusDTO();
|
noId.setStatus(1);
|
assertThrows(ServiceException.class, () -> service.updateStatus(noId));
|
AppUserWhitelistStatusDTO badStatus = new AppUserWhitelistStatusDTO();
|
badStatus.setId(1L);
|
badStatus.setStatus(3);
|
|
ServiceException exception = assertThrows(ServiceException.class, () -> service.updateStatus(badStatus));
|
|
assertEquals("白名单用户状态参数错误", exception.getMessage());
|
verify(mapper, never()).update(isNull(), any(Wrapper.class));
|
}
|
|
@Test
|
void updateStatusRejectsMissingRecord() {
|
when(mapper.selectById(1L)).thenReturn(null);
|
AppUserWhitelistStatusDTO dto = new AppUserWhitelistStatusDTO();
|
dto.setId(1L);
|
dto.setStatus(2);
|
|
ServiceException exception = assertThrows(ServiceException.class, () -> service.updateStatus(dto));
|
|
assertEquals("白名单用户不存在或已删除", exception.getMessage());
|
verify(mapper, never()).update(isNull(), any(Wrapper.class));
|
}
|
|
@Test
|
void updateStatusKeepsUnchangedStatusWithoutUpdate() {
|
TAppUserWhitelist existing = new TAppUserWhitelist();
|
existing.setId(1L);
|
existing.setStatus(1);
|
when(mapper.selectById(1L)).thenReturn(existing);
|
AppUserWhitelistStatusDTO dto = new AppUserWhitelistStatusDTO();
|
dto.setId(1L);
|
dto.setStatus(1);
|
|
assertTrue(service.updateStatus(dto));
|
|
// 状态未变化时视为幂等成功,不产生更新语句,避免污染 update_time / update_by
|
verify(mapper, never()).update(isNull(), any(Wrapper.class));
|
}
|
|
@Test
|
void updateStatusDisablesWhitelist() {
|
TAppUserWhitelist existing = new TAppUserWhitelist();
|
existing.setId(1L);
|
existing.setStatus(1);
|
when(mapper.selectById(1L)).thenReturn(existing);
|
when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(1);
|
AppUserWhitelistStatusDTO dto = new AppUserWhitelistStatusDTO();
|
dto.setId(1L);
|
dto.setStatus(2);
|
|
assertTrue(service.updateStatus(dto));
|
|
ArgumentCaptor<Wrapper> wrapperCaptor = ArgumentCaptor.forClass(Wrapper.class);
|
verify(mapper).update(isNull(), wrapperCaptor.capture());
|
String sqlSet = wrapperCaptor.getValue().getSqlSet();
|
assertTrue(sqlSet.contains("status"));
|
assertTrue(sqlSet.contains("update_time"));
|
}
|
|
@Test
|
void updateStatusThrowsWhenUpdateAffectsNoRow() {
|
TAppUserWhitelist existing = new TAppUserWhitelist();
|
existing.setId(1L);
|
existing.setStatus(1);
|
when(mapper.selectById(1L)).thenReturn(existing);
|
when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(0);
|
AppUserWhitelistStatusDTO dto = new AppUserWhitelistStatusDTO();
|
dto.setId(1L);
|
dto.setStatus(2);
|
|
ServiceException exception = assertThrows(ServiceException.class, () -> service.updateStatus(dto));
|
|
assertEquals("白名单用户状态更新失败,请重试", exception.getMessage());
|
}
|
|
private TGroupCompany allocationCompany(Integer id, String name) {
|
TGroupCompany company = new TGroupCompany();
|
company.setId(id);
|
company.setName(name);
|
company.setAccountMode(2);
|
company.setStatus(1);
|
return company;
|
}
|
|
private TAppUserWhitelist allocateWhitelist(Long id, Integer companyId, String phone, String balance) {
|
TAppUserWhitelist whitelist = new TAppUserWhitelist();
|
whitelist.setId(id);
|
whitelist.setCompanyId(companyId);
|
whitelist.setPhone(phone);
|
whitelist.setStatus(1);
|
whitelist.setBalance(new BigDecimal(balance));
|
return whitelist;
|
}
|
|
private AppUserWhitelistAllocateDTO allocateDto(Integer companyId, AppUserWhitelistAllocateItemDTO... items) {
|
AppUserWhitelistAllocateDTO dto = new AppUserWhitelistAllocateDTO();
|
dto.setCompanyId(companyId);
|
dto.setItems(Arrays.asList(items));
|
return dto;
|
}
|
|
private AppUserWhitelistAllocateItemDTO allocateItem(Long whitelistId, String amount) {
|
AppUserWhitelistAllocateItemDTO item = new AppUserWhitelistAllocateItemDTO();
|
item.setWhitelistId(whitelistId);
|
item.setAmount(new BigDecimal(amount));
|
return item;
|
}
|
|
private MockMultipartFile importFile() throws Exception {
|
try (XSSFWorkbook workbook = new XSSFWorkbook(); ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
org.apache.poi.ss.usermodel.Sheet sheet = workbook.createSheet("白名单用户");
|
org.apache.poi.ss.usermodel.Row header = sheet.createRow(0);
|
header.createCell(0).setCellValue("用户手机号");
|
header.createCell(1).setCellValue("享受权益");
|
header.createCell(2).setCellValue("白名单电站");
|
addRow(sheet, 1, "13540211236", "1", "all");
|
addRow(sheet, 2, "13540211238", "2", "all");
|
addRow(sheet, 3, "13540211237", "", "all");
|
addRow(sheet, 4, "1234", "", "all");
|
workbook.write(output);
|
return new MockMultipartFile("file", "whitelist.xlsx",
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", output.toByteArray());
|
}
|
}
|
|
private void addRow(org.apache.poi.ss.usermodel.Sheet sheet, int index,
|
String phone, String benefitType, String whitelistSite) {
|
org.apache.poi.ss.usermodel.Row row = sheet.createRow(index);
|
row.createCell(0).setCellValue(phone);
|
row.createCell(1).setCellValue(benefitType);
|
row.createCell(2).setCellValue(whitelistSite);
|
}
|
|
// ==================== 公司账号数据隔离 ====================
|
|
@Test
|
void getAllocateOverviewForcesCompanyFilterForCompanyAccount() {
|
// 公司账号:额度概览的公司参数被强制覆盖为本公司
|
when(partnerAppUserAccessService.resolveCompanyFilter(9)).thenReturn(2);
|
TGroupCompany company = new TGroupCompany();
|
company.setId(2);
|
company.setName("本公司");
|
company.setAccountMode(2);
|
company.setAvailableBalance(new BigDecimal("100.00"));
|
when(groupCompanyClient.getCompanyById(2)).thenReturn(R.ok(company));
|
|
AppUserWhitelistAllocateVO vo = service.getAllocateOverview(9);
|
|
assertEquals(Integer.valueOf(2), vo.getCompanyId());
|
verify(groupCompanyClient).getCompanyById(2);
|
}
|
|
@Test
|
void updateStatusRejectsCrossCompanyRecord() {
|
// 公司账号:启停其他公司的白名单被越权校验拦截
|
TAppUserWhitelist existing = new TAppUserWhitelist();
|
existing.setId(1L);
|
existing.setStatus(1);
|
existing.setCompanyId(9);
|
when(mapper.selectById(1L)).thenReturn(existing);
|
doThrow(new ServiceException("无权操作其他公司的数据")).when(partnerAppUserAccessService).assertCompanyVisible(9);
|
AppUserWhitelistStatusDTO dto = new AppUserWhitelistStatusDTO();
|
dto.setId(1L);
|
dto.setStatus(2);
|
|
ServiceException exception = assertThrows(ServiceException.class, () -> service.updateStatus(dto));
|
|
assertEquals("无权操作其他公司的数据", exception.getMessage());
|
verify(mapper, never()).update(isNull(), any(Wrapper.class));
|
}
|
}
|