瀏覽代碼

提交订单part1

chao 3 年之前
父節點
當前提交
763a08630a
共有 22 個文件被更改,包括 2089 次插入88 次删除
  1. 69 7
      src/main/java/com/caimei365/order/components/ProductService.java
  2. 3 3
      src/main/java/com/caimei365/order/controller/CartSellerApi.java
  3. 113 0
      src/main/java/com/caimei365/order/controller/SubmitApi.java
  4. 5 0
      src/main/java/com/caimei365/order/mapper/BaseMapper.java
  5. 42 0
      src/main/java/com/caimei365/order/mapper/SubmitMapper.java
  6. 104 0
      src/main/java/com/caimei365/order/model/bo/OrderUserBo.java
  7. 177 0
      src/main/java/com/caimei365/order/model/bo/ProductBo.java
  8. 112 0
      src/main/java/com/caimei365/order/model/dto/SubmitDto.java
  9. 56 0
      src/main/java/com/caimei365/order/model/po/InvoicePo.java
  10. 174 0
      src/main/java/com/caimei365/order/model/po/OrderPo.java
  11. 2 2
      src/main/java/com/caimei365/order/model/vo/CartItemVo.java
  12. 4 1
      src/main/java/com/caimei365/order/model/vo/ProductPostageVo.java
  13. 19 0
      src/main/java/com/caimei365/order/service/SubmitService.java
  14. 2 63
      src/main/java/com/caimei365/order/service/impl/CartClubServiceImpl.java
  15. 6 4
      src/main/java/com/caimei365/order/service/impl/CartSellerServiceImpl.java
  16. 1009 0
      src/main/java/com/caimei365/order/service/impl/SubmitServiceImpl.java
  17. 104 0
      src/main/java/com/caimei365/order/utils/CodeUtil.java
  18. 2 2
      src/main/java/com/caimei365/order/utils/ImageUtil.java
  19. 1 4
      src/main/java/com/caimei365/order/utils/MathUtil.java
  20. 24 1
      src/main/resources/mapper/BaseMapper.xml
  21. 51 0
      src/main/resources/mapper/SubmitMapper.xml
  22. 10 1
      src/test/java/com/caimei365/order/OrderApplicationTests.java

+ 69 - 7
src/main/java/com/caimei365/order/components/ProductService.java

@@ -1,12 +1,9 @@
 package com.caimei365.order.components;
 
 import com.caimei365.order.mapper.BaseMapper;
-import com.caimei365.order.model.vo.CartItemVo;
-import com.caimei365.order.model.vo.LadderPriceVo;
-import com.caimei365.order.model.vo.PromotionPriceVo;
-import com.caimei365.order.model.vo.PromotionsVo;
+import com.caimei365.order.model.vo.*;
 import com.caimei365.order.utils.MathUtil;
-import com.caimei365.order.utils.ProductUtil;
+import com.caimei365.order.utils.ImageUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.ArrayUtils;
 import org.springframework.beans.factory.annotation.Value;
