Browse Source

购物车结算与商品运费

chao 3 years ago
parent
commit
38c3f8948e

+ 12 - 0
src/main/java/com/caimei365/order/components/ProductService.java

@@ -8,6 +8,7 @@ import com.caimei365.order.model.vo.PromotionsVo;
 import com.caimei365.order.utils.MathUtil;
 import com.caimei365.order.utils.ProductUtil;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.ArrayUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
@@ -148,4 +149,15 @@ public class ProductService {
             totalPromotions.add(promotions);
         }
     }
+
+    /**
+     * 是否订单充值商品或定金商品
+     * @param productId 商品id
+     * @return Boolean
+     */
+    public boolean isRechargeProduct(Integer productId){
+        int[] products = {6060, 6061, 6062, 6063, 6064, 6065, 6066, 6067, 6068, 6069};
+        return ArrayUtils.contains(products, productId);
+    }
+
 }

+ 70 - 0
src/main/java/com/caimei365/order/controller/CartClubApi.java

@@ -5,6 +5,7 @@ import com.caimei365.order.model.dto.CartDto;
 import com.caimei365.order.service.CartClubService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang3.StringUtils;
@@ -122,4 +123,73 @@ public class CartClubApi {
         }
         return cartClubService.deleteShoppingCart(cartDto);
     }
+
+    /**
+     * 购物车结算
+     */
+    @ApiOperation("购物车结算(旧:/order/confirm)")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = false, name = "userId", value = "用户Id"),
+            @ApiImplicitParam(required = false, name = "productIds", value = "商品ids,逗号隔开")
+    })
+    @GetMapping("/cart/settlement")
+    public ResponseJson<Map<String, Object>> settlementShoppingCart(Integer userId, String productIds) {
+        if (null == userId) {
+            return ResponseJson.error("用户Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(productIds)) {
+            return ResponseJson.error("商品Id集合不能为空!", null);
+        }
+        return cartClubService.settlementShoppingCart(userId, productIds);
+    }
+
+    /**
+     * 立即购买
+     *
+     * @param cartDto {
+     *                userId       用户ID
+     *                productId    商品id
+     *                productCount 商品数量
+     * }
+     */
+    @ApiOperation("立即购买(旧:/order/confirm)")
+    @GetMapping("/product/settlement")
+    public ResponseJson<Map<String, Object>> buyNowProduct(CartDto cartDto){
+        if (null == cartDto.getUserId()) {
+            return ResponseJson.error("用户Id不能为空!", null);
+        }
+        if (null == cartDto.getProductId()) {
+            return ResponseJson.error("商品Id不能为空!", null);
+        }
+        if (null == cartDto.getProductCount()) {
+            return ResponseJson.error("商品数量不能为空!", null);
+        }
+        return cartClubService.buyNowProduct(cartDto);
+    }
+
+    /**
+     * 获取结算商品运费
+     */
+    @ApiOperation("计算运费(旧:/order/postage)")
+    @ApiImplicitParams({
+            @ApiImplicitParam(required = false, name = "userId", value = "用户Id"),
+            @ApiImplicitParam(required = false, name = "productIds", value = "商品ids,逗号隔开"),
+            @ApiImplicitParam(required = false, name = "totalPrice", value = "商品总金额"),
+            @ApiImplicitParam(required = false, name = "townId", value = "地区Id")
+    })
+    @GetMapping("/postage")
+    public ResponseJson<Map<String, Object>> orderPostage(Integer userId, String productIds, Integer townId) {
+        if (null == userId) {
+            return ResponseJson.error("用户Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(productIds)) {
+            return ResponseJson.error("商品Id集合不能为空!", null);
+        }
+        if (null == townId) {
+            return ResponseJson.error("地区Id不能为空!", null);
+        }
+        return cartClubService.getProductsPostage(userId, productIds, townId);
+    }
+
+
 }

+ 36 - 5
src/main/java/com/caimei365/order/mapper/BaseMapper.java

@@ -1,8 +1,6 @@
 package com.caimei365.order.mapper;
 
-import com.caimei365.order.model.vo.CartItemVo;
-import com.caimei365.order.model.vo.LadderPriceVo;
-import com.caimei365.order.model.vo.PromotionsVo;
+import com.caimei365.order.model.vo.*;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -49,6 +47,39 @@ public interface BaseMapper {
      * @param promotionsId 促销Id
      */
     List<CartItemVo> getPromotionGifts(Integer promotionsId);
-
-
+    /**
+     * 获取赠品供应商
+     * @param productId 商品Id
+     */
+    CartShopVo getPromotionGiftsShop(Integer productId);
+    /**
+     * 发票信息
+     * @param userId 用户Id
+     */
+    InvoiceVo getUserInvoice(Integer userId);
+    /**
+     * 可用余额
+     * @param userId 用户Id
+     */
+    Double getUserAbleUserMoney(Integer userId);
+    /**
+     * 可用采美豆
+     * @param userId 用户Id
+     */
+    Integer getUserBeans(Integer userId);
+    /**
+     * 获取商品运费 (0包邮 1到付 2默认(遵循运费规则))
+     * @param productIds 商品Id列表
+     */
+    List<ProductPostageVo> getPostageFlagList(@Param("productIds") List<String> productIds);
+    /**
+     * 统计用户订单数
+     * @param userId 用户Id
+     */
+    Integer countUserOrder(Integer userId);
+    /**
+     * 获取根据地区Id获取省市地址信息
+     * @param townId 地区Id
+     */
+    AddressVo getProvinceIdAndCityId(Integer townId);
 }

+ 12 - 1
src/main/java/com/caimei365/order/mapper/CartClubMapper.java

@@ -54,5 +54,16 @@ public interface CartClubMapper {
      * @param userId     用户Id
      * @param productIds 商品Id集合
      */
-    void deleteCartByProductIds(@Param("userId") Integer userId, @Param("productIds") List<Integer> productIds);
+    void deleteCartByProductIds(@Param("userId") Integer userId, @Param("productIds") List<String> productIds);
+    /**
+     * 根据商品Ids获取购物车供应商列表
+     * @param userId 用户Id
+     */
+    List<CartShopVo> getCartShopsByProductIds(@Param("userId") Integer userId, @Param("productIds") List<String> productIds);
+    /**
+     * 根据商品Ids获取购物车已上架商品列表
+     * @param userId 用户Id
+     */
+    List<CartItemVo> getCartProductsByShopIdAndProductIds(@Param("userId") Integer userId,@Param("shopId")  Integer shopId, @Param("productIds") List<String> productIds);
+
 }

+ 45 - 0
src/main/java/com/caimei365/order/model/vo/AddressVo.java

@@ -0,0 +1,45 @@
+package com.caimei365.order.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/2
+ */
+@Data
+public class AddressVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 用户地址Id
+     */
+    private Integer addressId;
+    /**
+     * 省ID
+     */
+    private Integer provinceId;
+    /**
+     * 省份名称
+     */
+    private String province;
+    /**
+     * 市ID
+     */
+    private Integer cityId;
+    /**
+     * 城市名称
+     */
+    private String city;
+    /**
+     * 区ID
+     */
+    private Integer townId;
+    /**
+     * 村镇名
+     */
+    private String town;
+
+}

