Prechádzať zdrojové kódy

add:下单时避免超卖+团购/代金券购买后售罄状态

lyx 1 mesiac pred
rodič
commit
3020f787a5

+ 16 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeCouponMapper.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.LifeCoupon;
 import shop.alien.entity.store.vo.LifeCouponVo;
 
@@ -64,4 +65,19 @@ public interface LifeCouponMapper extends BaseMapper<LifeCoupon> {
 
     @Select("SELECT * FROM life_coupon ${ew.customSqlSegment}")
     List<LifeCoupon> getList(@Param(Constants.WRAPPER) LambdaQueryWrapper<LifeCoupon> lambdaQueryWrapper);
+
+    @Update(" UPDATE life_coupon\n" +
+            "    SET \n" +
+            "        single_qty = single_qty - #{buyCount},\n" +
+            "        status = CASE WHEN (single_qty - #{buyCount}) = 0 \n" +
+            "                     THEN #{soldOutStatus} \n" +
+            "                     ELSE status END\n" +
+            "    WHERE \n" +
+            "        id = #{couponId} \n" +
+            "        AND single_qty >= #{buyCount}")
+    int deductInventoryAtomically(
+            @Param("couponId") Integer couponId,
+            @Param("buyCount") int buyCount,
+            @Param("soldOutStatus") int soldOutStatus
+    );
 }

+ 18 - 2
alien-entity/src/main/java/shop/alien/mapper/LifeGroupBuyMainMapper.java

@@ -1,14 +1,14 @@
 package shop.alien.mapper;
 
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 import shop.alien.entity.store.LifeGroupBuyMain;
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import shop.alien.entity.store.vo.LifeGroupBuyThaliVo;
 
 /**
@@ -28,6 +28,22 @@ public interface LifeGroupBuyMainMapper extends BaseMapper<LifeGroupBuyMain> {
             "        coupon_id,delete_flag,created_time,updated_time,created_user_id,\n" +
             "        updated_user_id from life_group_buy_main ${ew.customSqlSegment}")
     IPage<LifeGroupBuyThaliVo> selectPageByThaliVo(IPage<LifeGroupBuyThaliVo> lifeGroupBuyThaliVoIPage,@Param(Constants.WRAPPER) QueryWrapper<LifeGroupBuyThaliVo> queryWrapper);
+
+
+    @Update("UPDATE life_group_buy_main\n" +
+            "    SET \n" +
+            "        inventory_num = inventory_num - #{buyCount},\n" +
+            "        status = CASE WHEN (inventory_num - #{buyCount}) = 0 \n" +
+            "                     THEN #{soldOutStatus} \n" +
+            "                     ELSE status END\n" +
+            "    WHERE \n" +
+            "        id = #{couponId} \n" +
+            "        AND inventory_num >= #{buyCount}")
+    int deductInventoryAtomically(
+            @Param("couponId") Integer couponId,
+            @Param("buyCount") int buyCount,
+            @Param("soldOutStatus") int soldOutStatus
+    );
 }
 
 

+ 22 - 12
alien-store/src/main/java/shop/alien/store/service/LifeUserOrderService.java

@@ -14,7 +14,6 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import shop.alien.entity.result.BusinessException;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.LifeUserOrderDto;
@@ -777,20 +776,31 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
             orderCouponMiddleService.save(orderCouponMiddle);
         }
         //4. 代金券/团购库存扣除 coupon_type 1 代金券 2团购
-        int successful = 0;
-        if(lifeUserOrderDto.getCouponType() == 2){
-            // 团购库存扣除
-            successful = lifeGroupBuyMainMapper.update(null, new UpdateWrapper<LifeGroupBuyMain>()
-                    .eq("id", lifeUserOrderDto.getCouponId()).ge("inventory_num",lifeUserOrderDto.getCount()).setSql("inventory_num = inventory_num - " + lifeUserOrderDto.getCount()));
+        Map<String, Object> returnMap = new HashMap<>();
+        int soldOutStatus = CouponStatusEnum.SOLD_OUT.getCode();
+        int updateRows = 0;
+
+        if (lifeUserOrderDto.getCouponType() == 2) {
+            // 团购库存:原子扣减
+            updateRows = lifeGroupBuyMainMapper.deductInventoryAtomically(
+                    lifeUserOrderDto.getCouponId(),
+                    buyCount,
+                    soldOutStatus
+            );
         } else {
-            successful = lifeCouponMapper.update(null, new UpdateWrapper<LifeCoupon>()
-                    .eq("id", lifeUserOrderDto.getCouponId()).ge("single_qty",lifeUserOrderDto.getCount()).setSql("single_qty = single_qty - " + lifeUserOrderDto.getCount()));
+            // 代金券库存:原子扣减
+            updateRows = lifeCouponMapper.deductInventoryAtomically(
+                    lifeUserOrderDto.getCouponId(),
+                    buyCount,
+                    soldOutStatus
+            );
         }
-        if(successful == 0){
-            log.error("库存不足");
-            throw new BusinessException("库存不足");
+// 判断库存扣减结果
+        if (updateRows == 0) {
+            log.error("couponid:"+lifeUserOrderDto.getCouponId()+" 库存不足,当前购买数量:"+ buyCount);
+            // 手动抛出异常,触发事务回滚(回滚之前创建的订单和优惠券状态变更)
+            throw new RuntimeException("库存不足,下单失败");
         }
-        Map<String, Object> returnMap = new HashMap<>();
         returnMap.put("success", "下单成功");
         returnMap.put("orderNo", lifeUserOrderDto.getOrderNo());
         returnMap.put("lifeUserOrder", lifeUserOrder);