@@ -16,7 +13,9 @@ import org.springframework.util.CollectionUtils;
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.IntStream;
 
 /**
@@ -40,10 +39,10 @@ public class ProductService {
      */
     public boolean setCartItemImgAndTax(CartItemVo cartItemVo) {
         // 图片路径
-        String image = ProductUtil.getImageUrl("product", cartItemVo.getImage(), domain);
+        String image = ImageUtil.getImageUrl("product", cartItemVo.getImage(), domain);
         cartItemVo.setImage(image);
         // 是否添加税费,不含税商品 开票需添加税费
-        boolean taxFlag = "0".equals(cartItemVo.getIncludedTax()) && ("1".equals(cartItemVo.getInvoiceType()) || "2".equals(cartItemVo.getInvoiceType()));
+        boolean taxFlag = (0 == cartItemVo.getIncludedTax() && (1 == cartItemVo.getInvoiceType() || 2 == cartItemVo.getInvoiceType()));
         if (taxFlag) {
             BigDecimal cartItemTax = MathUtil.div(MathUtil.mul(cartItemVo.getPrice(), cartItemVo.getTaxRate()), 100, 2);
             cartItemVo.setPrice(MathUtil.add(cartItemVo.getPrice(), cartItemTax).doubleValue());
@@ -160,4 +159,67 @@ public class ProductService {
         return ArrayUtils.contains(products, productId);
     }
 
+    /**
+     * 计算运费
+     * @param userId     用户ID
+     * @param townId     地区Id
+     * @param productIdList 商品Id列表
+     */
+    public Map<String, Object> computePostage(Integer userId, Integer townId, List<String> productIdList) {
+        // 返回数据初始化
+        Map<String, Object> postageMap = new HashMap<>(2);
+        // 运费标志:0包邮 1到付 2遵循运费规则, 注意,旧接口返回前端是:-1到付(默认),0包邮,1有运费
+        int postageFlag = 0;
+        // 运费
+        Double postage = 0.00d;
+        // 可用采美豆
+        Integer userBeans = baseMapper.getUserBeans(userId);
+        postageMap.put("userBeans", userBeans);
+        // 获取商品运费 (0包邮 1到付 2默认(遵循运费规则))
+        List<ProductPostageVo> postageFlagList = baseMapper.getPostageFlagList(productIdList);
+        for (ProductPostageVo postageVo : postageFlagList){
+            // 是否是仪器 或 设置了运费到付
+            boolean flag = (2 == postageVo.getCommodityType() || (null != postageVo.getPostageFlag() && 1==postageVo.getPostageFlag()));
+            if (flag) {
+                // 到付
+                postageMap.put("postageFlag", 1);
+                postageMap.put("postage", 0.00d);
+                return postageMap;
+            } else if (null != postageVo.getPostageFlag() && 2==postageVo.getPostageFlag()) {
+                // 若有不包邮商品,则全部不包邮
+                postageFlag = 2;
+            }
+        }
+        // 是否首单(统计订单数)
+        Integer count = baseMapper.countUserOrder(userId);
+        // 包邮条件:首单 或 包邮(上一步未被设置成不包邮)
+        boolean freeFlag = ((null != count && count == 0) || postageFlag == 0);
+        if (freeFlag) {
+            // 包邮
+            postageMap.put("postageFlag", 0);
+            postageMap.put("postage", 0.00d);
+            return postageMap;
+        } else {
+            /*
+             * 运费计算:广东省内运费15元,深圳市内运费10,其他地区到付
+             */
+            postageFlag = 2;
+            // 获取根据地区Id获取省市地址信息
+            AddressVo address = baseMapper.getProvinceIdAndCityId(townId);
+            if (null != address && 202 == address.getCityId()) {
+                // 深圳市内运费10
+                postage = 10.00d;
+            } else if (null != address && 19 == address.getProvinceId()){
+                // 广东省内运费15元
+                postage = 15.00d;
+            } else {
+                // 到付
+                postageFlag = 1;
+            }
+            postageMap.put("postageFlag", postageFlag);
+            postageMap.put("postage", postage);
+            return postageMap;
+        }
+    }
+
 }

+ 3 - 3
src/main/java/com/caimei365/order/controller/CartSellerApi.java

@@ -207,7 +207,7 @@ public class CartSellerApi {
     }
 
     /**
-     * 协销再来一单
+     * 协销再来一单(订单商品加入购物车)
      *
      * @param againBuyDto {
      *                    serviceProviderId      协销Id
@@ -216,8 +216,8 @@ public class CartSellerApi {
      *                    confirmFlag            确认标识 0未确认 1已确认-将失效商品以外的正常商品加入购物车
      *                    }
      */
-    @ApiOperation("协销添加购物车(旧:/seller/addCart)(/seller/batchAddCart)")
-    @PostMapping("/cart/add/again")
+    @ApiOperation("协销再来一单(订单商品加入购物车)(旧:/seller/order/again)")
+    @PostMapping("/cart/again")
     public ResponseJson<Map<String, Object>> addCartBuyAgain(AgainBuyDto againBuyDto){
         if (null == againBuyDto.getServiceProviderId()) {
             return ResponseJson.error("协销Id不能为空!", null);

+ 113 - 0
src/main/java/com/caimei365/order/controller/SubmitApi.java

@@ -0,0 +1,113 @@
+package com.caimei365.order.controller;
+
+import com.caimei365.order.model.ResponseJson;
+import com.caimei365.order.model.dto.SubmitDto;
+import com.caimei365.order.service.SubmitService;
+import io.swagger.annotations.Api;
+import lombok.RequiredArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Map;
+
+/**
+ * 提交订单API
+ *
+ * @author : Charles
+ * @date : 2021/7/6
+ */
+@Api(tags="提交订单API")
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/order/submit")
+public class SubmitApi {
+    private final SubmitService submitService;
+
+    /**
+     * 生成订单
+     *
+     * @param submitDto {
+     *                  "unionId":"",               //微信unionId
+     *                  "cartType":3,               //购买类型:(1自主下单, 3协销下单)
+     *                  "orderSource": 2,           //订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     *                  "serviceProviderId": 1378,  //协销ID(小程序忽略)
+     *                  "clubUserId": 10708,        //机构用户ID
+     *                  "addressId": 2732,          //地址ID
+     *                  "orderInfo": [              //【订单商品】
+     *                      { "shopId":1001,                         // 供应商Id
+     *                          "note":备注,
+     *                          "productInfo":[                      // 商品id,数量,赠品数,商品类型
+     *                              {"productId": 2789, "productNum": 1, "presentNum":0,"productType":2},
+     *                              {"productId": 2789, "productNum": 1, "presentNum":0,"productType":0}
+     *                          ]
+     *                      },{多个供应商商品数据结构同上}
+     *                  ],
+     *                  "payInfo": {                //【订单金额】
+     *                      "orderShouldPayFee": 609.11,
+     *                       
+     *                      "balancePayFlag": 0,
+     *                      "clauseId": "2",
+     *                      "postage": "15",
+     *                      "postageFlag": 1,
+     *                      "userBeans": 100,//抵扣采美豆数量
+     *                      "rebateFlag":0
+     *                  },
+     *                  "orderInvoice":             //【发票信息】
+     *                          {"type": 0 // 不开发票  }
+     *                      或: { // 普通发票
+     *                              "type": 1,
+     *                              "invoiceTitle": "企业抬头",
+     *                              "invoiceTitleType": 1,
+     *                              "corporationTaxNum": "XXX4156465465",
+     *                              "invoiceContent": "明细 "
+     *                          }
+     *                      或: { // 增值税发票
+     *                              "type": 2,
+     *                              "invoiceTitle": "单位名称",
+     *                              "corporationTaxNum": "NSRSBM97897",
+     *                              "registeredAddress": "注册地址",
+     *                              "registeredPhone": "15814011616",
+     *                              "openBank": "开户银行",
+     *                              "bankAccountNo": "987987465465464"
+     *                          }
+     *              }
+     * @return {code: -1=(用户账户异常,数据异常,操作异常等),1提交成功(支付完成),2提交成功(未支付),
+     *              code为1和2时:data{orderNo:订单号,orderID:订单ID,payTotalFee:订单金额,orderMark:订单标识}
+     */
+    @PostMapping("/generate")
+    public ResponseJson<Map<String, Object>> generateOrder(SubmitDto submitDto){
+        if(null == submitDto.getOrderSource()){
+            return ResponseJson.error("订单来源不能为空!", null);
+        }
+//        // 1,www来源    2,crm来源    6,小程序来源
+//        if (1 != submitDto.getOrderSource() || 2 != submitDto.getOrderSource() || 6 != submitDto.getOrderSource()) {
+//            return ResponseJson.error("订单来源异常!", null);
+//        }
+        if(null == submitDto.getCartType()){
+            return ResponseJson.error("购买类型不能为空!", null);
+        }
+        if(null == submitDto.getClubId()){
+            return ResponseJson.error("机构Id不能为空!", null);
+        }
+        if(null == submitDto.getAddressId()){
+            return ResponseJson.error("收货地址Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(submitDto.getOrderInfo())){
+            return ResponseJson.error("订单商品数据不能为空!", null);
+        }
+        if (StringUtils.isEmpty(submitDto.getPayInfo())){
+            return ResponseJson.error("订单金额数据不能为空!", null);
+        }
+        if (StringUtils.isEmpty(submitDto.getOrderInvoice())){
+            return ResponseJson.error("发票信息数据不能为空!", null);
+        }
+        if (3 == submitDto.getCartType() && null == submitDto.getServiceProviderId()) {
+            return ResponseJson.error("协销Id不能为空!", null);
+        }
+        return submitService.generateOrder(submitDto);
+    }
+
+
+}

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

@@ -82,4 +82,9 @@ public interface BaseMapper {
      * @param townId 地区Id
      */
     AddressVo getProvinceIdAndCityId(Integer townId);
+    /**
+     * 获取详细地址信息
+     * @param addressId 地址Id
+     */
+    Integer getTownIdByAddressId(Integer addressId);
 }

+ 42 - 0
src/main/java/com/caimei365/order/mapper/SubmitMapper.java

@@ -0,0 +1,42 @@
+package com.caimei365.order.mapper;
+
+import com.caimei365.order.model.bo.OrderUserBo;
+import com.caimei365.order.model.bo.ProductBo;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/6
+ */
+@Mapper
+public interface SubmitMapper {
+    /**
+     * 获取运营人员Id
+     * @param unionId    运营人员unionId
+     * @param userId     机构用户Id
+     */
+    Integer getOperationIdByUnionId(String unionId, Integer userId);
+    /**
+     * 根据用户Id获取用户余额信息
+     * @param userId 用户Id
+     */
+    OrderUserBo getOrderUserBoById(Integer userId);
+    /**
+     * 获取协销用户Id
+     * @param serviceProviderId 协销Id
+     */
+    Integer getServiceProviderUserId(Integer serviceProviderId);
+    /**
+     * 供应商名称
+     * @param shopId 供应商Id
+     */
+    String getShopNameById(Integer shopId);
+    /**
+     * 获取数据库商品信息
+     * @param productId 商品Id
+     */
+    ProductBo getProductDetails(Integer productId);
+
+}

+ 104 - 0
src/main/java/com/caimei365/order/model/bo/OrderUserBo.java

@@ -0,0 +1,104 @@
+package com.caimei365.order.model.bo;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/6
+ */
+@Data
+public class OrderUserBo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 用户ID
+     */
+    private Integer userId;
+    /**
+     * 机构id
+     */
+    private Integer clubId;
+    /**
+     * 用户名
+     */
+    private String userName;
+    /**
+     * 企业绑定手机号
+     */
+    private String bindMobile;
+    /**
+     * 账户余额
+     */
+    private Double userMoney;
+    /**
+     * 账户实际可用余额(提交订单未支付的被抵扣后的余额)
+     */
+    private Double ableUserMoney;
+    /**
+     * 采美豆数量(数据库)
+     */
+    private Integer userBeans;
+    /**
+     * 当前订单抵扣的采美豆数量(前端传入)
+     */
+    private Integer offsetBeans;
+    /**
+     * 当前订单邮费标志: 0包邮 1到付 2默认(遵循运费规则)
+     */
+    private Integer postageFlag;
+    /**
+     * 当前订单邮费
+     */
+    private Double postage;
+    /**
+     * 当前订单余额支付标识,0不使用,1使用
+     */
+    private Integer balancePayFlag;
+    /**
+     * 当前订单应付总额
+     */
+    private Double orderShouldPayFee;
+    /**
+     * 售后条款id
+     */
+    private Integer clauseId;
+    /**
+     * 返佣订单标识 0非返佣订单,1返佣订单
+     */
+    private Integer rebateFlag;
+    /**
+     * 发票类型 0不开发票 1普通发票 2增值税发票
+     */
+    private Integer invoiceType;
+    /**
+     * 当前订单发票信息
+     */
+    private JSONObject orderInvoice;
+    /**
+     * 当前订单订单商品
+     */
+    private JSONArray orderInfo;
+    /**
+     * 购买类型:(1自主下单, 3协销下单)
+     */
+    private Integer cartType;
+    /**
+     * 下单人
+     */
+    private Integer buyUserId;
+    /**
+     * 订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     */
+    private Integer orderSource;
+    /**
+     * 收货地址Id
+     */
+    private Integer addressId;
+
+}

+ 177 - 0
src/main/java/com/caimei365/order/model/bo/ProductBo.java

@@ -0,0 +1,177 @@
+package com.caimei365.order.model.bo;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/7
+ */
+@Data
+public class ProductBo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 商品Id
+     */
+    private Integer productId;
+    /**
+     * 供应商Id
+     */
+    private Integer shopId;
+    /**
+     * 商品名称
+     */
+    private String name;
+    /**
+     * 主图
+     */
+    private String image;
+    /**
+     * 价格
+     */
+    private Double price;
+    /**
+     * 供应商名称
+     */
+    private String shopName;
+    /**
+     * 商品的类别:1正常商品(默认),2二手商品
+     */
+    private Integer productCategory;
+    /**
+     * 成本价选中标志:1固定成本 2比例成
+     */
+    private Integer costCheckFlag;
+    /**
+     * 成本价
+     */
+    private Double costPrice;
+    /**
+     * 市场价 = 商品表市场价
+     */
+    private Double normalPrice;
+    /**
+     * 比例成本百分比
+     */
+    private Double costProportional;
+    /**
+     * 启用阶梯价标志 0否 1是
+     */
+    private Integer ladderPriceFlag;
+    /**
+     * 折后单价
+     */
+    private Double discountPrice;
+    /**
+     * 折扣比例
+     */
+    private Double discount;
+    /**
+     * 总价  = price X num
+     */
+    private Double totalAmount;
+    /**
+     * 折后总价  = discountPrice X num + totalAddedValueTax
+     */
+    private Double totalFee;
+    /**
+     * 应付金额 = totalFee - discountFee(经理折扣,仅后台下单有经理折扣)
+     */
+    private Double shouldPayFee;
+    /**
+     * 包装规格
+     */
+    private String productUnit;
+    /**
+     * 购买数量
+     */
+    private Integer num;
+    /**
+     * 赠送数量
+     */
+    private Integer presentNum;
+    /**
+     * 协销订单:经理折扣(平摊到每个商品上,按照每种商品的总价占订单总价的比例来均分);普通订单 无
+     */
+    private Double discountFee;
+    /**
+     * 是否含税 0不含税,1含税,2未知
+     */
+    private Integer includedTax;
+    /**
+     * 发票类型(基于是否含税基础) 1增值税票,2普通票, 3不能开票
+     */
+    private Integer invoiceType;
+    /**
+     * 机构 税率
+     */
+    private Double taxRate;
+    /**
+     * 机构 单个税费=税率X折后单价
+     */
+    private Double addedValueTax;
+    /**
+     * 机构 总税费=单个税费X购买数量
+     */
+    private Double totalAddedValueTax;
+    /**
+     * 供应商 税率
+     */
+    private Double shopTaxRate;
+    /**
+     * 供应商 单个付供应商税费=税率X成本
+     */
+    private Double singleShouldPayTotalTax;
+    /**
+     * 供应商 总税费(应付税费)=单个税费X购买数量
+     */
+    private Double shouldPayTotalTax;
+    /**
+     * 供应商 商品费=成本价*(购买数量  + 赠品数量)
+     */
+    private Double shopProductAmount;
+    /**
+     * 后台设置的单个应付供应商金额
+     */
+    private Double singleShopFee;
+    /**
+     * 该商品总的应付供应商金额
+     */
+    private Double shopFee;
+    /**
+     * 后台设置单个应付第三方金额
+     */
+    private Double singleOtherFee;
+    /**
+     * 该商品总的应付第三方金额
+     */
+    private Double otherFee;
+    /**
+     * 后台计算的单个应付采美金额
+     */
+    private Double singleCmFee;
+    /**
+     * 该商品总的应付采美金额 (受赠品影响)
+     */
+    private Double cmFee;
+    /**
+     * 支付状态 0 未进账 1 待财务审核 2 已进账(适用协销的单笔线下进账和自助订单线下或异常进账)
+     */
+    private Integer payStatus;
+    /**
+     * 订单商品再次购买标识 0否 1是
+     */
+    private Integer buyAgainFlag;
+    /**
+     * 未出库数量
+     */
+    private Integer notOutStore;
+    /**
+     * 下单时商品购买价格类型快照 0 机构价,1活动价 ,2阶梯价
+     */
+    private Integer actProduct;
+}

+ 112 - 0
src/main/java/com/caimei365/order/model/dto/SubmitDto.java

@@ -0,0 +1,112 @@
+package com.caimei365.order.model.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/6
+ */
+@Data
+public class SubmitDto implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 机构ID
+     */
+    @ApiModelProperty("机构Id")
+    private Integer clubId;
+    /**
+     * 微信unionId
+     */
+    @ApiModelProperty("机构运营人员微信unionId")
+    private String unionId;
+    /**
+     * 收货地址Id
+     */
+    @ApiModelProperty("收货地址Id")
+    private Integer addressId;
+    /**
+     * 订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     */
+    @ApiModelProperty("订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序")
+    private Integer orderSource;
+    /**
+     * 购买类型:(1自主下单, 3协销下单)
+     */
+    @ApiModelProperty("购买类型:(1自主下单, 3协销下单)")
+    private Integer cartType;
+    /**
+     * 协销Id
+     */
+    @ApiModelProperty("协销Id")
+    private Integer serviceProviderId;
+    /**
+     * 订单商品数据:[
+     *            { "shopId":1001,    // 供应商ID
+     *              "note":备注,
+     *              "productInfo":[   // 商品id,数量,赠品数,商品类型
+     *                  {"productId": 2789, "productNum": 1, "presentNum":0,"productType":2},
+     *                  {"productId": 2789, "productNum": 1, "presentNum":0,"productType":0}
+     *               ]
+     *            },
+     *            {多个供应商商品数据结构同上}
+     *         ]
+     */
+    @ApiModelProperty("订单商品数据")
+    private String orderInfo;
+    /**
+     * 订单金额数据:{
+     *         "orderShouldPayFee": 609.11,
+     *         
+     *         "balancePayFlag": 0,   余额支付标识,0不使用,1使用
+     *         "clauseId": "2",
+     *         "postage": "15",
+     *         "postageFlag": 1,
+     *         "userBeans": 100,//抵扣采美豆数量
+     *         "rebateFlag":0
+     *        }
+     */
+    @ApiModelProperty("订单金额数据")
+    private String payInfo;
+    /**
+     * 发票信息:{"type": 0}// 不开发票
+     *      或:{ // 普通发票
+     *              "type": 1,
+     *              "invoiceTitle": "企业抬头",
+     *              "invoiceTitleType": 1,
+     *              "corporationTaxNum": "XXX4156465465",
+     *              "invoiceContent": "明细 "
+     *
+     *          }
+     *      或:{ // 增值税发票
+     *              "type": 2,
+     *              "invoiceTitle": "单位名称",
+     *              "corporationTaxNum": "NSRSBM97897",
+     *              "registeredAddress": "注册地址",
+     *              "registeredPhone": "15814011616",
+     *              "openBank": "开户银行",
+     *              "bankAccountNo": "987987465465464"
+     *          }
+     */
+    @ApiModelProperty("发票信息")
+    private String orderInvoice;
+
+    @Override
+    public String toString() {
+        return "SubmitDto{" +
+                "clubId=" + clubId +
+                ", unionId='" + unionId + '\'' +
+                ", addressId=" + addressId +
+                ", orderSource=" + orderSource +
+                ", cartType=" + cartType +
+                ", serviceProviderId=" + serviceProviderId +
+                ", orderInfo='" + orderInfo + '\'' +
+                ", payInfo='" + payInfo + '\'' +
+                ", orderInvoice='" + orderInvoice + '\'' +
+                '}';
+    }
+}

+ 56 - 0
src/main/java/com/caimei365/order/model/po/InvoicePo.java

@@ -0,0 +1,56 @@
+package com.caimei365.order.model.po;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/9
+ */
+@Data
+public class InvoicePo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * id
+     */
+    private Integer id;
+    /**
+     * 发票类型 0不开发票 1普通发票 2增值税发票
+     */
+    private Integer type;
+    /**
+     * 单位名,发票抬头
+     */
+    private String invoiceTitle;
+    /**
+     * 企业税号、纳税人识别号
+     */
+    private String corporationTaxNum;
+    /**
+     * 发票内容 商品明细
+     */
+    private String invoiceContent;
+    /**
+     * 发票抬头类型 0个人  1 企业--(普通发票使用)
+     */
+    private Integer invoiceTitleType;
+    /**
+     * 注册地址
+     */
+    private String registeredAddress;
+    /**
+     * 注册电话
+     */
+    private String registeredPhone;
+    /**
+     * 开户银行账户
+     */
+    private String bankAccountNo;
+    /**
+     * 开户银行
+     */
+    private String openBank;
+}

