From 7920beb7c7ed85e87721761e1b406e4a4890beb8 Mon Sep 17 00:00:00 2001 From: zxl <763096477@qq.com> Date: 星期五, 12 九月 2025 14:55:51 +0800 Subject: [PATCH] 虚拟商品优惠劵 --- framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java | 153 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 142 insertions(+), 11 deletions(-) diff --git a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java b/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java index bcf11bf..36c99c2 100644 --- a/framework/src/main/java/cn/lili/modules/order/order/serviceimpl/OrderServiceImpl.java +++ b/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; @@ -71,6 +75,7 @@ import cn.lili.trigger.util.DelayQueueTools; import cn.lili.utils.COSUtil; import cn.lili.utils.CommonUtil; +import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -86,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; @@ -98,6 +104,7 @@ import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.InputStream; +import java.math.BigDecimal; import java.net.URLEncoder; import java.util.*; import java.util.concurrent.TimeUnit; @@ -197,7 +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) { @@ -263,7 +281,7 @@ List<OrderSimpleVO> list = this.baseMapper.queryByParamsCount(queryWrapper); OrderCountVO orderCountVO = new OrderCountVO(); orderCountVO.setOrderNumCount(0); - orderCountVO.setOrderPriceCount(0.0); + orderCountVO.setOrderPriceCount(BigDecimal.ZERO); if (CollectionUtil.isEmpty(list)) { return orderCountVO; }else { @@ -273,9 +291,14 @@ continue; // 璺宠繃null鍏冪礌锛屾垨鏍规嵁涓氬姟澶勭悊 } orderCountVO.setOrderNumCount(orderCountVO.getOrderNumCount() + 1); - Double flowPrice = vo.getFlowPrice() != null ? vo.getFlowPrice() : 0.0; - orderCountVO.setOrderPriceCount(orderCountVO.getOrderPriceCount() + flowPrice);; + // 閲戦绱姞锛氱敤BigDecimal澶勭悊锛岄伩鍏嶇簿搴﹂棶棰� + BigDecimal flowPrice = vo.getFlowPrice() != null ? + BigDecimal.valueOf(vo.getFlowPrice()) : BigDecimal.ZERO; + + // 鐢˙igDecimal鐨刟dd鏂规硶绱姞 + BigDecimal totalPrice = orderCountVO.getOrderPriceCount().add(flowPrice); + orderCountVO.setOrderPriceCount(totalPrice); } } @@ -481,6 +504,18 @@ //鏌ヨ璁㈠崟鍜岃嚜璁㈠崟锛岀劧鍚庡啓鍏o杩斿洖 return new OrderDetailVO(order, orderItems, orderLogs, receipt); } + @Override + public OrderDetailVO queryEditAddressDetail(String orderSn) { + Order order = this.getBySn(orderSn); + if (order == null) { + throw new ServiceException(ResultCode.ORDER_NOT_EXIST); + } + //鏌ヨ璁㈠崟椤逛俊鎭� + List<OrderItem> orderItems = orderItemService.getByOrderSn(orderSn); + + //鏌ヨ璁㈠崟鍜岃嚜璁㈠崟锛岀劧鍚庡啓鍏o杩斿洖 + return new OrderDetailVO(order, orderItems, null, null); + } @Override @Transactional @@ -659,16 +694,52 @@ return order; } + @Override + @SystemLogPoint(description = "淇敼璁㈠崟", customerLog = "'璁㈠崟[' + #orderSn + ']鏀惰揣淇℃伅淇敼锛屼慨鏀逛负'+#memberAddressDTO.consigneeDetail") + @Transactional(rollbackFor = Exception.class) + public Order updateAddressConsignee(String orderSn, MemberAddressDTO memberAddressDTO) { + Order order = this.getBySn(orderSn); + if (order == null) { + throw new ServiceException(ResultCode.ORDER_NOT_EXIST); + } + //闄愬埗30绉掑彧鑳借姹備竴娆¢伩鍏嶅嚭鐜伴噸鏂版彁浜ら棶棰� + Boolean b = redisTemplate.opsForValue().setIfAbsent(LOCK_EDIT_ORDER_ADDRESS + orderSn, orderSn,30, TimeUnit.SECONDS); + if ( Boolean.FALSE.equals(b)){ + throw new ServiceException("璇峰湪30绉掑悗閲嶈瘯"); + } + String modifyAddressFlag = order.getModifyAddressFlag(); + if (StringUtils.isNotBlank(modifyAddressFlag)) { + throw new ServiceException("褰撳墠璁㈠崟宸茬粡琚鍙�"); + } + QueryWrapper<Order> wrapper = new QueryWrapper<>(); + wrapper.eq("id", order.getId()); + // 浣跨敤 last 鏂规硶鎷兼帴 FOR UPDATE 璇彞 + wrapper.last("FOR UPDATE"); + baseMapper.selectOne(wrapper); + //瑕佽褰曚箣鍓嶇殑鏀惰揣鍦板潃锛屾墍浠ラ渶瑕佷互浠g爜鏂瑰紡杩涜璋冪敤 涓嶉噰鐢ㄦ敞瑙� + String message = "璁㈠崟[" + orderSn + "]鏀惰揣淇℃伅淇敼锛岀敱[" +order.getConsigneeAddressPath()+ order.getConsigneeDetail() + "]淇敼涓篬" + memberAddressDTO.getConsigneeAddressPath()+ memberAddressDTO.getConsigneeDetail() + "]"; + //璁板綍璁㈠崟鎿嶄綔鏃ュ織 + BeanUtil.copyProperties(memberAddressDTO, order); + order.setModifyAddressFlag(ModifyAddressEnums.USED.name()); + this.updateById(order); + OrderLog orderLog = new OrderLog(orderSn, UserContext.getCurrentUser().getId(), UserContext.getCurrentUser().getRole().getRole(), + UserContext.getCurrentUser().getUsername(), message); + orderLogService.save(orderLog); + return order; + } @Override @OrderLogPoint(description = "'璁㈠崟['+#orderSn+']鍙戣揣锛屽彂璐у崟鍙穂'+#logisticsNo+']'", orderSn = "#orderSn") @Transactional(rollbackFor = Exception.class) public Order delivery(String orderSn, String logisticsNo, String logisticsId) { Order order = OperationalJudgment.judgment(this.getBySn(orderSn)); //濡傛灉璁㈠崟鏈彂璐э紝骞朵笖璁㈠崟鐘舵�佸�肩瓑浜庡緟鍙戣揣 + log.info("鑾峰彇鍒扮殑璁㈠崟淇℃伅涓簕}", JSON.toJSONString(order)); if (order.getDeliverStatus().equals(DeliverStatusEnum.UNDELIVERED.name()) && order.getOrderStatus().equals(OrderStatusEnum.UNDELIVERED.name())) { //鑾峰彇瀵瑰簲鐗╂祦 Logistics logistics = logisticsService.getById(logisticsId); + log.info("鑾峰彇鍒扮殑鐗╂祦淇℃伅id涓簕}", logisticsId); + log.info("鑾峰彇鍒扮殑鐗╂祦淇℃伅涓簕}", JSON.toJSONString(logistics)); if (logistics == null) { throw new ServiceException(ResultCode.ORDER_LOGISTICS_ERROR); } @@ -730,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(); @@ -1335,6 +1460,12 @@ this.update(new LambdaUpdateWrapper<Order>() .eq(Order::getSn, orderSn) .set(Order::getOrderStatus, orderStatusEnum.name())); + //淇敼璁㈠崟鍟嗗搧 todo 鎵�鏈夌殑璁㈠崟闇�瑕佸鏍稿悗鎵嶈兘閫�娆� + orderItemService.update(new LambdaUpdateWrapper<OrderItem>() + .eq(OrderItem::getOrderSn,orderSn) + .set(OrderItem::getAfterSaleStatus, OrderItemAfterSaleStatusEnum.NOT_APPLIED.name()) + .set(OrderItem::getCommentStatus,CommentStatusEnum.UNFINISHED.name()) + .set(OrderItem::getComplainStatus, OrderComplaintStatusEnum.NO_APPLY.name())); //淇敼璁㈠崟 OrderMessage orderMessage = new OrderMessage(); orderMessage.setNewStatus(orderStatusEnum); @@ -1457,7 +1588,7 @@ // 鍒涘缓琛ㄥご Row header = sheet.createRow(0); String[] headers = {"涓昏鍗曠紪鍙�", "瀛愯鍗曠紪鍙�", "閫夎喘鍟嗗搧", "鍟嗗搧鏁伴噺", "鍟嗗搧ID", "鍟嗗搧鍗曚环", "璁㈠崟搴斾粯閲戦", - "杩愯垂", "浼樻儬鎬婚噾棰�", "骞冲彴浼樻儬", "鍟嗗浼樻儬", "鍟嗗鏀逛环", "鏀粯鏂瑰紡","鍗栧鍚嶇О", "鏀朵欢浜�", "鏀朵欢浜烘墜鏈哄彿", + "杩愯垂", "浼樻儬鎬婚噾棰�", "骞冲彴浼樻儬", "鍟嗗浼樻儬", "鍟嗗鏀逛环", "鏀粯鏂瑰紡","涔板鍚嶇О", "鏀朵欢浜�", "鏀朵欢浜烘墜鏈哄彿", "鐪�", "甯�", "鍖�", "琛楅亾", "璇︾粏鍦板潃", "涔板鐣欒█", "璁㈠崟鎻愪氦鏃堕棿", "鏀粯瀹屾垚鏃堕棿", "鏉ユ簮", "璁㈠崟鐘舵��", "璁㈠崟绫诲瀷", "鍞悗鐘舵��", "鍙栨秷鍘熷洜", "鍙戣揣鏃堕棿", "瀹屾垚鏃堕棿", "搴楅摵"}; -- Gitblit v1.8.0