+ 47 - 0
src/main/java/com/caimei365/order/model/vo/InvoiceVo.java

@@ -0,0 +1,47 @@
+package com.caimei365.order.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/1
+ */
+@Data
+public class InvoiceVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Integer id;
+    /**
+     * 用户ID
+     */
+    private Integer userId;
+    /**
+     * 发票抬头 个人名称或企业名称或者单位名
+     */
+    private String invoiceTitle;
+    /**
+     * 企业税号、纳税人识别号
+     */
+    private String corporationTaxNum;
+    /**
+     * 注册地址
+     */
+    private String registeredAddress;
+    /**
+     * 注册电话
+     */
+    private String registeredPhone;
+    /**
+     * 开户银行账户
+     */
+    private String bankAccountNo;
+    /**
+     * 开户银行
+     */
+    private String openBank;
+
+}

+ 30 - 0
src/main/java/com/caimei365/order/model/vo/ProductPostageVo.java

@@ -0,0 +1,30 @@
+package com.caimei365.order.model.vo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/1
+ */
+@Data
+public class ProductPostageVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 商品Id
+     */
+    private Integer productId;
+    /**
+     * 邮费标志: 0包邮 1到付 2默认(遵循运费规则)
+     */
+    private Integer postageFlag;
+    /**
+     * 商品属性:1产品,2仪器(到付)
+     */
+    private Integer commodityType;
+
+
+}

+ 27 - 0
src/main/java/com/caimei365/order/service/CartClubService.java

@@ -56,4 +56,31 @@ public interface CartClubService {
      * }
      */
     ResponseJson<Integer> deleteShoppingCart(CartDto cartDto);
+
+    /**
+     * 购物车结算
+     *
+     * @param  userId       用户ID
+     * @param  productIds   商品ids,逗号隔开
+     */
+    ResponseJson<Map<String, Object>> settlementShoppingCart(Integer userId, String productIds);
+
+    /**
+     * 立即购买
+     *
+     * @param cartDto {
+     *                userId       用户ID
+     *                productId    商品id
+     *                productCount 商品数量
+     * }
+     */
+    ResponseJson<Map<String, Object>> buyNowProduct(CartDto cartDto);
+
+    /**
+     * 获取结算商品运费
+     * @param  userId       用户ID
+     * @param  productIds   商品ids,逗号隔开
+     * @param townId        地区Id
+     */
+    ResponseJson<Map<String, Object>> getProductsPostage(Integer userId, String productIds, Integer townId);
 }

