Selaa lähdekoodia

bugfix:避免超卖

lyx 1 kuukausi sitten
vanhempi
commit
bead270707

+ 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
+    );
 }

+ 37 - 1
alien-entity/src/main/java/shop/alien/mapper/StoreCommentMapper.java

@@ -129,7 +129,43 @@ public interface StoreCommentMapper extends BaseMapper<StoreComment> {
             "AND store_id = #{storeId}")
     StoreInfoScoreVo getCommentCountAndScoreInfo(@Param("storeId") Integer storeId);
 
-
+/*
+    with total_coupon as (
+select lgbm.id,lgbm.group_type,lgbm.group_name,lgbm.image_id,2 coupon_type
+from life_group_buy_main lgbm
+union all
+select lc.id,0 group_type,lc.name group_name,0 image_id,1 coupon_type
+from life_coupon lc
+)
+SELECT
+	luo.*,
+	tc.group_type groupBuyType,
+	tc.group_name groupBuyName,
+	tc.image_id groupBuyImgId,
+	store.business_section storeType
+FROM
+	life_user_order luo
+LEFT JOIN order_coupon_middle ocm ON
+	luo.id = ocm.order_id
+LEFT JOIN total_coupon tc ON
+	ocm.coupon_id = tc.id
+	and tc.coupon_type = luo.coupon_type
+LEFT JOIN store_info store on
+	luo.store_id = store.id
+WHERE
+	luo.`status` in (2, 7)
+	AND luo.delete_flag = 0
+	AND luo.user_id = 142
+	AND luo.id NOT IN (
+	SELECT
+		business_id
+	FROM
+		store_comment
+	WHERE
+		business_type = 5
+		AND user_id = 142
+		AND delete_flag = 0)
+ */
     @Select("SELECT " +
             "luo.*,lgbm.group_type groupBuyType,lgbm.group_name groupBuyName,lgbm.image_id groupBuyImgId,store.business_section storeType " +
             "FROM life_user_order luo LEFT JOIN order_coupon_middle ocm ON luo.id = ocm.order_id LEFT JOIN life_group_buy_main lgbm ON ocm.coupon_id = lgbm.id LEFT JOIN store_info store on luo.store_id = store.id " +

+ 21 - 11
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;
@@ -774,20 +773,31 @@ public class LifeUserOrderService extends ServiceImpl<LifeUserOrderMapper, LifeU
             orderCouponMiddleService.save(orderCouponMiddle);
         }
         //4. 代金券/团购库存扣除 coupon_type 1 代金券 2团购
-        int successful = 0;
+        Map<String, Object> returnMap = new HashMap<>();
+        int soldOutStatus = CouponStatusEnum.SOLD_OUT.getCode();
+        int updateRows = 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()));
+            // 团购库存:原子扣减
+            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);