Browse Source
- 新增 ShopCoupon 和 ShopUserCoupon 实体类 - 实现优惠券和用户优惠券的 CRUD 操作 - 添加分页查询、批量操作等接口 - 集成权限控制和操作日志记录main
59 changed files with 1187 additions and 541 deletions
@ -0,0 +1,129 @@ |
|||
package com.gxwebsoft.shop.controller; |
|||
|
|||
import com.gxwebsoft.common.core.web.BaseController; |
|||
import com.gxwebsoft.shop.service.ShopCouponService; |
|||
import com.gxwebsoft.shop.entity.ShopCoupon; |
|||
import com.gxwebsoft.shop.param.ShopCouponParam; |
|||
import com.gxwebsoft.common.core.web.ApiResult; |
|||
import com.gxwebsoft.common.core.web.PageResult; |
|||
import com.gxwebsoft.common.core.web.PageParam; |
|||
import com.gxwebsoft.common.core.web.BatchParam; |
|||
import com.gxwebsoft.common.core.annotation.OperationLog; |
|||
import com.gxwebsoft.common.system.entity.User; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 优惠券控制器 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
@Tag(name = "优惠券管理") |
|||
@RestController |
|||
@RequestMapping("/api/shop/shop-coupon") |
|||
public class ShopCouponController extends BaseController { |
|||
@Resource |
|||
private ShopCouponService shopCouponService; |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:list')") |
|||
@Operation(summary = "分页查询优惠券") |
|||
@GetMapping("/page") |
|||
public ApiResult<PageResult<ShopCoupon>> page(ShopCouponParam param) { |
|||
// 使用关联查询
|
|||
return success(shopCouponService.pageRel(param)); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:list')") |
|||
@Operation(summary = "查询全部优惠券") |
|||
@GetMapping() |
|||
public ApiResult<List<ShopCoupon>> list(ShopCouponParam param) { |
|||
// 使用关联查询
|
|||
return success(shopCouponService.listRel(param)); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:list')") |
|||
@Operation(summary = "根据id查询优惠券") |
|||
@GetMapping("/{id}") |
|||
public ApiResult<ShopCoupon> get(@PathVariable("id") Integer id) { |
|||
// 使用关联查询
|
|||
return success(shopCouponService.getByIdRel(id)); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:save')") |
|||
@OperationLog |
|||
@Operation(summary = "添加优惠券") |
|||
@PostMapping() |
|||
public ApiResult<?> save(@RequestBody ShopCoupon shopCoupon) { |
|||
// 记录当前登录用户id
|
|||
User loginUser = getLoginUser(); |
|||
if (loginUser != null) { |
|||
shopCoupon.setUserId(loginUser.getUserId()); |
|||
} |
|||
if (shopCouponService.save(shopCoupon)) { |
|||
return success("添加成功"); |
|||
} |
|||
return fail("添加失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:update')") |
|||
@OperationLog |
|||
@Operation(summary = "修改优惠券") |
|||
@PutMapping() |
|||
public ApiResult<?> update(@RequestBody ShopCoupon shopCoupon) { |
|||
if (shopCouponService.updateById(shopCoupon)) { |
|||
return success("修改成功"); |
|||
} |
|||
return fail("修改失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:remove')") |
|||
@OperationLog |
|||
@Operation(summary = "删除优惠券") |
|||
@DeleteMapping("/{id}") |
|||
public ApiResult<?> remove(@PathVariable("id") Integer id) { |
|||
if (shopCouponService.removeById(id)) { |
|||
return success("删除成功"); |
|||
} |
|||
return fail("删除失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:save')") |
|||
@OperationLog |
|||
@Operation(summary = "批量添加优惠券") |
|||
@PostMapping("/batch") |
|||
public ApiResult<?> saveBatch(@RequestBody List<ShopCoupon> list) { |
|||
if (shopCouponService.saveBatch(list)) { |
|||
return success("添加成功"); |
|||
} |
|||
return fail("添加失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:update')") |
|||
@OperationLog |
|||
@Operation(summary = "批量修改优惠券") |
|||
@PutMapping("/batch") |
|||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopCoupon> batchParam) { |
|||
if (batchParam.update(shopCouponService, "id")) { |
|||
return success("修改成功"); |
|||
} |
|||
return fail("修改失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopCoupon:remove')") |
|||
@OperationLog |
|||
@Operation(summary = "批量删除优惠券") |
|||
@DeleteMapping("/batch") |
|||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) { |
|||
if (shopCouponService.removeByIds(ids)) { |
|||
return success("删除成功"); |
|||
} |
|||
return fail("删除失败"); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,129 @@ |
|||
package com.gxwebsoft.shop.controller; |
|||
|
|||
import com.gxwebsoft.common.core.web.BaseController; |
|||
import com.gxwebsoft.shop.service.ShopUserCouponService; |
|||
import com.gxwebsoft.shop.entity.ShopUserCoupon; |
|||
import com.gxwebsoft.shop.param.ShopUserCouponParam; |
|||
import com.gxwebsoft.common.core.web.ApiResult; |
|||
import com.gxwebsoft.common.core.web.PageResult; |
|||
import com.gxwebsoft.common.core.web.PageParam; |
|||
import com.gxwebsoft.common.core.web.BatchParam; |
|||
import com.gxwebsoft.common.core.annotation.OperationLog; |
|||
import com.gxwebsoft.common.system.entity.User; |
|||
import io.swagger.v3.oas.annotations.Operation; |
|||
import io.swagger.v3.oas.annotations.tags.Tag; |
|||
import org.springframework.security.access.prepost.PreAuthorize; |
|||
import org.springframework.web.bind.annotation.*; |
|||
|
|||
import javax.annotation.Resource; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 用户优惠券控制器 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
@Tag(name = "用户优惠券管理") |
|||
@RestController |
|||
@RequestMapping("/api/shop/shop-user-coupon") |
|||
public class ShopUserCouponController extends BaseController { |
|||
@Resource |
|||
private ShopUserCouponService shopUserCouponService; |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:list')") |
|||
@Operation(summary = "分页查询用户优惠券") |
|||
@GetMapping("/page") |
|||
public ApiResult<PageResult<ShopUserCoupon>> page(ShopUserCouponParam param) { |
|||
// 使用关联查询
|
|||
return success(shopUserCouponService.pageRel(param)); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:list')") |
|||
@Operation(summary = "查询全部用户优惠券") |
|||
@GetMapping() |
|||
public ApiResult<List<ShopUserCoupon>> list(ShopUserCouponParam param) { |
|||
// 使用关联查询
|
|||
return success(shopUserCouponService.listRel(param)); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:list')") |
|||
@Operation(summary = "根据id查询用户优惠券") |
|||
@GetMapping("/{id}") |
|||
public ApiResult<ShopUserCoupon> get(@PathVariable("id") Integer id) { |
|||
// 使用关联查询
|
|||
return success(shopUserCouponService.getByIdRel(id)); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:save')") |
|||
@OperationLog |
|||
@Operation(summary = "添加用户优惠券") |
|||
@PostMapping() |
|||
public ApiResult<?> save(@RequestBody ShopUserCoupon shopUserCoupon) { |
|||
// 记录当前登录用户id
|
|||
User loginUser = getLoginUser(); |
|||
if (loginUser != null) { |
|||
shopUserCoupon.setUserId(loginUser.getUserId()); |
|||
} |
|||
if (shopUserCouponService.save(shopUserCoupon)) { |
|||
return success("添加成功"); |
|||
} |
|||
return fail("添加失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:update')") |
|||
@OperationLog |
|||
@Operation(summary = "修改用户优惠券") |
|||
@PutMapping() |
|||
public ApiResult<?> update(@RequestBody ShopUserCoupon shopUserCoupon) { |
|||
if (shopUserCouponService.updateById(shopUserCoupon)) { |
|||
return success("修改成功"); |
|||
} |
|||
return fail("修改失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:remove')") |
|||
@OperationLog |
|||
@Operation(summary = "删除用户优惠券") |
|||
@DeleteMapping("/{id}") |
|||
public ApiResult<?> remove(@PathVariable("id") Integer id) { |
|||
if (shopUserCouponService.removeById(id)) { |
|||
return success("删除成功"); |
|||
} |
|||
return fail("删除失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:save')") |
|||
@OperationLog |
|||
@Operation(summary = "批量添加用户优惠券") |
|||
@PostMapping("/batch") |
|||
public ApiResult<?> saveBatch(@RequestBody List<ShopUserCoupon> list) { |
|||
if (shopUserCouponService.saveBatch(list)) { |
|||
return success("添加成功"); |
|||
} |
|||
return fail("添加失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:update')") |
|||
@OperationLog |
|||
@Operation(summary = "批量修改用户优惠券") |
|||
@PutMapping("/batch") |
|||
public ApiResult<?> removeBatch(@RequestBody BatchParam<ShopUserCoupon> batchParam) { |
|||
if (batchParam.update(shopUserCouponService, "id")) { |
|||
return success("修改成功"); |
|||
} |
|||
return fail("修改失败"); |
|||
} |
|||
|
|||
@PreAuthorize("hasAuthority('shop:shopUserCoupon:remove')") |
|||
@OperationLog |
|||
@Operation(summary = "批量删除用户优惠券") |
|||
@DeleteMapping("/batch") |
|||
public ApiResult<?> removeBatch(@RequestBody List<Integer> ids) { |
|||
if (shopUserCouponService.removeByIds(ids)) { |
|||
return success("删除成功"); |
|||
} |
|||
return fail("删除失败"); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,105 @@ |
|||
package com.gxwebsoft.shop.entity; |
|||
|
|||
import java.math.BigDecimal; |
|||
import com.baomidou.mybatisplus.annotation.IdType; |
|||
import java.time.LocalDate; |
|||
import com.baomidou.mybatisplus.annotation.TableId; |
|||
import java.time.LocalDateTime; |
|||
import com.baomidou.mybatisplus.annotation.TableLogic; |
|||
import java.io.Serializable; |
|||
import java.util.Date; |
|||
|
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
/** |
|||
* 优惠券 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
@Data |
|||
@EqualsAndHashCode(callSuper = false) |
|||
@Schema(name = "ShopCoupon对象", description = "优惠券") |
|||
public class ShopCoupon implements Serializable { |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@Schema(description = "id") |
|||
@TableId(value = "id", type = IdType.AUTO) |
|||
private Integer id; |
|||
|
|||
@Schema(description = "优惠券名称") |
|||
private String name; |
|||
|
|||
@Schema(description = "优惠券描述") |
|||
private String description; |
|||
|
|||
@Schema(description = "优惠券类型(10满减券 20折扣券 30免费劵)") |
|||
private Integer type; |
|||
|
|||
@Schema(description = "满减券-减免金额") |
|||
private BigDecimal reducePrice; |
|||
|
|||
@Schema(description = "折扣券-折扣率(0-100)") |
|||
private Integer discount; |
|||
|
|||
@Schema(description = "最低消费金额") |
|||
private BigDecimal minPrice; |
|||
|
|||
@Schema(description = "到期类型(10领取后生效 20固定时间)") |
|||
private Integer expireType; |
|||
|
|||
@Schema(description = "领取后生效-有效天数") |
|||
private Integer expireDay; |
|||
|
|||
@Schema(description = "有效期开始时间") |
|||
private LocalDate startTime; |
|||
|
|||
@Schema(description = "有效期结束时间") |
|||
private LocalDate endTime; |
|||
|
|||
@Schema(description = "适用范围(10全部商品 20指定商品 30指定分类)") |
|||
private Integer applyRange; |
|||
|
|||
@Schema(description = "适用范围配置(json格式)") |
|||
private String applyRangeConfig; |
|||
|
|||
@Schema(description = "是否过期(0未过期 1已过期)") |
|||
private Integer isExpire; |
|||
|
|||
@Schema(description = "排序(数字越小越靠前)") |
|||
private Integer sortNumber; |
|||
|
|||
@Schema(description = "状态, 0正常, 1禁用") |
|||
private Integer status; |
|||
|
|||
@Schema(description = "是否删除, 0否, 1是") |
|||
@TableLogic |
|||
private Integer deleted; |
|||
|
|||
@Schema(description = "创建用户ID") |
|||
private Integer userId; |
|||
|
|||
@Schema(description = "租户id") |
|||
private Integer tenantId; |
|||
|
|||
@Schema(description = "创建时间") |
|||
private Data createTime; |
|||
|
|||
@Schema(description = "修改时间") |
|||
private Date updateTime; |
|||
|
|||
@Schema(description = "发放总数量(-1表示无限制)") |
|||
private Integer totalCount; |
|||
|
|||
@Schema(description = "已发放数量") |
|||
private Integer issuedCount; |
|||
|
|||
@Schema(description = "每人限领数量(-1表示无限制)") |
|||
private Integer limitPerUser; |
|||
|
|||
@Schema(description = "是否启用(0禁用 1启用)") |
|||
private Boolean enabled; |
|||
|
|||
} |
@ -0,0 +1,37 @@ |
|||
package com.gxwebsoft.shop.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.gxwebsoft.shop.entity.ShopCoupon; |
|||
import com.gxwebsoft.shop.param.ShopCouponParam; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 优惠券Mapper |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
public interface ShopCouponMapper extends BaseMapper<ShopCoupon> { |
|||
|
|||
/** |
|||
* 分页查询 |
|||
* |
|||
* @param page 分页对象 |
|||
* @param param 查询参数 |
|||
* @return List<ShopCoupon> |
|||
*/ |
|||
List<ShopCoupon> selectPageRel(@Param("page") IPage<ShopCoupon> page, |
|||
@Param("param") ShopCouponParam param); |
|||
|
|||
/** |
|||
* 查询全部 |
|||
* |
|||
* @param param 查询参数 |
|||
* @return List<User> |
|||
*/ |
|||
List<ShopCoupon> selectListRel(@Param("param") ShopCouponParam param); |
|||
|
|||
} |
@ -0,0 +1,37 @@ |
|||
package com.gxwebsoft.shop.mapper; |
|||
|
|||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
|||
import com.baomidou.mybatisplus.core.metadata.IPage; |
|||
import com.gxwebsoft.shop.entity.ShopUserCoupon; |
|||
import com.gxwebsoft.shop.param.ShopUserCouponParam; |
|||
import org.apache.ibatis.annotations.Param; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 用户优惠券Mapper |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
public interface ShopUserCouponMapper extends BaseMapper<ShopUserCoupon> { |
|||
|
|||
/** |
|||
* 分页查询 |
|||
* |
|||
* @param page 分页对象 |
|||
* @param param 查询参数 |
|||
* @return List<ShopUserCoupon> |
|||
*/ |
|||
List<ShopUserCoupon> selectPageRel(@Param("page") IPage<ShopUserCoupon> page, |
|||
@Param("param") ShopUserCouponParam param); |
|||
|
|||
/** |
|||
* 查询全部 |
|||
* |
|||
* @param param 查询参数 |
|||
* @return List<User> |
|||
*/ |
|||
List<ShopUserCoupon> selectListRel(@Param("param") ShopUserCouponParam param); |
|||
|
|||
} |
@ -0,0 +1,102 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.gxwebsoft.shop.mapper.ShopCouponMapper"> |
|||
|
|||
<!-- 关联查询sql --> |
|||
<sql id="selectSql"> |
|||
SELECT a.* |
|||
FROM shop_coupon a |
|||
<where> |
|||
<if test="param.id != null"> |
|||
AND a.id = #{param.id} |
|||
</if> |
|||
<if test="param.name != null"> |
|||
AND a.name LIKE CONCAT('%', #{param.name}, '%') |
|||
</if> |
|||
<if test="param.description != null"> |
|||
AND a.description LIKE CONCAT('%', #{param.description}, '%') |
|||
</if> |
|||
<if test="param.type != null"> |
|||
AND a.type = #{param.type} |
|||
</if> |
|||
<if test="param.reducePrice != null"> |
|||
AND a.reduce_price = #{param.reducePrice} |
|||
</if> |
|||
<if test="param.discount != null"> |
|||
AND a.discount = #{param.discount} |
|||
</if> |
|||
<if test="param.minPrice != null"> |
|||
AND a.min_price = #{param.minPrice} |
|||
</if> |
|||
<if test="param.expireType != null"> |
|||
AND a.expire_type = #{param.expireType} |
|||
</if> |
|||
<if test="param.expireDay != null"> |
|||
AND a.expire_day = #{param.expireDay} |
|||
</if> |
|||
<if test="param.startTime != null"> |
|||
AND a.start_time LIKE CONCAT('%', #{param.startTime}, '%') |
|||
</if> |
|||
<if test="param.endTime != null"> |
|||
AND a.end_time LIKE CONCAT('%', #{param.endTime}, '%') |
|||
</if> |
|||
<if test="param.applyRange != null"> |
|||
AND a.apply_range = #{param.applyRange} |
|||
</if> |
|||
<if test="param.applyRangeConfig != null"> |
|||
AND a.apply_range_config LIKE CONCAT('%', #{param.applyRangeConfig}, '%') |
|||
</if> |
|||
<if test="param.isExpire != null"> |
|||
AND a.is_expire = #{param.isExpire} |
|||
</if> |
|||
<if test="param.sortNumber != null"> |
|||
AND a.sort_number = #{param.sortNumber} |
|||
</if> |
|||
<if test="param.status != null"> |
|||
AND a.status = #{param.status} |
|||
</if> |
|||
<if test="param.deleted != null"> |
|||
AND a.deleted = #{param.deleted} |
|||
</if> |
|||
<if test="param.deleted == null"> |
|||
AND a.deleted = 0 |
|||
</if> |
|||
<if test="param.userId != null"> |
|||
AND a.user_id = #{param.userId} |
|||
</if> |
|||
<if test="param.createTimeStart != null"> |
|||
AND a.create_time >= #{param.createTimeStart} |
|||
</if> |
|||
<if test="param.createTimeEnd != null"> |
|||
AND a.create_time <= #{param.createTimeEnd} |
|||
</if> |
|||
<if test="param.totalCount != null"> |
|||
AND a.total_count = #{param.totalCount} |
|||
</if> |
|||
<if test="param.issuedCount != null"> |
|||
AND a.issued_count = #{param.issuedCount} |
|||
</if> |
|||
<if test="param.limitPerUser != null"> |
|||
AND a.limit_per_user = #{param.limitPerUser} |
|||
</if> |
|||
<if test="param.enabled != null"> |
|||
AND a.enabled = #{param.enabled} |
|||
</if> |
|||
<if test="param.keywords != null"> |
|||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') |
|||
) |
|||
</if> |
|||
</where> |
|||
</sql> |
|||
|
|||
<!-- 分页查询 --> |
|||
<select id="selectPageRel" resultType="com.gxwebsoft.shop.entity.ShopCoupon"> |
|||
<include refid="selectSql"></include> |
|||
</select> |
|||
|
|||
<!-- 查询全部 --> |
|||
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.ShopCoupon"> |
|||
<include refid="selectSql"></include> |
|||
</select> |
|||
|
|||
</mapper> |
@ -0,0 +1,96 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.gxwebsoft.shop.mapper.ShopUserCouponMapper"> |
|||
|
|||
<!-- 关联查询sql --> |
|||
<sql id="selectSql"> |
|||
SELECT a.* |
|||
FROM shop_user_coupon a |
|||
<where> |
|||
<if test="param.id != null"> |
|||
AND a.id = #{param.id} |
|||
</if> |
|||
<if test="param.couponId != null"> |
|||
AND a.coupon_id = #{param.couponId} |
|||
</if> |
|||
<if test="param.userId != null"> |
|||
AND a.user_id = #{param.userId} |
|||
</if> |
|||
<if test="param.name != null"> |
|||
AND a.name LIKE CONCAT('%', #{param.name}, '%') |
|||
</if> |
|||
<if test="param.description != null"> |
|||
AND a.description LIKE CONCAT('%', #{param.description}, '%') |
|||
</if> |
|||
<if test="param.type != null"> |
|||
AND a.type = #{param.type} |
|||
</if> |
|||
<if test="param.reducePrice != null"> |
|||
AND a.reduce_price = #{param.reducePrice} |
|||
</if> |
|||
<if test="param.discount != null"> |
|||
AND a.discount = #{param.discount} |
|||
</if> |
|||
<if test="param.minPrice != null"> |
|||
AND a.min_price = #{param.minPrice} |
|||
</if> |
|||
<if test="param.applyRange != null"> |
|||
AND a.apply_range = #{param.applyRange} |
|||
</if> |
|||
<if test="param.applyRangeConfig != null"> |
|||
AND a.apply_range_config LIKE CONCAT('%', #{param.applyRangeConfig}, '%') |
|||
</if> |
|||
<if test="param.startTime != null"> |
|||
AND a.start_time LIKE CONCAT('%', #{param.startTime}, '%') |
|||
</if> |
|||
<if test="param.endTime != null"> |
|||
AND a.end_time LIKE CONCAT('%', #{param.endTime}, '%') |
|||
</if> |
|||
<if test="param.status != null"> |
|||
AND a.status = #{param.status} |
|||
</if> |
|||
<if test="param.useTime != null"> |
|||
AND a.use_time LIKE CONCAT('%', #{param.useTime}, '%') |
|||
</if> |
|||
<if test="param.orderId != null"> |
|||
AND a.order_id LIKE CONCAT('%', #{param.orderId}, '%') |
|||
</if> |
|||
<if test="param.orderNo != null"> |
|||
AND a.order_no LIKE CONCAT('%', #{param.orderNo}, '%') |
|||
</if> |
|||
<if test="param.obtainType != null"> |
|||
AND a.obtain_type = #{param.obtainType} |
|||
</if> |
|||
<if test="param.obtainSource != null"> |
|||
AND a.obtain_source LIKE CONCAT('%', #{param.obtainSource}, '%') |
|||
</if> |
|||
<if test="param.deleted != null"> |
|||
AND a.deleted = #{param.deleted} |
|||
</if> |
|||
<if test="param.deleted == null"> |
|||
AND a.deleted = 0 |
|||
</if> |
|||
<if test="param.createTimeStart != null"> |
|||
AND a.create_time >= #{param.createTimeStart} |
|||
</if> |
|||
<if test="param.createTimeEnd != null"> |
|||
AND a.create_time <= #{param.createTimeEnd} |
|||
</if> |
|||
<if test="param.keywords != null"> |
|||
AND (a.comments LIKE CONCAT('%', #{param.keywords}, '%') |
|||
) |
|||
</if> |
|||
</where> |
|||
</sql> |
|||
|
|||
<!-- 分页查询 --> |
|||
<select id="selectPageRel" resultType="com.gxwebsoft.shop.entity.ShopUserCoupon"> |
|||
<include refid="selectSql"></include> |
|||
</select> |
|||
|
|||
<!-- 查询全部 --> |
|||
<select id="selectListRel" resultType="com.gxwebsoft.shop.entity.ShopUserCoupon"> |
|||
<include refid="selectSql"></include> |
|||
</select> |
|||
|
|||
</mapper> |
@ -0,0 +1,108 @@ |
|||
package com.gxwebsoft.shop.param; |
|||
|
|||
import java.math.BigDecimal; |
|||
import com.gxwebsoft.common.core.annotation.QueryField; |
|||
import com.gxwebsoft.common.core.annotation.QueryType; |
|||
import com.gxwebsoft.common.core.web.BaseParam; |
|||
import com.fasterxml.jackson.annotation.JsonInclude; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
/** |
|||
* 优惠券查询参数 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:37 |
|||
*/ |
|||
@Data |
|||
@EqualsAndHashCode(callSuper = false) |
|||
@JsonInclude(JsonInclude.Include.NON_NULL) |
|||
@Schema(name = "ShopCouponParam对象", description = "优惠券查询参数") |
|||
public class ShopCouponParam extends BaseParam { |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@Schema(description = "id") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer id; |
|||
|
|||
@Schema(description = "优惠券名称") |
|||
private String name; |
|||
|
|||
@Schema(description = "优惠券描述") |
|||
private String description; |
|||
|
|||
@Schema(description = "优惠券类型(10满减券 20折扣券 30免费劵)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer type; |
|||
|
|||
@Schema(description = "满减券-减免金额") |
|||
@QueryField(type = QueryType.EQ) |
|||
private BigDecimal reducePrice; |
|||
|
|||
@Schema(description = "折扣券-折扣率(0-100)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer discount; |
|||
|
|||
@Schema(description = "最低消费金额") |
|||
@QueryField(type = QueryType.EQ) |
|||
private BigDecimal minPrice; |
|||
|
|||
@Schema(description = "到期类型(10领取后生效 20固定时间)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer expireType; |
|||
|
|||
@Schema(description = "领取后生效-有效天数") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer expireDay; |
|||
|
|||
@Schema(description = "有效期开始时间") |
|||
private String startTime; |
|||
|
|||
@Schema(description = "有效期结束时间") |
|||
private String endTime; |
|||
|
|||
@Schema(description = "适用范围(10全部商品 20指定商品 30指定分类)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer applyRange; |
|||
|
|||
@Schema(description = "适用范围配置(json格式)") |
|||
private String applyRangeConfig; |
|||
|
|||
@Schema(description = "是否过期(0未过期 1已过期)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer isExpire; |
|||
|
|||
@Schema(description = "排序(数字越小越靠前)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer sortNumber; |
|||
|
|||
@Schema(description = "状态, 0正常, 1禁用") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer status; |
|||
|
|||
@Schema(description = "是否删除, 0否, 1是") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer deleted; |
|||
|
|||
@Schema(description = "创建用户ID") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer userId; |
|||
|
|||
@Schema(description = "发放总数量(-1表示无限制)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer totalCount; |
|||
|
|||
@Schema(description = "已发放数量") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer issuedCount; |
|||
|
|||
@Schema(description = "每人限领数量(-1表示无限制)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer limitPerUser; |
|||
|
|||
@Schema(description = "是否启用(0禁用 1启用)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Boolean enabled; |
|||
|
|||
} |
@ -0,0 +1,96 @@ |
|||
package com.gxwebsoft.shop.param; |
|||
|
|||
import java.math.BigDecimal; |
|||
import com.gxwebsoft.common.core.annotation.QueryField; |
|||
import com.gxwebsoft.common.core.annotation.QueryType; |
|||
import com.gxwebsoft.common.core.web.BaseParam; |
|||
import com.fasterxml.jackson.annotation.JsonInclude; |
|||
import io.swagger.v3.oas.annotations.media.Schema; |
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
/** |
|||
* 用户优惠券查询参数 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
@Data |
|||
@EqualsAndHashCode(callSuper = false) |
|||
@JsonInclude(JsonInclude.Include.NON_NULL) |
|||
@Schema(name = "ShopUserCouponParam对象", description = "用户优惠券查询参数") |
|||
public class ShopUserCouponParam extends BaseParam { |
|||
private static final long serialVersionUID = 1L; |
|||
|
|||
@Schema(description = "id") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer id; |
|||
|
|||
@Schema(description = "优惠券模板ID") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer couponId; |
|||
|
|||
@Schema(description = "用户ID") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer userId; |
|||
|
|||
@Schema(description = "优惠券名称") |
|||
private String name; |
|||
|
|||
@Schema(description = "优惠券描述") |
|||
private String description; |
|||
|
|||
@Schema(description = "优惠券类型(10满减券 20折扣券 30免费劵)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer type; |
|||
|
|||
@Schema(description = "满减券-减免金额") |
|||
@QueryField(type = QueryType.EQ) |
|||
private BigDecimal reducePrice; |
|||
|
|||
@Schema(description = "折扣券-折扣率(0-100)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer discount; |
|||
|
|||
@Schema(description = "最低消费金额") |
|||
@QueryField(type = QueryType.EQ) |
|||
private BigDecimal minPrice; |
|||
|
|||
@Schema(description = "适用范围(10全部商品 20指定商品 30指定分类)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer applyRange; |
|||
|
|||
@Schema(description = "适用范围配置(json格式)") |
|||
private String applyRangeConfig; |
|||
|
|||
@Schema(description = "有效期开始时间") |
|||
private String startTime; |
|||
|
|||
@Schema(description = "有效期结束时间") |
|||
private String endTime; |
|||
|
|||
@Schema(description = "使用状态(0未使用 1已使用 2已过期)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer status; |
|||
|
|||
@Schema(description = "使用时间") |
|||
private String useTime; |
|||
|
|||
@Schema(description = "使用订单ID") |
|||
private Long orderId; |
|||
|
|||
@Schema(description = "使用订单号") |
|||
private String orderNo; |
|||
|
|||
@Schema(description = "获取方式(10主动领取 20系统发放 30活动赠送)") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Integer obtainType; |
|||
|
|||
@Schema(description = "获取来源描述") |
|||
private String obtainSource; |
|||
|
|||
@Schema(description = "是否删除, 0否, 1是") |
|||
@QueryField(type = QueryType.EQ) |
|||
private Boolean deleted; |
|||
|
|||
} |
@ -0,0 +1,42 @@ |
|||
package com.gxwebsoft.shop.service; |
|||
|
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
import com.gxwebsoft.common.core.web.PageResult; |
|||
import com.gxwebsoft.shop.entity.ShopCoupon; |
|||
import com.gxwebsoft.shop.param.ShopCouponParam; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 优惠券Service |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
public interface ShopCouponService extends IService<ShopCoupon> { |
|||
|
|||
/** |
|||
* 分页关联查询 |
|||
* |
|||
* @param param 查询参数 |
|||
* @return PageResult<ShopCoupon> |
|||
*/ |
|||
PageResult<ShopCoupon> pageRel(ShopCouponParam param); |
|||
|
|||
/** |
|||
* 关联查询全部 |
|||
* |
|||
* @param param 查询参数 |
|||
* @return List<ShopCoupon> |
|||
*/ |
|||
List<ShopCoupon> listRel(ShopCouponParam param); |
|||
|
|||
/** |
|||
* 根据id查询 |
|||
* |
|||
* @param id id |
|||
* @return ShopCoupon |
|||
*/ |
|||
ShopCoupon getByIdRel(Integer id); |
|||
|
|||
} |
@ -0,0 +1,42 @@ |
|||
package com.gxwebsoft.shop.service; |
|||
|
|||
import com.baomidou.mybatisplus.extension.service.IService; |
|||
import com.gxwebsoft.common.core.web.PageResult; |
|||
import com.gxwebsoft.shop.entity.ShopUserCoupon; |
|||
import com.gxwebsoft.shop.param.ShopUserCouponParam; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 用户优惠券Service |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
public interface ShopUserCouponService extends IService<ShopUserCoupon> { |
|||
|
|||
/** |
|||
* 分页关联查询 |
|||
* |
|||
* @param param 查询参数 |
|||
* @return PageResult<ShopUserCoupon> |
|||
*/ |
|||
PageResult<ShopUserCoupon> pageRel(ShopUserCouponParam param); |
|||
|
|||
/** |
|||
* 关联查询全部 |
|||
* |
|||
* @param param 查询参数 |
|||
* @return List<ShopUserCoupon> |
|||
*/ |
|||
List<ShopUserCoupon> listRel(ShopUserCouponParam param); |
|||
|
|||
/** |
|||
* 根据id查询 |
|||
* |
|||
* @param id id |
|||
* @return ShopUserCoupon |
|||
*/ |
|||
ShopUserCoupon getByIdRel(Integer id); |
|||
|
|||
} |
@ -0,0 +1,47 @@ |
|||
package com.gxwebsoft.shop.service.impl; |
|||
|
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import com.gxwebsoft.shop.mapper.ShopCouponMapper; |
|||
import com.gxwebsoft.shop.service.ShopCouponService; |
|||
import com.gxwebsoft.shop.entity.ShopCoupon; |
|||
import com.gxwebsoft.shop.param.ShopCouponParam; |
|||
import com.gxwebsoft.common.core.web.PageParam; |
|||
import com.gxwebsoft.common.core.web.PageResult; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 优惠券Service实现 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
@Service |
|||
public class ShopCouponServiceImpl extends ServiceImpl<ShopCouponMapper, ShopCoupon> implements ShopCouponService { |
|||
|
|||
@Override |
|||
public PageResult<ShopCoupon> pageRel(ShopCouponParam param) { |
|||
PageParam<ShopCoupon, ShopCouponParam> page = new PageParam<>(param); |
|||
page.setDefaultOrder("sort_number asc, create_time desc"); |
|||
List<ShopCoupon> list = baseMapper.selectPageRel(page, param); |
|||
return new PageResult<>(list, page.getTotal()); |
|||
} |
|||
|
|||
@Override |
|||
public List<ShopCoupon> listRel(ShopCouponParam param) { |
|||
List<ShopCoupon> list = baseMapper.selectListRel(param); |
|||
// 排序
|
|||
PageParam<ShopCoupon, ShopCouponParam> page = new PageParam<>(); |
|||
page.setDefaultOrder("sort_number asc, create_time desc"); |
|||
return page.sortRecords(list); |
|||
} |
|||
|
|||
@Override |
|||
public ShopCoupon getByIdRel(Integer id) { |
|||
ShopCouponParam param = new ShopCouponParam(); |
|||
param.setId(id); |
|||
return param.getOne(baseMapper.selectListRel(param)); |
|||
} |
|||
|
|||
} |
@ -0,0 +1,47 @@ |
|||
package com.gxwebsoft.shop.service.impl; |
|||
|
|||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
|||
import com.gxwebsoft.shop.mapper.ShopUserCouponMapper; |
|||
import com.gxwebsoft.shop.service.ShopUserCouponService; |
|||
import com.gxwebsoft.shop.entity.ShopUserCoupon; |
|||
import com.gxwebsoft.shop.param.ShopUserCouponParam; |
|||
import com.gxwebsoft.common.core.web.PageParam; |
|||
import com.gxwebsoft.common.core.web.PageResult; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 用户优惠券Service实现 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-11 09:41:38 |
|||
*/ |
|||
@Service |
|||
public class ShopUserCouponServiceImpl extends ServiceImpl<ShopUserCouponMapper, ShopUserCoupon> implements ShopUserCouponService { |
|||
|
|||
@Override |
|||
public PageResult<ShopUserCoupon> pageRel(ShopUserCouponParam param) { |
|||
PageParam<ShopUserCoupon, ShopUserCouponParam> page = new PageParam<>(param); |
|||
page.setDefaultOrder("sort_number asc, create_time desc"); |
|||
List<ShopUserCoupon> list = baseMapper.selectPageRel(page, param); |
|||
return new PageResult<>(list, page.getTotal()); |
|||
} |
|||
|
|||
@Override |
|||
public List<ShopUserCoupon> listRel(ShopUserCouponParam param) { |
|||
List<ShopUserCoupon> list = baseMapper.selectListRel(param); |
|||
// 排序
|
|||
PageParam<ShopUserCoupon, ShopUserCouponParam> page = new PageParam<>(); |
|||
page.setDefaultOrder("sort_number asc, create_time desc"); |
|||
return page.sortRecords(list); |
|||
} |
|||
|
|||
@Override |
|||
public ShopUserCoupon getByIdRel(Integer id) { |
|||
ShopUserCouponParam param = new ShopUserCouponParam(); |
|||
param.setId(id); |
|||
return param.getOne(baseMapper.selectListRel(param)); |
|||
} |
|||
|
|||
} |
@ -1,276 +0,0 @@ |
|||
package com.gxwebsoft.shop.utils; |
|||
|
|||
import com.gxwebsoft.shop.entity.ShopUserCoupon; |
|||
|
|||
import java.math.BigDecimal; |
|||
import java.math.RoundingMode; |
|||
import java.time.LocalDateTime; |
|||
import java.time.format.DateTimeFormatter; |
|||
import java.util.Arrays; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 优惠券工具类 |
|||
* |
|||
* @author 科技小王子 |
|||
* @since 2025-08-08 23:00:00 |
|||
*/ |
|||
public class CouponUtils { |
|||
|
|||
/** |
|||
* 优惠券类型名称映射 |
|||
*/ |
|||
public static String getTypeName(Integer type) { |
|||
if (type == null) { |
|||
return "未知"; |
|||
} |
|||
switch (type) { |
|||
case 10: |
|||
return "满减券"; |
|||
case 20: |
|||
return "折扣券"; |
|||
case 30: |
|||
return "免费券"; |
|||
default: |
|||
return "未知"; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 优惠券状态名称映射 |
|||
*/ |
|||
public static String getStatusName(Integer status) { |
|||
if (status == null) { |
|||
return "未知"; |
|||
} |
|||
switch (status) { |
|||
case 0: |
|||
return "未使用"; |
|||
case 1: |
|||
return "已使用"; |
|||
case 2: |
|||
return "已过期"; |
|||
default: |
|||
return "未知"; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 适用范围名称映射 |
|||
*/ |
|||
public static String getApplyRangeName(Integer applyRange) { |
|||
if (applyRange == null) { |
|||
return "未知"; |
|||
} |
|||
switch (applyRange) { |
|||
case 10: |
|||
return "全部商品"; |
|||
case 20: |
|||
return "指定商品"; |
|||
case 30: |
|||
return "指定分类"; |
|||
default: |
|||
return "未知"; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 获取方式名称映射 |
|||
*/ |
|||
public static String getObtainTypeName(Integer obtainType) { |
|||
if (obtainType == null) { |
|||
return "未知"; |
|||
} |
|||
switch (obtainType) { |
|||
case 10: |
|||
return "主动领取"; |
|||
case 20: |
|||
return "系统发放"; |
|||
case 30: |
|||
return "活动赠送"; |
|||
default: |
|||
return "未知"; |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 计算优惠券优惠金额 |
|||
* |
|||
* @param userCoupon 用户优惠券 |
|||
* @param orderAmount 订单金额 |
|||
* @return 优惠金额 |
|||
*/ |
|||
public static BigDecimal calculateDiscountAmount(ShopUserCoupon userCoupon, BigDecimal orderAmount) { |
|||
if (userCoupon == null || orderAmount == null || orderAmount.compareTo(BigDecimal.ZERO) <= 0) { |
|||
return BigDecimal.ZERO; |
|||
} |
|||
|
|||
// 检查最低消费金额
|
|||
if (userCoupon.getMinPrice() != null && |
|||
orderAmount.compareTo(userCoupon.getMinPrice()) < 0) { |
|||
return BigDecimal.ZERO; |
|||
} |
|||
|
|||
BigDecimal discountAmount = BigDecimal.ZERO; |
|||
|
|||
if (ShopUserCoupon.TYPE_REDUCE.equals(userCoupon.getType())) { |
|||
// 满减券
|
|||
discountAmount = userCoupon.getReducePrice() != null ? |
|||
userCoupon.getReducePrice() : BigDecimal.ZERO; |
|||
} else if (ShopUserCoupon.TYPE_DISCOUNT.equals(userCoupon.getType())) { |
|||
// 折扣券
|
|||
if (userCoupon.getDiscount() != null && userCoupon.getDiscount() > 0 && userCoupon.getDiscount() < 100) { |
|||
BigDecimal discountRate = BigDecimal.valueOf(100 - userCoupon.getDiscount()) |
|||
.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_UP); |
|||
discountAmount = orderAmount.multiply(discountRate); |
|||
} |
|||
} else if (ShopUserCoupon.TYPE_FREE.equals(userCoupon.getType())) { |
|||
// 免费券
|
|||
discountAmount = orderAmount; |
|||
} |
|||
|
|||
// 优惠金额不能超过订单金额
|
|||
return discountAmount.compareTo(orderAmount) > 0 ? orderAmount : discountAmount; |
|||
} |
|||
|
|||
/** |
|||
* 检查优惠券是否适用于指定商品 |
|||
* |
|||
* @param userCoupon 用户优惠券 |
|||
* @param goodsId 商品ID |
|||
* @param categoryId 商品分类ID |
|||
* @return 是否适用 |
|||
*/ |
|||
public static boolean isApplicableToGoods(ShopUserCoupon userCoupon, Integer goodsId, Integer categoryId) { |
|||
if (userCoupon == null || userCoupon.getApplyRange() == null) { |
|||
return false; |
|||
} |
|||
|
|||
if (ShopUserCoupon.APPLY_ALL.equals(userCoupon.getApplyRange())) { |
|||
// 全部商品可用
|
|||
return true; |
|||
} else if (ShopUserCoupon.APPLY_GOODS.equals(userCoupon.getApplyRange())) { |
|||
// 指定商品可用
|
|||
if (goodsId == null || userCoupon.getApplyRangeConfig() == null || userCoupon.getApplyRangeConfig().trim().isEmpty()) { |
|||
return false; |
|||
} |
|||
List<String> goodsIds = Arrays.asList(userCoupon.getApplyRangeConfig().split(",")); |
|||
return goodsIds.contains(goodsId.toString()); |
|||
} else if (ShopUserCoupon.APPLY_CATEGORY.equals(userCoupon.getApplyRange())) { |
|||
// 指定分类可用
|
|||
if (categoryId == null || userCoupon.getApplyRangeConfig() == null || userCoupon.getApplyRangeConfig().trim().isEmpty()) { |
|||
return false; |
|||
} |
|||
List<String> categoryIds = Arrays.asList(userCoupon.getApplyRangeConfig().split(",")); |
|||
return categoryIds.contains(categoryId.toString()); |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/** |
|||
* 检查优惠券是否已过期 |
|||
* |
|||
* @param userCoupon 用户优惠券 |
|||
* @return 是否已过期 |
|||
*/ |
|||
public static boolean isExpired(ShopUserCoupon userCoupon) { |
|||
if (userCoupon == null || userCoupon.getEndTime() == null) { |
|||
return false; |
|||
} |
|||
return userCoupon.getEndTime().isBefore(LocalDateTime.now()); |
|||
} |
|||
|
|||
/** |
|||
* 检查优惠券是否可用 |
|||
* |
|||
* @param userCoupon 用户优惠券 |
|||
* @return 是否可用 |
|||
*/ |
|||
public static boolean isAvailable(ShopUserCoupon userCoupon) { |
|||
if (userCoupon == null) { |
|||
return false; |
|||
} |
|||
|
|||
// 检查状态
|
|||
if (!ShopUserCoupon.STATUS_UNUSED.equals(userCoupon.getStatus())) { |
|||
return false; |
|||
} |
|||
|
|||
// 检查是否过期
|
|||
if (isExpired(userCoupon)) { |
|||
return false; |
|||
} |
|||
|
|||
// 检查是否在有效期内
|
|||
LocalDateTime now = LocalDateTime.now(); |
|||
if (userCoupon.getStartTime() != null && userCoupon.getStartTime().isAfter(now)) { |
|||
return false; // 还未开始
|
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 格式化优惠券显示文本 |
|||
* |
|||
* @param userCoupon 用户优惠券 |
|||
* @return 显示文本 |
|||
*/ |
|||
public static String formatCouponDisplay(ShopUserCoupon userCoupon) { |
|||
if (userCoupon == null) { |
|||
return ""; |
|||
} |
|||
|
|||
StringBuilder sb = new StringBuilder(); |
|||
sb.append(userCoupon.getName()); |
|||
|
|||
if (ShopUserCoupon.TYPE_REDUCE.equals(userCoupon.getType()) && userCoupon.getReducePrice() != null) { |
|||
sb.append(" 减").append(userCoupon.getReducePrice()).append("元"); |
|||
if (userCoupon.getMinPrice() != null && userCoupon.getMinPrice().compareTo(BigDecimal.ZERO) > 0) { |
|||
sb.append("(满").append(userCoupon.getMinPrice()).append("可用)"); |
|||
} |
|||
} else if (ShopUserCoupon.TYPE_DISCOUNT.equals(userCoupon.getType()) && userCoupon.getDiscount() != null) { |
|||
sb.append(" ").append(userCoupon.getDiscount()).append("折"); |
|||
if (userCoupon.getMinPrice() != null && userCoupon.getMinPrice().compareTo(BigDecimal.ZERO) > 0) { |
|||
sb.append("(满").append(userCoupon.getMinPrice()).append("可用)"); |
|||
} |
|||
} else if (ShopUserCoupon.TYPE_FREE.equals(userCoupon.getType())) { |
|||
sb.append(" 免费券"); |
|||
} |
|||
|
|||
if (userCoupon.getEndTime() != null) { |
|||
sb.append(" 有效期至").append(userCoupon.getEndTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); |
|||
} |
|||
|
|||
return sb.toString(); |
|||
} |
|||
|
|||
/** |
|||
* 生成优惠券编码 |
|||
* |
|||
* @param userId 用户ID |
|||
* @param couponId 优惠券模板ID |
|||
* @return 优惠券编码 |
|||
*/ |
|||
public static String generateCouponCode(Integer userId, Integer couponId) { |
|||
String timestamp = String.valueOf(System.currentTimeMillis()); |
|||
return String.format("CPN%s%s%s", |
|||
String.format("%08d", userId), |
|||
String.format("%06d", couponId), |
|||
timestamp.substring(timestamp.length() - 6)); |
|||
} |
|||
|
|||
/** |
|||
* 验证优惠券编码格式 |
|||
* |
|||
* @param couponCode 优惠券编码 |
|||
* @return 是否有效 |
|||
*/ |
|||
public static boolean isValidCouponCode(String couponCode) { |
|||
if (couponCode == null || couponCode.length() != 23) { |
|||
return false; |
|||
} |
|||
return couponCode.startsWith("CPN") && couponCode.substring(3).matches("\\d{20}"); |
|||
} |
|||
} |
@ -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)); |
|||
} |
|||
} |
Loading…
Reference in new issue