feat(market):新增优惠卷核销的功能
This commit is contained in:
parent
a355354d5f
commit
75ab9620f4
@ -1,8 +1,12 @@
|
||||
package com.jzo2o.api.market;
|
||||
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
@ -19,4 +23,10 @@ public interface CouponApi {
|
||||
*/
|
||||
@GetMapping("/getAvailable")
|
||||
List<AvailableCouponsResDTO> getAvailableCoupon(@RequestParam BigDecimal totalAmount);
|
||||
|
||||
/**
|
||||
* 用户核销优惠卷返回优惠金额
|
||||
*/
|
||||
@PostMapping("/use")
|
||||
CouponUseResDTO useCoupon(@RequestBody CouponUseReqDTO couponUseReqDTO);
|
||||
}
|
||||
@ -2,11 +2,13 @@ package com.jzo2o.api.market.dto.request;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@ApiModel("优惠券使用模型")
|
||||
public class CouponUseReqDTO {
|
||||
@ApiModelProperty("优惠券id")
|
||||
|
||||
@ -2,12 +2,16 @@ package com.jzo2o.api.market.dto.response;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@ApiModel("优惠券使用返回信息模型")
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class CouponUseResDTO {
|
||||
@ApiModelProperty("优惠金额")
|
||||
private BigDecimal discountAmount;
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
package com.jzo2o.market.controller.inner;
|
||||
|
||||
import com.jzo2o.api.market.CouponApi;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.market.service.ICouponWriteOffService;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
@ -25,6 +25,8 @@ import java.util.List;
|
||||
public class CouponController implements CouponApi {
|
||||
@Resource
|
||||
private ICouponService couponService;
|
||||
@Resource
|
||||
private ICouponWriteOffService couponWriteOffService;
|
||||
|
||||
/**
|
||||
* 根据订单金额获取当前用户可用优惠卷
|
||||
@ -36,4 +38,11 @@ public class CouponController implements CouponApi {
|
||||
public List<AvailableCouponsResDTO> getAvailableCoupon(@RequestParam BigDecimal totalAmount) {
|
||||
return couponService.getAvailableCoupon(totalAmount);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PostMapping("/use")
|
||||
@ApiOperation("使用优惠卷并返回优惠金额")
|
||||
public CouponUseResDTO useCoupon(@RequestBody CouponUseReqDTO couponUseReqDTO) {
|
||||
return couponWriteOffService.use(couponUseReqDTO);
|
||||
}
|
||||
}
|
||||
@ -1,18 +1,17 @@
|
||||
package com.jzo2o.market.model.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券核销表
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
@ -26,7 +25,7 @@ public class CouponWriteOff implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@TableId(value = "id", type = IdType.NONE)
|
||||
@TableId(value = "id", type = IdType.ASSIGN_ID)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
@ -63,6 +62,4 @@ public class CouponWriteOff implements Serializable {
|
||||
* 核销人姓名
|
||||
*/
|
||||
private String writeOffManName;
|
||||
|
||||
|
||||
}
|
||||
@ -44,4 +44,11 @@ public interface ICouponService extends IService<Coupon> {
|
||||
* 根据订单金额获取当前用户可用优惠卷
|
||||
*/
|
||||
List<AvailableCouponsResDTO> getAvailableCoupon(BigDecimal totalAmount);
|
||||
|
||||
/**
|
||||
* 计算优惠卷的优惠价格
|
||||
* @param coupon 优惠卷信息
|
||||
* @param totalAmount 订单总金额
|
||||
*/
|
||||
BigDecimal calcDiscountAmount(Coupon coupon, BigDecimal totalAmount);
|
||||
}
|
||||
@ -1,5 +1,7 @@
|
||||
package com.jzo2o.market.service;
|
||||
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
@ -7,11 +9,12 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
* <p>
|
||||
* 优惠券核销表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
public interface ICouponWriteOffService extends IService<CouponWriteOff> {
|
||||
|
||||
|
||||
/**
|
||||
* 核销指定的优惠卷并返回优惠金额
|
||||
*/
|
||||
CouponUseResDTO use(CouponUseReqDTO couponUseReqDTO);
|
||||
}
|
||||
@ -179,7 +179,8 @@ public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> impleme
|
||||
* @param coupon 优惠卷信息
|
||||
* @param totalAmount 订单总金额
|
||||
*/
|
||||
private BigDecimal calcDiscountAmount(Coupon coupon, BigDecimal totalAmount) {
|
||||
@Override
|
||||
public BigDecimal calcDiscountAmount(Coupon coupon, BigDecimal totalAmount) {
|
||||
CouponTypeEnum type = coupon.getType();
|
||||
BigDecimal discountAmount = BigDecimal.ZERO;
|
||||
|
||||
|
||||
@ -1,20 +1,77 @@
|
||||
package com.jzo2o.market.service.impl;
|
||||
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.jzo2o.market.mapper.CouponWriteOffMapper;
|
||||
import com.jzo2o.market.service.ICouponWriteOffService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import com.jzo2o.common.expcetions.BadRequestException;
|
||||
import com.jzo2o.common.expcetions.DBException;
|
||||
import com.jzo2o.common.utils.ObjectUtils;
|
||||
import com.jzo2o.market.enums.CouponStatusEnum;
|
||||
import com.jzo2o.market.mapper.CouponWriteOffMapper;
|
||||
import com.jzo2o.market.model.domain.Coupon;
|
||||
import com.jzo2o.market.model.domain.CouponWriteOff;
|
||||
import com.jzo2o.market.service.ICouponService;
|
||||
import com.jzo2o.market.service.ICouponWriteOffService;
|
||||
import com.jzo2o.mvc.utils.UserContext;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 优惠券核销表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author itcast
|
||||
* @since 2023-09-22
|
||||
*/
|
||||
@Service
|
||||
public class CouponWriteOffServiceImpl extends ServiceImpl<CouponWriteOffMapper, CouponWriteOff> implements ICouponWriteOffService {
|
||||
@Resource
|
||||
private ICouponService couponService;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public CouponUseResDTO use(CouponUseReqDTO couponUseReqDTO) {
|
||||
Long couponId = couponUseReqDTO.getId();
|
||||
BigDecimal totalAmount = couponUseReqDTO.getTotalAmount();
|
||||
Long userId = UserContext.currentUserId();
|
||||
LocalDateTime nowTime = LocalDateTime.now();
|
||||
|
||||
Coupon coupon = couponService.getById(couponId);
|
||||
if (ObjectUtils.isEmpty(coupon) || ObjectUtils.notEqual(coupon.getUserId(), userId)) {
|
||||
throw new BadRequestException("优惠卷不存在");
|
||||
} else if (coupon.getStatus() != CouponStatusEnum.NO_USE
|
||||
|| coupon.getValidityTime().isBefore(nowTime)) {
|
||||
throw new BadRequestException("优惠卷已使用/已失效");
|
||||
} else if (coupon.getAmountCondition().compareTo(totalAmount) > 0) {
|
||||
throw new BadRequestException("订单金额未达到满减金额");
|
||||
}
|
||||
|
||||
Long ordersId = couponUseReqDTO.getOrdersId();
|
||||
if (!couponService.lambdaUpdate()
|
||||
.eq(Coupon::getId, couponId)
|
||||
.set(Coupon::getUseTime, nowTime)
|
||||
.set(Coupon::getStatus, CouponStatusEnum.USED)
|
||||
.set(Coupon::getOrdersId, ordersId)
|
||||
.update()) {
|
||||
throw new DBException("更新优惠卷表失败");
|
||||
}
|
||||
|
||||
if (!this.save(CouponWriteOff.builder()
|
||||
.couponId(couponId)
|
||||
.userId(userId)
|
||||
.ordersId(ordersId)
|
||||
.activityId(coupon.getActivityId())
|
||||
.writeOffTime(nowTime)
|
||||
.writeOffManName(coupon.getUserName())
|
||||
.writeOffManPhone(coupon.getUserPhone())
|
||||
.build())) {
|
||||
throw new DBException("更新核销表失败");
|
||||
}
|
||||
|
||||
return new CouponUseResDTO(couponService.calcDiscountAmount(coupon, totalAmount));
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,9 @@ package com.jzo2o.orders.manager.service.client;
|
||||
import com.alibaba.csp.sentinel.annotation.SentinelResource;
|
||||
import com.alibaba.csp.sentinel.slots.block.BlockException;
|
||||
import com.jzo2o.api.market.CouponApi;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -37,4 +39,20 @@ public class MarketClient {
|
||||
log.warn("优惠卷接口异常(触发熔断降级), 总金额: {}", totalAmount, blockException);
|
||||
return null;
|
||||
}
|
||||
|
||||
@SentinelResource(value = "useCoupon",
|
||||
fallback = "useCouponFallback", blockHandler = "useCouponBlockHandler")
|
||||
public CouponUseResDTO useCoupon(CouponUseReqDTO couponUseReqDTO) {
|
||||
return couponApi.useCoupon(couponUseReqDTO);
|
||||
}
|
||||
|
||||
public CouponUseResDTO useCouponFallback(CouponUseReqDTO couponUseReqDTO, Throwable throwable) {
|
||||
log.warn("优惠卷接口异常(未触发熔断), 相关信息: {}", couponUseReqDTO, throwable);
|
||||
return null;
|
||||
}
|
||||
|
||||
public CouponUseResDTO useCouponBlockHandler(CouponUseReqDTO couponUseReqDTO, BlockException blockException) {
|
||||
log.warn("优惠卷接口异常(触发熔断降级), 相关信息: {}", couponUseReqDTO, blockException);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,9 @@ package com.jzo2o.orders.manager.service.impl;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jzo2o.api.customer.dto.response.AddressBookResDTO;
|
||||
import com.jzo2o.api.foundations.dto.response.ServeAggregationResDTO;
|
||||
import com.jzo2o.api.market.dto.request.CouponUseReqDTO;
|
||||
import com.jzo2o.api.market.dto.response.AvailableCouponsResDTO;
|
||||
import com.jzo2o.api.market.dto.response.CouponUseResDTO;
|
||||
import com.jzo2o.api.trade.NativePayApi;
|
||||
import com.jzo2o.api.trade.TradingApi;
|
||||
import com.jzo2o.api.trade.dto.request.NativePayReqDTO;
|
||||
@ -98,10 +100,22 @@ public class OrdersCreateServiceImpl extends ServiceImpl<OrdersMapper, Orders> i
|
||||
}
|
||||
// 获取订单id
|
||||
Long orderId = generateOrderId();
|
||||
// TODO 获取优惠卷相关信息
|
||||
BigDecimal discountAmount = BigDecimal.ZERO;
|
||||
// 计算价格
|
||||
// 计算总金额
|
||||
BigDecimal totalAmount = serve.getPrice().multiply(BigDecimal.valueOf(placeOrderReqDTO.getPurNum()));
|
||||
// 计算优惠卷相关金额
|
||||
BigDecimal discountAmount = BigDecimal.ZERO;
|
||||
Long couponId = placeOrderReqDTO.getCouponId();
|
||||
if (ObjectUtils.isNotEmpty(couponId)) {
|
||||
CouponUseResDTO couponUseResDTO = Optional
|
||||
.ofNullable(marketClient.useCoupon(CouponUseReqDTO.builder()
|
||||
.ordersId(orderId)
|
||||
.id(couponId)
|
||||
.totalAmount(totalAmount)
|
||||
.build()))
|
||||
.orElseThrow(() -> new ForbiddenOperationException("优惠卷核销失败下单失败"));
|
||||
discountAmount = couponUseResDTO.getDiscountAmount();
|
||||
}
|
||||
// 计算实际金额
|
||||
BigDecimal realPayAmount = totalAmount.subtract(discountAmount);
|
||||
|
||||
// 组装订单信息插入数据库完成下单
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user