优惠券相关+后台

This commit is contained in:
2025-07-25 11:17:43 +08:00
parent 587c9de5b2
commit 1a1eb79914
12 changed files with 167 additions and 35 deletions

View File

@@ -1,42 +1,45 @@
package com.ycwl.basic.controller.mobile; package com.ycwl.basic.controller.mobile;
import com.ycwl.basic.constant.BaseContextHandler;
import com.ycwl.basic.model.mobile.coupon.req.ClaimCouponReq;
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity; import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
import com.ycwl.basic.service.mobile.CouponRecordService; import com.ycwl.basic.service.mobile.AppCouponRecordService;
import com.ycwl.basic.utils.ApiResponse; import com.ycwl.basic.utils.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController @RestController
@RequestMapping("/api/mobile/coupon/v1") @RequestMapping("/api/mobile/coupon/v1")
public class AppCouponController { public class AppCouponController {
@Autowired @Autowired
private CouponRecordService couponRecordService; private AppCouponRecordService appCouponRecordService;
/** /**
* 根据memberIdfaceId查找优惠券记录 * 根据memberIdfaceId和type查找优惠券记录
*/ */
@GetMapping("/records") @GetMapping("/record")
public ApiResponse<List<CouponRecordEntity>> getCouponRecords( public ApiResponse<CouponRecordEntity> getCouponRecords(
@RequestParam Long memberId, @RequestParam Long faceId,
@RequestParam Long faceId) { @RequestParam Integer type) {
List<CouponRecordEntity> records = couponRecordService.queryByMemberIdAndFaceId(memberId, faceId); CouponRecordEntity record = appCouponRecordService.queryByMemberIdAndFaceIdAndType(Long.valueOf(BaseContextHandler.getUserId()), faceId, type);
return ApiResponse.success(records); return ApiResponse.success(record);
} }
/** /**
* 领取优惠券 * 领取优惠券
*/ */
@PostMapping("/claim") @PostMapping("/claim")
public ApiResponse<CouponRecordEntity> claimCoupon( public ApiResponse<CouponEntity> claimCoupon(@RequestBody ClaimCouponReq request) {
@RequestParam Long memberId, request.setMemberId(Long.valueOf(BaseContextHandler.getUserId()));
@RequestParam Long faceId,
@RequestParam Integer type) {
try { try {
CouponRecordEntity record = couponRecordService.claimCoupon(memberId, faceId, type); CouponEntity coupon = appCouponRecordService.claimCoupon(
return ApiResponse.success(record); request.getMemberId(),
request.getFaceId(),
request.getType()
);
return ApiResponse.success(coupon);
} catch (RuntimeException e) { } catch (RuntimeException e) {
return ApiResponse.fail(e.getMessage()); return ApiResponse.fail(e.getMessage());
} }

View File

@@ -0,0 +1,22 @@
package com.ycwl.basic.controller.pc;
import com.github.pagehelper.PageInfo;
import com.ycwl.basic.model.pc.couponRecord.req.CouponRecordPageQueryReq;
import com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordPageResp;
import com.ycwl.basic.service.pc.CouponRecordService;
import com.ycwl.basic.utils.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/coupon/record/v1")
public class CouponRecordController {
@Autowired
private CouponRecordService couponRecordService;
@PostMapping("/page")
public ApiResponse<PageInfo<CouponRecordPageResp>> pageQuery(@RequestBody CouponRecordPageQueryReq query) {
return couponRecordService.pageQuery(query);
}
}

View File

@@ -2,6 +2,8 @@ package com.ycwl.basic.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity; import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
import com.ycwl.basic.model.pc.couponRecord.req.CouponRecordPageQueryReq;
import com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordPageResp;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import java.util.List; import java.util.List;
@@ -13,4 +15,6 @@ public interface CouponRecordMapper extends BaseMapper<CouponRecordEntity> {
List<CouponRecordEntity> queryByMemberIdAndFaceId(Long memberId, Long faceId); List<CouponRecordEntity> queryByMemberIdAndFaceId(Long memberId, Long faceId);
CouponRecordEntity queryByMemberIdAndFaceIdAndType(Long memberId, Long faceId, Integer type); CouponRecordEntity queryByMemberIdAndFaceIdAndType(Long memberId, Long faceId, Integer type);
List<CouponRecordPageResp> selectByPageQuery(CouponRecordPageQueryReq query);
} }

View File

@@ -40,8 +40,12 @@ public class VideoGoodsDetailVO {
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
private Date shotTime; private Date shotTime;
// 价格 // 价格
private Integer couponId;
private Integer couponRecordId;
private BigDecimal couponPrice;
private BigDecimal origPrice;
private String price; private String price;
private String slashPrice; private BigDecimal slashPrice;
// 是否已购买 0否 1是 // 是否已购买 0否 1是
private Integer isBuy; private Integer isBuy;
// 镜头数 // 镜头数
@@ -51,4 +55,14 @@ public class VideoGoodsDetailVO {
private Integer height; private Integer height;
private Integer width; private Integer width;
private BigDecimal duration; private BigDecimal duration;
public BigDecimal getDiscountPrice() {
if (slashPrice == null) {
return BigDecimal.ZERO;
}
if (slashPrice.compareTo(BigDecimal.ZERO) <= 0) {
return BigDecimal.ZERO;
}
return slashPrice.subtract(origPrice);
}
} }

View File

@@ -45,4 +45,20 @@ public class CouponEntity {
return originalPrice.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN).multiply(discountPrice); return originalPrice.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN).multiply(discountPrice);
} }
} }
public BigDecimal calculateDiscountPrice(String originalPrice) {
BigDecimal priceObj = new BigDecimal(originalPrice);
if (discountType == 0) {
return discountPrice;
} else {
return priceObj.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN).multiply(discountPrice);
}
}
public String calculateDiscountedPrice(String originalPrice) {
BigDecimal priceObj = new BigDecimal(originalPrice);
if (discountType == 0) {
return priceObj.subtract(discountPrice).setScale(2, RoundingMode.HALF_DOWN).toString();
} else {
return priceObj.subtract(priceObj.divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_DOWN).multiply(discountPrice)).setScale(2, RoundingMode.HALF_DOWN).toString();
}
}
} }

