puzhibing
8 小时以前 88580dae55106dcf4a8f80693b90638e07af02fa
ruoyi-service/ruoyi-account/src/test/java/com/ruoyi/account/service/impl/TAppUserWhitelistServiceImplTest.java
@@ -6,12 +6,15 @@
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;
@@ -47,6 +50,7 @@
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;
@@ -55,6 +59,7 @@
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;
@@ -74,6 +79,7 @@
    @Mock private GroupCompanyClient groupCompanyClient;
    @Mock private RedissonClient redissonClient;
    @Mock private TCompanyAllocateRecordService companyAllocateRecordService;
    @Mock private PartnerAppUserAccessService partnerAppUserAccessService;
    private TAppUserWhitelistServiceImpl service;
@@ -98,6 +104,10 @@
        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);
@@ -134,8 +144,8 @@
        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(1, saved.getBenefitType().intValue());
            // 导入统一按默认值写入:全部电站 + 启用;白名单权益已下线,不再写入享受权益,忽略模板中的享受权益/白名单电站列
            assertEquals(null, saved.getBenefitType());
            assertEquals(1, saved.getScopeType().intValue());
            assertEquals(1, saved.getStatus().intValue());
        }
@@ -197,6 +207,134 @@
        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);
    }
    // ---------------- 额度分配 ----------------
@@ -319,6 +457,89 @@
        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);
@@ -376,4 +597,42 @@
        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));
    }
}