plf 4 lat temu
rodzic
commit
46d45566c6

+ 21 - 1
base-module/src/main/java/com/caimei/module/base/entity/po/CmSplitAccount.java

@@ -25,7 +25,17 @@ public class CmSplitAccount implements Serializable {
     private Integer productId;
 
     /**
-     * 分账类型:1公账-专票,2私账-无票,3公账-普票
+     * 订单商品id
+     */
+    private Integer orderProductId;
+
+    /**
+     * 供应商id
+     */
+    private Integer shopId;
+
+    /**
+     * 分账类型:1公账-专票,2私账-无票,3公账-普票,4供应商子商户
      */
     private String type;
 
@@ -39,6 +49,11 @@ public class CmSplitAccount implements Serializable {
      */
     private BigDecimal splitAccount;
 
+    /**
+     * 分账手续费
+     */
+    private BigDecimal handlingFee;
+
     /**
      * 米花科技平台唯一流水号
      */
@@ -54,5 +69,10 @@ public class CmSplitAccount implements Serializable {
      */
     private String payStatus;
 
+    /**
+     * 商品类型:1商品成本,2供应商运费,3佣金,4二手发布
+     */
+    private String productType;
+
     private static final long serialVersionUID = 1L;
 }

+ 1 - 1
base-module/src/main/java/com/caimei/module/base/entity/vo/SplitAccount.java → base-module/src/main/java/com/caimei/module/base/entity/vo/SplitAccountVo.java

@@ -12,5 +12,5 @@ import lombok.EqualsAndHashCode;
  */
 @EqualsAndHashCode(callSuper = true)
 @Data
-public class SplitAccount extends CmSplitAccount {
+public class SplitAccountVo extends CmSplitAccount {
 }

+ 34 - 1
pay/src/main/java/com/caimei/module/pay/dao/PayDao.java

@@ -40,7 +40,7 @@ public interface PayDao {
 
     void updateSeconHand(SeconHandProduct seconHandProduct);
 
-    void insertSplitAccount(SplitAccount splitAccount);
+    void insertSplitAccount(SplitAccountVo splitAccount);
 
     void updateSplitAccountByPay(String mbOrderId);
 
@@ -64,4 +64,37 @@ public interface PayDao {
      * 获取线上支付开关状态
      */
     Integer getPayOnLineSwitch();
+
+    /**
+     * 查询子商户商编
+     *
+     * @param shopId
+     * @return
+     */
+    String findCommercialCode(Long shopId);
+
+    /**
+     * 查询已支付金额
+     *
+     * @param orderProductId
+     * @return
+     */
+    BigDecimal findPaidAmount(Integer orderProductId);
+
+    /**
+     * 查询子订单
+     *
+     * @param orderId
+     * @return
+     */
+    List<ShopOrderVo> findShopOrder(Long orderId);
+
+    /**
+     * 查询已支付运费
+     *
+     * @param orderId
+     * @param shopId
+     * @return
+     */
+    BigDecimal findShipping(@Param("orderId") Long orderId, @Param("shopId") Integer shopId);
 }

+ 203 - 43
pay/src/main/java/com/caimei/module/pay/service/impl/PayServiceImpl.java

@@ -1,7 +1,6 @@
 package com.caimei.module.pay.service.impl;
 
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.caimei.module.base.entity.bo.JsonModel;
 import com.caimei.module.base.entity.bo.Payment;
@@ -145,7 +144,7 @@ public class PayServiceImpl implements PayService {
         if (MathUtil.compare(MathUtil.mul(order.getPayableAmount(), 100), payment.getPayAmount()) < 0) {
             return model.error("付款金额错误");
         }
-        String splitBillDetail = null;
+        List<SplitAccountVo> splitBillDetail = null;
         try {
             // 时间戳
             long time = System.currentTimeMillis() / 1000;
@@ -160,8 +159,8 @@ public class PayServiceImpl implements PayService {
             json.put("attach", attach);
             //分账详情
             splitBillDetail = splitBillDetail(order, payment);
-            log.info("分账详情>>>>>>>单位/分>>>" + splitBillDetail);
-            json.put("splitBillDetail", splitBillDetail);
+            String parameters = ledgerParameters(splitBillDetail, order.getOrderID());
+            json.put("splitBillDetail", parameters);
             String sign = PayUtils.buildSign(json, merKey);
             json.put("sign", sign);
             String data = PayUtils.buildDataPrivate(json, merKey);
@@ -178,43 +177,66 @@ public class PayServiceImpl implements PayService {
         }
 
         //保存分账信息
-        saveSplitBillDetail(splitBillDetail, result, payment);
+        saveSplitBillDetail(splitBillDetail, result);
         return model.success(result);
     }
 
+    /**
+     * 整理第三方支付详情参数
+     */
+    private String ledgerParameters(List<SplitAccountVo> splitBillDetail, Long orderId) {
+        List<Map<String, String>> maps = new ArrayList<>();
+        List<ShopOrderVo> shopOrderList = payDao.findShopOrder(orderId);
+        //供应商子商户总金额
+        for (ShopOrderVo shopOrder : shopOrderList) {
+            BigDecimal shopTotalAmount = BigDecimal.ZERO;
+            String subUserNo = "";
+            for (SplitAccountVo account : splitBillDetail) {
+                if ("4".equals(account.getType()) && shopOrder.getShopID().equals(account.getShopId())) {
+                    shopTotalAmount = MathUtil.add(shopTotalAmount, account.getSplitAccount());
+                    subUserNo = account.getSubUserNo();
+                }
+            }
+            addMaps(maps, shopTotalAmount, subUserNo);
+        }
+        //公账-专票总金额,私账-无票总金额,公账-普票总金额
+        BigDecimal totalAmount1 = BigDecimal.ZERO;
+        BigDecimal totalAmount2 = BigDecimal.ZERO;
+        BigDecimal totalAmount3 = BigDecimal.ZERO;
+        for (SplitAccountVo account : splitBillDetail) {
+            if ("1".equals(account.getType())) {
+                totalAmount1 = MathUtil.add(totalAmount1, account.getSplitAccount());
+            } else if ("2".equals(account.getType())) {
+                totalAmount2 = MathUtil.add(totalAmount2, account.getSplitAccount());
+            } else if ("3".equals(account.getType())) {
+                totalAmount3 = MathUtil.add(totalAmount3, account.getSplitAccount());
+            }
+        }
+        addMaps(maps, totalAmount1, publicAccountNo);
+        addMaps(maps, totalAmount2, privateAccountNo);
+        addMaps(maps, totalAmount3, commonInvoiceNo);
+        return JSON.toJSONString(maps);
+    }
+
+    private void addMaps(List<Map<String, String>> maps, BigDecimal shopTotalAmount, String subUserNo) {
+        if (MathUtil.compare(shopTotalAmount, 0) > 0) {
+            Map<String, String> map = new HashMap<>(3);
+            map.put("subUserNo", subUserNo);
+            map.put("splitBillType", "2");
+            map.put("splitBillValue", MathUtil.mul(shopTotalAmount, 100).toString());
+            maps.add(map);
+        }
+    }
+
     /**
      * 保存分账信息
      */
-    private void saveSplitBillDetail(String splitBillDetail, JSONObject result, Payment payment) {
-        JSONArray parseArray = JSON.parseArray(splitBillDetail);
+    private void saveSplitBillDetail(List<SplitAccountVo> splitBillDetail, JSONObject result) {
         JSONObject data = result.getJSONObject("data");
         String mbOrderId = data.getString("mbOrderId");
         String orderRequestNo = data.getString("orderId");
-        for (int i = 0; i < parseArray.size(); i++) {
-            String subUserNo = parseArray.getJSONObject(i).getString("subUserNo");
-            String splitBillType = parseArray.getJSONObject(i).getString("splitBillType");
-            String splitBillValue = parseArray.getJSONObject(i).getString("splitBillValue");
-            SplitAccount splitAccount = new SplitAccount();
+        for (SplitAccountVo splitAccount : splitBillDetail) {
             splitAccount.setMbOrderId(mbOrderId);
-            if (subUserNo.equals(publicAccountNo)) {
-                splitAccount.setType("1");
-            } else if (subUserNo.equals(privateAccountNo)) {
-                splitAccount.setType("2");
-            } else {
-                splitAccount.setType("3");
-            }
-            splitAccount.setSubUserNo(subUserNo);
-            if ("1".equals(splitBillType)) {
-                splitAccount.setProductId(payment.getProductId());
-                if ("UNIONPAY".equals(payment.getPayWay())) {
-                    splitAccount.setSplitAccount(BigDecimal.valueOf(92));
-                } else {
-                    splitAccount.setSplitAccount(BigDecimal.valueOf(99.62));
-                }
-            } else {
-                splitAccount.setOrderId(payment.getOrderId());
-                splitAccount.setSplitAccount(MathUtil.div(splitBillValue, 100));
-            }
             splitAccount.setOrderRequestNo(orderRequestNo);
             splitAccount.setPayStatus("0");
             payDao.insertSplitAccount(splitAccount);
@@ -252,24 +274,143 @@ public class PayServiceImpl implements PayService {
     /**
      * 分账详情
      */
-    private String splitBillDetail(OrderVo order, Payment payment) {
-        List<Map<String, String>> list = new ArrayList<>();
-        //分账金额
-        BigDecimal fashionableAmount = BigDecimal.ZERO;
+    private List<SplitAccountVo> splitBillDetail(OrderVo order, Payment payment) {
+        List<SplitAccountVo> list = new ArrayList<>();
         //本次支付金额,单位/元
         BigDecimal payAmount = MathUtil.div(payment.getPayAmount(), 100);
+        //待分账总金额
+        BigDecimal splitAmount = payAmount;
+        //总手续费
+        BigDecimal procedureFee;
         if ("UNIONPAY".equals(payment.getPayWay())) {
-            fashionableAmount = MathUtil.sub(payAmount, 8);
+            procedureFee = new BigDecimal(8);
         } else {
             //手续费
-            BigDecimal procedureFee = MathUtil.mul(payAmount, 0.0038, 2);
+            procedureFee = MathUtil.mul(payAmount, 0.0038, 2);
             if (MathUtil.compare(procedureFee, 0) == 0) {
-                fashionableAmount = MathUtil.sub(payAmount, 0.01);
-            } else {
-                fashionableAmount = MathUtil.sub(payAmount, procedureFee);
+                procedureFee = new BigDecimal("0.01");
             }
         }
+        //剩余手续费
+        BigDecimal remainingFee = procedureFee;
         List<OrderProductVo> orderProductList = payDao.fandAllOrderProduct(order.getOrderID().intValue());
+        for (OrderProductVo orderProduct : orderProductList) {
+            BigDecimal costPrice = MathUtil.mul(orderProduct.getCostPrice(), orderProduct.getNum());
+            //不含税能开发票
+            if ("0".equals(orderProduct.getIncludedTax()) && !"3".equals(orderProduct.getInvoiceType())) {
+                //应付总税费
+                BigDecimal payableTax = MathUtil.mul(orderProduct.getSingleShouldPayTotalTax(), orderProduct.getNum());
+                costPrice = MathUtil.add(costPrice, payableTax);
+            }
+            //判断是否支付过
+            BigDecimal paidAmount = payDao.findPaidAmount(orderProduct.getOrderProductID());
+            if (paidAmount == null || MathUtil.compare(paidAmount, costPrice) < 0) {
+                if (paidAmount != null && MathUtil.compare(paidAmount, 0) > 0) {
+                    costPrice = MathUtil.sub(costPrice, paidAmount);
+                }
+                //本次分账手续费
+                BigDecimal handlingFee;
+                //待分账金额>=本次待分账金额
+                if (MathUtil.compare(splitAmount, costPrice) > -1) {
+                    handlingFee = MathUtil.mul(procedureFee, MathUtil.div(costPrice, payAmount, 2), 2);
+                    splitAmount = MathUtil.sub(splitAmount, costPrice);
+                } else {
+                    costPrice = splitAmount;
+                    handlingFee = MathUtil.mul(procedureFee, MathUtil.div(costPrice, payAmount, 2), 2);
+                    splitAmount = BigDecimal.ZERO;
+                }
+                costPrice = MathUtil.sub(costPrice, handlingFee);
+                remainingFee = MathUtil.sub(remainingFee, handlingFee);
+                String commercialCode = payDao.findCommercialCode(orderProduct.getShopID());
+                SplitAccountVo splitAccount = new SplitAccountVo();
+                splitAccount.setOrderId(order.getOrderID().intValue());
+                splitAccount.setOrderProductId(orderProduct.getOrderProductID());
+                splitAccount.setShopId(orderProduct.getShopID().intValue());
+                splitAccount.setSplitAccount(costPrice);
+                splitAccount.setHandlingFee(handlingFee);
+                splitAccount.setProductType("1");
+                if (StringUtils.isNotBlank(commercialCode)) {
+                    //供应商拥有子商户号
+                    splitAccount.setType("4");
+                    splitAccount.setSubUserNo(commercialCode);
+                } else {
+                    if ("3".equals(orderProduct.getInvoiceType())) {
+                        //不能开票,则分账到私账-无票
+                        splitAccount.setType("2");
+                        splitAccount.setSubUserNo(privateAccountNo);
+                    } else if ("1".equals(orderProduct.getInvoiceType())) {
+                        //开增值税发票,则分账到公账-专票
+                        splitAccount.setType("1");
+                        splitAccount.setSubUserNo(publicAccountNo);
+                    } else if ("2".equals(orderProduct.getInvoiceType())) {
+                        //开普通发票,则分账到公账-普票
+                        splitAccount.setType("3");
+                        splitAccount.setSubUserNo(commonInvoiceNo);
+                    }
+                }
+                list.add(splitAccount);
+                if (MathUtil.compare(splitAmount, 0) == 0) {
+                    break;
+                }
+            }
+        }
+
+        //付供应商运费,是以供应商为单位的
+        if (MathUtil.compare(splitAmount, 0) > 0) {
+            List<ShopOrderVo> shopOrderList = payDao.findShopOrder(order.getOrderID());
+            for (ShopOrderVo shopOrder : shopOrderList) {
+                //运费
+                BigDecimal shopPostFee = shopOrder.getShopPostFee();
+                //本次分账手续费
+                BigDecimal handlingFee;
+                if (MathUtil.compare(shopPostFee, 0) > 0) {
+                    BigDecimal shipping = payDao.findShipping(order.getOrderID(), shopOrder.getShopID());
+                    shopPostFee = MathUtil.sub(shopPostFee, shipping);
+                    if (MathUtil.compare(splitAmount, shopPostFee) > -1) {
+                        handlingFee = MathUtil.mul(procedureFee, MathUtil.div(shopPostFee, payAmount, 2), 2);
+                        splitAmount = MathUtil.sub(splitAmount, shipping);
+                    } else {
+                        shopPostFee = splitAmount;
+                        handlingFee = MathUtil.mul(procedureFee, MathUtil.div(splitAmount, payAmount, 2), 2);
+                        splitAmount = BigDecimal.ZERO;
+                    }
+                    shopPostFee = MathUtil.sub(shopPostFee, handlingFee);
+                    remainingFee = MathUtil.sub(remainingFee, handlingFee);
+                    String commercialCode = payDao.findCommercialCode(Long.valueOf(shopOrder.getShopID()));
+                    SplitAccountVo splitAccount = new SplitAccountVo();
+                    splitAccount.setOrderId(order.getOrderID().intValue());
+                    splitAccount.setShopId(shopOrder.getShopID());
+                    splitAccount.setSplitAccount(shopPostFee);
+                    splitAccount.setHandlingFee(handlingFee);
+                    splitAccount.setProductType("2");
+                    if (StringUtils.isNotBlank(commercialCode)) {
+                        //供应商拥有子商户号
+                        splitAccount.setType("4");
+                        splitAccount.setSubUserNo(commercialCode);
+                    } else {
+                        //私账
+                        splitAccount.setType("2");
+                        splitAccount.setSubUserNo(privateAccountNo);
+                    }
+                    list.add(splitAccount);
+                }
+            }
+        }
+
+        //佣金,私账
+        if (MathUtil.compare(splitAmount, 0) > 0) {
+            SplitAccountVo splitAccount = new SplitAccountVo();
+            splitAccount.setOrderId(order.getOrderID().intValue());
+            splitAccount.setSplitAccount(splitAmount);
+            splitAccount.setHandlingFee(remainingFee);
+            splitAccount.setProductType("3");
+            splitAccount.setType("2");
+            splitAccount.setSubUserNo(privateAccountNo);
+            list.add(splitAccount);
+        }
+        return list;
+
+        /*List<OrderProductVo> orderProductList = payDao.fandAllOrderProduct(order.getOrderID().intValue());
         //私账-无票总金额
         BigDecimal privateAccountAmount = BigDecimal.ZERO;
         //公账-普票总金额
@@ -330,8 +471,8 @@ public class PayServiceImpl implements PayService {
                 map2.put("splitBillValue", String.valueOf(splitBillValue));
                 list.add(map2);
             }
-        }
-        return JSONObject.toJSONString(list);
+        }*/
+        //return JSONObject.toJSONString(list);
     }
 
     @Override
@@ -670,7 +811,26 @@ public class PayServiceImpl implements PayService {
             log.info("第三方支付失败>>>>>>>msg:" + msg);
             return model.error(msg);
         }
-        saveSplitBillDetail(splitBillDetail, result, payment);
+        //保存二手发布分账参数
+        SplitAccountVo splitAccount = new SplitAccountVo();
+        splitAccount.setOrderId(payment.getOrderId());
+        splitAccount.setProductId(payment.getProductId());
+        //二手交易供应商
+        splitAccount.setShopId(1252);
+        splitAccount.setProductType("4");
+        splitAccount.setType("2");
+        if ("UNIONPAY".equals(payment.getPayWay())) {
+            splitAccount.setSplitAccount(BigDecimal.valueOf(92));
+            splitAccount.setHandlingFee(new BigDecimal(8));
+        } else {
+            splitAccount.setSplitAccount(BigDecimal.valueOf(99.62));
+            splitAccount.setHandlingFee(new BigDecimal("0.38"));
+        }
+        JSONObject data = result.getJSONObject("data");
+        splitAccount.setMbOrderId(data.getString("mbOrderId"));
+        splitAccount.setOrderRequestNo(data.getString("orderId"));
+        splitAccount.setPayStatus("0");
+        payDao.insertSplitAccount(splitAccount);
         return model.success(result);
     }
 

+ 45 - 7
pay/src/main/resources/com-caimei-module-pay/PayMapper.xml

@@ -352,7 +352,7 @@
     </select>
 
     <select id="fandAllOrderProduct" resultType="com.caimei.module.base.entity.vo.OrderProductVo">
-        SELECT * FROM cm_order_product WHERE orderID = #{orderId}
+        SELECT * FROM cm_order_product WHERE orderID = #{orderId} ORDER BY shopID ASC, productID ASC
     </select>
 
     <select id="findUser" resultType="com.caimei.module.base.entity.vo.UserVo">
@@ -381,12 +381,19 @@
     </update>
 
     <insert id="insertSplitAccount" keyColumn="id" keyProperty="id" parameterType="com.caimei.module.base.entity.po.CmSplitAccount" useGeneratedKeys="true">
-    insert into cm_split_account (orderId, productId, `type`, subUserNo,
-      splitAccount, mbOrderId, orderRequestNo,
-      payStatus)
-    values (#{orderId}, #{productId}, #{type}, #{subUserNo},
-      #{splitAccount}, #{mbOrderId}, #{orderRequestNo},
-      #{payStatus})
+        INSERT INTO `cm_split_account` (
+          `orderId`, `productId`, `orderProductId`,
+          `shopId`, `type`, `subUserNo`, `splitAccount`,
+          `handlingFee`, `mbOrderId`, `orderRequestNo`,
+          `payStatus`, `productType`
+        )
+        VALUES
+          (
+            #{orderId}, #{productId}, #{orderProductId},
+            #{shopId}, #{type}, #{subUserNo}, #{splitAccount},
+            #{handlingFee}, #{mbOrderId}, #{orderRequestNo},
+            #{payStatus}, #{productType}
+          );
     </insert>
 
     <update id="updateSplitAccountByPay">
@@ -421,4 +428,35 @@
             #{delFlag}
           )
     </insert>
+
+    <select id="findCommercialCode" resultType="string">
+        SELECT commercialCode FROM shop WHERE shopID = #{shopId}
+    </select>
+
+    <select id="findPaidAmount" resultType="java.math.BigDecimal">
+        SELECT
+          SUM(splitAccount + handlingFee)
+        FROM
+          cm_split_account
+        WHERE
+          orderProductId = #{orderProductId}
+          AND payStatus = 1
+          AND productType = 1
+    </select>
+
+    <select id="findShopOrder" resultType="com.caimei.module.base.entity.vo.ShopOrderVo">
+        SELECT * FROM cm_shop_order WHERE orderID = #{orderId}
+    </select>
+
+    <select id="findShipping" resultType="java.math.BigDecimal">
+        SELECT
+          SUM(splitAccount + handlingFee)
+        FROM
+          cm_split_account
+        WHERE
+          orderId = #{orderId}
+          AND shopId = #{shopId}
+          AND productType = 2
+          AND payStatus = 1
+    </select>
 </mapper>