feat(shop): 添加优惠券管理和用户优惠券管理功能

- 新增 ShopCoupon 和 ShopUserCoupon 实体类
- 实现优惠券和用户优惠券的 CRUD 操作
- 添加分页查询、批量操作等接口
- 集成权限控制和操作日志记录
This commit is contained in:
2025-08-11 09:49:27 +08:00
parent 0c58ced973
commit 735f9b6f90
59 changed files with 1187 additions and 541 deletions

View File

@@ -50,7 +50,6 @@ public class ShopGenerator {
// "shop_spec",
// "shop_spec_value",
// "shop_goods",
// "shop_coupon",
// "shop_category",
// "shop_goods_spec",
// "shop_goods_sku",

View File

@@ -1,156 +0,0 @@
package com.gxwebsoft.shop.utils;
import com.gxwebsoft.shop.entity.ShopUserCoupon;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* CouponUtils 测试类
*/
public class CouponUtilsTest {
@Test
public void testGetTypeName() {
assertEquals("满减券", CouponUtils.getTypeName(ShopUserCoupon.TYPE_REDUCE));
assertEquals("折扣券", CouponUtils.getTypeName(ShopUserCoupon.TYPE_DISCOUNT));
assertEquals("免费券", CouponUtils.getTypeName(ShopUserCoupon.TYPE_FREE));
assertEquals("未知", CouponUtils.getTypeName(null));
assertEquals("未知", CouponUtils.getTypeName(99));
}
@Test
public void testGetStatusName() {
assertEquals("未使用", CouponUtils.getStatusName(ShopUserCoupon.STATUS_UNUSED));
assertEquals("已使用", CouponUtils.getStatusName(ShopUserCoupon.STATUS_USED));
assertEquals("已过期", CouponUtils.getStatusName(ShopUserCoupon.STATUS_EXPIRED));
assertEquals("未知", CouponUtils.getStatusName(null));
assertEquals("未知", CouponUtils.getStatusName(99));
}
@Test
public void testGetApplyRangeName() {
assertEquals("全部商品", CouponUtils.getApplyRangeName(ShopUserCoupon.APPLY_ALL));
assertEquals("指定商品", CouponUtils.getApplyRangeName(ShopUserCoupon.APPLY_GOODS));
assertEquals("指定分类", CouponUtils.getApplyRangeName(ShopUserCoupon.APPLY_CATEGORY));
assertEquals("未知", CouponUtils.getApplyRangeName(null));
assertEquals("未知", CouponUtils.getApplyRangeName(99));
}
@Test
public void testCalculateDiscountAmount() {
// 测试满减券
ShopUserCoupon reduceCoupon = new ShopUserCoupon();
reduceCoupon.setType(ShopUserCoupon.TYPE_REDUCE);
reduceCoupon.setReducePrice(new BigDecimal("10.00"));
reduceCoupon.setMinPrice(new BigDecimal("50.00"));
BigDecimal discount = CouponUtils.calculateDiscountAmount(reduceCoupon, new BigDecimal("100.00"));
assertEquals(0, new BigDecimal("10.00").compareTo(discount));
// 测试不满足最低消费
discount = CouponUtils.calculateDiscountAmount(reduceCoupon, new BigDecimal("30.00"));
assertEquals(0, BigDecimal.ZERO.compareTo(discount));
// 测试折扣券
ShopUserCoupon discountCoupon = new ShopUserCoupon();
discountCoupon.setType(ShopUserCoupon.TYPE_DISCOUNT);
discountCoupon.setDiscount(80); // 8折
discountCoupon.setMinPrice(new BigDecimal("50.00"));
discount = CouponUtils.calculateDiscountAmount(discountCoupon, new BigDecimal("100.00"));
assertEquals(0, new BigDecimal("20.0000").compareTo(discount));
// 测试免费券
ShopUserCoupon freeCoupon = new ShopUserCoupon();
freeCoupon.setType(ShopUserCoupon.TYPE_FREE);
discount = CouponUtils.calculateDiscountAmount(freeCoupon, new BigDecimal("100.00"));
assertEquals(0, new BigDecimal("100.00").compareTo(discount));
}
@Test
public void testIsApplicableToGoods() {
// 测试全部商品可用
ShopUserCoupon allCoupon = new ShopUserCoupon();
allCoupon.setApplyRange(ShopUserCoupon.APPLY_ALL);
assertTrue(CouponUtils.isApplicableToGoods(allCoupon, 123, 456));
// 测试指定商品可用
ShopUserCoupon goodsCoupon = new ShopUserCoupon();
goodsCoupon.setApplyRange(ShopUserCoupon.APPLY_GOODS);
goodsCoupon.setApplyRangeConfig("123,456,789");
assertTrue(CouponUtils.isApplicableToGoods(goodsCoupon, 123, 999));
assertFalse(CouponUtils.isApplicableToGoods(goodsCoupon, 999, 999));
// 测试指定分类可用
ShopUserCoupon categoryCoupon = new ShopUserCoupon();
categoryCoupon.setApplyRange(ShopUserCoupon.APPLY_CATEGORY);
categoryCoupon.setApplyRangeConfig("10,20,30");
assertTrue(CouponUtils.isApplicableToGoods(categoryCoupon, 999, 20));
assertFalse(CouponUtils.isApplicableToGoods(categoryCoupon, 999, 99));
}
@Test
public void testIsExpired() {
ShopUserCoupon coupon = new ShopUserCoupon();
// 测试未过期
coupon.setEndTime(LocalDateTime.now().plusDays(1));
assertFalse(CouponUtils.isExpired(coupon));
// 测试已过期
coupon.setEndTime(LocalDateTime.now().minusDays(1));
assertTrue(CouponUtils.isExpired(coupon));
// 测试无结束时间
coupon.setEndTime(null);
assertFalse(CouponUtils.isExpired(coupon));
}
@Test
public void testIsAvailable() {
ShopUserCoupon coupon = new ShopUserCoupon();
coupon.setStatus(ShopUserCoupon.STATUS_UNUSED);
coupon.setStartTime(LocalDateTime.now().minusDays(1));
coupon.setEndTime(LocalDateTime.now().plusDays(1));
assertTrue(CouponUtils.isAvailable(coupon));
// 测试已使用
coupon.setStatus(ShopUserCoupon.STATUS_USED);
assertFalse(CouponUtils.isAvailable(coupon));
// 测试已过期
coupon.setStatus(ShopUserCoupon.STATUS_UNUSED);
coupon.setEndTime(LocalDateTime.now().minusDays(1));
assertFalse(CouponUtils.isAvailable(coupon));
// 测试还未开始
coupon.setEndTime(LocalDateTime.now().plusDays(1));
coupon.setStartTime(LocalDateTime.now().plusDays(1));
assertFalse(CouponUtils.isAvailable(coupon));
}
@Test
public void testIsValidCouponCode() {
assertTrue(CouponUtils.isValidCouponCode("CPN00000001000001123456"));
assertFalse(CouponUtils.isValidCouponCode("CPN123"));
assertFalse(CouponUtils.isValidCouponCode("ABC00000001000001123456"));
assertFalse(CouponUtils.isValidCouponCode(null));
}
@Test
public void testGenerateCouponCode() {
String code = CouponUtils.generateCouponCode(1, 1);
assertNotNull(code);
assertTrue(code.startsWith("CPN"));
assertEquals(23, code.length());
assertTrue(CouponUtils.isValidCouponCode(code));
}
}