+ 174 - 0
src/main/java/com/caimei365/order/model/po/OrderPo.java

@@ -0,0 +1,174 @@
+package com.caimei365.order.model.po;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/7
+ */
+@Data
+public class OrderPo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 订单号
+     */
+    private Integer orderId;
+    /**
+     * 订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     */
+    private Integer orderSource;
+    /**
+     * 订单编号
+     */
+    private String orderNo;
+    /**
+     * 用户Id
+     */
+    private Integer userId;
+    /**
+     * 机构Id
+     */
+    private Integer clubId;
+    /**
+     * 下单人Id(协销Id,或运营人Id,或用户Id)
+     */
+    private Integer buyUserId;
+    /**
+     * 协销Id
+     */
+    private Integer serviceProviderId;
+    /**
+     * 订单提交时间
+     */
+    private String orderTime;
+    /**
+     * 更新时间
+     */
+    private String updateDate;
+    /**
+     * 订单状态 0 有效  其它无效
+     */
+    private Integer delFlag;
+    /**
+     * 采美豆抵扣运费的抵扣数量
+     */
+    private Integer userBeans;
+    /**
+     * 订单类型 协销订单 0, 普通订单 1
+     */
+    private Integer orderType;
+    /**
+     * 订单提交类型 0:个人自己下单 1:企业自己下单 2:员工帮会所下单 3:协销帮会所下单  4:后台下单 5:采美豆订单
+     */
+    private Integer orderSubmitType;
+    /**
+     * 订单确认标志,0否,1后台确认,2买家确认(适用协销订单并且1或2都算已确认订单,主动订单默认1为确认)
+     */
+    private Integer confirmFlag;
+    /**
+     * 是否能走线上支付 0可以 1不可以 只能线下
+     */
+    private Integer onlinePayFlag;
+    /**
+     * 订单是否可拆分   1可拆分 0不可拆分
+     */
+    private Integer splitFlag;
+    /**
+     * 是否已支付 未支付0 已支付1
+     */
+    private Integer payFlag;
+    /**
+     * (向买家)收款状态:1待收款、2部分收款、3已收款
+     */
+    private Integer receiptStatus;
+    /**
+     * (向供应商)付款状态:1待付款、2部分付款、3已付款
+     */
+    private Integer payStatus;
+    /**
+     * 订单0成本标识:0订单有成本,1订单无成本(订单中所有商品成本为0)
+     */
+    private Integer zeroCostFlag;
+    /**
+     * 发货状态:1待发货、2部分发货、3已发货
+     */
+    private Integer sendOutStatus;
+    /**
+     * 退货退款类型:0未发生退款、1部分退、2全部退
+     */
+    private Integer refundType;
+    /**
+     * 确认付款供应商标识 0未确认,1已确认
+     */
+    private Integer affirmPaymentFlag;
+    /**
+     * 购买总数
+     */
+    private Integer productCount;
+
+    /**
+     * 赠送总数  不计算价格
+     */
+    private Integer presentCount;
+    /**
+     * 促销赠品总数
+     */
+    private Integer promotionalGiftsCount;
+    /**
+     * 是否包含活动商品(受订单未支付自动关闭时间影响)  0 否 1 是
+     */
+    private Integer hasActProduct;
+    /**
+     * 促销满减优惠
+     */
+    private Double promotionFullReduction;
+    /**
+     * 二手商品订单标识  0非二手商品订单、 1二手商品订单
+     */
+    private Integer secondHandOrderFlag;
+    /**
+     * 是否开发票 没开发票 0 开个人发票 1 开企业发票2
+     */
+    private Integer invoiceFlag;
+    /**
+     * 免邮标志  运费:-1到付,0包邮,1需要运费,-2仪器到付其它包邮
+     */
+    private Integer freePostFlag;
+    /**
+     * -1到付,0包邮,大于0具体金额,-2仪器到付其它包邮(且运费已使用商品形式存储)
+     */
+    private Double freight;
+    /**
+     * 商品总金额 (商品单价乘以数量,再加上税费)
+     */
+    private Double productTotalFee;
+    /**
+     * 小计金额 (商品折后单价乘以数量,再加上税费)
+     */
+    private Double orderTotalFee;
+    /**
+     * 订单总额(小计金额减去经理折扣后,再加上运费)
+     */
+    private Double payTotalFee;
+    /**
+     * 真实支付金额(订单总额减去抵扣的账户余额)
+     */
+    private Double payableAmount;
+    /**
+     * 余额支付金额
+     */
+    private Double balancePayFee;
+    /**
+     * 0待确认,11待收待发,12待收部发,13待收全发,21部收待发,22部收部发,23部收全发,31已收待发,32已收部发,33已收全发,4交易完成,5订单完成,6已关闭,7交易全退
+     */
+    private Integer status;
+    /**
+     * 订单确认时间
+     */
+    private String confirmTime;
+}

+ 2 - 2
src/main/java/com/caimei365/order/model/vo/CartItemVo.java