View File

@@ -2,11 +2,13 @@ package com.ycwl.basic.model.pc.couponRecord.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import java.util.Date; import java.util.Date;
@Data @Data
@TableName("coupon_record")
public class CouponRecordEntity { public class CouponRecordEntity {
@TableId(value = "id", type = IdType.AUTO) @TableId(value = "id", type = IdType.AUTO)
private Integer id; private Integer id;

View File

@@ -9,4 +9,5 @@ public class CouponRecordPageQueryReq {
private Long scenicId; private Long scenicId;
private String couponName; private String couponName;
private Integer couponType; private Integer couponType;
private Integer status;
} }

View File

@@ -0,0 +1,15 @@
package com.ycwl.basic.service.mobile;
import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
import java.util.List;
public interface AppCouponRecordService {
List<CouponRecordEntity> queryByMemberIdAndFaceId(Long memberId, Long faceId);
CouponRecordEntity queryByMemberIdAndFaceIdAndType(Long memberId, Long faceId, Integer type);
CouponEntity claimCoupon(Long memberId, Long faceId, Integer type);
}

View File

@@ -1,12 +0,0 @@
package com.ycwl.basic.service.mobile;
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
import java.util.List;
public interface CouponRecordService {
List<CouponRecordEntity> queryByMemberIdAndFaceId(Long memberId, Long faceId);
CouponRecordEntity claimCoupon(Long memberId, Long faceId, Integer type);
}

View File

@@ -7,7 +7,7 @@ import com.ycwl.basic.model.pc.coupon.entity.CouponEntity;
import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity; import com.ycwl.basic.model.pc.couponRecord.entity.CouponRecordEntity;
import com.ycwl.basic.model.pc.face.entity.FaceEntity; import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.repository.FaceRepository; import com.ycwl.basic.repository.FaceRepository;
import com.ycwl.basic.service.mobile.CouponRecordService; import com.ycwl.basic.service.mobile.AppCouponRecordService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -16,7 +16,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
@Service @Service
public class CouponRecordServiceImpl implements CouponRecordService { public class AppCouponRecordServiceImpl implements AppCouponRecordService {
@Autowired @Autowired
private CouponRecordMapper couponRecordMapper; private CouponRecordMapper couponRecordMapper;
@@ -31,9 +31,14 @@ public class CouponRecordServiceImpl implements CouponRecordService {
return couponRecordMapper.queryByMemberIdAndFaceId(memberId, faceId); return couponRecordMapper.queryByMemberIdAndFaceId(memberId, faceId);
} }
@Override
public CouponRecordEntity queryByMemberIdAndFaceIdAndType(Long memberId, Long faceId, Integer type) {
return couponRecordMapper.queryByMemberIdAndFaceIdAndType(memberId, faceId, type);
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public CouponRecordEntity claimCoupon(Long memberId, Long faceId, Integer type) { public CouponEntity claimCoupon(Long memberId, Long faceId, Integer type) {
// 检查是否已经领取过该类型的优惠券 // 检查是否已经领取过该类型的优惠券
CouponRecordEntity existingRecord = couponRecordMapper.queryByMemberIdAndFaceIdAndType(memberId, faceId, type); CouponRecordEntity existingRecord = couponRecordMapper.queryByMemberIdAndFaceIdAndType(memberId, faceId, type);
if (existingRecord != null) { if (existingRecord != null) {
@@ -64,6 +69,6 @@ public class CouponRecordServiceImpl implements CouponRecordService {
record.setCreateTime(new Date()); record.setCreateTime(new Date());
couponRecordMapper.insert(record); couponRecordMapper.insert(record);
return record; return coupon;
} }
} }

View File

@@ -6,6 +6,7 @@ import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.ycwl.basic.biz.CouponBiz;
import com.ycwl.basic.biz.OrderBiz; import com.ycwl.basic.biz.OrderBiz;
import com.ycwl.basic.biz.TaskStatusBiz; import com.ycwl.basic.biz.TaskStatusBiz;
import com.ycwl.basic.constant.BaseContextHandler; import com.ycwl.basic.constant.BaseContextHandler;
@@ -19,6 +20,7 @@ import com.ycwl.basic.mapper.*;
import com.ycwl.basic.model.mobile.goods.*; import com.ycwl.basic.model.mobile.goods.*;
import com.ycwl.basic.model.mobile.order.IsBuyRespVO; import com.ycwl.basic.model.mobile.order.IsBuyRespVO;
import com.ycwl.basic.model.mobile.order.PriceObj; import com.ycwl.basic.model.mobile.order.PriceObj;
import com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordQueryResp;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity; import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
import com.ycwl.basic.model.pc.face.entity.FaceEntity; import com.ycwl.basic.model.pc.face.entity.FaceEntity;
import com.ycwl.basic.model.pc.face.resp.FaceRespVO; import com.ycwl.basic.model.pc.face.resp.FaceRespVO;
@@ -92,6 +94,8 @@ public class GoodsServiceImpl implements GoodsService {
private TaskStatusBiz taskStatusBiz; private TaskStatusBiz taskStatusBiz;
@Autowired @Autowired
private DeviceRepository deviceRepository; private DeviceRepository deviceRepository;
@Autowired
private CouponBiz couponBiz;
public ApiResponse<List<GoodsPageVO>> goodsList(GoodsReqQuery query) { public ApiResponse<List<GoodsPageVO>> goodsList(GoodsReqQuery query) {
Long scenicId = query.getScenicId(); Long scenicId = query.getScenicId();
@@ -273,7 +277,8 @@ public class GoodsServiceImpl implements GoodsService {
} else { } else {
goodsDetailVO.setIsBuy(0); goodsDetailVO.setIsBuy(0);
goodsDetailVO.setPrice(priceObj.getPrice().toString()); goodsDetailVO.setPrice(priceObj.getPrice().toString());
goodsDetailVO.setSlashPrice(priceObj.getSlashPrice().toString()); goodsDetailVO.setOrigPrice(priceObj.getPrice());
goodsDetailVO.setSlashPrice(priceObj.getSlashPrice());
} }
} }
} }
@@ -304,6 +309,16 @@ public class GoodsServiceImpl implements GoodsService {
}); });
} }
goodsDetailVO.setLensNum(deviceCount.get()); goodsDetailVO.setLensNum(deviceCount.get());
CouponRecordQueryResp couponRecord = couponBiz.queryUserCouponRecord(task.getScenicId(), userId, task.getFaceId(), task.getTemplateId().toString());
if (couponRecord != null) {
if (couponRecord.isUsable()) {
goodsDetailVO.setCouponId(couponRecord.getCouponId());
goodsDetailVO.setCouponRecordId(couponRecord.getId());
goodsDetailVO.setCouponPrice(couponRecord.getCoupon().calculateDiscountPrice(goodsDetailVO.getOrigPrice()));
goodsDetailVO.setPrice(couponRecord.getCoupon().calculateDiscountedPrice(goodsDetailVO.getPrice()));
}
}
return ApiResponse.success(goodsDetailVO); return ApiResponse.success(goodsDetailVO);
} }

