yangyb 3 týždňov pred
rodič
commit
58e6add399
22 zmenil súbory, kde vykonal 1197 pridanie a 66 odobranie
  1. 1 1
      mall-api/src/main/java/com/txz/mall/constants/Constants.java
  2. 10 1
      mall-service/pom.xml
  3. 24 11
      mall-service/src/main/java/com/txz/mall/controller/OrderController.java
  4. 19 0
      mall-service/src/main/java/com/txz/mall/dubbo/client/CifUserDubboServiceClient.java
  5. 10 6
      mall-service/src/main/java/com/txz/mall/dubbo/client/OperatingConfigDubboServiceClient.java
  6. 1 1
      mall-service/src/main/java/com/txz/mall/model/StoreProduct.java
  7. 19 0
      mall-service/src/main/java/com/txz/mall/service/ProductAttrValueService.java
  8. 8 0
      mall-service/src/main/java/com/txz/mall/service/StoreCombinationService.java
  9. 39 2
      mall-service/src/main/java/com/txz/mall/service/StoreOrderService.java
  10. 6 0
      mall-service/src/main/java/com/txz/mall/service/UserAddressService.java
  11. 32 0
      mall-service/src/main/java/com/txz/mall/service/impl/ProductAttrValueServiceImpl.java
  12. 14 0
      mall-service/src/main/java/com/txz/mall/service/impl/StoreCombinationServiceImpl.java
  13. 567 19
      mall-service/src/main/java/com/txz/mall/service/impl/StoreOrderServiceImpl.java
  14. 16 0
      mall-service/src/main/java/com/txz/mall/service/impl/UserAddressServiceImpl.java
  15. 0 25
      mall-service/src/main/java/com/txz/mall/util/MyDateUtil.java
  16. 55 0
      mall-service/src/main/java/dto/ComputedOrderPriceResponse.java
  17. 38 0
      mall-service/src/main/java/dto/OrderComputedPriceRequest.java
  18. 57 0
      mall-service/src/main/java/dto/PreOrderDetailRequest.java
  19. 37 0
      mall-service/src/main/java/dto/PreOrderRequest.java
  20. 50 0
      mall-service/src/main/java/dto/PreOrderResponse.java
  21. 96 0
      mall-service/src/main/java/vo/OrderInfoDetailVO.java
  22. 98 0
      mall-service/src/main/java/vo/OrderInfoVO.java

+ 1 - 1
mall-api/src/main/java/com/txz/mall/constants/Constants.java

