| | |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.account.api.dto.ChargingCardAllocateDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardAllocateItemDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardAuthDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardBalanceDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardDeductDTO; |
| | |
| | | import com.ruoyi.account.api.dto.ChargingCardSaveDTO; |
| | | import com.ruoyi.account.api.dto.ChargingCardStatusDTO; |
| | | import com.ruoyi.account.api.model.TChargingCard; |
| | | import com.ruoyi.account.api.vo.ChargingCardAllocateVO; |
| | | import com.ruoyi.account.api.vo.ChargingCardDeductVO; |
| | | import com.ruoyi.account.mapper.TChargingCardMapper; |
| | | import com.ruoyi.common.core.context.SecurityContextHolder; |
| | |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.common.security.utils.SecurityUtils; |
| | | import com.ruoyi.other.api.domain.TFleet; |
| | | import com.ruoyi.other.api.domain.TGroupCompany; |
| | | import com.ruoyi.other.api.feignClient.GroupCompanyClient; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import com.ruoyi.system.api.model.LoginUser; |
| | |
| | | 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.dao.DuplicateKeyException; |
| | | import org.springframework.test.util.ReflectionTestUtils; |
| | | import org.springframework.transaction.support.TransactionCallback; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.util.Arrays; |
| | | import java.util.Collections; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | import static org.junit.jupiter.api.Assertions.assertEquals; |
| | | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| | |
| | | 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.anyList; |
| | | import static org.mockito.ArgumentMatchers.anyLong; |
| | | import static org.mockito.ArgumentMatchers.anyString; |
| | | import static org.mockito.ArgumentMatchers.isNull; |
| | | import static org.mockito.Mockito.doReturn; |
| | | import static org.mockito.Mockito.lenient; |
| | | import static org.mockito.Mockito.never; |
| | | import static org.mockito.Mockito.spy; |
| | | import static org.mockito.Mockito.verify; |
| | |
| | | @Mock private TokenService tokenService; |
| | | @Mock private SysUserClient sysUserClient; |
| | | @Mock private TransactionTemplate transactionTemplate; |
| | | @Mock private GroupCompanyClient groupCompanyClient; |
| | | @Mock private RedissonClient redissonClient; |
| | | @Mock private RLock quotaLock; |
| | | private TChargingCardServiceImpl service; |
| | | |
| | | @BeforeEach |
| | | void setUp() { |
| | | void setUp() throws InterruptedException { |
| | | service = spy(new TChargingCardServiceImpl()); |
| | | ReflectionTestUtils.setField(service, "baseMapper", mapper); |
| | | ReflectionTestUtils.setField(service, "tokenService", tokenService); |
| | | ReflectionTestUtils.setField(service, "sysUserClient", sysUserClient); |
| | | ReflectionTestUtils.setField(service, "transactionTemplate", transactionTemplate); |
| | | ReflectionTestUtils.setField(service, "groupCompanyClient", groupCompanyClient); |
| | | ReflectionTestUtils.setField(service, "redissonClient", redissonClient); |
| | | lenient().when(redissonClient.getLock(anyString())).thenReturn(quotaLock); |
| | | lenient().when(quotaLock.tryLock(anyLong(), anyLong(), any(TimeUnit.class))).thenReturn(true); |
| | | lenient().when(quotaLock.isHeldByCurrentThread()).thenReturn(true); |
| | | SecurityContextHolder.setUserId("123"); |
| | | } |
| | | |
| | |
| | | verify(mapper, never()).adjustBalance(anyList(), any(), any(), any(), any()); |
| | | } |
| | | |
| | | // ==================== 卡片所属公司/车队 + 初始分配额度 ==================== |
| | | |
| | | @Test |
| | | void saveCardDeductsCompanyBalanceWhenAllocationQuotaProvided() { |
| | | when(mapper.countByCardNo(anyString(), isNull())).thenReturn(0); |
| | | when(mapper.insert(any(TChargingCard.class))).thenReturn(1); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | when(groupCompanyClient.getFleetById(3)).thenReturn(R.ok(fleet(3, 9, "测试车队"))); |
| | | when(groupCompanyClient.deductBalance(9, new BigDecimal("100.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("900.00"))); |
| | | ChargingCardSaveDTO dto = new ChargingCardSaveDTO(); |
| | | dto.setCardNo(" CARD-Q1 "); |
| | | dto.setCompanyId(9); |
| | | dto.setFleetId(3); |
| | | dto.setInitQuota(new BigDecimal("100")); |
| | | |
| | | assertTrue(service.saveCard(dto)); |
| | | |
| | | ArgumentCaptor<TChargingCard> card = ArgumentCaptor.forClass(TChargingCard.class); |
| | | verify(mapper).insert(card.capture()); |
| | | assertEquals(Integer.valueOf(9), card.getValue().getCompanyId()); |
| | | assertEquals(Integer.valueOf(3), card.getValue().getFleetId()); |
| | | assertEquals(new BigDecimal("100.00"), card.getValue().getInitQuota()); |
| | | verify(groupCompanyClient).deductBalance(9, new BigDecimal("100.00")); |
| | | } |
| | | |
| | | @Test |
| | | void saveCardRejectsQuotaForShareModeCompany() { |
| | | when(mapper.countByCardNo(anyString(), isNull())).thenReturn(0); |
| | | TGroupCompany shareCompany = allocationCompany(9, "共享公司"); |
| | | shareCompany.setAccountMode(1); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(shareCompany)); |
| | | ChargingCardSaveDTO dto = new ChargingCardSaveDTO(); |
| | | dto.setCardNo("CARD-Q2"); |
| | | dto.setCompanyId(9); |
| | | dto.setInitQuota(new BigDecimal("10.00")); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, () -> service.saveCard(dto)); |
| | | |
| | | assertEquals("仅分配模式的公司可填写初始分配额度", exception.getMessage()); |
| | | verify(groupCompanyClient, never()).deductBalance(any(), any()); |
| | | verify(mapper, never()).insert(any(TChargingCard.class)); |
| | | } |
| | | |
| | | @Test |
| | | void saveCardKeepsQuotaEmptyAndSkipsBalanceWhenCompanyMissing() { |
| | | when(mapper.countByCardNo(anyString(), isNull())).thenReturn(0); |
| | | when(mapper.insert(any(TChargingCard.class))).thenReturn(1); |
| | | ChargingCardSaveDTO dto = new ChargingCardSaveDTO(); |
| | | dto.setCardNo("CARD-Q3"); |
| | | |
| | | assertTrue(service.saveCard(dto)); |
| | | |
| | | ArgumentCaptor<TChargingCard> card = ArgumentCaptor.forClass(TChargingCard.class); |
| | | verify(mapper).insert(card.capture()); |
| | | assertEquals(null, card.getValue().getCompanyId()); |
| | | assertEquals(null, card.getValue().getInitQuota()); |
| | | verify(groupCompanyClient, never()).deductBalance(any(), any()); |
| | | } |
| | | |
| | | @Test |
| | | void saveCardRejectsFleetNotBelongingToCompany() { |
| | | when(mapper.countByCardNo(anyString(), isNull())).thenReturn(0); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | when(groupCompanyClient.getFleetById(3)).thenReturn(R.ok(fleet(3, 11, "他司车队"))); |
| | | ChargingCardSaveDTO dto = new ChargingCardSaveDTO(); |
| | | dto.setCardNo("CARD-Q4"); |
| | | dto.setCompanyId(9); |
| | | dto.setFleetId(3); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, () -> service.saveCard(dto)); |
| | | |
| | | assertEquals("所属车队不属于所选公司", exception.getMessage()); |
| | | } |
| | | |
| | | @Test |
| | | void updateCardDeductsQuotaDiffWhenQuotaIncreased() { |
| | | ChargingCardSaveDTO dto = quotaUpdateDto(7L, "CARD-7", 9, new BigDecimal("150.00")); |
| | | when(mapper.countByCardNo("CARD-7", 7L)).thenReturn(0); |
| | | when(mapper.selectById(7L)).thenReturn(cardWithQuota(7L, 9, new BigDecimal("100.00"))); |
| | | when(mapper.updateById(any(TChargingCard.class))).thenReturn(1); |
| | | when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(1); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | when(groupCompanyClient.deductBalance(9, new BigDecimal("50.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("50.00"))); |
| | | |
| | | assertTrue(service.updateCard(dto)); |
| | | |
| | | verify(groupCompanyClient).deductBalance(9, new BigDecimal("50.00")); |
| | | verify(groupCompanyClient, never()).refundBalance(any(), any()); |
| | | } |
| | | |
| | | @Test |
| | | void updateCardRefundsQuotaDiffWhenQuotaReduced() { |
| | | ChargingCardSaveDTO dto = quotaUpdateDto(7L, "CARD-7", 9, new BigDecimal("80.00")); |
| | | when(mapper.countByCardNo("CARD-7", 7L)).thenReturn(0); |
| | | when(mapper.selectById(7L)).thenReturn(cardWithQuota(7L, 9, new BigDecimal("150.00"))); |
| | | when(mapper.updateById(any(TChargingCard.class))).thenReturn(1); |
| | | when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(1); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | when(groupCompanyClient.refundBalance(9, new BigDecimal("70.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("70.00"))); |
| | | |
| | | assertTrue(service.updateCard(dto)); |
| | | |
| | | verify(groupCompanyClient).refundBalance(9, new BigDecimal("70.00")); |
| | | verify(groupCompanyClient, never()).deductBalance(any(), any()); |
| | | } |
| | | |
| | | @Test |
| | | void updateCardSwitchesCompanyRefundsOldAndDeductsNew() { |
| | | ChargingCardSaveDTO dto = quotaUpdateDto(7L, "CARD-7", 11, new BigDecimal("60.00")); |
| | | when(mapper.countByCardNo("CARD-7", 7L)).thenReturn(0); |
| | | when(mapper.selectById(7L)).thenReturn(cardWithQuota(7L, 9, new BigDecimal("100.00"))); |
| | | when(mapper.updateById(any(TChargingCard.class))).thenReturn(1); |
| | | when(mapper.update(isNull(), any(Wrapper.class))).thenReturn(1); |
| | | when(groupCompanyClient.getCompanyById(11)).thenReturn(R.ok(allocationCompany(11, "新公司"))); |
| | | when(groupCompanyClient.refundBalance(9, new BigDecimal("100.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("100.00"))); |
| | | when(groupCompanyClient.deductBalance(11, new BigDecimal("60.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("60.00"))); |
| | | |
| | | assertTrue(service.updateCard(dto)); |
| | | |
| | | verify(groupCompanyClient).refundBalance(9, new BigDecimal("100.00")); |
| | | verify(groupCompanyClient).deductBalance(11, new BigDecimal("60.00")); |
| | | } |
| | | |
| | | @Test |
| | | void updateCardCompensatesRefundWhenUpdateFails() { |
| | | ChargingCardSaveDTO dto = quotaUpdateDto(7L, "CARD-7", 9, new BigDecimal("150.00")); |
| | | when(mapper.countByCardNo("CARD-7", 7L)).thenReturn(0); |
| | | when(mapper.selectById(7L)).thenReturn(cardWithQuota(7L, 9, new BigDecimal("100.00"))); |
| | | when(mapper.updateById(any(TChargingCard.class))).thenReturn(0); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | when(groupCompanyClient.deductBalance(9, new BigDecimal("50.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("100.00"))); |
| | | when(groupCompanyClient.refundBalance(9, new BigDecimal("50.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("150.00"))); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, () -> service.updateCard(dto)); |
| | | |
| | | assertEquals("修改卡片失败", exception.getMessage()); |
| | | verify(groupCompanyClient).refundBalance(9, new BigDecimal("50.00")); |
| | | } |
| | | |
| | | @Test |
| | | void updateCardRejectsWhenQuotaLockUnavailable() throws InterruptedException { |
| | | ChargingCardSaveDTO dto = quotaUpdateDto(7L, "CARD-7", 9, new BigDecimal("150.00")); |
| | | when(mapper.countByCardNo("CARD-7", 7L)).thenReturn(0); |
| | | when(mapper.selectById(7L)).thenReturn(cardWithQuota(7L, 9, new BigDecimal("100.00"))); |
| | | when(quotaLock.tryLock(anyLong(), anyLong(), any(TimeUnit.class))).thenReturn(false); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, () -> service.updateCard(dto)); |
| | | |
| | | assertEquals("该卡片额度正在处理中,请稍后重试", exception.getMessage()); |
| | | verify(groupCompanyClient, never()).deductBalance(any(), any()); |
| | | } |
| | | |
| | | @Test |
| | | void selectCardPageFillsCompanyAndFleetNames() { |
| | | TChargingCard record = cardWithQuota(1L, 9, new BigDecimal("10.00")); |
| | | record.setFleetId(3); |
| | | Page<TChargingCard> page = new Page<>(1, 10); |
| | | page.setRecords(Collections.singletonList(record)); |
| | | when(mapper.selectCardPage(any(Page.class), any())).thenReturn(page); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | when(groupCompanyClient.listFleetsByIds(anyList())) |
| | | .thenReturn(R.ok(Collections.singletonList(fleet(3, 9, "测试车队")))); |
| | | |
| | | IPage<TChargingCard> result = service.selectCardPage(null); |
| | | |
| | | assertEquals("测试公司", result.getRecords().get(0).getCompanyName()); |
| | | assertEquals("测试车队", result.getRecords().get(0).getFleetName()); |
| | | } |
| | | |
| | | 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 TFleet fleet(Integer id, Integer companyId, String name) { |
| | | TFleet fleet = new TFleet(); |
| | | fleet.setId(id); |
| | | fleet.setCompanyId(companyId); |
| | | fleet.setFleetName(name); |
| | | return fleet; |
| | | } |
| | | |
| | | private TChargingCard cardWithQuota(Long id, Integer companyId, BigDecimal quota) { |
| | | TChargingCard card = new TChargingCard(); |
| | | card.setId(id); |
| | | card.setCompanyId(companyId); |
| | | card.setInitQuota(quota); |
| | | return card; |
| | | } |
| | | |
| | | private ChargingCardSaveDTO quotaUpdateDto(Long id, String cardNo, Integer companyId, BigDecimal quota) { |
| | | ChargingCardSaveDTO dto = new ChargingCardSaveDTO(); |
| | | dto.setId(id); |
| | | dto.setCardNo(cardNo); |
| | | dto.setCompanyId(companyId); |
| | | dto.setInitQuota(quota); |
| | | return dto; |
| | | } |
| | | |
| | | // ==================== V0.2 定稿:刷卡启动鉴权(条件密码校验) ==================== |
| | | |
| | | @Test |
| | |
| | | dto.setAmount(amount); |
| | | return dto; |
| | | } |
| | | |
| | | // ==================== 卡片额度分配 ==================== |
| | | |
| | | @Test |
| | | void getAllocateOverviewNormalizesAmounts() { |
| | | TGroupCompany company = allocationCompany(9, "测试公司"); |
| | | company.setAvailableBalance(new BigDecimal("8420.5")); |
| | | company.setTotalRechargeAmount(null); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(company)); |
| | | |
| | | ChargingCardAllocateVO vo = service.getAllocateOverview(9); |
| | | |
| | | assertEquals(Integer.valueOf(9), vo.getCompanyId()); |
| | | assertEquals("测试公司", vo.getCompanyName()); |
| | | assertEquals(new BigDecimal("8420.50"), vo.getAvailableBalance()); |
| | | assertEquals(new BigDecimal("0.00"), vo.getTotalRechargeAmount()); |
| | | } |
| | | |
| | | @Test |
| | | void getAllocateOverviewRejectsMissingCompanyId() { |
| | | ServiceException exception = assertThrows(ServiceException.class, () -> service.getAllocateOverview(null)); |
| | | |
| | | assertEquals("请选择公司", exception.getMessage()); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaAddsCardBalanceAndDeductsCompanyBalance() { |
| | | mockOperationPassword(); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | TChargingCard first = allocateCard(1L, 9, "CARD-1", "10.00"); |
| | | TChargingCard second = allocateCard(2L, 9, "CARD-2", "20.00"); |
| | | doReturn(Arrays.asList(first, second)).when(service).listByIds(anyCollection()); |
| | | when(mapper.adjustBalance(anyList(), any(BigDecimal.class), any(Integer.class), any(BigDecimal.class), |
| | | any(Long.class))).thenReturn(1); |
| | | when(mapper.insertBalanceRecord(anyLong(), any(Integer.class), any(BigDecimal.class), any(), any(Long.class))) |
| | | .thenReturn(1); |
| | | when(groupCompanyClient.deductBalance(9, new BigDecimal("30.00"))).thenReturn(R.ok(new BigDecimal("970.00"))); |
| | | |
| | | ChargingCardAllocateVO vo = service.allocateQuota(allocateDto(9, "pwd", |
| | | allocateItem(1L, "10.00"), allocateItem(2L, "20.00"))); |
| | | |
| | | assertEquals(new BigDecimal("970.00"), vo.getAvailableBalance()); |
| | | assertEquals("测试公司", vo.getCompanyName()); |
| | | verify(groupCompanyClient).deductBalance(9, new BigDecimal("30.00")); |
| | | verify(mapper).insertBalanceRecord(1L, 1, new BigDecimal("10.00"), "额度分配(公司:测试公司)", 123L); |
| | | verify(mapper).insertBalanceRecord(2L, 1, new BigDecimal("20.00"), "额度分配(公司:测试公司)", 123L); |
| | | verify(redissonClient).getLock("CHARGING_CARD_QUOTA:COMPANY:9"); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRejectsSharedModeCompany() { |
| | | mockOperationPassword(); |
| | | TGroupCompany shared = allocationCompany(9, "共享公司"); |
| | | shared.setAccountMode(1); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(shared)); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "10.00")))); |
| | | |
| | | assertEquals("该公司为共享模式,不支持额度分配", exception.getMessage()); |
| | | verify(groupCompanyClient, never()).deductBalance(any(Integer.class), any(BigDecimal.class)); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRejectsCardOfAnotherCompany() { |
| | | mockOperationPassword(); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | TChargingCard foreign = allocateCard(1L, 8, "CARD-1", "10.00"); |
| | | doReturn(Collections.singletonList(foreign)).when(service).listByIds(anyCollection()); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "10.00")))); |
| | | |
| | | assertTrue(exception.getMessage().contains("不属于所选公司")); |
| | | verify(groupCompanyClient, never()).deductBalance(any(Integer.class), any(BigDecimal.class)); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRefundsCompanyBalanceWhenCardUpdateFails() { |
| | | mockOperationPassword(); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | TChargingCard card = allocateCard(1L, 9, "CARD-1", "10.00"); |
| | | doReturn(Collections.singletonList(card)).when(service).listByIds(anyCollection()); |
| | | when(groupCompanyClient.deductBalance(9, new BigDecimal("10.00"))) |
| | | .thenReturn(R.ok(new BigDecimal("990.00"))); |
| | | when(mapper.adjustBalance(anyList(), any(BigDecimal.class), any(Integer.class), any(BigDecimal.class), |
| | | any(Long.class))).thenReturn(0); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "10.00")))); |
| | | |
| | | assertTrue(exception.getMessage().contains("余额分配失败")); |
| | | verify(groupCompanyClient).refundBalance(9, new BigDecimal("10.00")); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaReportsInsufficientCompanyBalance() { |
| | | mockOperationPassword(); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | TChargingCard card = allocateCard(1L, 9, "CARD-1", "0.00"); |
| | | doReturn(Collections.singletonList(card)).when(service).listByIds(anyCollection()); |
| | | when(groupCompanyClient.deductBalance(9, new BigDecimal("500.00"))).thenReturn(R.fail("公司可用余额不足")); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "500.00")))); |
| | | |
| | | assertEquals("公司可分配余额不足,无法完成本次分配", exception.getMessage()); |
| | | verify(mapper, never()).adjustBalance(anyList(), any(BigDecimal.class), any(Integer.class), |
| | | any(BigDecimal.class), any(Long.class)); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRejectsInvalidAmount() { |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "0")))); |
| | | |
| | | assertEquals("分配金额必须大于0", exception.getMessage()); |
| | | verify(groupCompanyClient, never()).getCompanyById(any(Integer.class)); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRejectsDuplicateCards() { |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "10.00"), allocateItem(1L, "5.00")))); |
| | | |
| | | assertEquals("分配明细中存在重复卡片", exception.getMessage()); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRejectsMissingPassword() { |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, null, allocateItem(1L, "10.00")))); |
| | | |
| | | assertEquals("请输入操作密码", exception.getMessage()); |
| | | verify(mapper, never()).adjustBalance(anyList(), any(BigDecimal.class), any(Integer.class), |
| | | any(BigDecimal.class), any(Long.class)); |
| | | } |
| | | |
| | | @Test |
| | | void allocateQuotaRejectsChargingLockedCard() { |
| | | mockOperationPassword(); |
| | | when(groupCompanyClient.getCompanyById(9)).thenReturn(R.ok(allocationCompany(9, "测试公司"))); |
| | | TChargingCard card = allocateCard(1L, 9, "CARD-1", "10.00"); |
| | | card.setChargingFlag(1); |
| | | doReturn(Collections.singletonList(card)).when(service).listByIds(anyCollection()); |
| | | |
| | | ServiceException exception = assertThrows(ServiceException.class, |
| | | () -> service.allocateQuota(allocateDto(9, "pwd", allocateItem(1L, "10.00")))); |
| | | |
| | | assertTrue(exception.getMessage().contains("充电中")); |
| | | verify(groupCompanyClient, never()).deductBalance(any(Integer.class), any(BigDecimal.class)); |
| | | } |
| | | |
| | | private void mockOperationPassword() { |
| | | LoginUser loginUser = new LoginUser(); |
| | | loginUser.setUserid(123L); |
| | | SysUser user = new SysUser(); |
| | | user.setOperationPassword(SecurityUtils.encryptPassword("pwd")); |
| | | when(tokenService.getLoginUser()).thenReturn(loginUser); |
| | | when(sysUserClient.getSysUser(123L)).thenReturn(R.ok(user)); |
| | | } |
| | | |
| | | private TChargingCard allocateCard(Long id, Integer companyId, String cardNo, String balance) { |
| | | TChargingCard card = new TChargingCard(); |
| | | card.setId(id); |
| | | card.setCompanyId(companyId); |
| | | card.setCardNo(cardNo); |
| | | card.setBalance(new BigDecimal(balance)); |
| | | card.setStatus(1); |
| | | card.setChargingFlag(0); |
| | | return card; |
| | | } |
| | | |
| | | private ChargingCardAllocateItemDTO allocateItem(Long cardId, String amount) { |
| | | ChargingCardAllocateItemDTO item = new ChargingCardAllocateItemDTO(); |
| | | item.setCardId(cardId); |
| | | item.setAmount(new BigDecimal(amount)); |
| | | return item; |
| | | } |
| | | |
| | | private ChargingCardAllocateDTO allocateDto(Integer companyId, String password, ChargingCardAllocateItemDTO... items) { |
| | | ChargingCardAllocateDTO dto = new ChargingCardAllocateDTO(); |
| | | dto.setCompanyId(companyId); |
| | | dto.setItems(Arrays.asList(items)); |
| | | dto.setOperationPassword(password); |
| | | return dto; |
| | | } |
| | | } |