diff --git a/src/main/java/com/ycwl/basic/pricing/dto/CouponClaimRequest.java b/src/main/java/com/ycwl/basic/pricing/dto/CouponClaimRequest.java new file mode 100644 index 0000000..fc27050 --- /dev/null +++ b/src/main/java/com/ycwl/basic/pricing/dto/CouponClaimRequest.java @@ -0,0 +1,51 @@ +package com.ycwl.basic.pricing.dto; + +import lombok.Data; + +/** + * 优惠券领取请求DTO + */ +@Data +public class CouponClaimRequest { + + /** + * 用户ID + */ + private Long userId; + + /** + * 优惠券ID + */ + private Long couponId; + + /** + * 景区ID(可选,记录在哪个景区领取) + */ + private String scenicId; + + /** + * 领取来源(可选,如:活动页面、签到奖励等) + */ + private String claimSource; + + public CouponClaimRequest() { + } + + public CouponClaimRequest(Long userId, Long couponId) { + this.userId = userId; + this.couponId = couponId; + } + + public CouponClaimRequest(Long userId, Long couponId, String scenicId) { + this.userId = userId; + this.couponId = couponId; + this.scenicId = scenicId; + } + + public CouponClaimRequest(Long userId, Long couponId, String scenicId, String claimSource) { + this.userId = userId; + this.couponId = couponId; + this.scenicId = scenicId; + this.claimSource = claimSource; + } +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/dto/CouponClaimResult.java b/src/main/java/com/ycwl/basic/pricing/dto/CouponClaimResult.java new file mode 100644 index 0000000..d9173ed --- /dev/null +++ b/src/main/java/com/ycwl/basic/pricing/dto/CouponClaimResult.java @@ -0,0 +1,100 @@ +package com.ycwl.basic.pricing.dto; + +import com.ycwl.basic.pricing.entity.PriceCouponClaimRecord; +import lombok.Data; + +import java.util.Date; + +/** + * 优惠券领取结果DTO + */ +@Data +public class CouponClaimResult { + + /** + * 是否成功 + */ + private boolean success; + + /** + * 错误消息(失败时) + */ + private String errorMessage; + + /** + * 错误码(失败时) + */ + private String errorCode; + + /** + * 领取记录ID(成功时) + */ + private Long claimRecordId; + + /** + * 优惠券ID + */ + private Long couponId; + + /** + * 优惠券名称 + */ + private String couponName; + + /** + * 领取时间 + */ + private Date claimTime; + + /** + * 用户ID + */ + private Long userId; + + /** + * 景区ID + */ + private String scenicId; + + /** + * 创建成功结果 + */ + public static CouponClaimResult success(PriceCouponClaimRecord record, String couponName) { + CouponClaimResult result = new CouponClaimResult(); + result.success = true; + result.claimRecordId = record.getId(); + result.couponId = record.getCouponId(); + result.couponName = couponName; + result.claimTime = record.getClaimTime(); + result.userId = record.getUserId(); + result.scenicId = record.getScenicId(); + return result; + } + + /** + * 创建失败结果 + */ + public static CouponClaimResult failure(String errorCode, String errorMessage) { + CouponClaimResult result = new CouponClaimResult(); + result.success = false; + result.errorCode = errorCode; + result.errorMessage = errorMessage; + return result; + } + + /** + * 创建失败结果(仅错误消息) + */ + public static CouponClaimResult failure(String errorMessage) { + return failure("CLAIM_FAILED", errorMessage); + } + + // 常用错误码常量 + public static final String ERROR_COUPON_NOT_FOUND = "COUPON_NOT_FOUND"; + public static final String ERROR_COUPON_EXPIRED = "COUPON_EXPIRED"; + public static final String ERROR_COUPON_INACTIVE = "COUPON_INACTIVE"; + public static final String ERROR_COUPON_OUT_OF_STOCK = "COUPON_OUT_OF_STOCK"; + public static final String ERROR_ALREADY_CLAIMED = "ALREADY_CLAIMED"; + public static final String ERROR_INVALID_PARAMS = "INVALID_PARAMS"; + public static final String ERROR_SYSTEM_ERROR = "SYSTEM_ERROR"; +} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/service/ICouponService.java b/src/main/java/com/ycwl/basic/pricing/service/ICouponService.java index 3acd166..21a84ff 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/ICouponService.java +++ b/src/main/java/com/ycwl/basic/pricing/service/ICouponService.java @@ -3,6 +3,8 @@ package com.ycwl.basic.pricing.service; import com.ycwl.basic.pricing.dto.CouponInfo; import com.ycwl.basic.pricing.dto.CouponUseRequest; import com.ycwl.basic.pricing.dto.CouponUseResult; +import com.ycwl.basic.pricing.dto.CouponClaimRequest; +import com.ycwl.basic.pricing.dto.CouponClaimResult; import com.ycwl.basic.pricing.dto.ProductItem; import com.ycwl.basic.pricing.entity.PriceCouponConfig; @@ -59,4 +61,12 @@ public interface ICouponService { * @return 可用优惠券列表 */ List getUserAvailableCoupons(Long userId); + + /** + * 领取优惠券(内部调用方法) + * + * @param request 领取请求 + * @return 领取结果 + */ + CouponClaimResult claimCoupon(CouponClaimRequest request); } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java b/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java index 82bbc13..7235076 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java +++ b/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java @@ -196,4 +196,90 @@ public class CouponServiceImpl implements ICouponService { info.setActualDiscountAmount(actualDiscountAmount); return info; } + + @Override + @Transactional + public CouponClaimResult claimCoupon(CouponClaimRequest request) { + log.info("开始领取优惠券: userId={}, couponId={}, scenicId={}", + request.getUserId(), request.getCouponId(), request.getScenicId()); + + try { + // 1. 参数验证 + if (request.getUserId() == null || request.getCouponId() == null) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_INVALID_PARAMS, "用户ID和优惠券ID不能为空"); + } + + // 2. 查询优惠券配置 + PriceCouponConfig coupon = couponConfigMapper.selectById(request.getCouponId()); + if (coupon == null || coupon.getDeleted() == 1) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_NOT_FOUND, "优惠券不存在"); + } + + // 3. 检查优惠券是否启用 + if (!Boolean.TRUE.equals(coupon.getIsActive())) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_INACTIVE, "优惠券已停用"); + } + + // 4. 检查优惠券有效期 + LocalDateTime now = LocalDateTime.now(); + if (coupon.getValidFrom() != null && now.isBefore(coupon.getValidFrom())) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_EXPIRED, "优惠券尚未生效"); + } + if (coupon.getValidUntil() != null && now.isAfter(coupon.getValidUntil())) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_EXPIRED, "优惠券已过期"); + } + + // 5. 检查库存(如果有总量限制) + if (coupon.getTotalQuantity() != null && coupon.getUsedQuantity() != null) { + if (coupon.getUsedQuantity() >= coupon.getTotalQuantity()) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_COUPON_OUT_OF_STOCK, "优惠券已领完"); + } + } + + // 6. 检查用户是否已经领取过该优惠券 + PriceCouponClaimRecord existingRecord = couponClaimRecordMapper.selectUserCouponRecord( + request.getUserId(), request.getCouponId()); + if (existingRecord != null) { + return CouponClaimResult.failure(CouponClaimResult.ERROR_ALREADY_CLAIMED, "您已经领取过该优惠券"); + } + + // 7. 创建领取记录 + Date claimTime = new Date(); + PriceCouponClaimRecord claimRecord = new PriceCouponClaimRecord(); + claimRecord.setCouponId(request.getCouponId()); + claimRecord.setUserId(request.getUserId()); + claimRecord.setClaimTime(claimTime); + claimRecord.setStatus(CouponStatus.CLAIMED); + claimRecord.setScenicId(request.getScenicId()); + claimRecord.setCreateTime(claimTime); + claimRecord.setUpdateTime(claimTime); + claimRecord.setDeleted(0); + + // 8. 插入领取记录 + int insertResult = couponClaimRecordMapper.insert(claimRecord); + if (insertResult <= 0) { + log.error("插入优惠券领取记录失败: userId={}, couponId={}", + request.getUserId(), request.getCouponId()); + return CouponClaimResult.failure(CouponClaimResult.ERROR_SYSTEM_ERROR, "领取失败,请稍后重试"); + } + + // 9. 更新优惠券已使用数量(如果有总量限制) + if (coupon.getTotalQuantity() != null) { + int updatedUsedQuantity = (coupon.getUsedQuantity() == null ? 0 : coupon.getUsedQuantity()) + 1; + coupon.setUsedQuantity(updatedUsedQuantity); + couponConfigMapper.updateById(coupon); + } + + log.info("优惠券领取成功: userId={}, couponId={}, claimRecordId={}", + request.getUserId(), request.getCouponId(), claimRecord.getId()); + + // 10. 返回成功结果 + return CouponClaimResult.success(claimRecord, coupon.getCouponName()); + + } catch (Exception e) { + log.error("领取优惠券失败: userId={}, couponId={}", + request.getUserId(), request.getCouponId(), e); + return CouponClaimResult.failure(CouponClaimResult.ERROR_SYSTEM_ERROR, "系统错误,领取失败:" + e.getMessage()); + } + } } \ No newline at end of file