View File

@@ -19,4 +19,51 @@
where cr.member_id = #{memberId} and cr.face_id = #{faceId} and c.type = #{type} where cr.member_id = #{memberId} and cr.face_id = #{faceId} and c.type = #{type}
limit 1 limit 1
</select> </select>
<select id="selectByPageQuery"
resultType="com.ycwl.basic.model.pc.couponRecord.resp.CouponRecordPageResp">
select
cr.id,
cr.coupon_id as couponId,
c.name as couponName,
c.type as couponType,
CASE c.type
WHEN 0 THEN '普通优惠券'
WHEN 1 THEN '第一次推送'
WHEN 2 THEN '第二次推送'
WHEN 3 THEN '第三次推送'
ELSE '未知类型'
END as couponTypeName,
cr.member_id as memberId,
cr.face_id as faceId,
c.scenic_id as scenicId,
s.name as scenicName,
cr.status,
CASE cr.status
WHEN 0 THEN '未使用'
WHEN 1 THEN '已使用'
ELSE '未知状态'
END as statusName,
cr.create_time as createTime,
cr.used_time as usedTime,
cr.used_order_id as usedOrderId
from coupon_record cr
inner join coupon c on cr.coupon_id = c.id
inner join scenic s on c.scenic_id = s.id
<where>
<if test="scenicId != null">
and c.scenic_id = #{scenicId}
</if>
<if test="couponName != null and couponName != ''">
and c.name like concat('%', #{couponName}, '%')
</if>
<if test="couponType != null">
and c.type = #{couponType}
</if>
<if test="status != null">
and cr.status = #{status}
</if>
</where>
order by cr.create_time desc
</select>
</mapper> </mapper>