@@ -436,7 +436,7 @@ public class Constants {
 
 
     // 订单缓存
-    public static final long ORDER_CASH_CONFIRM = (60);
+    public static final long ORDER_CASH_CONFIRM = (60 * 60);
     public static final String ORDER_CACHE_PER = "ORDER_CACHE:"; // redis缓存订单前缀
 
     //订单操作类型 -> 消息

+ 10 - 1
mall-service/pom.xml

@@ -87,7 +87,16 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
+        <dependency>
+            <groupId>com.txz</groupId>
+            <artifactId>operating-api</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.txz</groupId>
+            <artifactId>cif-api</artifactId>
+            <version>1.0.0-SNAPSHOT</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 24 - 11
mall-service/src/main/java/com/txz/mall/controller/OrderController.java

@@ -6,12 +6,12 @@ import com.txz.mall.core.Result;
 import com.txz.mall.core.ResultCode;
 import com.txz.mall.model.StoreOrder;
 import com.txz.mall.service.StoreOrderService;
-import dto.StoreOrderDTO;
-import dto.StoreOrderDeliveryDTO;
+import dto.*;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import vo.StoreOrderCountItemVO;
 import vo.StoreOrderVO;
@@ -91,18 +91,12 @@ public class OrderController {
 
     @PostMapping("/detail")
     @ApiOperation(value = "订单获取详情")
-    public Result<StoreOrder> detail(@RequestParam Long id) {
+    public Result<StoreOrderVO> detail(@RequestParam Long id) {
         if (id == null) {
             return Result.fail(ResultCode.ID_IS_NULL);
         }
-        StoreOrder storeOrder = null;
-        try {
-            storeOrder = storeOrderService.findById(id);
-        } catch (Exception e) {
-            log.error("查询对象操作异常e:{}", e);
-            return Result.fail(ResultCode.INTERNAL_SERVER_ERROR);
-        }
-        return Result.success(storeOrder);
+        StoreOrderVO vo = storeOrderService.orderDetail(id);
+        return Result.success(vo);
     }
 
     @PostMapping("/list")
@@ -160,4 +154,23 @@ public class OrderController {
         storeOrderService.batchDelivery(list);
         return Result.success();
     }
+
+    @ApiOperation(value = "预下单")
+    @PostMapping(value = "/pre/order")
+    public Result<String> preOrder(@RequestBody @Validated PreOrderRequest request) {
+        String orderNO = storeOrderService.preOrder(request);
+        return Result.success(orderNO);
+    }
+
+    @ApiOperation(value = "加载预下单")
+    @PostMapping(value = "load/pre")
+    public Result<PreOrderResponse> loadPreOrder(@RequestParam String preOrderNo) {
+        return Result.success(storeOrderService.loadPreOrder(preOrderNo));
+    }
+
+    @ApiOperation(value = "计算订单价格")
+    @PostMapping(value = "/computed/price")
+    public Result<ComputedOrderPriceResponse> computedPrice(@Validated @RequestBody OrderComputedPriceRequest request) {
+        return Result.success(storeOrderService.computedOrderPrice(request));
+    }
 }

+ 19 - 0
mall-service/src/main/java/com/txz/mall/dubbo/client/CifUserDubboServiceClient.java

@@ -0,0 +1,19 @@
+package com.txz.mall.dubbo.client;
+
+import com.txz.cif.dto.UserDTO;
+import com.txz.cif.service.UserDubboService;
+import jdk.nashorn.internal.ir.annotations.Reference;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class CifUserDubboServiceClient {
+
+    @Reference
+    private UserDubboService userDubboService;
+
+    public UserDTO getUser(Long userId) {
+        return userDubboService.getUser(userId);
+    }
+}

+ 10 - 6
mall-service/src/main/java/com/txz/mall/dubbo/client/OperatingConfigDubboServiceClient.java

@@ -1,5 +1,9 @@
 package com.txz.mall.dubbo.client;
 
+import com.txz.operating.dto.ConfigDTO;
+import com.txz.operating.result.Result;
+import com.txz.operating.service.OperatingConfigDubboService;
+import jdk.nashorn.internal.ir.annotations.Reference;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 
@@ -7,10 +11,10 @@ import org.springframework.stereotype.Component;
 @Component
 public class OperatingConfigDubboServiceClient {
 
-//    @Reference
-//    private OperatingConfigDubboService operatingConfigDubboService;
-//
-//    public Result<ConfigDTO> getConfigByCode(String code){
-//        return operatingConfigDubboService.getConfigByCode(code);
-//    }
+    @Reference
+    private OperatingConfigDubboService operatingConfigDubboService;
+
+    public Result<ConfigDTO> getConfigByCode(String code) {
+        return operatingConfigDubboService.getConfigByCode(code);
+    }
 }

+ 1 - 1
mall-service/src/main/java/com/txz/mall/model/StoreProduct.java

@@ -228,7 +228,7 @@ public class StoreProduct {
      */
     @Column(name = "temp_id")
     @ApiModelProperty("运费模板ID")
-    private Integer tempId;
+    private Long tempId;
 
     /**
      * 规格 0单 1多

+ 19 - 0
mall-service/src/main/java/com/txz/mall/service/ProductAttrValueService.java

@@ -19,4 +19,23 @@ public interface ProductAttrValueService extends Service<ProductAttrValue> {
      * @return List
      */
     List<ProductAttrValue> getListByProductIdAndType(Long productId, Integer type);
+
+    /**
+     * 根据id、类型查询
+     *
+     * @param id   ID
+     * @param type 类型
+     * @return StoreProductAttrValue
+     */
+    ProductAttrValue getByIdAndProductIdAndType(Long id, Long productId, Integer type);
+
+    /**
+     * 根据sku查询
+     *
+     * @param productId 商品id
+     * @param suk       sku
+     * @param type      规格类型
+     * @return StoreProductAttrValue
+     */
+    ProductAttrValue getByProductIdAndSkuAndType(Long productId, String suk, Integer type);
 }

+ 8 - 0
mall-service/src/main/java/com/txz/mall/service/StoreCombinationService.java

@@ -44,5 +44,13 @@ public interface StoreCombinationService extends Service<StoreCombination> {
      */
     List<StoreCombination> getMore(Integer comId);
 
+    /**
+     * 查询带异常
+     *
+     * @param id 秒杀商品id
+     * @return StoreSeckill
+     */
+    StoreCombination getByIdException(Long id);
+
 
 }

+ 39 - 2
mall-service/src/main/java/com/txz/mall/service/StoreOrderService.java

@@ -2,8 +2,7 @@ package com.txz.mall.service;
 
 import com.txz.mall.core.Service;
 import com.txz.mall.model.StoreOrder;
-import dto.StoreOrderDTO;
-import dto.StoreOrderDeliveryDTO;
+import dto.*;
 import vo.OrderRefundApplyVO;
 import vo.StoreOrderCountItemVO;
 import vo.StoreOrderVO;
@@ -36,6 +35,21 @@ public interface StoreOrderService extends Service<StoreOrder> {
      */
     void batchDelivery(List<StoreOrderDeliveryDTO> dto);
 
+    /**
+     * 获取订单详情
+     *
+     * @return StoreOrderVO
+     */
+    ComputedOrderPriceResponse computedOrderPrice(OrderComputedPriceRequest request);
+
+    /**
+     * 订单预下单
+     *
+     * @param request 预下单请求参数
+     * @return PreOrderResponse
+     */
+    String preOrder(PreOrderRequest request);
+
     /**
      * 订单退款申请Task使用
      *
@@ -50,4 +64,27 @@ public interface StoreOrderService extends Service<StoreOrder> {
      * @return 订单列表
      */
     List<StoreOrderVO> orderList(StoreOrderDTO dto);
+
+    /**
+     * 获取订单列表
+     *
+     * @return 订单列表
+     */
+    StoreOrderVO orderDetail(Long id);
+
+    /**
+     * 获取用户当前的拼团订单
+     *
+     * @param uid 用户uid
+     * @return 用户当前的拼团订单
+     */
+    List<StoreOrder> getUserCurrentCombinationOrders(Long uid, Long combinationId);
+
+    /**
+     * 加载预下单信息
+     *
+     * @param preOrderNo 预下单号
+     * @return 预下单信息
+     */
+    PreOrderResponse loadPreOrder(String preOrderNo);
 }

+ 6 - 0
mall-service/src/main/java/com/txz/mall/service/UserAddressService.java

@@ -9,4 +9,10 @@ import com.txz.mall.model.UserAddress;
  */
 public interface UserAddressService extends Service<UserAddress> {
 
+    /**
+     * 获取默认地址
+     *
+     * @return UserAddress
+     */
+    UserAddress getDefaultByUid(Long uid);
 }

+ 32 - 0
mall-service/src/main/java/com/txz/mall/service/impl/ProductAttrValueServiceImpl.java

@@ -1,5 +1,7 @@
 package com.txz.mall.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.txz.mall.core.AbstractService;
 import com.txz.mall.dao.ProductAttrValueMapper;
 import com.txz.mall.model.ProductAttrValue;
@@ -31,4 +33,34 @@ public class ProductAttrValueServiceImpl extends AbstractService<ProductAttrValu
         criteria.andEqualTo("type", type);
         return this.findByCondition(condition);
     }
+
+    @Override
+    public ProductAttrValue getByIdAndProductIdAndType(Long id, Long productId, Integer type) {
+        Condition condition = new Condition(ProductAttrValue.class);
+        Example.Criteria criteria = condition.createCriteria();
+        criteria.andEqualTo("id", id);
+        criteria.andEqualTo("productId", productId);
+        criteria.andEqualTo("type", type);
+        criteria.andEqualTo("isDelete", 0);
+        List<ProductAttrValue> list = this.findByCondition(condition);
+        if (CollUtil.isEmpty(list)) {
+            return null;
+        }
+        return this.findByCondition(condition).get(0);
+    }
+
+    @Override
+    public ProductAttrValue getByProductIdAndSkuAndType(Long productId, String suk, Integer type) {
+        Condition condition = new Condition(ProductAttrValue.class);
+        Example.Criteria criteria = condition.createCriteria();
+        criteria.andEqualTo("productId", productId);
+        criteria.andEqualTo("sku", suk);
+        criteria.andEqualTo("type", type);
+        criteria.andEqualTo("isDelete", 0);
+        List<ProductAttrValue> list = this.findByCondition(condition);
+        if (CollectionUtils.isNotEmpty(list)) {
+            return list.get(0);
+        }
+        return null;
+    }
 }

+ 14 - 0
mall-service/src/main/java/com/txz/mall/service/impl/StoreCombinationServiceImpl.java

@@ -331,5 +331,19 @@ public class StoreCombinationServiceImpl extends AbstractService<StoreCombinatio
         return findByCondition(condition);
     }
 
+    @Override
+    public StoreCombination getByIdException(Long combinationId) {
+        Condition condition = new Condition(StoreCombination.class);
+        Example.Criteria criteria = condition.createCriteria();
+        criteria.andEqualTo("isDelete", 0);
+        criteria.andEqualTo("id", combinationId);
+        criteria.andEqualTo("isShow", 1);
+        List<StoreCombination> combinationList = findByCondition(condition);
+        if (CollUtil.isEmpty(combinationList)) {
+            throw new ServiceException("拼团商品不存在或未开启");
+        }
+        return combinationList.get(0);
+    }
+
 
 }

+ 567 - 19
mall-service/src/main/java/com/txz/mall/service/impl/StoreOrderServiceImpl.java

@@ -1,37 +1,35 @@
 package com.txz.mall.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
 import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.txz.cif.dto.UserDTO;
 import com.txz.mall.constants.Constants;
 import com.txz.mall.core.AbstractService;
+import com.txz.mall.core.RedisUtil;
 import com.txz.mall.core.ServiceException;
-import com.txz.mall.dao.StoreOrderMapper;
-import com.txz.mall.model.StoreOrder;
-import com.txz.mall.model.StoreOrderInfo;
-import com.txz.mall.model.StoreProduct;
-import com.txz.mall.service.StoreOrderInfoService;
-import com.txz.mall.service.StoreOrderService;
-import dto.StoreOrderDTO;
-import dto.StoreOrderDeliveryDTO;
+import com.txz.mall.dubbo.client.CifUserDubboServiceClient;
+import com.txz.mall.model.*;
+import com.txz.mall.service.*;
+import com.txz.mall.util.OrderUtils;
+import dto.*;
+import lombok.AllArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import tk.mybatis.mapper.entity.Condition;
 import tk.mybatis.mapper.entity.Example;
