|
@@ -1,37 +1,35 @@
|
|
package com.txz.mall.service.impl;
|
|
package com.txz.mall.service.impl;
|
|
|
|
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
import cn.hutool.core.util.StrUtil;
|
|
import cn.hutool.core.util.StrUtil;
|
|
import com.alibaba.excel.EasyExcel;
|
|
import com.alibaba.excel.EasyExcel;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
|
|
|
+import com.txz.cif.dto.UserDTO;
|
|
import com.txz.mall.constants.Constants;
|
|
import com.txz.mall.constants.Constants;
|
|
import com.txz.mall.core.AbstractService;
|
|
import com.txz.mall.core.AbstractService;
|
|
|
|
+import com.txz.mall.core.RedisUtil;
|
|
import com.txz.mall.core.ServiceException;
|
|
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 lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.beans.BeanUtils;
|
|
import org.springframework.beans.BeanUtils;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import tk.mybatis.mapper.entity.Condition;
|
|
import tk.mybatis.mapper.entity.Condition;
|
|
import tk.mybatis.mapper.entity.Example;
|
|
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 javax.servlet.http.HttpServletResponse;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStream;
|
|
|
|
+import java.math.BigDecimal;
|
|
import java.net.URLEncoder;
|
|
import java.net.URLEncoder;
|
|
-import java.util.ArrayList;
|
|
|
|
-import java.util.Arrays;
|
|
|
|
-import java.util.List;
|
|
|
|
|
|
+import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
@@ -41,12 +39,18 @@ import java.util.stream.Collectors;
|
|
@Service
|
|
@Service
|
|
@Transactional
|
|
@Transactional
|
|
@Slf4j
|
|
@Slf4j
|
|
|
|
+@AllArgsConstructor
|
|
public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implements StoreOrderService {
|
|
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
|
|
@Override
|
|
public StoreOrderCountItemVO getOrderStatusNum() {
|
|
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
|
|
@Override
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
public Boolean refundApplyTask(List<OrderRefundApplyVO> applyList) {
|
|
public Boolean refundApplyTask(List<OrderRefundApplyVO> applyList) {
|
|
@@ -200,6 +708,30 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
|
|
return arrayList;
|
|
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) {
|
|
private Integer getCount(String status, Integer type) {
|
|
//总数只计算时间
|
|
//总数只计算时间
|
|
Condition condition = new Condition(StoreOrder.class);
|
|
Condition condition = new Condition(StoreOrder.class);
|
|
@@ -281,4 +813,20 @@ public class StoreOrderServiceImpl extends AbstractService<StoreOrder> implement
|
|
break;
|
|
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;
|
|
|
|
+ }
|
|
}
|
|
}
|