+ 419 - 52
src/main/java/com/caimei365/order/service/impl/CartClubServiceImpl.java

@@ -18,7 +18,10 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 
 /**
@@ -188,56 +191,58 @@ public class CartClubServiceImpl implements CartClubService {
                         productIterator.remove();
                     }
                 }
-                // 店铺促销
-                if (null != shopPromotion) {
-                    shop.setPromotions(shopPromotion);
-                    if (!promotionsIds.contains(shopPromotion.getId())) {
-                        promotionsIds.add(shopPromotion.getId());
-                        // 店铺满赠
-                        if (shopPromotion.getMode() == 3) {
-                            // 获取赠品
-                            List<CartItemVo> giftList = baseMapper.getPromotionGifts(shopPromotion.getId());
-                            shopPromotion.setGiftList(giftList);
-                        }
-                        // 设置该优惠下的商品列表
-                        List<PromotionPriceVo> promotionPriceList = new ArrayList<>();
-                        productList.forEach(item -> {
-                            PromotionPriceVo promotionPrice = new PromotionPriceVo();
-                            promotionPrice.setProductId(item.getProductId());
-                            promotionPrice.setNumber(item.getNumber());
-                            promotionPrice.setPrice(item.getPrice());
-                            promotionPriceList.add(promotionPrice);
-                        });
-                        shopPromotion.setProductList(promotionPriceList);
-                        // 添加到总促销
-                        totalPromotions.add(shopPromotion);
-                        // 店铺满减-计算供应商总价/满减金额
-                        if (shopPromotion.getMode() == 2 && MathUtil.compare(shopPrice, shopPromotion.getTouchPrice()) > -1) {
-                            // 该供应商总价 - 满减金额
-                            shopPrice.set(MathUtil.sub(shopPrice.get(), shopPromotion.getReducedPrice()).doubleValue());
-                            // 该供应商优惠总额 + 满减金额
-                            shopReducedPrice.set(MathUtil.add(shopReducedPrice.get(), shopPromotion.getReducedPrice()).doubleValue());
+                // 供应商下商品种类
+                shop.setCount(shopKindCount.get());
+                if (shopKindCount.get() > 0) {
+                    // 店铺促销
+                    if (null != shopPromotion) {
+                        shop.setPromotions(shopPromotion);
+                        if (!promotionsIds.contains(shopPromotion.getId())) {
+                            promotionsIds.add(shopPromotion.getId());
+                            // 店铺满赠
+                            if (shopPromotion.getMode() == 3) {
+                                // 获取赠品
+                                List<CartItemVo> giftList = baseMapper.getPromotionGifts(shopPromotion.getId());
+                                shopPromotion.setGiftList(giftList);
+                            }
+                            // 设置该优惠下的商品列表
+                            List<PromotionPriceVo> promotionPriceList = new ArrayList<>();
+                            productList.forEach(item -> {
+                                PromotionPriceVo promotionPrice = new PromotionPriceVo();
+                                promotionPrice.setProductId(item.getProductId());
+                                promotionPrice.setNumber(item.getNumber());
+                                promotionPrice.setPrice(item.getPrice());
+                                promotionPriceList.add(promotionPrice);
+                            });
+                            shopPromotion.setProductList(promotionPriceList);
+                            // 添加到总促销
+                            totalPromotions.add(shopPromotion);
+                            // 店铺满减-计算供应商总价/满减金额
+                            if (shopPromotion.getMode() == 2 && MathUtil.compare(shopPrice, shopPromotion.getTouchPrice()) > -1) {
+                                // 该供应商总价 - 满减金额
+                                shopPrice.set(MathUtil.sub(shopPrice.get(), shopPromotion.getReducedPrice()).doubleValue());
+                                // 该供应商优惠总额 + 满减金额
+                                shopReducedPrice.set(MathUtil.add(shopReducedPrice.get(), shopPromotion.getReducedPrice()).doubleValue());
+                            }
                         }
                     }
+                    // 供应商商品
+                    shop.setCartList(productList);
+                    // 供应商总价
+                    shop.setTotalPrice(shopPrice.get());
+                    // 供应商总优惠
+                    shop.setReducedPrice(shopReducedPrice.get());
+                    // 供应商划线价
+                    shop.setOriginalPrice(MathUtil.add(shopPrice.get(), shopReducedPrice.get()).doubleValue());
+                    // 计算总价
+                    totalPrice.set(MathUtil.add(totalPrice, shop.getTotalPrice()).doubleValue());
+                    // 优惠总额
+                    reducedPrice.set(MathUtil.add(reducedPrice, shop.getReducedPrice()).doubleValue());
+                    // 总划线价
+                    totalOriginalPrice.set(MathUtil.add(totalOriginalPrice, shop.getOriginalPrice()).doubleValue());
+                    // 商品种类
+                    kindCount.updateAndGet(v -> v + shopKindCount.get());
                 }
-                // 供应商商品
-                shop.setCartList(productList);
-                // 供应商总价
-                shop.setTotalPrice(shopPrice.get());
-                // 供应商总优惠
-                shop.setReducedPrice(shopReducedPrice.get());
-                // 供应商划线价
-                shop.setOriginalPrice(MathUtil.add(shopPrice.get(), shopReducedPrice.get()).doubleValue());
-                // 供应商下商品种类
-                shop.setCount(shopKindCount.get());
-                // 计算总价
-                totalPrice.set(MathUtil.add(totalPrice, shop.getTotalPrice()).doubleValue());
-                // 优惠总额
-                reducedPrice.set(MathUtil.add(reducedPrice, shop.getReducedPrice()).doubleValue());
-                // 总划线价
-                totalOriginalPrice.set(MathUtil.add(totalOriginalPrice, shop.getOriginalPrice()).doubleValue());
-                // 商品种类
-                kindCount.updateAndGet(v -> v + shopKindCount.get());
             });
             // 删除空数据
             shopInfoList.removeIf(shop -> (null == shop || shop.getCount() == 0));
@@ -437,14 +442,12 @@ public class CartClubServiceImpl implements CartClubService {
      */
     @Override
     public ResponseJson<Integer> deleteShoppingCart(CartDto cartDto) {
-        List<Integer> productIdList = Lists.newArrayList();
+        List<String> productIdList = Lists.newArrayList();
         if (cartDto.getProductIds().contains(",")) {
             String[] productArr = cartDto.getProductIds().split(",");
-            for (String id : productArr) {
-                productIdList.add(Integer.parseInt(id));
-            }
+            Collections.addAll(productIdList, productArr);
         } else {
-            productIdList.add(Integer.parseInt(cartDto.getProductIds()));
+            productIdList.add(cartDto.getProductIds());
         }
         cartClubMapper.deleteCartByProductIds(cartDto.getUserId(), productIdList);
         // 获取购物车数量(商品种类数)
@@ -475,6 +478,370 @@ public class CartClubServiceImpl implements CartClubService {
     }
 
 
+    /**
+     * 购物车结算
+     *
+     * @param userId     用户ID
+     * @param productIds 商品ids,逗号隔开
+     */
+    @Override
+    public ResponseJson<Map<String, Object>> settlementShoppingCart(Integer userId, String productIds) {
+        log.info("¥¥¥¥¥¥¥¥¥¥ > 商品结算");
+        // 商品种类
+        AtomicInteger kindCount = new AtomicInteger(0);
+        // 商品总数量
+        AtomicInteger totalCount = new AtomicInteger(0);
+        // 统计商品总金额
+        AtomicDouble totalPrice = new AtomicDouble(0);
+        // 统计总促销满减
+        AtomicDouble reducedPrice = new AtomicDouble(0);
+        // 统计总划线价
+        AtomicDouble totalOriginalPrice = new AtomicDouble(0);
+        // 促销活动(总)
+        List<PromotionsVo> totalPromotions = new ArrayList<>();
+        // 是否包含充值商品,默认false
+        AtomicBoolean includeRecharge = new AtomicBoolean(false);
+
+        // 促销活动Id集合,用于合并促销活动
+        List<Integer> promotionsIds = new ArrayList<>();
+        // 供应商Id集合,用户判断赠品供应商是否在当前供应商中
+        List<Integer> shopIds = new ArrayList<>();
+        // 用户身份
+        Integer userIdentity = baseMapper.getIdentityByUserId(userId);
+
+        // 前端接收商品Id信息
+        List<String> productIdList = new ArrayList<>();
+        if (productIds.contains(",")) {
+            productIdList = Stream.of(productIds.split(",")).collect(Collectors.toList());
+        } else {
+            productIdList.add(productIds);
+        }
+        // 最终商品Id列表,排除失效商品
+        List<String> resultProductIds = new ArrayList<>();
+
+        // 是否库存充足
+        AtomicBoolean isStocked = new AtomicBoolean(true);
+        // 供应商列表
+        List<CartShopVo> shopList = cartClubMapper.getCartShopsByProductIds(userId, productIdList);
+        if (null != shopList && shopList.size()>0) {
+            // 遍历供应商列表
+            List<String> finalIdList = productIdList;
+            shopList.forEach(shop -> {
+                // 该供应商下商品种类
+                AtomicInteger shopKindCount = new AtomicInteger(0);
+                // 该供应商总价
+                AtomicDouble shopPrice = new AtomicDouble(0);
+                // 该供应商满减金额(供应商满减,单品满减)
+                AtomicDouble shopReducedPrice = new AtomicDouble(0);
+                // 供应商促销优惠活动
+                PromotionsVo shopPromotion = baseMapper.getPromotionByShopId(shop.getShopId());
+                // 供应商下商品列表
+                List<CartItemVo> productList = cartClubMapper.getCartProductsByShopIdAndProductIds(userId, shop.getShopId(), finalIdList);
+                if (null != productList && productList.size()>0) {
+                    productList.removeIf(cartItemVo -> !(cartItemVo.getPriceFlag() == 0 || (cartItemVo.getPriceFlag() == 2 && userIdentity == 2)));
+                    // 迭代器设置商品信息
+                    for (CartItemVo cartItemVo : productList) {
+                        // 加入最终商品Id列表
+                        resultProductIds.add(cartItemVo.getProductId().toString());
+                        // 设置商品图片及税费
+                        boolean taxFlag = productService.setCartItemImgAndTax(cartItemVo);
+                        // 是否充值商品
+                        boolean recharge = productService.isRechargeProduct(cartItemVo.getProductId());
+                        if (recharge) {
+                            includeRecharge.set(true);
+                        }
+                        // 是否库存充足
+                        isStocked.set((cartItemVo.getStock() != null && cartItemVo.getStock() > 0 && cartItemVo.getStock() >= cartItemVo.getMin() && cartItemVo.getStock() >= cartItemVo.getNumber()));
+                        if (isStocked.get()) {
+                            // 获取商品促销信息
+                            PromotionsVo promotions = null;
+                            // 没有店铺促销时,商品促销才有效
+                            if (null == shopPromotion) {
+                                // 获取商品促销信息
+                                promotions = baseMapper.getPromotionByProductId(cartItemVo.getProductId());
+                                /*
+                                 * 设置商品促销优惠
+                                 */
+                                if (null != promotions) {
+                                    // 当前促销活动的价格计算列表
+                                    List<PromotionPriceVo> promotionPriceList = productService.getPromotionProducts(promotions, cartItemVo, taxFlag);
+                                    // 更新到总促销列表
+                                    productService.updateTotalPromotions(totalPromotions, promotionsIds, promotions, promotionPriceList);
+                                    //单品满减-计算供应商总价/满减金额
+                                    if (promotions.getType() == 1 && promotions.getMode() == 2) {
+                                        BigDecimal totalAmount = MathUtil.mul(cartItemVo.getNumber(), cartItemVo.getPrice());
+                                        if (MathUtil.compare(totalAmount, promotions.getTouchPrice()) > -1) {
+                                            // 如果满足促销条件,设置供应商价格-满减金额,满减总额 + 当前促销满减金额
+                                            shopPrice.set(MathUtil.sub(shopPrice.get(), promotions.getReducedPrice()).doubleValue());
+                                            shopReducedPrice.set(MathUtil.add(shopReducedPrice, promotions.getReducedPrice()).doubleValue());
+                                        }
+                                    }
+                                    cartItemVo.setPromotions(promotions);
+                                }
+                            }
+                            if (null != promotions || null != shopPromotion) {
+                                // 商品处于活动状态
+                                cartItemVo.setActStatus(1);
+                                // 关闭阶梯价格,活动优先
+                                cartItemVo.setLadderFlag(0);
+                            } else {
+                                if (cartItemVo.getLadderFlag() == 1) {
+                                    // 设置阶梯价
+                                    productService.setCartLadderPrices(cartItemVo, taxFlag);
+                                } else {
+                                    // 复购价
+                                    Double repurchase = baseMapper.getRepurchasePrice(cartItemVo.getProductId(), userId);
+                                    if (null != repurchase && repurchase > 0) {
+                                        cartItemVo.setPrice(repurchase);
+                                    }
+                                }
+                            }
+                            // 该供应商下价格累加
+                            shopPrice.set(MathUtil.add(shopPrice, MathUtil.mul(cartItemVo.getNumber(), cartItemVo.getPrice())).doubleValue());
+                            // 该供应商下商品种类 +1
+                            shopKindCount.incrementAndGet();
+                            // 总数量 + 当前商品购买数量
+                            totalCount.updateAndGet(v -> v + cartItemVo.getNumber());
+                        }
+                    }
+                    if (shopKindCount.get() > 0) {
+                        // 店铺促销
+                        if (null != shopPromotion) {
+                            shop.setPromotions(shopPromotion);
+                            if (!promotionsIds.contains(shopPromotion.getId())) {
+                                promotionsIds.add(shopPromotion.getId());
+                                // 店铺满赠
+                                if (shopPromotion.getMode() == 3) {
+                                    // 获取赠品
+                                    List<CartItemVo> giftList = baseMapper.getPromotionGifts(shopPromotion.getId());
+                                    shopPromotion.setGiftList(giftList);
+                                }
+                                // 设置该优惠下的商品列表
+                                List<PromotionPriceVo> promotionPriceList = new ArrayList<>();
+                                productList.forEach(item -> {
+                                    PromotionPriceVo promotionPrice = new PromotionPriceVo();
+                                    promotionPrice.setProductId(item.getProductId());
+                                    promotionPrice.setNumber(item.getNumber());
+                                    promotionPrice.setPrice(item.getPrice());
+                                    promotionPriceList.add(promotionPrice);
+                                });
+                                shopPromotion.setProductList(promotionPriceList);
+                                // 添加到总促销
+                                totalPromotions.add(shopPromotion);
+                                // 店铺满减-计算供应商总价/满减金额
+                                if (shopPromotion.getMode() == 2 && MathUtil.compare(shopPrice, shopPromotion.getTouchPrice()) > -1) {
+                                    // 该供应商总价 - 满减金额
+                                    shopPrice.set(MathUtil.sub(shopPrice.get(), shopPromotion.getReducedPrice()).doubleValue());
+                                    // 该供应商优惠总额 + 满减金额
+                                    shopReducedPrice.set(MathUtil.add(shopReducedPrice.get(), shopPromotion.getReducedPrice()).doubleValue());
+                                }
+                            }
+                        }
+                        // 供应商商品
+                        shop.setCartList(productList);
+                        // 供应商总价
+                        shop.setTotalPrice(shopPrice.get());
+                        // 供应商总优惠
+                        shop.setReducedPrice(shopReducedPrice.get());
+                        // 供应商划线价
+                        shop.setOriginalPrice(MathUtil.add(shopPrice.get(), shopReducedPrice.get()).doubleValue());
+
+                        // 添加供应商Id集合
+                        shopIds.add(shop.getShopId());
+                        // 计算总价
+                        totalPrice.set(MathUtil.add(totalPrice, shop.getTotalPrice()).doubleValue());
+                        // 优惠总额
+                        reducedPrice.set(MathUtil.add(reducedPrice, shop.getReducedPrice()).doubleValue());
+                        // 总划线价
+                        totalOriginalPrice.set(MathUtil.add(totalOriginalPrice, shop.getOriginalPrice()).doubleValue());
+                        // 商品种类
+                        kindCount.updateAndGet(v -> v + shopKindCount.get());
+                    }
+                }
+                // 供应商下商品种类
+                shop.setCount(shopKindCount.get());
+            });
+            // 删除空数据
+            shopList.removeIf(shop -> (null == shop || shop.getCount() == 0));
+
+        }
+        // 总促销计算
+        totalPromotions.forEach(promotions -> {
+            // 该促销内商品总价
+            double touchPrice = promotions.getProductList().stream().mapToDouble(product -> product.getNumber() * product.getPrice()).sum();
+            // 凑单满减
+            if (promotions.getType() == 2 && promotions.getMode() == 2) {
+                if (MathUtil.compare(touchPrice, promotions.getTouchPrice()) > -1) {
+                    // 总价 - 满减金额
+                    totalPrice.set(MathUtil.sub(totalPrice, promotions.getReducedPrice()).doubleValue());
+                    // 优惠总额 + 满减金额
+                    reducedPrice.set(MathUtil.add(reducedPrice, promotions.getReducedPrice()).doubleValue());
+                }
+            } else if (promotions.getMode() == 3) {
+                // 全部满赠
+                promotions.getGiftList().forEach(gift -> {
+                    if (shopIds.contains(gift.getShopId())) {
+                        // 赠品在当前订单内的供应商下
+                        shopList.forEach(shop -> {
+                            if (shop.getShopId().equals(gift.getShopId())) {
+                                shop.getCartList().add(gift);
+                            }
+                        });
+                    } else {
+                        // 获取赠品供应商
+                        CartShopVo giftShop = baseMapper.getPromotionGiftsShop(gift.getProductId());
+                        shopIds.add(giftShop.getShopId());
+                        giftShop.setCartList(new ArrayList<>());
+                        giftShop.getCartList().add(gift);
+                        shopList.add(giftShop);
+                    }
+                });
+            }
+        });
+        // 发票信息
+        InvoiceVo invoice = baseMapper.getUserInvoice(userId);
+        // 可用余额
+        Double availableMoney = baseMapper.getUserAbleUserMoney(userId);
+        // 可用采美豆
+        Integer userBeans = baseMapper.getUserBeans(userId);
+        // 包装返回数据
+        Map<String, Object> resultData = new HashMap<>();
+        resultData.put("list", shopList);
+        resultData.put("kindCount", kindCount);
+        resultData.put("totalCount", totalCount);
+        resultData.put("totalPrice", totalPrice);
+        resultData.put("reducedPrice", reducedPrice);
+        resultData.put("totalOriginalPrice", totalOriginalPrice);
+        resultData.put("promotions", totalPromotions);
+        resultData.put("invoice", invoice);
+        resultData.put("userMoney", availableMoney);
+        resultData.put("userBeans", userBeans);
+        resultData.put("includeRecharge", includeRecharge);
+        return ResponseJson.success(resultData);
+    }
+
+    /**
+     * 立即购买
+     *
+     * @param cartDto {
+     *                userId       用户ID
+     *                productId    商品id
+     *                productCount 商品数量
+     *                }
+     */
+    @Override
+    public ResponseJson<Map<String, Object>> buyNowProduct(CartDto cartDto) {
+        CartPo cart = cartClubMapper.getCartPo(cartDto);
+        if (cart != null) {
+            // 购物车已存在该商品,更新数量
+            cart.setProductCount(cartDto.getProductCount());
+            cart.setAddTime(new Date());
+            cartClubMapper.updateCart(cart);
+        } else {
+            // 添加新购物车
+            cart = new CartPo();
+            cart.setUserId(cartDto.getUserId());
+            cart.setProductId(cartDto.getProductId());
+            cart.setProductCount(cartDto.getProductCount());
+            //判断是否是再次购买
+            Double repurchase = baseMapper.getRepurchasePrice(cartDto.getProductId(), cartDto.getUserId());
+            if (null != repurchase && repurchase > 0) {
+                // 再次购买
+                cart.setReBuyFlag(1);
+            } else {
+                cart.setReBuyFlag(0);
+            }
+            cart.setAddTime(new Date());
+            cartClubMapper.insertCart(cart);
+        }
+        // 结算商品
+        return settlementShoppingCart(cartDto.getUserId(), cartDto.getProductId().toString());
+    }
+
+    /**
+     * 获取结算商品运费
+     *
+     * @param userId     用户ID
+     * @param productIds 商品ids,逗号隔开
+     * @param townId     地区Id
+     */
+    @Override
+    public ResponseJson<Map<String, Object>> getProductsPostage(Integer userId, String productIds, Integer townId) {
+        // 商品Id信息
+        List<String> productIdList = new ArrayList<>();
+        if (productIds.contains(",")) {
+            productIdList = Stream.of(productIds.split(",")).collect(Collectors.toList());
+        } else {
+            productIdList.add(productIds);
+        }
+        // 计算运费
+        Map<String, Object> resultMap = computePostage(userId, townId, productIdList);
+        return ResponseJson.success(resultMap);
+    }
+
+    /**
+     * 计算运费
+     * @param userId     用户ID
+     * @param townId     地区Id
+     * @param productIdList 商品Id列表
+     */
+    private Map<String, Object> computePostage(Integer userId, Integer townId, List<String> productIdList) {
+        // 返回数据初始化
+        Map<String, Object> postageMap = new HashMap<>(2);
+        // 运费标志:0包邮 1到付 2遵循运费规则, 注意,旧接口返回前端是:-1到付(默认),0包邮,1有运费
+        int postageFlag = 0;
+        // 运费
+        Double postage = 0.00d;
+        // 可用采美豆
+        Integer userBeans = baseMapper.getUserBeans(userId);
+        postageMap.put("userBeans", userBeans);
+        // 获取商品运费 (0包邮 1到付 2默认(遵循运费规则))
+        List<ProductPostageVo> postageFlagList = baseMapper.getPostageFlagList(productIdList);
+        for (ProductPostageVo postageVo : postageFlagList){
+            // 是否是仪器 或 设置了运费到付
+            boolean flag = (2 == postageVo.getCommodityType() || (null != postageVo.getPostageFlag() && 1==postageVo.getPostageFlag()));
+            if (flag) {
+                // 到付
+                postageMap.put("postageFlag", 1);
+                postageMap.put("postage", 0.00d);
+                return postageMap;
+            } else if (null != postageVo.getPostageFlag() && 2==postageVo.getPostageFlag()) {
+                // 若有不包邮商品,则全部不包邮
+                postageFlag = 2;
+            }
+        }
+        // 是否首单(统计订单数)
+        Integer count = baseMapper.countUserOrder(userId);
+        // 包邮条件:首单 或 包邮(上一步未被设置成不包邮)
+        boolean freeFlag = ((null != count && count == 0) || postageFlag == 0);
+        if (freeFlag) {
+            // 包邮
+            postageMap.put("postageFlag", 0);
+            postageMap.put("postage", 0.00d);
+            return postageMap;
+        } else {
+            /*
+             * 运费计算:广东省内运费15元,深圳市内运费10,其他地区到付
+             */
+            postageFlag = 2;
+            // 获取根据地区Id获取省市地址信息
+            AddressVo address = baseMapper.getProvinceIdAndCityId(townId);
+            if (null != address && 202 == address.getCityId()) {
+                // 深圳市内运费10
+                postage = 10.00d;
+            } else if (null != address && 19 == address.getProvinceId()){
+                // 广东省内运费15元
+                postage = 15.00d;
+            } else {
+                // 到付
+                postageFlag = 1;
+            }
+            postageMap.put("postageFlag", postageFlag);
+            postageMap.put("postage", postage);
+            return postageMap;
+        }
+    }
+
 
 
 

+ 49 - 1
src/main/resources/mapper/BaseMapper.xml

@@ -78,10 +78,58 @@
         p.stock AS stock,
         p.validFlag AS validFlag
         FROM cm_promotions_gift cpg
-        LEFT JOIN FROM product p ON cpg.productId = p.productID
+        LEFT JOIN product p ON cpg.productId = p.productID
         WHERE cpg.promotionsId = #{promotionsId}
         ORDER BY cpg.id DESC
     </select>
+    <select id="getPromotionGiftsShop" resultType="com.caimei365.order.model.vo.CartShopVo">
+        SELECT
+        s.shopID AS shopId,
+        s.name AS shopName,
+        s.logo AS shopLogo
+        FROM shop s
+        LEFT JOIN product p ON p.shopID = s.shopID
+        WHERE p.productId = #{productId}
+        LIMIT 1
+    </select>
+    <select id="getUserInvoice" resultType="com.caimei365.order.model.vo.InvoiceVo">
+        SELECT
+            id,
+            userId,
+            invoiceTitle,
+            corporationTaxNum,
+            registeredAddress,
+            registeredPhone,
+            bankAccountNo,
+            openBank
+        FROM cm_user_invoiceinfo
+        WHERE userId = #{userId}
+        LIMIT 1
+    </select>
+    <select id="getUserAbleUserMoney" resultType="java.lang.Double">
+        SELECT ableUserMoney FROM user WHERE userID = #{userId}
+    </select>
+    <select id="getUserBeans" resultType="java.lang.Integer">
+        SELECT userBeans FROM user WHERE userID = #{userId}
+    </select>
+    <select id="getPostageFlagList" resultType="com.caimei365.order.model.vo.ProductPostageVo">
+        SELECT
+            productID AS productId,
+            freePostFlag AS postageFlag,
+            commodityType
+        FROM product
+        WHERE validFlag='2' AND productID in
+        <foreach collection="productIds" open="(" separator="," close=")" item="productId">
+            #{productId}
+        </foreach>
+    </select>
+    <select id="countUserOrder" resultType="java.lang.Integer">
+        SELECT COUNT(*) FROM cm_order WHERE userID = #{userId} AND delFlag=0 AND STATUS != 6
+    </select>
+    <select id="getProvinceIdAndCityId" resultType="com.caimei365.order.model.vo.AddressVo">
+        SELECT provinceID AS provinceId, cityID AS cityId FROM city
+        WHERE cityID =(SELECT cityID from town where townID = #{townId})
+    </select>
 
 
 </mapper>

+ 44 - 0
src/main/resources/mapper/CartClubMapper.xml

@@ -13,6 +13,21 @@
         GROUP BY c.shopID
         ORDER BY c.cm_cartID DESC
     </select>
+    <select id="getCartShopsByProductIds" resultType="com.caimei365.order.model.vo.CartShopVo">
+        SELECT
+        c.shopID AS shopId,
+        s.name AS shopName,
+        s.logo AS shopLogo
+        FROM cm_cart c
+        LEFT JOIN shop s ON c.shopID = s.shopID
+        WHERE c.userID = #{userId}
+        AND productID in
+        <foreach collection="productIds" open="(" separator="," close=")" item="productId">
+            #{productId}
+        </foreach>
+        GROUP BY c.shopID
+        ORDER BY c.cm_cartID DESC
+    </select>
     <select id="getCartProductsByShopId" resultType="com.caimei365.order.model.vo.CartItemVo">
         SELECT
             c.cm_cartID AS id,
@@ -38,6 +53,35 @@
         WHERE c.userID = #{userId} and p.shopID = #{shopId}
         ORDER BY c.cm_cartID DESC
     </select>
+    <select id="getCartProductsByShopIdAndProductIds" resultType="com.caimei365.order.model.vo.CartItemVo">
+        SELECT
+        c.cm_cartID AS id,
+        c.productCount AS number,
+        p.productID AS productId,
+        p.shopID AS shopId,
+        p.`name` AS `name`,
+        p.mainImage AS image,
+        p.price1 AS price,
+        p.price1 AS originalPrice,
+        p.unit AS unit,
+        p.stock AS stock,
+        p.step AS step,
+        p.minBuyNumber AS MIN,
+        p.price1TextFlag AS priceFlag,
+        p.ladderPriceFlag AS ladderFlag,
+        p.includedTax AS includedTax,
+        p.invoiceType AS invoiceType,
+        p.taxPoint AS taxRate,
+        p.validFlag AS validFlag
+        FROM cm_cart c
+        LEFT JOIN product p ON c.productID = p.productID
+        WHERE c.userID = #{userId} and p.shopID = #{shopId}
+        AND p.validFlag='2' AND productID in
+        <foreach collection="productIds" open="(" separator="," close=")" item="productId">
+            #{productId}
+        </foreach>
+        ORDER BY c.cm_cartID DESC
+    </select>
     <select id="getCartProductList" resultType="com.caimei365.order.model.vo.CartItemVo">
         SELECT
             c.cm_cartID AS id,