-import vo.OrderRefundApplyVO;
-import vo.StoreOrderCountItemVO;
-import vo.StoreOrderVO;
+import vo.*;
 
-import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.OutputStream;
+import java.math.BigDecimal;
 import java.net.URLEncoder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import java.util.*;
 import java.util.stream.Collectors;
 
 
@@ -41,12 +39,18 @@ import java.util.stream.Collectors;
 @Service
 @Transactional
 @Slf4j
+@AllArgsConstructor
 public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implements StoreOrderService {
-    @Resource
-    private StoreOrderMapper storeOrderMapper;
 
-    @Resource
-    private StoreOrderInfoService storeOrderInfoService;
+    private final StoreOrderInfoService storeOrderInfoService;
+    private final UserAddressService userAddressService;
+    private final StoreCombinationService storeCombinationService;
+    private final ProductAttrService productAttrService;
+    private final ProductAttrValueService productAttrValueService;
+    private final StoreProductService storeProductService;
+    private final CifUserDubboServiceClient userDubboServiceClient;
+    private final Long userId = 1L;
+    private RedisUtil redisUtil;
 
     @Override
     public StoreOrderCountItemVO getOrderStatusNum() {
@@ -97,6 +101,510 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
 
     }
 
+    @Override
+    public String preOrder(PreOrderRequest request) {
+        if (CollUtil.isEmpty(request.getOrderDetails())) {
+            throw new ServiceException("预下单订单详情列表不能为空");
+        }
+        UserDTO user = userDubboServiceClient.getUser(userId);
+        // 校验预下单商品信息
+        OrderInfoVO orderInfoVo = validatePreOrderRequest(request, user);
+        // 商品总计金额
+        BigDecimal totalPrice;
+        if (orderInfoVo.getOrderDetailList().get(0).getProductType().equals(Constants.PRODUCT_TYPE_NORMAL)) {
+            // 普通商品
+            totalPrice = orderInfoVo.getOrderDetailList().stream().map(e -> e.getVipPrice().multiply(new BigDecimal(e.getPayNum()))).reduce(BigDecimal.ZERO, BigDecimal::add);
+        } else {
+            totalPrice = orderInfoVo.getOrderDetailList().stream().map(e -> e.getPrice().multiply(new BigDecimal(e.getPayNum()))).reduce(BigDecimal.ZERO, BigDecimal::add);
+        }
+        orderInfoVo.setProTotalFee(totalPrice);
+        // 购买商品总数量
+        int orderProNum = orderInfoVo.getOrderDetailList().stream().mapToInt(OrderInfoDetailVO::getPayNum).sum();
+        orderInfoVo.setOrderProNum(orderProNum);
+        // 获取默认地址
+        UserAddress userAddress = userAddressService.getDefaultByUid(userId);
+        if (ObjectUtil.isNotNull(userAddress)) {
+            // 计算运费
+            getFreightFee(orderInfoVo, userAddress);
+            orderInfoVo.setAddressId(userAddress.getId());
+            orderInfoVo.setRealName(userAddress.getRealName());
+            orderInfoVo.setPhone(userAddress.getPhone());
+            orderInfoVo.setProvince(userAddress.getProvince());
+            orderInfoVo.setCity(userAddress.getCity());
+            orderInfoVo.setDistrict(userAddress.getDistrict());
+            orderInfoVo.setDetail(userAddress.getDetail());
+        } else {
+            orderInfoVo.setFreightFee(BigDecimal.ZERO);
+        }
+        // 实际支付金额
+        orderInfoVo.setPayFee(orderInfoVo.getProTotalFee().add(orderInfoVo.getFreightFee()));
+//        orderInfoVo.setUserIntegral(user.getIntegral());
+//        orderInfoVo.setUserBalance(user.getNowMoney());
+        // 缓存订单
+//        String key = user.getUid() + DateUtil.getNowTime().toString() + CrmebUtil.getUuid();
+        String key = OrderUtils.getOrderCode();
+        redisUtil.set("user_order:" + key, JSONObject.toJSONString(orderInfoVo), Constants.ORDER_CASH_CONFIRM);
+        return key;
+    }
+
+    /**
+     * 计算订单运费
+     */
+    private void getFreightFee(OrderInfoVO orderInfoVo, UserAddress userAddress) {
+//        // 判断是否满额包邮 type=1按件数 2按重量 3按体积
+//        // 全场满额包邮开关
+//        String postageSwitchString = systemConfigService.getValueByKey(SysConfigConstants.STORE_FEE_POSTAGE_SWITCH);
+//        // 全场满额包邮金额
+//        String storeFreePostageString = systemConfigService.getValueByKey(SysConfigConstants.STORE_FEE_POSTAGE);
+        BigDecimal storePostage = BigDecimal.ZERO;
+//        if ("true".equals(postageSwitchString) && ("0".equals(storeFreePostageString) || orderInfoVo.getProTotalFee().compareTo(new BigDecimal(storeFreePostageString)) >= 0)) {
+//            storePostage = BigDecimal.ZERO;
+//        } else if (ObjectUtil.isNull(userAddress) || userAddress.getCityId() <= 0) {
+//            // 用户地址不存在,默认运费为0元
+//            storePostage = BigDecimal.ZERO;
+//        } else {
+//            // 有用户地址的情况下
+//            // 运费根据商品计算
+//            Map<Integer, MyRecord> proMap = CollUtil.newHashMap();
+//            orderInfoVo.getOrderDetailList().forEach(e -> {
+//                Integer proId = e.getProductId();
+//                if (proMap.containsKey(proId)) {
+//                    MyRecord record = proMap.get(proId);
+//                    record.set("totalPrice", record.getBigDecimal("totalPrice").add(e.getPrice().multiply(BigDecimal.valueOf(e.getPayNum()))));
+//                    record.set("totalNum", record.getInt("totalNum") + e.getPayNum());
+//                    BigDecimal weight = e.getWeight().multiply(BigDecimal.valueOf(e.getPayNum()));
+//                    record.set("weight", record.getBigDecimal("weight").add(weight));
+//                    BigDecimal volume = e.getVolume().multiply(BigDecimal.valueOf(e.getPayNum()));
+//                    record.set("volume", record.getBigDecimal("volume").add(volume));
+//                } else {
+//                    MyRecord record = new MyRecord();
+//                    record.set("totalPrice", e.getPrice().multiply(BigDecimal.valueOf(e.getPayNum())));
+//                    record.set("totalNum", e.getPayNum());
+//                    record.set("tempId", e.getTempId());
+//                    record.set("proId", proId);
+//                    BigDecimal weight = e.getWeight().multiply(BigDecimal.valueOf(e.getPayNum()));
+//                    record.set("weight", weight);
+//                    BigDecimal volume = e.getVolume().multiply(BigDecimal.valueOf(e.getPayNum()));
+//                    record.set("volume", volume);
+//
+//                    proMap.put(proId, record);
+//                }
+//            });
+//
+//            // 指定包邮(单品运费模板)> 指定区域配送(单品运费模板)
+//            int cityId = userAddress.getCityId();
+//
+//            for (Map.Entry<Integer, MyRecord> m : proMap.entrySet()) {
+//                MyRecord value = m.getValue();
+//                Integer tempId = value.getInt("tempId");
+//                ShippingTemplates shippingTemplate = shippingTemplatesService.getById(tempId);
+//                if (shippingTemplate.getAppoint()) {// 指定包邮
+//                    // 判断是否在指定包邮区域内
+//                    // 必须满足件数 + 金额 才能包邮
+//                    ShippingTemplatesFree shippingTemplatesFree = shippingTemplatesFreeService.getByTempIdAndCityId(tempId, cityId);
+//                    if (ObjectUtil.isNotNull(shippingTemplatesFree)) { // 在包邮区域内
+//                        BigDecimal freeNum = shippingTemplatesFree.getNumber();
+//                        BigDecimal multiply = value.getBigDecimal("totalPrice");
+//                        if (new BigDecimal(value.getInt("totalNum")).compareTo(freeNum) >= 0 && multiply.compareTo(shippingTemplatesFree.getPrice()) >= 0) {
+//                            // 满足件数 + 金额 = 包邮
+//                            continue;
+//                        }
+//                    }
+//                }
+//                // 不满足指定包邮条件,走指定区域配送
+//                ShippingTemplatesRegion shippingTemplatesRegion = shippingTemplatesRegionService.getByTempIdAndCityId(tempId, cityId);
+//                if (ObjectUtil.isNull(shippingTemplatesRegion)) {
+//                    throw new ServiceException("计算运费时,未找到全国运费配置");
+//                }
+//
+//                // 判断计费方式:件数、重量、体积
+//                switch (shippingTemplate.getType()) {
+//                    case 1: // 件数
+//                        // 判断件数是否超过首件
+//                        Integer num = value.getInt("totalNum");
+//                        if (num <= shippingTemplatesRegion.getFirst().intValue()) {
+//                            storePostage = storePostage.add(shippingTemplatesRegion.getFirstPrice());
+//                        } else {// 超过首件的需要计算续件
+//                            int renewalNum = num - shippingTemplatesRegion.getFirst().intValue();
+//                            // 剩余件数/续件 = 需要计算的续件费用的次数
+//                            BigDecimal divide = new BigDecimal(renewalNum).divide(shippingTemplatesRegion.getRenewal(), 0, BigDecimal.ROUND_UP);
+//                            BigDecimal renewalPrice = shippingTemplatesRegion.getRenewalPrice().multiply(divide);
+//                            storePostage = storePostage.add(shippingTemplatesRegion.getFirstPrice()).add(renewalPrice);
+//                        }
+//                        break;
+//                    case 2: // 重量
+//                        BigDecimal weight = value.getBigDecimal("weight");
+//                        if (weight.compareTo(shippingTemplatesRegion.getFirst()) <= 0) {
+//                            storePostage = storePostage.add(shippingTemplatesRegion.getFirstPrice());
+//                        } else {// 超过首件的需要计算续件
+//                            BigDecimal renewalNum = weight.subtract(shippingTemplatesRegion.getFirst());
+//                            // 剩余件数/续件 = 需要计算的续件费用的次数
+//                            BigDecimal divide = renewalNum.divide(shippingTemplatesRegion.getRenewal(), 0, BigDecimal.ROUND_UP);
+//                            BigDecimal renewalPrice = shippingTemplatesRegion.getRenewalPrice().multiply(divide);
+//                            storePostage = storePostage.add(shippingTemplatesRegion.getFirstPrice()).add(renewalPrice);
+//                        }
+//                        break;
+//                    case 3: // 体积
+//                        BigDecimal volume = value.getBigDecimal("volume");
+//                        if (volume.compareTo(shippingTemplatesRegion.getFirst()) <= 0) {
+//                            storePostage = storePostage.add(shippingTemplatesRegion.getFirstPrice());
+//                        } else {// 超过首件的需要计算续件
+//                            BigDecimal renewalNum = volume.subtract(shippingTemplatesRegion.getFirst());
+//                            // 剩余件数/续件 = 需要计算的续件费用的次数
+//                            BigDecimal divide = renewalNum.divide(shippingTemplatesRegion.getRenewal(), 0, BigDecimal.ROUND_UP);
+//                            BigDecimal renewalPrice = shippingTemplatesRegion.getRenewalPrice().multiply(divide);
+//                            storePostage = storePostage.add(shippingTemplatesRegion.getFirstPrice()).add(renewalPrice);
+//                        }
+//                        break;
+//                }
+//            }
+//        }
+        orderInfoVo.setFreightFee(storePostage);
+    }
+
+    /**
+     * 校验预下单商品信息
+     *
+     * @param request 预下单请求参数
+     * @return OrderInfoVo
+     */
+    private OrderInfoVO validatePreOrderRequest(PreOrderRequest request, UserDTO user) {
+        OrderInfoVO orderInfoVo = new OrderInfoVO();
+        List<OrderInfoDetailVO> detailVoList = CollUtil.newArrayList();
+//        if ("shoppingCart".equals(request.getPreOrderType())) {
+//            // 购物车购买
+//            detailVoList = validatePreOrderShopping(request, user);
+//            List<Long> cartIdList = request.getOrderDetails().stream().map(PreOrderDetailRequest::getShoppingCartId).distinct().collect(Collectors.toList());
+//            orderInfoVo.setCartIdList(cartIdList);
+//        }
+        if ("buyNow".equals(request.getPreOrderType())) {
+            // 立即购买
+            // 立即购买只会有一条详情
+            PreOrderDetailRequest detailRequest = request.getOrderDetails().get(0);
+//            if (detailRequest.getSeckillId() > 0) {
+//                // 秒杀
+//                detailVoList.add(validatePreOrderSeckill(detailRequest, user));
+//                orderInfoVo.setSeckillId(detailRequest.getSeckillId());
+//            } else if (detailRequest.getBargainId() > 0) {
+//                // 砍价
+//                detailVoList.add(validatePreOrderBargain(detailRequest, user));
+//                orderInfoVo.setBargainId(detailRequest.getBargainId());
+//                orderInfoVo.setBargainUserId(detailRequest.getBargainUserId());
+//            } else
+            if (detailRequest.getCombinationId() > 0) {
+                // 拼团
+                detailVoList.add(validatePreOrderCombination(detailRequest, user));
+                orderInfoVo.setCombinationId(detailRequest.getCombinationId());
+                orderInfoVo.setPinkId(detailRequest.getPinkId());
+            } else {
+                // 普通商品
+                if (ObjectUtil.isNull(detailRequest.getProductId())) {
+                    throw new ServiceException("商品编号不能为空");
+                }
+                if (ObjectUtil.isNull(detailRequest.getAttrValueId())) {
+                    throw new ServiceException("商品规格属性值不能为空");
+                }
+                if (ObjectUtil.isNull(detailRequest.getProductNum()) || detailRequest.getProductNum() < 0) {
+                    throw new ServiceException("购买数量必须大于0");
+                }
+                // 查询商品信息
+                StoreProduct storeProduct = storeProductService.findById(detailRequest.getProductId());
+                if (ObjectUtil.isNull(storeProduct)) {
+                    throw new ServiceException("商品信息不存在,请刷新后重新选择");
+                }
+                if (storeProduct.getIsDelete().equals(1)) {
+                    throw new ServiceException("商品已删除,请刷新后重新选择");
+                }
+                if (storeProduct.getIsShow().equals(0)) {
+                    throw new ServiceException("商品已下架,请刷新后重新选择");
+                }
+                if (storeProduct.getStock() < detailRequest.getProductNum()) {
+                    throw new ServiceException("商品库存不足,请刷新后重新选择");
+                }
+                // 查询商品规格属性值信息
+                ProductAttrValue attrValue = productAttrValueService.getByIdAndProductIdAndType(detailRequest.getAttrValueId(), detailRequest.getProductId(), Constants.PRODUCT_TYPE_NORMAL);
+                if (ObjectUtil.isNull(attrValue)) {
+                    throw new ServiceException("商品规格信息不存在,请刷新后重新选择");
+                }
+                if (attrValue.getStock() < detailRequest.getProductNum()) {
+                    throw new ServiceException("商品规格库存不足,请刷新后重新选择");
+                }
+//                SystemUserLevel userLevel = null;
+//                if (user.getLevel() > 0) {
+//                    userLevel = systemUserLevelService.getByLevelId(user.getLevel());
+//                }
+                OrderInfoDetailVO detailVo = new OrderInfoDetailVO();
+                detailVo.setProductId(storeProduct.getId());
+                detailVo.setProductName(storeProduct.getStoreName());
+                detailVo.setAttrValueId(attrValue.getId());
+                detailVo.setSku(attrValue.getSuk());
+                detailVo.setPrice(attrValue.getPrice());
+                detailVo.setPayNum(detailRequest.getProductNum());
+                detailVo.setImage(StrUtil.isNotBlank(attrValue.getImage()) ? attrValue.getImage() : storeProduct.getImage());
+                detailVo.setVolume(attrValue.getVolume());
+                detailVo.setWeight(attrValue.getWeight());
+                detailVo.setTempId(storeProduct.getTempId());
+                detailVo.setIsSub(storeProduct.getIsSub());
+                detailVo.setProductType(Constants.PRODUCT_TYPE_NORMAL);
+                detailVo.setVipPrice(detailVo.getPrice());
+                detailVo.setGiveIntegral(storeProduct.getGiveIntegral());
+//                if (ObjectUtil.isNotNull(userLevel)) {
+//                    detailVo.setVipPrice(detailVo.getPrice());
+//                }
+                detailVoList.add(detailVo);
+            }
+        }
+//        if ("again".equals(request.getPreOrderType())) {// 再次购买
+//            PreOrderDetailRequest detailRequest = request.getOrderDetails().get(0);
+//            detailVoList = validatePreOrderAgain(detailRequest, user);
+//        }
+        orderInfoVo.setOrderDetailList(detailVoList);
+        return orderInfoVo;
+    }
+
+    /**
+     * 拼团预下单校验
+     *
+     * @param detailRequest 请求参数
+     * @param user          用户
+     * @return OrderInfoDetailVo
+     */
+    private OrderInfoDetailVO validatePreOrderCombination(PreOrderDetailRequest detailRequest, UserDTO user) {
+        // 拼团部分判断
+        Long combinationId = detailRequest.getCombinationId();
+        StoreCombination storeCombination = storeCombinationService.getByIdException(combinationId);
+        if (storeCombination.getStock().equals(0) || detailRequest.getProductNum() > storeCombination.getStock()) {
+            throw new ServiceException("拼团商品库存不足");
+        }
+        ProductAttrValue combinationAttrValue = productAttrValueService.getByIdAndProductIdAndType(detailRequest.getAttrValueId(), combinationId, Constants.PRODUCT_TYPE_PINGTUAN);
+        if (ObjectUtil.isNull(combinationAttrValue)) {
+            throw new ServiceException("拼团商品规格不存在");
+        }
+        commonValidateCombination(storeCombination, combinationAttrValue, user, detailRequest.getProductNum());
+
+        OrderInfoDetailVO detailVo = new OrderInfoDetailVO();
+        detailVo.setProductId(storeCombination.getProductId());
+        detailVo.setProductName(storeCombination.getTitle());
+        detailVo.setAttrValueId(combinationAttrValue.getId());
+        detailVo.setSku(combinationAttrValue.getSuk());
+        detailVo.setPrice(combinationAttrValue.getPrice());
+        detailVo.setPayNum(detailRequest.getProductNum());
+        detailVo.setImage(StrUtil.isNotBlank(combinationAttrValue.getImage()) ? combinationAttrValue.getImage() : combinationAttrValue.getImage());
+        detailVo.setVolume(combinationAttrValue.getVolume());
+        detailVo.setWeight(combinationAttrValue.getWeight());
+        detailVo.setTempId(storeCombination.getTempId());
+        detailVo.setProductType(Constants.PRODUCT_TYPE_PINGTUAN);
+        return detailVo;
+    }
+
+    /**
+     * 公共校验拼团
+     *
+     * @param storeCombination     砍价商品
+     * @param combinationAttrValue 砍价商品规格属性
+     * @param user                 用户
+     * @param productNum           购买数量
+     * @return MyRecord
+     */
+    private Map<String, Object> commonValidateCombination(StoreCombination storeCombination, ProductAttrValue combinationAttrValue, UserDTO user, Integer productNum) {
+        // 判断拼团时间段
+        Date date = new Date();
+        if (date.before(storeCombination.getStartTime())) {
+            throw new ServiceException("拼团商品活动未开始");
+        }
+        if (date.after(storeCombination.getStopTime())) {
+            throw new ServiceException("拼团商品已过期");
+        }
+        // 判断购买数量
+        if (productNum > storeCombination.getOnceNum()) {
+            throw new ServiceException("购买数量超过单次拼团购买上限");
+        }
+
+        if (combinationAttrValue.getStock() <= 0 || combinationAttrValue.getQuota() <= 0 || productNum > combinationAttrValue.getStock()) {
+            throw new ServiceException("拼团商品规格库存不足");
+        }
+        // 普通商品部分判断
+        StoreProduct product = storeProductService.findById(storeCombination.getProductId());
+        if (ObjectUtil.isNull(product) || product.getIsDelete().equals(1)) {
+            throw new ServiceException("拼团主商品不存在");
+        }
+        if (product.getStock().equals(0) || productNum > product.getStock()) {
+            throw new ServiceException("拼团主商品库存不足");
+        }
+        // 主商品sku
+        ProductAttrValue productAttrValue = productAttrValueService.getByProductIdAndSkuAndType(storeCombination.getProductId(), combinationAttrValue.getSuk(), Constants.PRODUCT_TYPE_NORMAL);
+        if (ObjectUtil.isNull(productAttrValue)) {
+            throw new ServiceException("拼团主商品规格不存在");
+        }
+        if (productAttrValue.getStock() <= 0 || productNum > productAttrValue.getStock()) {
+            throw new ServiceException("拼团主商品规格库存不足");
+        }
+
+        // 用户参与活动的次数
+        List<StoreOrder> userCombinationOrders = this.getUserCurrentCombinationOrders(user.getId(), storeCombination.getId());
+        if (CollUtil.isNotEmpty(userCombinationOrders)) {
+            // 判断是否有待支付订单
+            List<StoreOrder> unPayOrders = userCombinationOrders.stream().filter(e -> e.getPaid().equals(0)).collect(Collectors.toList());
+            if (!unPayOrders.isEmpty()) {
+                throw new ServiceException("您有拼团待支付订单,请支付后再购买");
+            }
+            int payNum = userCombinationOrders.stream().mapToInt(StoreOrder::getTotalNum).sum();
+            if (storeCombination.getNum() <= payNum) {
+                throw new ServiceException("您已达到该商品拼团活动上限");
+            }
+            if ((payNum + productNum) > storeCombination.getNum()) {
+                throw new ServiceException("超过该商品拼团活动您的购买上限");
+            }
+        }
+
+        HashMap<String, Object> map = new LinkedHashMap<>();
+        map.put("productAttrValue", productAttrValue);
+        return map;
+    }
+
+
+    @Override
+    public ComputedOrderPriceResponse computedOrderPrice(OrderComputedPriceRequest request) {
+        // 通过缓存获取预下单对象
+        String key = "user_order:" + request.getPreOrderNo();
+        boolean exists = redisUtil.hasKey(key);
+        if (!exists) {
+            throw new ServiceException("预下单订单不存在");
+        }
+        String orderVoString = redisUtil.get(key).toString();
+        OrderInfoVO orderInfoVo = JSONObject.parseObject(orderVoString, OrderInfoVO.class);
+        UserDTO user = userDubboServiceClient.getUser(userId);
+        return computedPrice(request, orderInfoVo, user);
+    }
+
+    private ComputedOrderPriceResponse computedPrice(OrderComputedPriceRequest request, OrderInfoVO orderInfoVo, UserDTO user) {
+        // 计算各种价格
+        ComputedOrderPriceResponse priceResponse = new ComputedOrderPriceResponse();
+        // 计算运费
+        if (request.getShippingType().equals(2)) {
+            // 到店自提,不计算运费
+            priceResponse.setFreightFee(BigDecimal.ZERO);
+        } else if (ObjectUtil.isNull(request.getAddressId()) || request.getAddressId() <= 0) {
+            // 快递配送,无地址
+            priceResponse.setFreightFee(BigDecimal.ZERO);
+        }
+//        else {// 快递配送,有地址
+//            UserAddress userAddress = userAddressService.findById(request.getAddressId());
+//            if (ObjectUtil.isNull(userAddress)) {
+//                priceResponse.setFreightFee(BigDecimal.ZERO);
+//            } else {
+//                getFreightFee(orderInfoVo, userAddress);
+//                priceResponse.setFreightFee(orderInfoVo.getFreightFee());
+//            }
+//        }
+//        // 计算优惠券金额
+//        if (ObjectUtil.isNull(request.getCouponId()) || request.getCouponId() <= 0) {
+//            priceResponse.setCouponFee(BigDecimal.ZERO);
+//        } else if (orderInfoVo.getSeckillId() > 0 || orderInfoVo.getBargainId() > 0 || orderInfoVo.getCombinationId() > 0) {
+//            throw new ServiceException("营销活动商品无法使用优惠券");
+//        }else {
+//            // 判断优惠券是否可以使用
+//            StoreCouponUser storeCouponUser = storeCouponUserService.getById(request.getCouponId());
+//            if (ObjectUtil.isNull(storeCouponUser) || !storeCouponUser.getUid().equals(user.getUid())) {
+//                throw new ServiceException("优惠券领取记录不存在!");
+//            }
+//            if (storeCouponUser.getStatus() == 1) {
+//                throw new ServiceException("此优惠券已使用!");
+//            }
+//
+//            if (storeCouponUser.getStatus() == 2) {
+//                throw new ServiceException("此优惠券已失效!");
+//            }
+//            //判断是否在使用时间内
+//            Date date = DateUtil.nowDateTime();
+//            if (storeCouponUser.getStartTime().compareTo(date) > 0) {
+//                throw new ServiceException("此优惠券还未到达使用时间范围之内!");
+//            }
+//            if (date.compareTo(storeCouponUser.getEndTime()) > 0) {
+//                throw new ServiceException("此优惠券已经失效了");
+//            }
+//            if (storeCouponUser.getMinPrice().compareTo(orderInfoVo.getProTotalFee()) > 0) {
+//                throw new ServiceException("总金额小于优惠券最小使用金额");
+//            }
+//            //检测优惠券信息
+//            if (storeCouponUser.getUseType() > 1) {
+//                List<Integer> productIdList = orderInfoVo.getOrderDetailList().stream().map(OrderInfoDetailVo::getProductId).collect(Collectors.toList());
+//                if (productIdList.size() < 1) {
+//                    throw new ServiceException("没有找到商品");
+//                }
+//
+//                //设置优惠券所提供的集合
+//                List<Integer> primaryKeyIdList = CrmebUtil.stringToArray(storeCouponUser.getPrimaryKey());
+//
+//                //取两个集合的交集,如果是false则证明没有相同的值
+//                //oldList.retainAll(newList)返回值代表oldList是否保持原样,如果old和new完全相同,那old保持原样并返回false。
+//                //交集:listA.retainAll(listB) ——listA内容变为listA和listB都存在的对象;listB不变
+//                if (storeCouponUser.getUseType() == 2) {
+//                    primaryKeyIdList.retainAll(productIdList);
+//                    if (CollUtil.isEmpty(primaryKeyIdList)) {
+//                        throw new ServiceException("此优惠券为商品券,请购买相关商品之后再使用!");
+//                    }
+//                }
+//
+//                if (storeCouponUser.getUseType() == 3) {
+//                    //拿出需要使用优惠券的商品分类集合
+//                    List<Integer> categoryIdList = storeProductService.getSecondaryCategoryByProductId(StringUtils.join(productIdList, ","));
+//
+//                    primaryKeyIdList.retainAll(categoryIdList);
+//                    if (CollUtil.isEmpty(primaryKeyIdList)) {
+//                        throw new ServiceException("此优惠券为分类券,请购买相关分类下的商品之后再使用!");
+//                    }
+//                }
+//            }
+//            if (orderInfoVo.getProTotalFee().compareTo(storeCouponUser.getMoney()) <= 0) {
+//                priceResponse.setCouponFee(orderInfoVo.getProTotalFee());
+//                priceResponse.setDeductionPrice(BigDecimal.ZERO);
+//                priceResponse.setSurplusIntegral(user.getIntegral());
+//                priceResponse.setPayFee(priceResponse.getFreightFee());
+//                priceResponse.setUsedIntegral(0);
+//                priceResponse.setUseIntegral(false);
+//                priceResponse.setProTotalFee(orderInfoVo.getProTotalFee());
+//                return priceResponse;
+//            } else {
+//                priceResponse.setCouponFee(storeCouponUser.getMoney());
+//            }
+//        }
+//        // 积分部分
+//        BigDecimal payPrice = orderInfoVo.getProTotalFee().add(priceResponse.getFreightFee()).subtract(priceResponse.getCouponFee());
+//        priceResponse.setUseIntegral(request.getUseIntegral());
+//        priceResponse.setProTotalFee(orderInfoVo.getProTotalFee());
+//        if (!request.getUseIntegral() || user.getIntegral() <= 0) {// 不使用积分
+//            priceResponse.setDeductionPrice(BigDecimal.ZERO);
+//            priceResponse.setSurplusIntegral(user.getIntegral());
+//            priceResponse.setPayFee(payPrice);
+//            priceResponse.setUsedIntegral(0);
+//            return priceResponse;
+//        }
+//        // 使用积分
+//        // 查询积分使用比例
+//        String integralRatio = systemConfigService.getValueByKey(SysConfigConstants.CONFIG_KEY_INTEGRAL_RATE);
+//        BigDecimal deductionPrice = new BigDecimal(user.getIntegral()).multiply(new BigDecimal(integralRatio));
+//        if (request.getUseIntegral()) {
+//            // 积分兑换金额小于实际支付金额
+//            if (deductionPrice.compareTo(payPrice) < 0) {
+//                payPrice = payPrice.subtract(deductionPrice);
+//                priceResponse.setSurplusIntegral(0);
+//                priceResponse.setUsedIntegral(user.getIntegral());
+//            } else {
+//                deductionPrice = payPrice;
+//                if (payPrice.compareTo(BigDecimal.ZERO) > 0) {
+//                    int usedIntegral = payPrice.divide(new BigDecimal(integralRatio), 0, BigDecimal.ROUND_UP).intValue();
+//                    priceResponse.setSurplusIntegral(user.getIntegral() - usedIntegral);
+//                    priceResponse.setUsedIntegral(usedIntegral);
+//                }
+//                payPrice = BigDecimal.ZERO;
+//            }
+//            priceResponse.setPayFee(payPrice);
+//            priceResponse.setDeductionPrice(deductionPrice);
+//        }
+        return priceResponse;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean refundApplyTask(List<OrderRefundApplyVO> applyList) {
@@ -200,6 +708,30 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
         return arrayList;
     }
 
+    @Override
+    public StoreOrderVO orderDetail(Long id) {
+        StoreOrder storeOrder = findById(id);
+        Condition infoCondition = new Condition(StoreOrderInfo.class);
+        Example.Criteria infoCriteria = infoCondition.createCriteria();
+        infoCriteria.andEqualTo("isDelete", 0);
+        infoCriteria.andEqualTo("orderId", storeOrder.getOrderId());
+        List<StoreOrderInfo> infoList = storeOrderInfoService.findByCondition(infoCondition);
+        StoreOrderVO vo = new StoreOrderVO();
+        BeanUtils.copyProperties(storeOrder, vo);
+        vo.setOrderInfoVO(infoList);
+        return vo;
+    }
+
+    @Override
+    public List<StoreOrder> getUserCurrentCombinationOrders(Long uid, Long combinationId) {
+        Condition condition = new Condition(StoreOrder.class);
+        Example.Criteria criteria = condition.createCriteria();
+        criteria.andEqualTo("isDelete", 0);
+        criteria.andEqualTo("combinationId", combinationId);
+        criteria.andEqualTo("uid", uid);
+        return this.findByCondition(condition);
+    }
+
     private Integer getCount(String status, Integer type) {
         //总数只计算时间
         Condition condition = new Condition(StoreOrder.class);
@@ -281,4 +813,20 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
                 break;
         }
     }
+
+    @Override
+    public PreOrderResponse loadPreOrder(String preOrderNo) {
+        // 通过缓存获取预下单对象
+        String key = "user_order:" + preOrderNo;
+        boolean exists = redisUtil.hasKey(key);
+        if (!exists) {
+            throw new ServiceException("预下单订单不存在");
+        }
+        String orderVoString = redisUtil.get(key).toString();
+        OrderInfoVO orderInfoVo = JSONObject.parseObject(orderVoString, OrderInfoVO.class);
+        PreOrderResponse preOrderResponse = new PreOrderResponse();
+        preOrderResponse.setOrderInfoVo(orderInfoVo);
+        preOrderResponse.setYuePayStatus(1);
+        return preOrderResponse;
+    }
 }

