buyer-api/src/main/java/cn/lili/controller/lmk/CouponCardController.java
New file @@ -0,0 +1,33 @@ package cn.lili.controller.lmk; import cn.lili.base.Result; import cn.lili.modules.lmk.domain.query.ActivityQuery; import cn.lili.modules.lmk.service.CouponVirtualService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Validated @RequiredArgsConstructor @Api(value = "小程序购物卡接口", tags = "小程序购物卡接口") @RestController @RequestMapping("/buyer/lmk/coupon/card") public class CouponCardController { private CouponVirtualService couponVirtualService; @PostMapping("/{cardId}") @ApiOperation(value = "领取购物卡", notes = "领取购物卡") public Result tackCardById(@PathVariable String cardId){ return couponVirtualService.tackCardById(cardId); } @PostMapping("/changShareStatus/{cardId}") @ApiOperation(value = "领取购物卡", notes = "领取购物卡") public Result changShareStatus(@PathVariable String cardId){ return couponVirtualService.changShareStatus(cardId); } } framework/src/main/java/cn/lili/modules/lmk/domain/entity/CouponVirtual.java
@@ -26,6 +26,11 @@ /** 订单id */ private String orderId; @TableField("item_order_id") /** 订单id */ private String itemOrderId; @TableField("goods_id") /** 商品id */ private String goodsId; framework/src/main/java/cn/lili/modules/lmk/service/CouponVirtualService.java
@@ -6,6 +6,7 @@ import cn.lili.modules.lmk.domain.form.CouponVirtualForm; import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; import com.baomidou.mybatisplus.extension.service.IService; import org.springframework.web.bind.annotation.PathVariable; import java.util.List; @@ -64,4 +65,8 @@ * @return */ Result all(); Result tackCardById( String cardId); Result changShareStatus( String cardId); } framework/src/main/java/cn/lili/modules/lmk/service/impl/CouponVirtualServiceImpl.java
@@ -1,22 +1,42 @@ package cn.lili.modules.lmk.service.impl; import cn.lili.base.Result; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.AuthUser; import cn.lili.common.security.context.UserContext; import cn.lili.modules.lmk.domain.entity.CouponVirtual; import cn.lili.modules.lmk.domain.form.CouponVirtualForm; import cn.lili.modules.lmk.domain.query.CouponVirtualQuery; import cn.lili.modules.lmk.domain.vo.CouponVirtualVO; import cn.lili.modules.lmk.mapper.CouponVirtualMapper; import cn.lili.modules.lmk.service.CouponVirtualService; import cn.lili.modules.order.order.entity.dos.Order; import cn.lili.modules.order.order.entity.dos.OrderItem; import cn.lili.modules.order.order.entity.enums.ClaimStatusEnum; import cn.lili.modules.order.order.entity.enums.OrderStatusEnum; import cn.lili.modules.order.order.entity.enums.RefundStatusEnum; import cn.lili.modules.order.order.entity.enums.ShareStatusEnum; import cn.lili.modules.order.order.service.OrderItemService; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.promotion.service.MemberCouponService; import cn.lili.utils.PageUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.stereotype.Service; import lombok.RequiredArgsConstructor; import org.springframework.beans.BeanUtils; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -28,12 +48,23 @@ */ @Service @RequiredArgsConstructor @Slf4j public class CouponVirtualServiceImpl extends ServiceImpl<CouponVirtualMapper, CouponVirtual> implements CouponVirtualService { private final CouponVirtualMapper couponVirtualMapper; private final RedissonClient redissonClient; private final static String LOCK_COUPON_VIRTUAL_CARD_ID = "lock_coupon_virtual_card_id:"; private final OrderItemService orderItemService; private final OrderService orderService; private final MemberCouponService memberCouponService; /** * 添加 * * @param form * @return */ @@ -46,6 +77,7 @@ /** * 修改 * * @param form * @return */ @@ -62,6 +94,7 @@ /** * 批量删除 * * @param ids * @return */ @@ -73,6 +106,7 @@ /** * id删除 * * @param id * @return */ @@ -84,6 +118,7 @@ /** * 分页查询 * * @param query * @return */ @@ -96,6 +131,7 @@ /** * 根据id查找 * * @param id * @return */ @@ -108,6 +144,7 @@ /** * 列表 * * @return */ @Override @@ -118,4 +155,74 @@ .collect(Collectors.toList()); return Result.ok().data(vos); } @Override @Transactional(rollbackFor = Exception.class) public Result tackCardById(String cardId) { log.info("被领取的礼品卡的id为--------------------------->{}",cardId); AuthUser currentUser = UserContext.getCurrentUser(); if (currentUser == null) { throw new ServiceException("当前用户没有登录"); } String userId = currentUser.getId(); String nickName = currentUser.getNickName(); RLock lock = null; try { lock = redissonClient.getLock(LOCK_COUPON_VIRTUAL_CARD_ID + cardId); LambdaQueryWrapper<CouponVirtual> forUpdate = Wrappers.<CouponVirtual>lambdaQuery().eq(CouponVirtual::getId, cardId).last("FOR UPDATE"); CouponVirtual cardInfo = this.getOne(forUpdate); if (ClaimStatusEnum.CLAIM.name().equals(cardInfo.getClaimStatus())) { throw new ServiceException("当前购物卡已经被领取"); } //校验订单状态是否正常 String orderNo = cardInfo.getOrderId(); if (StringUtils.isBlank(orderNo)) { throw new ServiceException("当前订单不存在无法领取"); } String itemOrderId = cardInfo.getItemOrderId(); Order order = orderService.getBySn(orderNo); if (order == null) { throw new ServiceException("当前订单不存在无法领取"); } if (!OrderStatusEnum.COMPLETED.name().equals(order.getOrderStatus())) { throw new ServiceException("订单状态异常无法领取"); } OrderItem orderItem = orderItemService.getById(itemOrderId); if (orderItem == null) { throw new ServiceException("当前订单不存在"); } String orderSn = orderItem.getOrderSn(); if (!orderNo.equals(orderSn)) { throw new ServiceException("订单无法对应无法领取"); } if (!RefundStatusEnum.NO_REFUND.name().equals(orderItem.getIsRefund())) { throw new ServiceException("当前订单已退款无法领取"); } //领取对应的优惠卷 memberCouponService.receiveCoupon(cardInfo.getCouponId(),userId , nickName); cardInfo.setUserNickname(nickName); cardInfo.setUserId(userId); cardInfo.setClaimStatus(ClaimStatusEnum.CLAIM.name()); cardInfo.setClaimTime(new Date()); boolean b = this.updateById(cardInfo); //去领取优惠卷 if (!b) { throw new RuntimeException("领取失败"); } return Result.ok("领取成功"); } finally { assert lock != null; if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } @Override public Result changShareStatus(String cardId) { CouponVirtual couponVirtual = this.getById(cardId); couponVirtual.setShareStatus(ShareStatusEnum.SHARE.name()); this.updateById(couponVirtual); return Result.ok(); } } framework/src/main/java/cn/lili/modules/order/order/entity/dos/Order.java
@@ -185,6 +185,12 @@ */ @ApiModelProperty(value = "订单类型") private String orderType; /** * @see CouPonFlagEnum */ @ApiModelProperty(value = "是否是礼品卡") private String couponFlag; /** * 订单地址修改状态 */ framework/src/main/java/cn/lili/modules/order/order/entity/enums/CouPonFlagEnum.java
New file @@ -0,0 +1,29 @@ package cn.lili.modules.order.order.entity.enums; /** * 分享状态 * **/ public enum CouPonFlagEnum { /** * 礼品卡 */ COUPON("礼品卡"), /** * 不是礼品卡 */ NOT_COUPON("不是礼品卡"); private final String description; CouPonFlagEnum(String description) { this.description = description; } public String description() { return this.description; } } framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java
@@ -27,8 +27,10 @@ import cn.lili.modules.goods.entity.dos.Goods; import cn.lili.modules.goods.entity.dto.GoodsCompleteMessage; import cn.lili.modules.goods.service.GoodsService; import cn.lili.modules.lmk.domain.entity.CouponVirtual; import cn.lili.modules.lmk.domain.vo.OrderCountVO; import cn.lili.modules.lmk.enums.general.AdminRoleEnum; import cn.lili.modules.lmk.service.CouponVirtualService; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.entity.dto.MemberAddressDTO; import cn.lili.modules.member.mapper.MemberMapper; @@ -47,7 +49,9 @@ import cn.lili.modules.permission.entity.dos.AdminUser; import cn.lili.modules.permission.service.AdminUserService; import cn.lili.modules.permission.service.RoleService; import cn.lili.modules.promotion.entity.dos.Coupon; import cn.lili.modules.promotion.entity.dos.Pintuan; import cn.lili.modules.promotion.service.CouponService; import cn.lili.modules.promotion.service.PintuanService; import cn.lili.modules.store.entity.dto.StoreDeliverGoodsAddressDTO; import cn.lili.modules.store.service.StoreDetailService; @@ -87,6 +91,7 @@ import org.apache.poi.ss.util.CellRangeAddressList; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; @@ -199,8 +204,18 @@ @Resource private RedisTemplate<Object,Object> redisTemplate; @Autowired private CouponService couponService; @Autowired private CouponVirtualService couponVirtualService; @Autowired private RedissonClient redissonClient; private final static String LOCK_ORDER_NO_MQ="lock_order_no_mq:"; private final static String LOCK_EDIT_ORDER_ADDRESS="lock_edit_order_address:"; private final static String LOCK_COUPON_CARD="lock_coupon_card:"; @Override @Transactional(rollbackFor = Exception.class) public void intoDB(TradeDTO tradeDTO) { @@ -786,17 +801,71 @@ @OrderLogPoint(description = "'订单['+#orderSn+']核销,核销码['+#verificationCode+']'", orderSn = "#orderSn") @Transactional(rollbackFor = Exception.class) public Order take(String orderSn, String verificationCode) { Order order; RLock lock = redissonClient.getLock(LOCK_COUPON_CARD + orderSn); try { lock.lock(); //获取订单信息 order = this.getBySn(orderSn); //检测虚拟订单信息 checkVerificationOrder(order, verificationCode); order.setOrderStatus(OrderStatusEnum.COMPLETED.name()); //订单完成 //获取所有的订单子项用于生成优惠卷订单信息 List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn); List<CouponVirtual> couponVirtuals = new ArrayList<>(); for (OrderItem orderItem : orderItems) { String couponId = orderItem.getCouponId(); if (StringUtils.isBlank(couponId)) { continue; } String storeId = order.getStoreId(); Coupon one = couponService.getOne(Wrappers.<Coupon>lambdaQuery().eq(Coupon::getStoreId, storeId).eq(Coupon::getId, couponId)); if (one == null) { log.error("当前订单订单号为:{}不存在中的优惠卷不存在----------------------->{}",order.getId(),orderItem.getOrderSn()); }else { Integer num = orderItem.getNum(); //当购买数量部位空的时候进行 if (num != null) { for (int i = 1; i <= num; i++) { CouponVirtual couponVirtual = getCouponVirtual(orderItem); couponVirtual.setCouponNo(String.format("%08d", i)); couponVirtuals.add(couponVirtual); } } //获取订单信息 Order order = this.getBySn(orderSn); //检测虚拟订单信息 checkVerificationOrder(order, verificationCode); order.setOrderStatus(OrderStatusEnum.COMPLETED.name()); //订单完成 this.complete(orderSn); } } if (!couponVirtuals.isEmpty()) { order.setCouponFlag(CouPonFlagEnum.COUPON.name()); couponVirtualService.saveBatch(couponVirtuals); //更新状态用于后续小程序判断弹出卷列表 this.updateById(order); } this.complete(orderSn); } finally { assert lock != null; if (lock.isHeldByCurrentThread()) { lock.unlock(); } } return order; } private static CouponVirtual getCouponVirtual(OrderItem orderItem) { CouponVirtual couponVirtual = new CouponVirtual(); couponVirtual.setOrderId(orderItem.getSn()); couponVirtual.setCouponId(orderItem.getCouponId()); couponVirtual.setCouponName(orderItem.getCouponName()); couponVirtual.setGoodsId(orderItem.getGoodsId()); couponVirtual.setSkuId(orderItem.getSkuId()); couponVirtual.setItemOrderId(orderItem.getId()); couponVirtual.setSkuName(orderItem.getGoodsName()); couponVirtual.setName(orderItem.getCouponName()); couponVirtual.setShareStatus(ShareStatusEnum.NOT_SHARE.name()); couponVirtual.setClaimStatus(ClaimStatusEnum.NOT_CLAIM.name()); return couponVirtual; } @Override public Order take(String verificationCode) { String storeId = OperationalJudgment.judgment(UserContext.getCurrentUser()).getStoreId();