@@ -77,7 +77,7 @@ public class CartItemVo implements Serializable {
     /**
      * 是否含税 0不含税,1含税,2未知
      */
-    private String includedTax;
+    private Integer includedTax;
     /**
      * 机构税率
      */
@@ -85,7 +85,7 @@ public class CartItemVo implements Serializable {
     /**
      * 发票类型(基于是否含税基础) 1增值税票,2普通票, 3不能开票
      */
-    private String invoiceType;
+    private Integer invoiceType;
     /**
      * 商品是否处于活动状态 1是 0否
      */

+ 4 - 1
src/main/java/com/caimei365/order/model/vo/ProductPostageVo.java

@@ -21,10 +21,13 @@ public class ProductPostageVo implements Serializable {
      * 邮费标志: 0包邮 1到付 2默认(遵循运费规则)
      */
     private Integer postageFlag;
+    /**
+     * 邮费
+     */
+    private Double postage;
     /**
      * 商品属性:1产品,2仪器(到付)
      */
     private Integer commodityType;
 
-
 }

+ 19 - 0
src/main/java/com/caimei365/order/service/SubmitService.java

@@ -0,0 +1,19 @@
+package com.caimei365.order.service;
+
+import com.caimei365.order.model.ResponseJson;
+import com.caimei365.order.model.dto.SubmitDto;
+
+import java.util.Map;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/6
+ */
+public interface SubmitService {
+    /**
+     * 生成订单
+     */
+    ResponseJson<Map<String, Object>> generateOrder(SubmitDto submitDto);
+}

+ 2 - 63
src/main/java/com/caimei365/order/service/impl/CartClubServiceImpl.java

@@ -768,72 +768,11 @@ public class CartClubServiceImpl implements CartClubService {
             productIdList.add(productIds);
         }
         // 计算运费
-        Map<String, Object> resultMap = computePostage(userId, townId, productIdList);
+        Map<String, Object> resultMap = productService.computePostage(userId, townId, productIdList);
         return ResponseJson.success(resultMap);
     }
 
-    /**
-     * 计算运费
-     * @param userId     用户ID
-     * @param townId     地区Id
-     * @param productIdList 商品Id列表
-     */
-    private Map<String, Object> computePostage(Integer userId, Integer townId, List<String> productIdList) {
-        // 返回数据初始化
-        Map<String, Object> postageMap = new HashMap<>(2);
-        // 运费标志:0包邮 1到付 2遵循运费规则, 注意,旧接口返回前端是:-1到付(默认),0包邮,1有运费
-        int postageFlag = 0;
-        // 运费
-        Double postage = 0.00d;
-        // 可用采美豆
-        Integer userBeans = baseMapper.getUserBeans(userId);
-        postageMap.put("userBeans", userBeans);
-        // 获取商品运费 (0包邮 1到付 2默认(遵循运费规则))
-        List<ProductPostageVo> postageFlagList = baseMapper.getPostageFlagList(productIdList);
-        for (ProductPostageVo postageVo : postageFlagList){
-            // 是否是仪器 或 设置了运费到付
-            boolean flag = (2 == postageVo.getCommodityType() || (null != postageVo.getPostageFlag() && 1==postageVo.getPostageFlag()));
-            if (flag) {
-                // 到付
-                postageMap.put("postageFlag", 1);
-                postageMap.put("postage", 0.00d);
-                return postageMap;
-            } else if (null != postageVo.getPostageFlag() && 2==postageVo.getPostageFlag()) {
-                // 若有不包邮商品,则全部不包邮
-                postageFlag = 2;
-            }
-        }
-        // 是否首单(统计订单数)
-        Integer count = baseMapper.countUserOrder(userId);
-        // 包邮条件:首单 或 包邮(上一步未被设置成不包邮)
-        boolean freeFlag = ((null != count && count == 0) || postageFlag == 0);
-        if (freeFlag) {
-            // 包邮
-            postageMap.put("postageFlag", 0);
-            postageMap.put("postage", 0.00d);
-            return postageMap;
-        } else {
-            /*
-             * 运费计算:广东省内运费15元,深圳市内运费10,其他地区到付
-             */
-            postageFlag = 2;
-            // 获取根据地区Id获取省市地址信息
-            AddressVo address = baseMapper.getProvinceIdAndCityId(townId);
-            if (null != address && 202 == address.getCityId()) {
-                // 深圳市内运费10
-                postage = 10.00d;
-            } else if (null != address && 19 == address.getProvinceId()){
-                // 广东省内运费15元
-                postage = 15.00d;
-            } else {
-                // 到付
-                postageFlag = 1;
-            }
-            postageMap.put("postageFlag", postageFlag);
-            postageMap.put("postage", postage);
-            return postageMap;
-        }
-    }
+
 
 
 

+ 6 - 4
src/main/java/com/caimei365/order/service/impl/CartSellerServiceImpl.java

@@ -28,6 +28,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static com.alibaba.fastjson.JSON.parseArray;
+
 /**
  * Description
  *
@@ -255,9 +257,9 @@ public class CartSellerServiceImpl implements CartSellerService {
             addSellerCart(sellerCartDto);
         } else if (2 == sellerCartDto.getType()) {
             try {
-                JSONArray productArr = JSONArray.parseArray(sellerCartDto.getProductInfo());
-                for (Iterator iterator = productArr.iterator(); iterator.hasNext();) {
-                    JSONObject product = (JSONObject) iterator.next();
+                JSONArray productArr = parseArray(sellerCartDto.getProductInfo());
+                for (Object o : productArr) {
+                    JSONObject product = (JSONObject) o;
                     Integer productId = product.getInteger("id");
                     Integer productCount = product.getInteger("count");
                     sellerCartDto.setProductId(productId);
@@ -275,7 +277,7 @@ public class CartSellerServiceImpl implements CartSellerService {
 
     /**
      * 添加购物车,插入数据库
-     * @param sellerCartDto
+     * @param sellerCartDto SellerCartDto
      */
     private void addSellerCart(SellerCartDto sellerCartDto) {
         SellerCartPo cart = cartSellerMapper.getSellerCart(sellerCartDto);

+ 1009 - 0
src/main/java/com/caimei365/order/service/impl/SubmitServiceImpl.java

@@ -0,0 +1,1009 @@
+package com.caimei365.order.service.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.caimei365.order.components.ProductService;
+import com.caimei365.order.mapper.BaseMapper;
+import com.caimei365.order.mapper.SubmitMapper;
+import com.caimei365.order.model.ResponseJson;
+import com.caimei365.order.model.bo.ProductBo;
+import com.caimei365.order.model.dto.SubmitDto;
+import com.caimei365.order.model.bo.OrderUserBo;
+import com.caimei365.order.model.po.InvoicePo;
+import com.caimei365.order.model.po.OrderPo;
+import com.caimei365.order.model.vo.*;
+import com.caimei365.order.service.SubmitService;
+import com.caimei365.order.utils.CodeUtil;
+import com.caimei365.order.utils.ImageUtil;
+import com.caimei365.order.utils.MathUtil;
+import com.google.common.util.concurrent.AtomicDouble;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.interceptor.TransactionAspectSupport;
+import org.springframework.util.CollectionUtils;
+
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static com.alibaba.fastjson.JSON.parseArray;
+import static com.alibaba.fastjson.JSON.parseObject;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/6
+ */
+@Slf4j
+@Service
+public class SubmitServiceImpl implements SubmitService {
+    @Resource
+    private BaseMapper baseMapper;
+    @Resource
+    private SubmitMapper submitMapper;
+    @Value("${caimei.wwwDomain}")
+    private String domain;
+    @Resource
+    private ProductService productService;
+
+    /**
+     * 生成订单
+     *
+     * @param submitDto {
+     *                  "unionId":"",               //微信unionId
+     *                  "cartType":3,               //购买类型:(1自主下单, 3协销下单)
+     *                  "orderSource": 2,           //订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     *                  "serviceProviderId": 1378,  //协销ID(小程序忽略)
+     *                  "clubUserId": 10708,        //机构用户ID
+     *                  "addressId": 2732,          //地址ID
+     *                  "orderInfo": [              //【订单商品】
+     *                      { "shopId":1001,                         // 供应商Id
+     *                          "note":备注,
+     *                          "productInfo":[                      // 商品id,数量,赠品数,商品类型
+     *                              {"productId": 2789, "productNum": 1, "presentNum":0,"productType":2},
+     *                              {"productId": 2789, "productNum": 1, "presentNum":0,"productType":0}
+     *                          ]
+     *                      },{多个供应商商品数据结构同上}
+     *                  ],
+     *                  "payInfo": {                //【订单金额】
+     *                      "orderShouldPayFee": 609.11,
+     *                      
+     *                      "balancePayFlag": 0,
+     *                      "clauseId": "2",
+     *                      "postage": "15",
+     *                      "postageFlag": 1,
+     *                      "userBeans": 100,//抵扣采美豆数量
+     *                      "rebateFlag":0
+     *                  },
+     *                  "orderInvoice":             //【发票信息】
+     *                          {"type": 0 // 不开发票  }
+     *                      或: { // 普通发票
+     *                              "type": 1,
+     *                              "invoiceTitle": "企业抬头",
+     *                              "invoiceTitleType": 1,
+     *                              "corporationTaxNum": "XXX4156465465",
+     *                              "invoiceContent": "明细 "
+     *                          }
+     *                      或: { // 增值税发票
+     *                              "type": 2,
+     *                              "invoiceTitle": "单位名称",
+     *                              "corporationTaxNum": "NSRSBM97897",
+     *                              "registeredAddress": "注册地址",
+     *                              "registeredPhone": "15814011616",
+     *                              "openBank": "开户银行",
+     *                              "bankAccountNo": "987987465465464"
+     *                          }
+     *              }
+     * @return {code: -1=(用户账户异常,数据异常,操作异常等),1提交成功(支付完成),2提交成功(未支付),
+     *              code为1和2时:data{orderNo:订单号,orderID:订单ID,payTotalFee:订单金额,orderMark:订单标识}
+     */
+    @Override
+    public ResponseJson<Map<String, Object>> generateOrder(SubmitDto submitDto) {
+        // 获取机构用户Id
+        Integer clubUserId = baseMapper.getUserIdByClubId(submitDto.getClubId());
+        if (null == clubUserId || clubUserId == 0){
+            return ResponseJson.error("机构用户信息异常!", null);
+        }
+        JSONArray orderInfo = null;
+        JSONObject payInfo = null;
+        JSONObject orderInvoice = null;
+        try {
+            orderInfo = parseArray(submitDto.getOrderInfo());
+            payInfo = parseObject(submitDto.getPayInfo());
+            orderInvoice = parseObject(submitDto.getOrderInvoice());
+        } catch (Exception e) {
+            log.error("订单参数解析异常try-catch:", e);
+            return ResponseJson.error("订单参数解析异常!", null);
+        }
+        if (null == orderInfo){
+            return ResponseJson.error("订单商品数据异常!", null);
+        }
+        if (null == payInfo){
+            return ResponseJson.error("订单金额数据异常!", null);
+        }
+        if (null == orderInvoice){
+            return ResponseJson.error("发票信息数据异常!", null);
+        }
+        // 打印参数
+        if (3 == submitDto.getCartType()){
+            log.info("******************** 【协销订单】提交订单参数:"+ submitDto);
+        } else {
+            log.info("******************** 【自主订单】提交订单参数:"+ submitDto);
+        }
+        // 机构用户
+        OrderUserBo orderUserBo = submitMapper.getOrderUserBoById(clubUserId);
+        orderUserBo.setOrderSource(submitDto.getOrderSource());
+        orderUserBo.setOrderInfo(orderInfo);
+        orderUserBo.setOrderInvoice(orderInvoice);
+        // 余额支付标识,0不使用,1使用
+        Integer balancePayFlag = (Integer) payInfo.get("balancePayFlag");
+        // 判断用户可用余额是否wei0
+        if (1 == balancePayFlag && null != orderUserBo.getAbleUserMoney() && MathUtil.compare(orderUserBo.getAbleUserMoney(), BigDecimal.ZERO) == 0) {
+            return ResponseJson.error("用户可用余额为0.00元!", null);
+        }
+        orderUserBo.setBalancePayFlag(balancePayFlag);
+        Double orderShouldPayFee = (Double) payInfo.get("orderShouldPayFee");
+        orderUserBo.setOrderShouldPayFee(orderShouldPayFee);
+        // 邮费标志: 0包邮 1到付 2默认(遵循运费规则)
+        Integer postageFlag = (Integer) payInfo.get("postageFlag");
+        // 运费
+        Double postage = (Double) payInfo.get("postage");
+        if (null == postageFlag || null == postage) {
+            return ResponseJson.error("运费数据异常!", null);
+        }
+        orderUserBo.setPostageFlag(postageFlag);
+        orderUserBo.setPostage(postage);
+        // 采美豆抵扣运费,1:100,到付默认30元,抵扣3000豆
+        Integer userBeans = (Integer) payInfo.get("userBeans");
+        if (null != userBeans && userBeans > 0) {
+            // 计算需抵扣采美豆数量
+            int offsetBeans = MathUtil.mul(postage, 100).intValue();
+            if (1 == postageFlag) {
+                // 到付默认30元,抵扣3000豆
+                offsetBeans = 3000;
+            }
+            // 与前端传入采美豆数量比较
+            if (null == orderUserBo.getUserBeans() || !userBeans.equals(offsetBeans)){
+                return ResponseJson.error("采美豆数据异常!", null);
+            }
+            if (MathUtil.compare(offsetBeans, orderUserBo.getUserBeans())>0) {
+                return ResponseJson.error("用户剩余采美豆不足!", null);
+            }
+        } else {
+            userBeans = 0;
+        }
+        orderUserBo.setOffsetBeans(userBeans);
+        // 发票类型 0不开发票 1普通发票 2增值税发票
+        Integer invoiceType = (Integer) orderInvoice.get("type");
+        if (null == invoiceType) {
+            return ResponseJson.error("发票类型不能为空!", null);
+        }
+        orderUserBo.setInvoiceType(invoiceType);
+        // 返佣订单标识 0非返佣订单,1返佣订单
+        Integer rebateFlag = (Integer) payInfo.get("rebateFlag");
+        orderUserBo.setRebateFlag(rebateFlag);
+        // 售后条款id
+        Integer clauseId = (Integer) payInfo.get("clauseId");
+        orderUserBo.setClauseId(clauseId);
+        // 购买类型:(1自主下单, 3协销下单)
+        orderUserBo.setCartType(submitDto.getCartType());
+        // 下单人
+        Integer buyUserId = null;
+        if (1 == submitDto.getCartType()){
+            // 自主下单
+            buyUserId = clubUserId;
+            if (StringUtils.isNotEmpty(submitDto.getUnionId())) {
+                // 运营人员Id
+                Integer operationId = submitMapper.getOperationIdByUnionId(submitDto.getUnionId(), clubUserId);
+                if (null != operationId && operationId>0) {
+                    buyUserId = operationId;
+                }
+            }
+        } else if (3 == submitDto.getCartType()){
+            // 协销下单, 获取协销用户Id
+            Integer spUserId = submitMapper.getServiceProviderUserId(submitDto.getServiceProviderId());
+            if (null != spUserId && spUserId>0) {
+                buyUserId = spUserId;
+            } else {
+                return ResponseJson.error("协销用户异常!", null);
+            }
+        } else {
+            return ResponseJson.error("购买类型不正确!", null);
+        }
+        orderUserBo.setBuyUserId(buyUserId);
+        orderUserBo.setAddressId(submitDto.getAddressId());
+
+
+//     *                  "unionId":"",               //微信unionId
+//     *                  "cartType":3,               //购买类型:(1自主下单, 3协销下单)
+//     *                  "serviceProviderId": 1378,  //协销ID(小程序忽略)
+//     *                  "clubUserId": 10708,        //机构用户ID
+//     *                  "addressId": 2732,          //地址ID
+
+
+        return saveOrder(orderUserBo);
+    }
+
+
+
+    private ResponseJson<Map<String, Object>> saveOrder(OrderUserBo orderUserBo) {
+        log.info("******************** 提交订单逻辑处理 start *******************");
+        /*
+         * 初始化主订单
+         */
+        OrderPo mainOrder = new OrderPo();
+        // 订单来源
+        mainOrder.setOrderSource(orderUserBo.getOrderSource());
+        // 订单号
+        String orderNo = CodeUtil.generateOrderNo(orderUserBo.getOrderSource());
+        mainOrder.setOrderNo(orderNo);
+        // 用户Id
+        mainOrder.setUserId(orderUserBo.getUserId());
+        mainOrder.setClubId(orderUserBo.getClubId());
+        mainOrder.setBuyUserId(orderUserBo.getBuyUserId());
+        // 订单提交时间
+        Date date = new Date();
+        String curDateStr = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(date);
+        mainOrder.setOrderTime(curDateStr);
+        mainOrder.setUpdateDate(curDateStr);
+        // 订单状态 0 有效  其它无效
+        mainOrder.setDelFlag(0);
+        if (3 == orderUserBo.getCartType()) {
+            // 协销订单
+            mainOrder.setOrderType(0);
+            // 3:协销帮会所下单
+            mainOrder.setOrderSubmitType(3);
+            // 订单未确认
+            mainOrder.setConfirmFlag(0);
+            // 协销Id
+            mainOrder.setServiceProviderId(orderUserBo.getBuyUserId());
+        } else {
+            // 普通订单
+            mainOrder.setOrderType(1);
+            // 其他默认 2:员工帮会所下单
+            mainOrder.setOrderSubmitType(2);
+            // 2买家确认
+            mainOrder.setConfirmFlag(2);
+        }
+        // 抵扣采美豆数量
+        mainOrder.setUserBeans(orderUserBo.getOffsetBeans());
+        // 默认可以线上支付:0可以 1不可以
+        mainOrder.setOnlinePayFlag(0);
+        // 默认订单可以拆分:1可拆分 0不可拆分
+        mainOrder.setSplitFlag(1);
+        // 默认订单未支付:未支付0 已支付1
+        mainOrder.setPayFlag(0);
+        // 默认待向买家收款:1待收款、2部分收款、3已收款
+        mainOrder.setReceiptStatus(1);
+        // 默认未付款供应商:1待付款、2部分付款、3已付款
+        mainOrder.setPayStatus(1);
+        // 默认有成本
+        mainOrder.setZeroCostFlag(0);
+        // 发货状态:1待发货、2部分发货、3已发货
+        mainOrder.setSendOutStatus(1);
+        // 退货退款类型:0未发生退款、1部分退、2全部退
+        mainOrder.setRefundType(0);
+        // 未确认付款供应商
+        mainOrder.setAffirmPaymentFlag(0);
+
+        /*
+         * 整理订单商品信息
+         */
+        // 商品总数量
+        AtomicInteger productCount = new AtomicInteger(0);
+        // 赠品数量
+        AtomicInteger presentCount = new AtomicInteger(0);
+        // 促销赠品数量
+        AtomicInteger promotionalGiftsCount = new AtomicInteger(0);
+        // 商品总金额 (商品单价乘以数量,再加上税费)
+        AtomicDouble productTotalFee = new AtomicDouble(0);
+        // 订单总额(小计金额减去经理折扣后,再加上运费[默认0])
+        AtomicDouble payTotalFee = new AtomicDouble(0);
+        // 真实支付金额(订单总额减去抵扣的账户余额)
+        AtomicDouble payableAmount = new AtomicDouble(0);
+        // 余额支付金额
+        AtomicDouble balancePayFee = new AtomicDouble(0);
+
+        // 二手订单标记(二手订单不能同正常商品下单,只能单个商品立即购买下单)
+        boolean secondHandOrderFlag = false;
+        // 是否包含活动商品
+        boolean hasActProductFlag = false;
+        //促销活动ids
+        List<Integer> promotionsIds = new ArrayList<>();
+        // 促销活动信息
+        List<PromotionsVo> promotionList= new ArrayList<>();
+        // 订单商品列表
+        List<ProductBo> orderProductList = new ArrayList<>();
+        List<String> productIdList = new ArrayList<>();
+        JSONArray orderInfo = orderUserBo.getOrderInfo();
+        for (Object infoObject: orderInfo) {
+            JSONObject shopInfo = (JSONObject) infoObject;
+            Integer shopId = (Integer) shopInfo.get("shopId");
+            if (null == shopId) {
+                return ResponseJson.error("供应商数据异常!", null);
+            }
+            JSONArray productArr = (JSONArray) shopInfo.get("productInfo");
+            if (null == productArr) {
+                return ResponseJson.error("订单商品数据异常!", null);
+            }
+            // 供应商名称
+            String shopName = submitMapper.getShopNameById(shopId);
+            // 商品信息ids
+            List<Integer> shopProductIds = new ArrayList<>();
+            // 遍历所有商品
+            for (Object productObject : productArr) {
+                JSONObject productTemp = (JSONObject) productObject;
+                Integer productId = (Integer) productTemp.get("productId");
+                Integer productNum = (Integer) productTemp.get("productNum");
+                Integer presentNum = (Integer) productTemp.get("presentNum");
+                Integer productType = (Integer) productTemp.get("productType");
+                productType = (null == productType) ? 0 : productType;
+                if (null == productId) {
+                    return ResponseJson.error("订单商品数据异常!", null);
+                }
+                if (null == productNum || productNum == 0) {
+                    return ResponseJson.error("商品购买数量异常!", null);
+                }
+                shopProductIds.add(productId);
+                // 统计商品总数量
+                productCount.updateAndGet(v -> v + productNum);
+                // 赠品数
+                presentCount.updateAndGet(v -> v + presentNum);
+                // 获取数据库商品信息
+                ProductBo product = submitMapper.getProductDetails(productId);
+                if (null == product) {
+                    return ResponseJson.error("订单商品不存在!", null);
+                }
+                // 是否二手商品
+                if (null != product.getProductCategory() && 2 == product.getProductCategory()) {
+                    secondHandOrderFlag = true;
+                }
+                // 成本价
+                Double costPrice = null;
+                // 判断是否选中固定成本价
+                if (null != product.getCostPrice() && 1 == product.getCostCheckFlag() && product.getCostPrice() > 0d) {
+                    costPrice = product.getCostPrice();
+                }
+                // 判断是否选中比例成本价
+                if (null != product.getCostProportional() && 2 == product.getCostCheckFlag() && product.getCostProportional() > 0d) {
+                    // 通过售价*比例得到成本价
+                    costPrice = MathUtil.div(MathUtil.mul(product.getPrice(), product.getCostProportional()), 100).doubleValue();
+                }
+                if (null == costPrice) {
+                    return ResponseJson.error("订单商品成本异常!", null);
+                }
+                // 是否添加税费,不含税商品 开票需添加税费
+                boolean taxFlag = (0 == product.getIncludedTax() && (1 == product.getInvoiceType() || 2 == product.getInvoiceType()));
+                Double shopTax = 0d;
+                // 图片路径
+                String image = ImageUtil.getImageUrl("product", product.getImage(), domain);
+                product.setImage(image);
+                product.setShopName(shopName);
+                product.setCostPrice(costPrice);
+                product.setNum(productNum);
+                product.setPresentNum(presentNum);
+                // 是否是促销赠品
+                if (productType == 2) {
+                    // 促销赠品数+1
+                    promotionalGiftsCount.incrementAndGet();
+                    product.setPrice(0d);
+                    product.setDiscountPrice(0d);
+                    product.setDiscount(0d);
+                    product.setTotalAmount(0d);
+                    product.setTotalFee(0d);
+                    product.setTaxRate(0d);
+                    product.setAddedValueTax(0d);
+                    product.setTotalAddedValueTax(0d);
+                } else {
+                    // 获取商品购买价格(活动价格>>>阶梯价格>>>复购价格库>>>商品原始价)
+                    Double productPrice = product.getPrice();
+                    Double discountPrice = product.getPrice();
+                    // 商品税费
+                    Double productTax = 0d;
+                    Double discountTax = 0d;
+                    // 商品是否处于活动状态
+                    PromotionsVo promotions = baseMapper.getPromotionByProductId(productId);
+                    // 计算单价
+                    if (promotions != null) {
+                        // 是否包含活动商品(受订单未支付自动关闭时间影响)  0 否 1 是
+                        hasActProductFlag = true;
+                        // 关闭阶梯价格,活动优先
+                        product.setLadderPriceFlag(0);
+                        if (promotions.getType() == 1 && promotions.getMode() == 1) {
+                            discountPrice = promotions.getTouchPrice();
+                        }
+                        product.setActProduct(1);
+                    } else if (1 == product.getLadderPriceFlag()) {
+                        // 启用了阶梯价格
+                        List<LadderPriceVo> ladderPrices = baseMapper.getLadderPriceList(productId);
+                        // 判断阶梯价格的购买数量校验
+                        int minBuyNumber = null != ladderPrices.get(0) ? ladderPrices.get(0).getBuyNum() : 0;
+                        if (productNum < minBuyNumber) {
+                            return ResponseJson.error("商品购买量低于最小起订量!", null);
+                        }
+                        //根据商品购买数量获取商品对应阶梯价格
+                        for (LadderPriceVo ladderPrice : ladderPrices) {
+                            if (productNum >= ladderPrice.getBuyNum()) {
+                                discountPrice = ladderPrice.getBuyPrice();
+                            }
+                        }
+                        product.setActProduct(2);
+                    } else {
+                        // 复购价
+                        Double repurchase = baseMapper.getRepurchasePrice(productId, orderUserBo.getUserId());
+                        if (null != repurchase && repurchase > 0) {
+                            discountPrice = repurchase;
+                        }
+                        product.setActProduct(0);
+                    }
+                    if (MathUtil.compare(discountPrice, BigDecimal.ZERO) == 0) {
+                        return ResponseJson.error("商品购买价格不能为0!", null);
+                    }
+                    // 不含税可开票商品计算税费
+                    if (null == product.getTaxRate() || product.getTaxRate() <= 0) {
+                        product.setTaxRate(0d);
+                    }
+                    if (taxFlag) {
+                        productTax = MathUtil.div(MathUtil.mul(productPrice, product.getTaxRate()), 100, 2).doubleValue();
+                        discountTax = MathUtil.div(MathUtil.mul(discountPrice, product.getTaxRate()), 100, 2).doubleValue();
+                    } else if (1 != product.getIncludedTax()) {
+                        // 不含税不可开票商品和未知商品,税率置为0
+                        product.setTaxRate(0d);
+                    }
+                    // 商品价格
+                    productPrice = MathUtil.add(productPrice, productTax).doubleValue();
+                    product.setPrice(productPrice);
+                    // 折后单价
+                    discountPrice = MathUtil.add(discountPrice, discountTax).doubleValue();
+                    product.setDiscountPrice(discountPrice);
+                    // 折扣率 = 折后单价/机构价
+                    Double discountRate = MathUtil.mul(MathUtil.div(discountPrice, productPrice), 100).doubleValue();
+                    product.setDiscount(discountRate);
+                    // 单个商品的金额
+                    Double productAmount = MathUtil.mul(productPrice, productNum).doubleValue();
+                    product.setTotalAmount(productAmount);
+                    // 单个商品的折后金额
+                    Double productFee = MathUtil.mul(discountPrice, productNum).doubleValue();
+                    product.setTotalFee(productFee);
+                    product.setShouldPayFee(productFee);
+                    // 单个商品总税费
+                    Double taxFee = MathUtil.mul(discountTax, productNum).doubleValue();
+                    // 税费
+                    product.setAddedValueTax(discountTax);
+                    product.setTotalAddedValueTax(taxFee);
+                    if (hasActProductFlag && null != promotions) {
+                        // 商品添加到总促销
+                        PromotionPriceVo promotionPrice = new PromotionPriceVo();
+                        promotionPrice.setProductId(productId);
+                        promotionPrice.setNumber(productNum);
+                        promotionPrice.setPrice(discountPrice);
+                        promotions.getProductList().add(promotionPrice);
+                        if (!promotionsIds.contains(promotions.getId())) {
+                            promotionsIds.add(promotions.getId());
+                            promotionList.add(promotions);
+                        } else {
+                            promotionList.forEach(promotionsTemp -> {
+                                if (promotions.getId().equals(promotionsTemp.getId())){
+                                    promotionsTemp.getProductList().add(promotionPrice);
+                                }
+                            });
+                        }
+                    }
+                }
+                // 统计商品总金额
+                productTotalFee.set(MathUtil.add(productTotalFee.get(), product.getTotalFee()).doubleValue());
+
+                // 付供应商税费
+                if (null == product.getShopTaxRate() || product.getShopTaxRate() <= 0) {
+                    product.setShopTaxRate(product.getTaxRate());
+                }
+                if (taxFlag) {
+                    shopTax = MathUtil.div(MathUtil.mul(costPrice, product.getTaxRate()), 100, 2).doubleValue();
+                } else if (1 != product.getIncludedTax()) {
+                    // 不含税不可开票商品和未知商品,税率置为0
+                    product.setShopTaxRate(0d);
+                }
+                // 单个付供应商税费
+                product.setSingleShouldPayTotalTax(shopTax);
+                // 单个商品付供应商总税费
+                Double shopTaxFee = MathUtil.mul(shopTax, productNum).doubleValue();
+                product.setShouldPayTotalTax(shopTaxFee);
+                // 付供应商 商品费=成本价*(购买数量  + 赠品数量)
+                Double shopProductAmount = MathUtil.mul(costPrice, MathUtil.add(productNum, presentNum)).doubleValue();
+                product.setShopProductAmount(shopProductAmount);
+                //应付供应商(单)=成本价+供应商税费(单)
+                Double singleShopFee = MathUtil.add(product.getCostPrice(), shopTax).doubleValue();
+                product.setSingleShopFee(singleShopFee);
+                // 应付供应商(总)=应付供应商(单) * 商品数量
+                Double shopFee = MathUtil.add(product.getCostPrice(), shopTax).doubleValue();
+                product.setShopFee(shopFee);
+                // 付第三方,默认0
+                product.setOtherFee(0d);
+                product.setSingleOtherFee(0d);
+                //应付采美(单)=单价+机构税费(单)-(成本(单)+供应商税费(单))
+                Double singleCmFee = MathUtil.sub(MathUtil.add(BigDecimal.valueOf(product.getPrice()), product.getAddedValueTax()), MathUtil.add(product.getCostPrice(), shopTax)).doubleValue();
+                product.setSingleCmFee(singleCmFee);
+                // 应付采美(总)=应付采美(单)*商品数量
+                Double cmFee = MathUtil.mul(singleCmFee, productNum).doubleValue();
+                product.setCmFee(cmFee);
+                // 默认未支付
+                product.setPayStatus(0);
+                // 默认非再次购买商品
+                product.setBuyAgainFlag(0);
+                // 未出库数量
+                product.setNotOutStore(productNum);
+
+                // 加入订单商品列表
+                orderProductList.add(product);
+                productIdList.add(product.getProductId().toString());
+            }
+        }
+        // 设置是否是二手订单
+        if (secondHandOrderFlag) {
+            mainOrder.setSecondHandOrderFlag(1);
+        } else {
+            mainOrder.setSecondHandOrderFlag(0);
+        }
+        // 是否包含活动商品(受订单未支付自动关闭时间影响)  0 否 1 是
+        if (!hasActProductFlag) {
+            mainOrder.setHasActProduct(0);
+        } else {
+            mainOrder.setHasActProduct(1);
+            // 促销满减优惠
+            AtomicDouble promotionFullReduction = new AtomicDouble(0);
+            // 促销活动优惠计算
+            Iterator<PromotionsVo> promotionsIterator = promotionList.iterator();
+            while (promotionsIterator.hasNext()) {
+                PromotionsVo promotions = promotionsIterator.next();
+                // 这里计算满减满赠
+                if (promotions.getMode() == 2 || promotions.getMode() == 3) {
+                    // 实际该促销商品总额
+                    AtomicDouble touchPrice = new AtomicDouble(0);
+                    promotions.getProductList().forEach(item -> {
+                        touchPrice.set(MathUtil.add(touchPrice.get(), MathUtil.mul(item.getNumber(), item.getPrice())).doubleValue());
+                    });
+                    //判断是否达到满减满赠要求
+                    if (MathUtil.compare(touchPrice.get(), promotions.getTouchPrice()) >= 0) {
+                        if (promotions.getMode() == 2) {
+                            // 满减
+                            promotionFullReduction.set(MathUtil.add(promotionFullReduction.get(), promotions.getReducedPrice()).doubleValue());
+                            // 统计商品总金额
+                            productTotalFee.set(MathUtil.sub(productTotalFee.get(), promotions.getReducedPrice()).doubleValue());
+                        }
+                    } else {
+                        // 删除不满足条件的促销
+                        promotionsIterator.remove();
+                    }
+                }
+            }
+            // 促销满减优惠
+            mainOrder.setPromotionFullReduction(promotionFullReduction.get());
+        }
+        // 商品总数量
+        mainOrder.setProductCount(productCount.get());
+        // 赠品数量
+        mainOrder.setPresentCount(presentCount.get());
+        //促销赠品数量
+        mainOrder.setPromotionalGiftsCount(promotionalGiftsCount.get());
+        /*
+         * 发票信息
+         */
+        mainOrder.setInvoiceFlag(orderUserBo.getInvoiceType());
+        // 发票类型 0不开发票 1普通发票 2增值税发票
+        if (1== orderUserBo.getInvoiceType() || 2 == orderUserBo.getInvoiceType()){
+            JSONObject orderInvoice = orderUserBo.getOrderInvoice();
+            Integer invoiceType = (Integer) orderInvoice.get("type");
+            String invoiceTitle = (String) orderInvoice.get("invoiceTitle");
+            if (StringUtils.isNotEmpty(invoiceTitle)){
+                return ResponseJson.error("发票抬头信息不正确!", null);
+            }
+            String corporationTaxNum = (String) orderInvoice.get("corporationTaxNum");
+            if (StringUtils.isNotEmpty(corporationTaxNum)){
+                return ResponseJson.error("纳税人识别号信息不正确!", null);
+            }
+            InvoicePo invoice = new InvoicePo();
+            invoice.setType(invoiceType);
+            invoice.setInvoiceTitle(invoiceTitle);
+            invoice.setCorporationTaxNum(corporationTaxNum);
+            if (1== orderUserBo.getInvoiceType()) {
+                // 普通发票:发票类型、发票内容(商品明细)、抬头(公司名称)、纳税人识别号[普通发票的公司]
+                String invoiceContent = (String) orderInvoice.get("invoiceContent");
+                Integer invoiceTitleType = (Integer) orderInvoice.get("invoiceTitleType");
+                if (StringUtils.isNotEmpty(invoiceContent) || null == invoiceTitleType) {
+                    return ResponseJson.error("发票信息不完整!", null);
+                }
+                invoice.setInvoiceContent(invoiceContent);
+                invoice.setInvoiceTitleType(invoiceTitleType);
+            }
+            if (2== orderUserBo.getInvoiceType()) {
+                // 增值税发票:发票类型、发票、抬头(公司名称)、纳税人识别号、注册地址、注册电话、开户银行、开户银行账户
+                String registeredAddress = (String) orderInvoice.get("registeredAddress");
+                String registeredPhone = (String) orderInvoice.get("registeredPhone");
+                String openBank = (String) orderInvoice.get("openBank");
+                String bankAccountNo = (String) orderInvoice.get("bankAccountNo");
+                if (StringUtils.isNotEmpty(registeredAddress) || StringUtils.isNotEmpty(registeredPhone) || StringUtils.isNotEmpty(openBank) || StringUtils.isNotEmpty(bankAccountNo)) {
+                    return ResponseJson.error("发票信息不完整!", null);
+                }
+                invoice.setRegisteredAddress(registeredAddress);
+                invoice.setRegisteredPhone(registeredPhone);
+                invoice.setOpenBank(openBank);
+                invoice.setBankAccountNo(bankAccountNo);
+            }
+        }
+
+        /*
+         * 计算运费
+         */
+        if (3 != orderUserBo.getCartType()){
+            // 机构用户 计算商品运费
+            Integer townId = baseMapper.getTownIdByAddressId(orderUserBo.getAddressId());
+            Map<String, Object> postageMap = productService.computePostage(orderUserBo.getUserId(), townId, productIdList);
+            // 当前订单邮费标志: 0包邮 1到付 2默认(遵循运费规则)
+            Integer postageFlag = (Integer) postageMap.get("postageFlag");
+            Double postage = (Double) postageMap.get("postage");
+            if (!orderUserBo.getPostageFlag().equals(postageFlag) || MathUtil.compare(orderUserBo.getPostage(), postage) != 0) {
+                return ResponseJson.error("订单邮费不正确!", null);
+            }
+        }
+        // 设置运费
+        mainOrder.setFreight(orderUserBo.getPostage());
+        // 订单总额 = 商品费 + 运费
+        payTotalFee.set(MathUtil.add(productTotalFee.get(), orderUserBo.getPostage()).doubleValue());
+        // order免邮标志  运费:-1到付,0包邮,1需要运费,-2仪器到付其它包邮
+        if (0 == orderUserBo.getPostageFlag()) {
+            mainOrder.setFreePostFlag(0);
+        } else if (1 == orderUserBo.getPostageFlag()){
+            mainOrder.setFreePostFlag(-1);
+        } else {
+            // 遵循运费规则
+            mainOrder.setFreePostFlag(1);
+            if (orderUserBo.getOffsetBeans() > 0) {
+                // 采美豆抵扣运费,订单总额 = 商品费
+                payTotalFee.set(productTotalFee.get());
+            }
+        }
+        // 商品总额
+        mainOrder.setProductTotalFee(productTotalFee.get());
+        mainOrder.setOrderTotalFee(productTotalFee.get());
+        // 订单总额(商品金额+运费)
+        mainOrder.setPayTotalFee(payTotalFee.get());
+        // 订单状态
+        if (3 == orderUserBo.getCartType()) {
+            // 协销 状态为 待确认
+            mainOrder.setStatus(0);
+        } else {
+            // 机构用户 状态为 待收待发
+            mainOrder.setStatus(11);
+            mainOrder.setConfirmTime(curDateStr);
+        }
+        // 是否完成支付(默认不是,只有余额抵扣才算)
+        boolean isPaySuccessFlag = false;
+        // 余额支付标识,0不使用,1使用
+        if (1 == orderUserBo.getBalancePayFlag()) {
+            // 抵扣后用户剩余可用余额
+            Double lastAbleUserMoney = orderUserBo.getAbleUserMoney();
+            // 抵扣后账户余额
+            Double lastUserMoney = orderUserBo.getUserMoney();
+            // 部分抵扣
+            if (MathUtil.compare(payTotalFee.get(), orderUserBo.getAbleUserMoney()) > 0) {
+                balancePayFee.set(orderUserBo.getAbleUserMoney());
+                payableAmount.set(MathUtil.sub(payTotalFee.get(), balancePayFee.get()).doubleValue());
+                // 余额抵扣用完
+                lastAbleUserMoney = 0d;
+                if (3 != orderUserBo.getCartType()) {
+                    // 部收款待发货
+                    mainOrder.setStatus(21);
+                    lastUserMoney = MathUtil.sub(orderUserBo.getUserMoney(), balancePayFee.get()).doubleValue();
+                }
+                mainOrder.setReceiptStatus(2);
+            } else {
+                // 全部用余额抵扣, 直接变成支付完成
+                balancePayFee.set(payTotalFee.get());
+                payableAmount.set(0d);
+                lastAbleUserMoney = MathUtil.sub(orderUserBo.getAbleUserMoney(), balancePayFee.get()).doubleValue();
+                if (3 != orderUserBo.getCartType()) {
+                    // 已收款待发货
+                    mainOrder.setStatus(31);
+                    lastUserMoney = MathUtil.sub(orderUserBo.getUserMoney(), balancePayFee.get()).doubleValue();
+                }
+                mainOrder.setReceiptStatus(3);
+                mainOrder.setPayFlag(1);
+                isPaySuccessFlag = true;
+            }
+
+
+
+
+
+//            userDao.updateMoney(user.getUserMoney(), user.getAbleUserMoney(), user.getUserID());
+//
+//
+//
+//            log.info(">>>>>更新余额抵扣:[userMoney:" + user.getUserMoney() + "] ,ableUserMoney:" + user.getAbleUserMoney());
+//            // 支付时间
+//            mainOrder.setPayTime(curDateStr);
+
+
+
+
+        }
+//        // 余额支付金额
+//        mainOrder.setBalancePayFee(balancePayFee);
+//        // 实际支付金额(商品金额+运费-余额抵扣)
+//        mainOrder.setPayableAmount(payableAmount);
+//        // 售后条款
+//        if (payInfo.get("clauseId") != null) {
+//            ClauseVo clauseById = sellerDao.findClauseById(Integer.parseInt(payInfo.get("clauseId").toString()));
+//            if (clauseById != null) {
+//                mainOrder.setClauseID(Long.parseLong(payInfo.get("clauseId").toString()));
+//                mainOrder.setClauseName(clauseById.getName());
+//            } else {
+//                mainOrder.setClauseID(1L);
+//                mainOrder.setClauseName("无条款");
+//            }
+//        } else {
+//            mainOrder.setClauseID(1L);
+//            mainOrder.setClauseName("无条款");
+//        }
+//        // 是否返佣订单
+//        mainOrder.setRebateFlag(payInfo.get("rebateFlag") == null ? "0" : payInfo.get("rebateFlag").toString());
+//        // 判断前端传入orderShouldPayFee订单应付金额,和后台计算应付金额对比
+//        BigDecimal orderShouldPayFee = new BigDecimal(payInfo.get("orderShouldPayFee").toString());
+//        double v = MathUtil.sub(payableAmount, orderShouldPayFee).doubleValue();
+//        log.info(">>>>>payableAmount:" + payableAmount + " ,orderShouldPayFee:" + orderShouldPayFee);
+//        // 考虑前端计算不精确
+//        if (v < -0.1d || v > 0.1d) {
+//            // 设置手动回滚事务
+//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+//            return JsonModel.newInstance().error(-1, "订单付款金额异常");
+//        }
+//
+//        /*
+//         * 保存主订单数据
+//         */
+//        orderSubmitDao.insertSelective(mainOrder);
+//        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>新增主订单(insert[cm_order])orderId:" + mainOrder.getOrderID());
+//
+//        //设置订单促销订单号,并保存
+//        promotionsList.forEach(promotions -> {
+//            promotions.setOrderId(mainOrder.getOrderID().intValue());
+//            orderSubmitDao.insertOrderPromotions(promotions);
+//            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>新增订单促销活动(insert[cm_promotions_order])id:" + promotions.getId());
+//        });
+//
+//        /*
+//         * 设置订单商品订单号
+//         */
+//        for (OrderProductVo orderProduct : orderProductList) {
+//            orderProduct.setOrderID(mainOrder.getOrderID());
+//            orderProduct.setOrderNo(mainOrder.getOrderNo());
+//            PromotionsVo promotions = promotionsDao.getPromotionsByProductId(orderProduct.getProductID());
+//            if (promotions != null) {
+//                PromotionsVo promotionsVo = promotionsDao.findOrderPromotions(orderProduct.getOrderID(), promotions.getId());
+//                if (promotionsVo != null) {
+//                    orderProduct.setOrderPromotionsId(promotionsVo.getId());
+//                }
+//
+//            }
+//        }
+//
+//        /*
+//         * 整理 子订单信息
+//         */
+//        // 收集子订单供应商ID字符串
+//        String shopOrderIds = "";
+//        for (Map<String, Object> shopOrderInfo : orderInfo) {
+//            Integer shopId = (Integer) shopOrderInfo.get("shopId");
+//            String shopNote = (String) shopOrderInfo.get("note");
+//            // 初始化子订单信息
+//            ShopOrderVo shopOrder = saveShopOrder(mainOrder, orderProductList, shopId, shopNote);
+//            // 保存子订单号
+//            shopOrderIds += (("".equals(shopOrderIds) ? "" : ",") + shopOrder.getShopOrderID());
+//            // 设置订单商品子订单号
+//            for (OrderProductVo orderProduct : orderProductList) {
+//                if (shopId.longValue() == orderProduct.getShopID()) {
+//                    orderProduct.setShopOrderID(shopOrder.getShopOrderID());
+//                    orderProduct.setShopOrderNo(shopOrder.getShopOrderNo());
+//                }
+//            }
+//        }
+//        /*
+//         * 保存订单商品
+//         */
+//        StringBuilder productName = new StringBuilder();
+//        List<OrderProductLadderPriceVo> orderProductLadderPriceList = new ArrayList<>();
+//        for (OrderProductVo orderProduct : orderProductList) {
+//            productName.append(orderProduct.getName());
+//            // 保存订单商品数据
+//            orderSubmitDao.insertOrderProduct(orderProduct);
+//            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>保存订单商品(insert[cm_order_product])OrderProductID:" + orderProduct.getOrderProductID());
+//            if (orderProduct.getLadderPriceFlag() == 1) {
+//                //使用阶梯价格的订单商品保存下单时的阶梯价格列表
+//                List<LadderPriceVo> ladderPriceList = shoppingCartDao.findLadderPrice(orderProduct.getProductID());
+//                ladderPriceList.forEach(ladderPriceVo -> {
+//                    OrderProductLadderPriceVo orderProductLadderPrice = new OrderProductLadderPriceVo();
+//                    orderProductLadderPrice.setOrderProductId(orderProduct.getOrderProductID());
+//                    orderProductLadderPrice.setBuyNum(ladderPriceVo.getBuyNum().intValue());
+//                    orderProductLadderPrice.setBuyPrice(ladderPriceVo.getBuyPrice());
+//                    orderProductLadderPrice.setCreateDate(date);
+//                    orderProductLadderPrice.setLadderNum(ladderPriceVo.getLadderNum().intValue());
+//                    orderProductLadderPriceList.add(orderProductLadderPrice);
+//                });
+//            }
+//        }
+//        if (!CollectionUtils.isEmpty(orderProductLadderPriceList)) {
+//            orderProductLadderPriceList.forEach(ladderPrice -> {
+//                orderSubmitDao.insertOrderProductLadderPrice(ladderPrice);
+//            });
+//        }
+//
+//        /*
+//         * 设置邮费子订单
+//         */
+//        if ("1".equals(mainOrder.getFreePostFlag())) {
+//            shopOrderIds = setPostFeeShopOrder(mainOrder, shopOrderIds, orderInfo.size());
+//        }
+//
+//        // 更新主订单信息, 子订单ID:1000,1002
+//        mainOrder.setShopOrderIDs(shopOrderIds);
+//        orderSubmitDao.updateSelective(mainOrder);
+//
+//        /*
+//         * 保存 订单用户地址
+//         */
+//        if (null != address) {
+//            //保存地址信息
+//            UserinfoVo userInfo = new UserinfoVo();
+//            userInfo.setOrderId(mainOrder.getOrderID());
+//            userInfo.setClubId(user.getClubID().longValue());
+//            userInfo.setUserId(user.getUserID().longValue());
+//            userInfo.setName(user.getName() == null ? user.getUserName() : user.getName());
+//            userInfo.setShouHuoRen(address.getShouHuoRen());
+//            userInfo.setMobile(address.getMobile());
+//            userInfo.setPostalCode(address.getPhone());
+//            userInfo.setPostalCode(address.getPostalCode());
+//            userInfo.setTownId(address.getTownID());
+//            userInfo.setProvince(address.getProvince());
+//            userInfo.setCity(address.getCity());
+//            userInfo.setTown(address.getTown());
+//            userInfo.setAddress(address.getAddress());
+//            orderSubmitDao.insertUserInfo(userInfo);
+//            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>保存订单用户地址(insert[bp_order_userinfo])orderId:" + mainOrder.getOrderID());
+//        } else {
+//            //设置手动回滚事务
+//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+//            return JsonModel.newInstance().error("订单地址异常");
+//        }
+//
+//        /*
+//         *保存余额到余额收支记录
+//         */
+//        if (1 == balancePayFlag && MathUtil.compare(balancePayFee, 0) > 0) {
+//            // 余额支付标识,0不使用,1使用
+//            saveBalanceRecord(balancePayFee, mainOrder.getOrderID().intValue(), user.getUserID());
+//            //保存余额到收款记录
+//            if (cartType != 3) {
+//                saveDiscernReceipt(balancePayFee, mainOrder.getOrderID().intValue());
+//            }
+//        }
+//
+//        /*
+//         * 保存 订单发票信息
+//         */
+//        if (invoiceFlag) {
+//            // 开发票才保存
+//            invoice.setOrderId(mainOrder.getOrderID());
+//            // 查询是否存在老的增值税信息
+//            OrderInvoiceVo userInvoice = orderDao.getOrderInvoice(mainOrder.getOrderID().intValue());
+//            if (null != userInvoice) {
+//                // 更新 发票信息
+//                orderSubmitDao.updateOrderInvoice(invoice);
+//                log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>更新发票信息(update[bp_order_invoice])orderId:" + mainOrder.getOrderID());
+//            } else {
+//                //  保存 发票信息
+//                orderSubmitDao.insertOrderInvoice(invoice);
+//                log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>新增发票信息(insert[bp_order_invoice])orderId:" + mainOrder.getOrderID());
+//            }
+//        }
+//
+//        /*
+//         * pc商城提交订单,保存更新用户增值税发票
+//         */
+//        if ("1".equals(orderSource) && "2".equals(invoice.getType())) {
+//            InvoiceVo userInvoiceVo = new InvoiceVo();
+//            BeanUtils.copyProperties(invoice, userInvoiceVo);
+//            userInvoiceVo.setUserId(clubUserId.longValue());
+//            String userInvoiceId = String.valueOf(orderInvoice.get("id"));
+//            if (org.apache.commons.lang.StringUtils.isBlank(userInvoiceId)) {
+//                personalCenterDao.invoice(userInvoiceVo);
+//            } else {
+//                userInvoiceVo.setId(Long.valueOf(userInvoiceId));
+//                personalCenterDao.updateInvoice(userInvoiceVo);
+//            }
+//            log.info("pc商城提交订单,保存更新用户增值税发票>>>>>>>userId: " + clubUserId);
+//        }
+//
+//        //保存采美豆使用记录
+//        if (userBeans > 0) {
+//            UserBeansHistoryPo beansHistory = new UserBeansHistoryPo();
+//            beansHistory.setUserId(user.getUserID());
+//            beansHistory.setOrderId(mainOrder.getOrderID().intValue());
+//            beansHistory.setBeansType(10);
+//            beansHistory.setType(2);
+//            beansHistory.setNum(userBeans);
+//            beansHistory.setPushStatus(0);
+//            beansHistory.setAddTime(date);
+//            payDao.insertBeansHistory(beansHistory);
+//            int beans = user.getUserBeans() - userBeans;
+//            payDao.updateUserBeans(user.getUserID().longValue(), beans);
+//        }
+//
+//        log.info("******************** 提交订单逻辑处理 end *******************");
+//        /*
+//         * 构造返回参数
+//         */
+//        Map<String, String> info = new HashMap<>();
+//        info.put("orderID", String.valueOf(mainOrder.getOrderID()));
+//        info.put("orderNo", String.valueOf(mainOrder.getOrderNo()));
+//        info.put("orderMark", "#" + mainOrder.getOrderID() + "#");
+//        //应付订单金额
+//        info.put("payTotalFee", String.valueOf(mainOrder.getPayTotalFee()));
+//        //真实需要付款金额
+//        info.put("payableAmount", String.valueOf(mainOrder.getPayableAmount()));
+//
+//        //下单推送
+//        if (org.apache.commons.lang.StringUtils.isNotBlank(user.getBindMobile())) {
+//            String shortLink = orderPushService.getShortLink(8, 3, domain + "/user/mainOrder/detail.html?orderId=" + mainOrder.getOrderID());
+//            String name = productName.toString();
+//            if (name.length() > 10) {
+//                name = name.substring(0, 10);
+//            }
+//            String content = "您已成功下单“" + name + "...”等" + mainOrder.getProductCount() + "件商品,订单编号:" + mainOrder.getOrderNo() + ",订单等待支付,支付完成后采美将尽快安排发货。" +
+//                    "您可关注采美公众号或者访问采美微信小程序和网站查看并支付订单。平台公众号:微信搜索“采美365网”; 微信小程序:微信搜索“采美采购商城”;网址:www.caimei365.com/t/" + shortLink;
+//            boolean sendSms = orderPushService.getSendSms(3, user.getBindMobile(), content);
+//            if (!sendSms) {
+//                log.info("下单推送失败,orderId>>>>" + mainOrder.getOrderID());
+//            }
+//        }
+//
+//        if (isPaySuccessFlag) {
+//            // 余额抵扣成功
+//            // 1提交成功[且支付完成]
+//            info.put("code", "1");
+//            info.put("msg", "提交成功且已支付");
+//            return JsonModel.newInstance().success(info);
+//        } else {
+//            info.put("code", "2");
+//            info.put("msg", "提交成功但未支付");
+//            return JsonModel.newInstance().success(info);
+//        }
+
+
+
+
+
+
+
+
+
+
+
+
+        return null;
+    }
+
+
+
+
+
+
+
+
+}

+ 104 - 0
src/main/java/com/caimei365/order/utils/CodeUtil.java

@@ -0,0 +1,104 @@
+package com.caimei365.order.utils;
+
+import lombok.val;
+
+import java.util.Random;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/7
+ */
+public class CodeUtil {
+    /**
+     * 随机数源
+     */
+    private static final char[] INT_SEQUENCE = {'2', '3', '4', '5', '6', '7', '8', '9'};
+    /**
+     * 随机字母源
+     */
+    private static final char[] LETTER_SEQUENCE = {
+            'A', 'a', 'B', 'b', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h',
+            'L', 'N', 'n', 'Q', 'q', 'R', 'r', 'T', 't', 'Y', 'y'
+    };
+    /**
+     * 随机字符源(排除歧义字符)
+     */
+    private static final char[] CODE_SEQUENCE = {
+            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+            'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+            'W', 'X', 'Y', 'Z', '2', '3', '4', '5', '6', '7',
+            '8', '9'
+    };
+
+    /**
+     * 获取随机数字
+     * @param size 位数
+     * @return 随机数字符串
+     */
+    public static String randomInt(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < INT_SEQUENCE.length && i < size; ++i) {
+            sb.append(INT_SEQUENCE[random.nextInt(INT_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 获取随机字母
+     * @param size 位数
+     * @return 随机字母字符串
+     */
+    public static String randomLetter(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < LETTER_SEQUENCE.length && i < size; ++i) {
+            sb.append(LETTER_SEQUENCE[random.nextInt(LETTER_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 获取随机码(字母+数字)
+     * @param size 位数
+     * @return 随机码字符串
+     */
+    public static String generateCode(int size) {
+        StringBuilder sb = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < CODE_SEQUENCE.length && i < size; ++i) {
+            sb.append(CODE_SEQUENCE[random.nextInt(CODE_SEQUENCE.length)]);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * 生成主订单编号
+     * @param orderSource 订单来源:1WWW、2CRM、4客服[适用后台下单]、5外单[适用后台下单]、6小程序[采美,星范]、7呵呵商城小程序、8维沙小程序
+     * @return 主订单编号
+     */
+    public static String generateOrderNo(Integer orderSource) {
+        String platform = "";
+        if (1 == orderSource){
+            platform = "W";
+        } else if (2 == orderSource) {
+            platform = "C";
+        } else if (4 == orderSource) {
+            platform = "P";
+        } else if (5 == orderSource) {
+            platform = "T";
+        } else if (6 == orderSource) {
+            platform = "X";
+        } else if (7 == orderSource) {
+            platform = "H";
+        } else if (8 == orderSource) {
+            platform = "A";
+        } else {
+            // 未知来源
+            platform = "E";
+        }
+        return platform + System.currentTimeMillis() + randomInt(2);
+    }
+}

+ 2 - 2
src/main/java/com/caimei365/order/utils/ProductUtil.java → src/main/java/com/caimei365/order/utils/ImageUtil.java

@@ -9,9 +9,9 @@ import org.apache.commons.lang3.StringUtils;
  * @author : Charles
  * @date : 2021/6/25
  */
-public class ProductUtil {
+public class ImageUtil {
 
-    private ProductUtil(){}
+    private ImageUtil(){}
 
     public static String getImageUrl(String dirName, String src, String domain) {
         // http -> https处理

+ 1 - 4
src/main/java/com/caimei365/order/utils/MathUtil.java

@@ -107,7 +107,7 @@ public class MathUtil {
 	 *
 	 * @param v1 BigDecimal
 	 * @param v2 BigDecimal
-	 * @return int [1:v1>v2, 0:v1=v2, 1:v1<v2]
+	 * @return int [-1:v1<v2, 0:v1=v2, 1:v1>v2]
 	 */
 	public static int compare(Object v1, Object v2) {
 		BigDecimal b1 = convert(v1);
@@ -155,7 +155,4 @@ public class MathUtil {
 		return b.setScale(scale, BigDecimal.ROUND_HALF_UP);
 	}
 
-//	public static void main(String[] args){
-//	}
-
 }

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

@@ -115,7 +115,7 @@
     <select id="getPostageFlagList" resultType="com.caimei365.order.model.vo.ProductPostageVo">
         SELECT
             productID AS productId,
-            freePostFlag AS postageFlag,
+            postageFlag AS postageFlag,
             commodityType
         FROM product
         WHERE validFlag='2' AND productID in
@@ -130,6 +130,29 @@
         SELECT provinceID AS provinceId, cityID AS cityId FROM city
         WHERE cityID =(SELECT cityID from town where townID = #{townId})
     </select>
+    <select id="getTownIdByAddressId" resultType="java.lang.Integer">
+        SELECT townID FROM address WHERE addressID = #{addressId}
+    </select>
+    <!--    <select id="getAddressDetailById" resultType="com.caimei365.order.model.vo.AddressVo">-->
+<!--        SELECT-->
+<!--            a.addressID AS addressId,-->
+<!--            a.userID AS userId,-->
+<!--            a.shouHuoRen AS name,-->
+<!--            p.provinceID AS provinceId,-->
+<!--            p.name AS province,-->
+<!--            c.cityID AS cityId,-->
+<!--            c.name AS city,-->
+<!--            a.townID AS townId,-->
+<!--            t.name AS town,-->
+<!--            a.address,-->
+<!--            a.mobile,-->
+<!--            a.defaultFlag-->
+<!--        FROM address a-->
+<!--        LEFT JOIN town t ON t.townID = a.townID-->
+<!--        LEFT JOIN city c ON c.cityID = t.cityID-->
+<!--        LEFT JOIN province p ON p.provinceID = c.provinceID-->
+<!--        WHERE a.addressID = #{addressId}-->
+<!--    </select>-->
 
 
 </mapper>

+ 51 - 0
src/main/resources/mapper/SubmitMapper.xml

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.caimei365.order.mapper.SubmitMapper">
+    <select id="getOperationIdByUnionId" resultType="java.lang.Integer">
+        SELECT `id` FROM cm_mall_operation_user
+        WHERE unionId = #{unionId} AND userID = #{userId} AND delFlag = '0'
+    </select>
+    <select id="getServiceProviderUserId" resultType="java.lang.Integer">
+        select userID from serviceprovider where serviceProviderID = #{serviceProviderId}
+    </select>
+    <select id="getOrderUserBoById" resultType="com.caimei365.order.model.bo.OrderUserBo">
+        SELECT
+            userID AS userId,
+            clubID AS clubId,
+            userName,
+            bindMobile,
+            userMoney,
+            ableUserMoney,
+            userBeans
+        FROM user
+        WHERE userID = #{userID}
+    </select>
+    <select id="getShopNameById" resultType="java.lang.String">
+        SELECT `name` FROM shop WHERE shopID = #{shopId}
+    </select>
+    <select id="getProductDetails" resultType="com.caimei365.order.model.bo.ProductBo">
+        select
+            p.productID AS productId,
+            p.shopID AS shopId,
+            p.`name` AS `name`,
+            p.mainImage AS image,
+            p.price1 AS price,
+            p.costPrice,
+            p.costCheckFlag,
+            p.costProportional,
+            p.productCategory,
+            p.ladderPriceFlag,
+            p.includedTax,
+            p.invoiceType,
+            p.taxPoint AS taxRate,
+        p.unit AS productUnit,
+        p.normalPrice,
+        p.supplierTaxPoint AS shopTaxRate,
+
+
+        from product p
+        where p.productId = #{productId}
+    </select>
+
+
+</mapper>

+ 10 - 1
src/test/java/com/caimei365/order/OrderApplicationTests.java

@@ -3,6 +3,8 @@ package com.caimei365.order;
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
+import java.util.Random;
+
 /**
  * Description
  *
@@ -14,7 +16,14 @@ class OrderApplicationTests {
 
     @Test
     void contextLoads() {
-
+        Random rand = new Random();
+        String code = "";
+        for (int j = 0; j < 5; j++) {
+            code += rand.nextInt(10) + "";
+        }
+        System.out.println(code);
+        System.out.println(System.currentTimeMillis());
+        System.out.println(System.currentTimeMillis()/1000);
     }
 
 }