+ 16 - 0
mall-service/src/main/java/com/txz/mall/service/impl/UserAddressServiceImpl.java

@@ -1,13 +1,17 @@
 package com.txz.mall.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.txz.mall.core.AbstractService;
 import com.txz.mall.dao.UserAddressMapper;
 import com.txz.mall.model.UserAddress;
 import com.txz.mall.service.UserAddressService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import tk.mybatis.mapper.entity.Condition;
+import tk.mybatis.mapper.entity.Example;
 
 import javax.annotation.Resource;
+import java.util.List;
 
 
 /**
@@ -19,4 +23,16 @@ public class UserAddressServiceImpl extends AbstractService<UserAddress> impleme
     @Resource
     private UserAddressMapper userAddressMapper;
 
+    @Override
+    public UserAddress getDefaultByUid(Long uid) {
+        Condition condition = new Condition(UserAddress.class);
+        Example.Criteria criteria = condition.createCriteria();
+        criteria.andEqualTo("isDefault", 1);
+        criteria.andEqualTo("uid", uid);
+        List<UserAddress> list = findByCondition(condition);
+        if (CollUtil.isNotEmpty(list)) {
+            return list.get(0);
+        }
+        return null;
+    }
 }

+ 0 - 25
mall-service/src/main/java/com/txz/mall/util/MyDateUtil.java

@@ -1,25 +0,0 @@
-package com.txz.mall.util;
-
-import cn.hutool.core.date.DateUtil;
-
-import java.util.Date;
-
-public class MyDateUtil extends DateUtil {
-
-    /**
-     * 当前时分秒是否在时分秒指定范围内<br>
-     * 起始时分秒和结束时分秒可以互换
-     *
-     * @param date      被检查的日期
-     * @param beginDate 起始时分秒
-     * @param endDate   结束时分秒
-     * @return 是否在范围内
-     * @since 3.0.8
-     */
-    public static boolean isInTime(Date date, Date beginDate, Date endDate) {
-        String dayStr = DateUtil.format(date,"yyyy-MM-dd");
-        String beginTime = DateUtil.format(beginDate,"HH:mm:ss");
-        String endTime = DateUtil.format(endDate,"HH:mm:ss");
-        return DateUtil.isIn(date,DateUtil.parse(dayStr+" "+beginTime),DateUtil.parse(dayStr+" "+endTime));
-    }
-}

