package com.ruoyi.other.service.impl;
|
|
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
|
import com.ruoyi.account.api.dto.SendMessageDTO;
|
import com.ruoyi.account.api.feignClient.AppUserClient;
|
import com.ruoyi.account.api.feignClient.AppUserWhitelistClient;
|
import com.ruoyi.account.api.feignClient.ChargingCardClient;
|
import com.ruoyi.account.api.feignClient.VinManagementClient;
|
import com.ruoyi.account.api.model.TAppUserWhitelist;
|
import com.ruoyi.account.api.model.TChargingCard;
|
import com.ruoyi.account.api.model.TVinManagement;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.other.api.domain.TBalanceWarningRecord;
|
import com.ruoyi.other.api.domain.TCompanyBalanceWarning;
|
import com.ruoyi.other.api.domain.TGroup;
|
import com.ruoyi.other.api.domain.TGroupCompany;
|
import com.ruoyi.other.mapper.TCompanyBalanceWarningMapper;
|
import com.ruoyi.other.mapper.TGroupCompanyMapper;
|
import com.ruoyi.other.mapper.TGroupMapper;
|
import com.ruoyi.other.service.TBalanceWarningRecordService;
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.Test;
|
import org.mockito.ArgumentCaptor;
|
import org.mockito.Mockito;
|
import org.springframework.test.util.ReflectionTestUtils;
|
|
import java.math.BigDecimal;
|
import java.util.Arrays;
|
import java.util.Collections;
|
import java.util.List;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
/**
|
* 公司余额预警扫描服务单测,不依赖 Spring 容器与数据库。
|
*/
|
class TBalanceWarningScanServiceImplTest {
|
|
@BeforeAll
|
static void initTableInfo() {
|
// 初始化 MyBatis-Plus 表元数据,使 scan() 中的 LambdaQueryWrapper 可在无 Spring/DB 环境下解析字段
|
TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""),
|
TCompanyBalanceWarning.class);
|
}
|
|
@Test
|
void sendsCompanyWarnSmsWhenBalanceBelowThreshold() {
|
TCompanyBalanceWarningMapper warningMapper = Mockito.mock(TCompanyBalanceWarningMapper.class);
|
TCompanyBalanceWarning warning = warning();
|
warning.setSubWarnAmount(null);
|
Mockito.when(warningMapper.selectList(Mockito.any())).thenReturn(Collections.singletonList(warning));
|
|
TGroupCompany company = company();
|
company.setAccountMode(1);
|
company.setAvailableBalance(new BigDecimal("500"));
|
company.setContactPhone("13800138000");
|
|
TGroupCompanyMapper companyMapper = Mockito.mock(TGroupCompanyMapper.class);
|
Mockito.when(companyMapper.selectById(11)).thenReturn(company);
|
|
TBalanceWarningRecordService recordService = Mockito.mock(TBalanceWarningRecordService.class);
|
AppUserClient appUserClient = Mockito.mock(AppUserClient.class);
|
Mockito.when(appUserClient.sendMessage(Mockito.any(SendMessageDTO.class))).thenReturn(R.ok("ok"));
|
|
buildService(warningMapper, companyMapper, null, recordService,
|
Mockito.mock(VinManagementClient.class), Mockito.mock(ChargingCardClient.class),
|
Mockito.mock(AppUserWhitelistClient.class), appUserClient).scan();
|
|
ArgumentCaptor<SendMessageDTO> captor = ArgumentCaptor.forClass(SendMessageDTO.class);
|
Mockito.verify(appUserClient).sendMessage(captor.capture());
|
SendMessageDTO dto = captor.getValue();
|
assertEquals(5, dto.getType());
|
assertEquals("13800138000", dto.getPhone());
|
assertEquals("利普芯科技有限公司", dto.getCompanyName());
|
assertEquals("500.00", dto.getBalance());
|
assertEquals("1000.00", dto.getWarnAmount());
|
|
ArgumentCaptor<TBalanceWarningRecord> recordCaptor = ArgumentCaptor.forClass(TBalanceWarningRecord.class);
|
Mockito.verify(recordService).save(recordCaptor.capture());
|
assertEquals(11, recordCaptor.getValue().getCompanyId());
|
assertEquals(1, recordCaptor.getValue().getWarnScope());
|
}
|
|
@Test
|
void skipsWhenAlreadyNotifiedToday() {
|
TCompanyBalanceWarningMapper warningMapper = Mockito.mock(TCompanyBalanceWarningMapper.class);
|
TCompanyBalanceWarning warning = warning();
|
warning.setSubWarnAmount(null);
|
Mockito.when(warningMapper.selectList(Mockito.any())).thenReturn(Collections.singletonList(warning));
|
|
TGroupCompany company = company();
|
company.setAccountMode(1);
|
company.setAvailableBalance(new BigDecimal("500"));
|
company.setContactPhone("13800138000");
|
|
TGroupCompanyMapper companyMapper = Mockito.mock(TGroupCompanyMapper.class);
|
Mockito.when(companyMapper.selectById(11)).thenReturn(company);
|
|
TBalanceWarningRecordService recordService = Mockito.mock(TBalanceWarningRecordService.class);
|
Mockito.when(recordService.isNotifiedToday(11, 1, "")).thenReturn(true);
|
AppUserClient appUserClient = Mockito.mock(AppUserClient.class);
|
|
buildService(warningMapper, companyMapper, null, recordService,
|
Mockito.mock(VinManagementClient.class), Mockito.mock(ChargingCardClient.class),
|
Mockito.mock(AppUserWhitelistClient.class), appUserClient).scan();
|
|
Mockito.verify(appUserClient, Mockito.never()).sendMessage(Mockito.any(SendMessageDTO.class));
|
Mockito.verify(recordService, Mockito.never()).save(Mockito.any(TBalanceWarningRecord.class));
|
}
|
|
@Test
|
void skipsWhenNotifyPhoneBlank() {
|
TCompanyBalanceWarningMapper warningMapper = Mockito.mock(TCompanyBalanceWarningMapper.class);
|
TCompanyBalanceWarning warning = warning();
|
warning.setSubWarnAmount(null);
|
Mockito.when(warningMapper.selectList(Mockito.any())).thenReturn(Collections.singletonList(warning));
|
|
TGroupCompany company = company();
|
company.setAccountMode(1);
|
company.setAvailableBalance(new BigDecimal("500"));
|
company.setContactPhone(null);
|
|
TGroupCompanyMapper companyMapper = Mockito.mock(TGroupCompanyMapper.class);
|
Mockito.when(companyMapper.selectById(11)).thenReturn(company);
|
|
TBalanceWarningRecordService recordService = Mockito.mock(TBalanceWarningRecordService.class);
|
AppUserClient appUserClient = Mockito.mock(AppUserClient.class);
|
|
buildService(warningMapper, companyMapper, null, recordService,
|
Mockito.mock(VinManagementClient.class), Mockito.mock(ChargingCardClient.class),
|
Mockito.mock(AppUserWhitelistClient.class), appUserClient).scan();
|
|
Mockito.verifyNoInteractions(appUserClient, recordService);
|
}
|
|
@Test
|
void sendsSubAccountWarnSmsForAllocationMode() {
|
TCompanyBalanceWarningMapper warningMapper = Mockito.mock(TCompanyBalanceWarningMapper.class);
|
TCompanyBalanceWarning warning = warning();
|
warning.setCompanyWarnAmount(new BigDecimal("100000"));
|
Mockito.when(warningMapper.selectList(Mockito.any())).thenReturn(Collections.singletonList(warning));
|
|
TGroupCompany company = company();
|
company.setAccountMode(2);
|
company.setAvailableBalance(new BigDecimal("500000"));
|
company.setContactPhone("13800138000");
|
|
TGroupCompanyMapper companyMapper = Mockito.mock(TGroupCompanyMapper.class);
|
Mockito.when(companyMapper.selectById(11)).thenReturn(company);
|
|
// VIN1 余额低于子账户预警线且车牌号为空(回退VIN码),VIN2 余额充足不提醒
|
TVinManagement vin1 = vin("VIN123456", null, new BigDecimal("100"));
|
TVinManagement vin2 = vin("VIN999999", "川B88888", new BigDecimal("300"));
|
VinManagementClient vinClient = Mockito.mock(VinManagementClient.class);
|
Mockito.when(vinClient.listByCompany(11)).thenReturn(R.ok(Arrays.asList(vin1, vin2)));
|
|
// 卡余额低于预警线
|
TChargingCard card = new TChargingCard();
|
card.setCardNo("CARD001");
|
card.setBalance(new BigDecimal("150"));
|
ChargingCardClient cardClient = Mockito.mock(ChargingCardClient.class);
|
Mockito.when(cardClient.listByCompany(11)).thenReturn(R.ok(Collections.singletonList(card)));
|
|
// 白名单1余额低于预警线(姓名回退手机号),白名单2余额充足
|
TAppUserWhitelist wl1 = whitelist("13900000001", null, new BigDecimal("180"));
|
TAppUserWhitelist wl2 = whitelist("13900000002", "李四", new BigDecimal("250"));
|
AppUserWhitelistClient whitelistClient = Mockito.mock(AppUserWhitelistClient.class);
|
Mockito.when(whitelistClient.listByCompany(11)).thenReturn(R.ok(Arrays.asList(wl1, wl2)));
|
|
TBalanceWarningRecordService recordService = Mockito.mock(TBalanceWarningRecordService.class);
|
AppUserClient appUserClient = Mockito.mock(AppUserClient.class);
|
Mockito.when(appUserClient.sendMessage(Mockito.any(SendMessageDTO.class))).thenReturn(R.ok("ok"));
|
|
buildService(warningMapper, companyMapper, null, recordService,
|
vinClient, cardClient, whitelistClient, appUserClient).scan();
|
|
ArgumentCaptor<SendMessageDTO> captor = ArgumentCaptor.forClass(SendMessageDTO.class);
|
Mockito.verify(appUserClient, Mockito.times(3)).sendMessage(captor.capture());
|
List<SendMessageDTO> sent = captor.getAllValues();
|
for (SendMessageDTO dto : sent) {
|
assertEquals(6, dto.getType());
|
assertEquals("13800138000", dto.getPhone());
|
assertEquals("200.00", dto.getWarnAmount());
|
}
|
// VIN:车牌号为空回退VIN码
|
assertTrue(sent.stream().anyMatch(dto -> "VIN123456".equals(dto.getUserInfo()) && "100.00".equals(dto.getBalance())));
|
// 卡:用户信息取卡号
|
assertTrue(sent.stream().anyMatch(dto -> "CARD001".equals(dto.getUserInfo()) && "150.00".equals(dto.getBalance())));
|
// 白名单:姓名为空回退手机号
|
assertTrue(sent.stream().anyMatch(dto -> "13900000001".equals(dto.getUserInfo()) && "180.00".equals(dto.getBalance())));
|
}
|
|
@Test
|
void skipsSubAccountScanInSharedMode() {
|
TCompanyBalanceWarningMapper warningMapper = Mockito.mock(TCompanyBalanceWarningMapper.class);
|
TCompanyBalanceWarning warning = warning();
|
warning.setCompanyWarnAmount(new BigDecimal("100000"));
|
Mockito.when(warningMapper.selectList(Mockito.any())).thenReturn(Collections.singletonList(warning));
|
|
TGroupCompany company = company();
|
company.setAccountMode(1);
|
company.setAvailableBalance(new BigDecimal("500000"));
|
company.setContactPhone("13800138000");
|
|
TGroupCompanyMapper companyMapper = Mockito.mock(TGroupCompanyMapper.class);
|
Mockito.when(companyMapper.selectById(11)).thenReturn(company);
|
|
VinManagementClient vinClient = Mockito.mock(VinManagementClient.class);
|
ChargingCardClient cardClient = Mockito.mock(ChargingCardClient.class);
|
AppUserWhitelistClient whitelistClient = Mockito.mock(AppUserWhitelistClient.class);
|
AppUserClient appUserClient = Mockito.mock(AppUserClient.class);
|
|
buildService(warningMapper, companyMapper, null, Mockito.mock(TBalanceWarningRecordService.class),
|
vinClient, cardClient, whitelistClient, appUserClient).scan();
|
|
Mockito.verifyNoInteractions(vinClient, cardClient, whitelistClient, appUserClient);
|
}
|
|
@Test
|
void routesToGroupContactWhenNotifyObjectIsGroup() {
|
TCompanyBalanceWarningMapper warningMapper = Mockito.mock(TCompanyBalanceWarningMapper.class);
|
TCompanyBalanceWarning warning = warning();
|
warning.setSubWarnAmount(null);
|
warning.setNotifyObject(1);
|
Mockito.when(warningMapper.selectList(Mockito.any())).thenReturn(Collections.singletonList(warning));
|
|
TGroupCompany company = company();
|
company.setAccountMode(1);
|
company.setAvailableBalance(new BigDecimal("500"));
|
company.setContactPhone("13800138000");
|
company.setGroupId(5);
|
|
TGroupCompanyMapper companyMapper = Mockito.mock(TGroupCompanyMapper.class);
|
Mockito.when(companyMapper.selectById(11)).thenReturn(company);
|
|
TGroup group = new TGroup();
|
group.setId(5);
|
group.setContactPhone("13711112222");
|
TGroupMapper groupMapper = Mockito.mock(TGroupMapper.class);
|
Mockito.when(groupMapper.selectById(5)).thenReturn(group);
|
|
AppUserClient appUserClient = Mockito.mock(AppUserClient.class);
|
Mockito.when(appUserClient.sendMessage(Mockito.any(SendMessageDTO.class))).thenReturn(R.ok("ok"));
|
|
buildService(warningMapper, companyMapper, groupMapper, Mockito.mock(TBalanceWarningRecordService.class),
|
Mockito.mock(VinManagementClient.class), Mockito.mock(ChargingCardClient.class),
|
Mockito.mock(AppUserWhitelistClient.class), appUserClient).scan();
|
|
ArgumentCaptor<SendMessageDTO> captor = ArgumentCaptor.forClass(SendMessageDTO.class);
|
Mockito.verify(appUserClient).sendMessage(captor.capture());
|
assertEquals("13711112222", captor.getValue().getPhone());
|
}
|
|
private TBalanceWarningScanServiceImpl buildService(TCompanyBalanceWarningMapper warningMapper,
|
TGroupCompanyMapper companyMapper,
|
TGroupMapper groupMapper,
|
TBalanceWarningRecordService recordService,
|
VinManagementClient vinClient,
|
ChargingCardClient cardClient,
|
AppUserWhitelistClient whitelistClient,
|
AppUserClient appUserClient) {
|
TBalanceWarningScanServiceImpl service = new TBalanceWarningScanServiceImpl();
|
ReflectionTestUtils.setField(service, "companyBalanceWarningMapper", warningMapper);
|
ReflectionTestUtils.setField(service, "groupCompanyMapper", companyMapper);
|
ReflectionTestUtils.setField(service, "groupMapper", groupMapper);
|
ReflectionTestUtils.setField(service, "balanceWarningRecordService", recordService);
|
ReflectionTestUtils.setField(service, "vinManagementClient", vinClient);
|
ReflectionTestUtils.setField(service, "chargingCardClient", cardClient);
|
ReflectionTestUtils.setField(service, "appUserWhitelistClient", whitelistClient);
|
ReflectionTestUtils.setField(service, "appUserClient", appUserClient);
|
return service;
|
}
|
|
private TCompanyBalanceWarning warning() {
|
TCompanyBalanceWarning warning = new TCompanyBalanceWarning();
|
warning.setCompanyId(11);
|
warning.setCompanyWarnAmount(new BigDecimal("1000"));
|
warning.setSubWarnAmount(new BigDecimal("200"));
|
warning.setNotifyObject(2);
|
warning.setNotifyType(1);
|
return warning;
|
}
|
|
private TGroupCompany company() {
|
TGroupCompany company = new TGroupCompany();
|
company.setId(11);
|
company.setName("利普芯科技有限公司");
|
company.setStatus(1);
|
company.setAccountMode(2);
|
return company;
|
}
|
|
private TVinManagement vin(String vin, String plateNumber, BigDecimal balance) {
|
TVinManagement entity = new TVinManagement();
|
entity.setVin(vin);
|
entity.setPlateNumber(plateNumber);
|
entity.setBalance(balance);
|
return entity;
|
}
|
|
private TAppUserWhitelist whitelist(String phone, String name, BigDecimal balance) {
|
TAppUserWhitelist entity = new TAppUserWhitelist();
|
entity.setPhone(phone);
|
entity.setName(name);
|
entity.setBalance(balance);
|
return entity;
|
}
|
|
}
|