Files
FrameTour-BE/src/test/java/com/ycwl/basic/pricing/service/ReusableVoucherServiceTest.java
Jerry Yan 5d5643e7d7 feat(pricing): 新增照片打印SKU及价格计算逻辑
- 添加 PHOTO_PRINT_MU 和 PHOTO_PRINT_FX 枚举类型定义
- 实现手机照片打印和特效照片打印的基础价格计算(单价×数量)
- 支持景区特定配置的价格计算逻辑
- 验证新SKU与现有 PHOTO_PRINT 的行为一致性
- 添加相关单元测试确保价格计算准确性
2025-11-17 08:53:08 +08:00

206 lines
8.6 KiB
Java

package com.ycwl.basic.pricing.service;
import com.ycwl.basic.pricing.dto.VoucherInfo;
import com.ycwl.basic.pricing.entity.PriceVoucherBatchConfig;
import com.ycwl.basic.pricing.entity.PriceVoucherCode;
import com.ycwl.basic.pricing.entity.PriceVoucherUsageRecord;
import com.ycwl.basic.pricing.enums.VoucherCodeStatus;
import com.ycwl.basic.pricing.enums.VoucherDiscountType;
import com.ycwl.basic.pricing.mapper.PriceVoucherBatchConfigMapper;
import com.ycwl.basic.pricing.mapper.PriceVoucherCodeMapper;
import com.ycwl.basic.pricing.mapper.PriceVoucherUsageRecordMapper;
import com.ycwl.basic.pricing.service.impl.VoucherServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.math.BigDecimal;
import java.util.Date;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;
/**
* 可重复使用券码服务测试
*/
public class ReusableVoucherServiceTest {
@Mock
private PriceVoucherCodeMapper voucherCodeMapper;
@Mock
private PriceVoucherBatchConfigMapper voucherBatchConfigMapper;
@Mock
private PriceVoucherUsageRecordMapper usageRecordMapper;
@InjectMocks
private VoucherServiceImpl voucherService;
private PriceVoucherCode testVoucherCode;
private PriceVoucherBatchConfig testBatchConfig;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
// 创建测试数据
testVoucherCode = new PriceVoucherCode();
testVoucherCode.setId(1L);
testVoucherCode.setCode("TEST123");
testVoucherCode.setBatchId(1L);
testVoucherCode.setScenicId(1L);
testVoucherCode.setFaceId(1001L);
testVoucherCode.setStatus(VoucherCodeStatus.CLAIMED_AVAILABLE.getCode());
testVoucherCode.setCurrentUseCount(1);
testVoucherCode.setLastUsedTime(new Date());
testVoucherCode.setDeleted(0);
testBatchConfig = new PriceVoucherBatchConfig();
testBatchConfig.setId(1L);
testBatchConfig.setBatchName("测试批次");
testBatchConfig.setDiscountType(VoucherDiscountType.REDUCE_PRICE.getCode());
testBatchConfig.setDiscountValue(new BigDecimal("10.00"));
testBatchConfig.setMaxUseCount(3); // 可使用3次
testBatchConfig.setMaxUsePerUser(2); // 每用户最多2次
testBatchConfig.setUseIntervalHours(24); // 间隔24小时
testBatchConfig.setStatus(1);
testBatchConfig.setDeleted(0);
}
@Test
void testValidateReusableVoucherCode_Success() {
// Given
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
when(usageRecordMapper.countByFaceIdAndVoucherCodeId(1001L, 1L)).thenReturn(1); // 用户已使用1次
// 模拟距离上次使用已超过24小时
Date lastUseTime = new Date(System.currentTimeMillis() - 25 * 60 * 60 * 1000); // 25小时前
when(usageRecordMapper.getLastUseTimeByFaceIdAndVoucherCodeId(1001L, 1L)).thenReturn(lastUseTime);
// When
VoucherInfo result = voucherService.validateAndGetVoucherInfo("TEST123", 1001L, 1L);
// Then
assertNotNull(result);
assertEquals("TEST123", result.getVoucherCode());
assertTrue(result.getAvailable());
assertEquals(Integer.valueOf(1), result.getCurrentUseCount());
assertEquals(Integer.valueOf(3), result.getMaxUseCount());
assertEquals(Integer.valueOf(2), result.getRemainingUseCount());
}
@Test
void testValidateVoucherCode_ReachedMaxUseCount() {
// Given - 券码已达到最大使用次数
testVoucherCode.setCurrentUseCount(3);
testVoucherCode.setStatus(VoucherCodeStatus.CLAIMED_EXHAUSTED.getCode());
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
// When
VoucherInfo result = voucherService.validateAndGetVoucherInfo("TEST123", 1001L, 1L);
// Then
assertNotNull(result);
assertFalse(result.getAvailable());
assertEquals("券码已用完", result.getUnavailableReason());
}
@Test
void testValidateVoucherCode_UserReachedMaxUsePerUser() {
// Given - 用户已达到个人使用上限
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
when(usageRecordMapper.countByFaceIdAndVoucherCodeId(1001L, 1L)).thenReturn(2); // 用户已使用2次
// When
VoucherInfo result = voucherService.validateAndGetVoucherInfo("TEST123", 1001L, 1L);
// Then
assertNotNull(result);
assertFalse(result.getAvailable());
assertEquals("您使用该券码的次数已达上限", result.getUnavailableReason());
}
@Test
void testValidateVoucherCode_WithinInterval() {
// Given - 距离上次使用不足24小时
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
when(usageRecordMapper.countByFaceIdAndVoucherCodeId(1001L, 1L)).thenReturn(1);
// 模拟距离上次使用仅10小时
Date lastUseTime = new Date(System.currentTimeMillis() - 10 * 60 * 60 * 1000);
when(usageRecordMapper.getLastUseTimeByFaceIdAndVoucherCodeId(1001L, 1L)).thenReturn(lastUseTime);
// When
VoucherInfo result = voucherService.validateAndGetVoucherInfo("TEST123", 1001L, 1L);
// Then
assertNotNull(result);
assertFalse(result.getAvailable());
assertTrue(result.getUnavailableReason().contains("请等待"));
assertTrue(result.getUnavailableReason().contains("小时后再次使用"));
}
@Test
void testMarkVoucherAsUsed_UpdateCountAndStatus() {
// Given
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
// When
voucherService.markVoucherAsUsed("TEST123", "测试使用", "ORDER001", new BigDecimal("10.00"), 1L);
// Then
verify(usageRecordMapper, times(1)).insert(any(PriceVoucherUsageRecord.class));
verify(voucherCodeMapper, times(1)).updateById(any(PriceVoucherCode.class));
verify(voucherBatchConfigMapper, times(1)).updateUsedCount(eq(1L), eq(1));
}
@Test
void testMarkVoucherAsUsed_ReachMaxUseCount() {
// Given - 使用后将达到最大使用次数
testVoucherCode.setCurrentUseCount(2); // 当前已使用2次,再使用1次将达到上限3次
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
// When
voucherService.markVoucherAsUsed("TEST123", "测试使用", "ORDER001", new BigDecimal("10.00"), 1L);
// Then
verify(usageRecordMapper, times(1)).insert(any(PriceVoucherUsageRecord.class));
verify(voucherCodeMapper, times(1)).updateById(argThat(voucherCode ->
voucherCode.getCurrentUseCount() == 3 &&
voucherCode.getStatus().equals(VoucherCodeStatus.CLAIMED_EXHAUSTED.getCode())
));
verify(voucherBatchConfigMapper, times(1)).updateUsedCount(eq(1L), eq(1));
}
@Test
void testMarkVoucherAsUsed_SingleUseCompatibility() {
// Given - 测试单次使用兼容性(maxUseCount = 1)
testBatchConfig.setMaxUseCount(1);
testVoucherCode.setCurrentUseCount(0);
when(voucherCodeMapper.selectByCode("TEST123")).thenReturn(testVoucherCode);
when(voucherBatchConfigMapper.selectById(1L)).thenReturn(testBatchConfig);
// When
voucherService.markVoucherAsUsed("TEST123", "测试使用", "ORDER001", new BigDecimal("10.00"), 1L);
// Then - 应该设置为USED状态以兼容原有逻辑
verify(voucherCodeMapper, times(1)).updateById(argThat(voucherCode ->
voucherCode.getCurrentUseCount() == 1 &&
voucherCode.getStatus().equals(VoucherCodeStatus.USED.getCode()) &&
voucherCode.getUsedTime() != null
));
}
}