+ 55 - 0
mall-service/src/main/java/dto/ComputedOrderPriceResponse.java

@@ -0,0 +1,55 @@
+package dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 计算订单价格响应对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "ComputedOrderPriceResponse对象", description = "计算订单价格响应对象")
+public class ComputedOrderPriceResponse implements Serializable {
+
+    private static final long serialVersionUID = 7282892323898493847L;
+
+    @ApiModelProperty(value = "优惠券优惠金额")
+    private BigDecimal couponFee;
+
+    @ApiModelProperty(value = "积分抵扣金额")
+    private BigDecimal deductionPrice;
+
+    @ApiModelProperty(value = "运费金额")
+    private BigDecimal freightFee;
+
+    @ApiModelProperty(value = "实际支付金额")
+    private BigDecimal payFee;
+
+    @ApiModelProperty(value = "商品总金额")
+    private BigDecimal proTotalFee;
+
+    @ApiModelProperty(value = "剩余积分")
+    private Integer surplusIntegral;
+
+    @ApiModelProperty(value = "是否使用积分")
+    private Boolean useIntegral;
+
+    @ApiModelProperty(value = "使用的积分")
+    private Integer usedIntegral;
+}

+ 38 - 0
mall-service/src/main/java/dto/OrderComputedPriceRequest.java

@@ -0,0 +1,38 @@
+package dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.hibernate.validator.constraints.Range;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "OrderComputedPriceRequest对象", description = "计算订单价格请求对象")
+public class OrderComputedPriceRequest {
+
+    @ApiModelProperty(value = "预下单订单号")
+    @NotBlank(message = "预下单订单号不能为空")
+    private String preOrderNo;
+
+    @ApiModelProperty(value = "地址id")
+    private Integer addressId;
+
+    @ApiModelProperty(value = "优惠券id")
+    private Integer couponId;
+
+    @ApiModelProperty(value = "快递类型: 1-快递配送,2-到店自提")
+    @NotNull(message = "快递类型不能为空")
+    @Range(min = 1, max = 2, message = "未知的快递类型")
+    private Integer shippingType;
+
+    @ApiModelProperty(value = "是否使用积分")
+    @NotNull(message = "是否使用积分不能为空")
+    private Boolean useIntegral;
+
+}

+ 57 - 0
mall-service/src/main/java/dto/PreOrderDetailRequest.java

@@ -0,0 +1,57 @@
+package dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * 预下单详情请求对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "PreOrderRequest对象", description = "预下单详情请求对象")
+public class PreOrderDetailRequest {
+
+    @ApiModelProperty(value = "购物车编号,购物车预下单时必填")
+    private Long shoppingCartId;
+
+    @ApiModelProperty(value = "商品id(立即购买必填)")
+    private Long productId;
+
+    @ApiModelProperty(value = "商品规格属性id(立即购买、活动购买必填)")
+    private Long attrValueId;
+
+    @ApiModelProperty(value = "商品数量(立即购买、活动购买必填)")
+    private Integer productNum;
+
+    @ApiModelProperty(value = "订单编号(再次购买必填)")
+    private String orderNo;
+
+    @ApiModelProperty(value = "砍价商品id")
+    private Integer bargainId = 0;
+
+    @ApiModelProperty(value = "用户砍价活动id")
+    private Integer bargainUserId = 0;
+
+    @ApiModelProperty(value = "拼团商品id")
+    private Long combinationId = 0L;
+
+    @ApiModelProperty(value = "拼团团长id")
+    private Integer pinkId = 0;
+
+    @ApiModelProperty(value = "秒杀商品id")
+    private Integer seckillId = 0;
+
+}

+ 37 - 0
mall-service/src/main/java/dto/PreOrderRequest.java

@@ -0,0 +1,37 @@
+package dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+/**
+ * 预下单请求对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "PreOrderRequest对象", description = "预下单请求对象")
+public class PreOrderRequest {
+
+    @ApiModelProperty(value = "预下单类型(“shoppingCart”:购物车下单,“buyNow”:立即购买,”again“: 再次购买)")
+    @NotBlank(message = "预下单类型不能为空")
+    private String preOrderType;
+
+    @ApiModelProperty(value = "订单详情列表")
+    private List<PreOrderDetailRequest> orderDetails;
+
+}

+ 50 - 0
mall-service/src/main/java/dto/PreOrderResponse.java

@@ -0,0 +1,50 @@
+package dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import vo.OrderInfoVO;
+
+import java.io.Serializable;
+
+/**
+ * 预下单响应对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "PreOrderResponse对象", description = "预下单响应对象")
+public class PreOrderResponse implements Serializable {
+
+    private static final long serialVersionUID = 7282892323898493847L;
+
+    @ApiModelProperty(value = "订单详情对象")
+    private OrderInfoVO orderInfoVo;
+
+    @ApiModelProperty(value = "预下单订单号")
+    private String preOrderNo;
+
+//    @ApiModelProperty(value = "门店自提是否开启")
+//    private String storeSelfMention;
+
+    @ApiModelProperty(value = "余额支付 1 开启 2 关闭")
+    private Integer yuePayStatus;
+//
+//    @ApiModelProperty(value = "微信支付 1 开启 0 关闭")
+//    private String payWeixinOpen;
+//
+//    @ApiModelProperty(value = "支付宝支付 1 开启 0 关闭")
+//    private String aliPayStatus;
+
+}

+ 96 - 0
mall-service/src/main/java/vo/OrderInfoDetailVO.java

@@ -0,0 +1,96 @@
+package vo;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 订单详情Vo对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+public class OrderInfoDetailVO {
+
+    /**
+     * 商品id
+     */
+    private Long productId;
+
+    /**
+     * 商品名称
+     */
+    private String productName;
+
+    /**
+     * 规格属性id
+     */
+    private Long attrValueId;
+
+    /**
+     * 商品图片
+     */
+    private String image;
+
+    /**
+     * sku
+     */
+    private String sku;
+
+    /**
+     * 单价
+     */
+    private BigDecimal price;
+
+    /**
+     * 购买数量
+     */
+    private Integer payNum;
+
+    /**
+     * 重量
+     */
+    private BigDecimal weight;
+
+    /**
+     * 体积
+     */
+    private BigDecimal volume;
+
+    /**
+     * 运费模板ID
+     */
+    private Long tempId;
+
+    /**
+     * 获得积分
+     */
+    private Integer giveIntegral;
+
+    /**
+     * 是否评价
+     */
+    private Integer isReply;
+
+    /**
+     * 是否单独分佣
+     */
+    private Integer isSub;
+
+    /**
+     * 会员价
+     */
+    private BigDecimal vipPrice;
+
+    /**
+     * 商品类型:0-普通,1-秒杀,2-砍价,3-拼团,4-视频号
+     */
+    private Integer productType;
+}

+ 98 - 0
mall-service/src/main/java/vo/OrderInfoVO.java

@@ -0,0 +1,98 @@
+package vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 预下单Vo对象
+ * +----------------------------------------------------------------------
+ * | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
+ * +----------------------------------------------------------------------
+ * | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
+ * +----------------------------------------------------------------------
+ * | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
+ * +----------------------------------------------------------------------
+ * | Author: CRMEB Team <admin@crmeb.com>
+ * +----------------------------------------------------------------------
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@ApiModel(value = "OrderInfoVo对象", description = "预下单Vo对象")
+public class OrderInfoVO {
+
+    @ApiModelProperty(value = "运费金额")
+    private BigDecimal freightFee;
+
+    @ApiModelProperty(value = "优惠券编号(选择优惠券时有值")
+    private Integer userCouponId;
+
+    @ApiModelProperty(value = "优惠金额")
+    private BigDecimal couponFee;
+
+    @ApiModelProperty(value = "商品总计金额")
+    private BigDecimal proTotalFee;
+
+    @ApiModelProperty(value = "订单商品数量")
+    private Integer orderProNum;
+
+    @ApiModelProperty(value = "实际支付金额")
+    private BigDecimal payFee;
+
+    @ApiModelProperty(value = "地址id")
+    private Long addressId;
+
+    @ApiModelProperty(value = "收货人姓名(前端用)")
+    private String realName;
+
+    @ApiModelProperty(value = "收货人电话(前端用)")
+    private String phone;
+
+    @ApiModelProperty(value = "收货人所在省(前端用)")
+    private String province;
+
+    @ApiModelProperty(value = "收货人所在市(前端用)")
+    private String city;
+
+    @ApiModelProperty(value = "收货人所在区(前端用)")
+    private String district;
+
+    @ApiModelProperty(value = "收货人详细地址(前端用)")
+    private String detail;
+
+    @ApiModelProperty(value = "用户剩余积分")
+    private Integer userIntegral;
+
+    @ApiModelProperty(value = "用户可用余额")
+    private BigDecimal userBalance;
+
+    @ApiModelProperty(value = "订单备注")
+    private String remark;
+
+    @ApiModelProperty(value = "订单详情数组")
+    private List<OrderInfoDetailVO> orderDetailList;
+
+    @ApiModelProperty(value = "秒杀商品Id")
+    private Integer seckillId = 0;
+
+    @ApiModelProperty(value = "砍价商品Id")
+    private Integer bargainId = 0;
+
+    @ApiModelProperty(value = "用户砍价活动id")
+    private Integer bargainUserId;
+
+    @ApiModelProperty(value = "拼团商品Id")
+    private Long combinationId = 0L;
+
+    @ApiModelProperty(value = "拼团团长Id")
+    private Integer pinkId = 0;
+
+    @ApiModelProperty(value = "购物车编号列表")
+    private List<Long> cartIdList;
+}