| package com.mzl.flower.service.payment; | 
|   | 
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
| import com.mzl.flower.constant.Constants; | 
| import com.mzl.flower.entity.flower.FlowerSupplierSaleNum; | 
| import com.mzl.flower.entity.payment.OrderItem; | 
| import com.mzl.flower.entity.payment.OrderItemCheck; | 
| import com.mzl.flower.entity.payment.OrderItemSales; | 
| import com.mzl.flower.entity.payment.OrderItemSettlement; | 
| import com.mzl.flower.entity.supplier.Station; | 
| import com.mzl.flower.mapper.flower.FlowerSupplierSaleNumMapper; | 
| import com.mzl.flower.mapper.payment.*; | 
| import com.mzl.flower.mapper.supplier.StationMapper; | 
| import com.mzl.flower.service.BaseService; | 
| import com.mzl.flower.utils.UUIDGenerator; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.scheduling.annotation.Async; | 
| import org.springframework.stereotype.Service; | 
| import org.springframework.transaction.annotation.Transactional; | 
|   | 
| import java.math.BigDecimal; | 
| import java.math.RoundingMode; | 
| import java.time.LocalDateTime; | 
| import java.util.List; | 
|   | 
|   | 
| @Slf4j | 
| @Service | 
| @Transactional | 
| public class OrderItemSettlementService extends BaseService { | 
|   | 
|     @Autowired | 
|     private OrderMapper orderMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemMapper orderItemMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemCheckMapper orderItemCheckMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemSalesMapper orderItemSalesMapper; | 
|   | 
|     @Autowired | 
|     private StationMapper stationMapper; | 
|   | 
|     @Autowired | 
|     private FlowerSupplierSaleNumMapper saleNumMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemSettlementMapper orderItemSettlementMapper; | 
|   | 
|     public void createItemSettlement(OrderItem oi){ | 
|         OrderItemSettlement ois = new OrderItemSettlement(); | 
|         ois.setId(UUIDGenerator.getUUID()); | 
|         ois.setOrderItemId(oi.getId()); | 
|         ois.setOrderId(oi.getOrderId()); | 
|         ois.setCheckNum(0); | 
|         ois.setCheckFee(new BigDecimal(0)); | 
|         ois.setReplaceNum(0); | 
|         ois.setReplaceFee(new BigDecimal(0)); | 
|         ois.setLackNum(0); | 
|         ois.setLackFeeSupplier(new BigDecimal(0)); | 
|         ois.setLackFeePartner(new BigDecimal(0)); | 
|         ois.setLackFeePlatform(new BigDecimal(0)); | 
|         ois.setServiceFeeRate(getFeeRate(oi)); | 
|         ois.setServiceFee(getServiceFee(oi, 0, 0, ois.getServiceFeeRate())); | 
|         ois.setStationFee(getStationFee(oi, 0, 0)); | 
|         ois.setSalesFeePlatform(new BigDecimal(0)); | 
|         ois.setSalesFeePartner(new BigDecimal(0)); | 
|         ois.setSalesFeeSupplier(new BigDecimal(0)); | 
|   | 
|         setSupplierIncome(oi, ois); | 
|         setPartnerIncome(oi, ois); | 
|   | 
|         ois.create("sys"); | 
|         orderItemSettlementMapper.insert(ois); | 
|     } | 
|   | 
|     public void saveItemSettlementInfo(List<String> orderIds){//在结算前使用 | 
|         List<OrderItem> ls = orderItemMapper.selectList(new QueryWrapper<OrderItem>() | 
|                 .in("order_id", orderIds)); | 
|         if(ls != null && ls.size() > 0){ | 
|             for(OrderItem oi : ls){ | 
|                 saveItemSettlementInfo(oi, "sys", Constants.S_TYPE.ALL); | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void saveItemSettlementInfo(OrderItem oi, String userId, Constants.S_TYPE sType){ | 
|         String orderItemId = oi.getId(); | 
|         OrderItemSettlement ois = orderItemSettlementMapper.selectOne(new QueryWrapper<OrderItemSettlement>() | 
|                 .eq("order_item_id", orderItemId)); | 
|         boolean isCreate = false; | 
|         if(ois == null){ | 
|             isCreate = true; | 
|             ois = new OrderItemSettlement(); | 
|             ois.setId(UUIDGenerator.getUUID()); | 
|             ois.setOrderItemId(orderItemId); | 
|             ois.setOrderId(oi.getOrderId()); | 
|         } | 
|   | 
|         if (Constants.S_TYPE.CHECK.equals(sType) || Constants.S_TYPE.ALL.equals(sType)) { | 
|             List<OrderItemCheck> orderItemCheckList = orderItemCheckMapper.selectList(new QueryWrapper<OrderItemCheck>() | 
|                     .eq("order_item_id", orderItemId) | 
|                     .eq("audit_status", Constants.CHECK_AUDIT_STATUS.AGREED.name())); | 
|             int checkNum = 0;//降级数量 | 
|             BigDecimal checkFee = new BigDecimal(0);//降级扣款 | 
|             int replaceNum = 0;//补货数量 | 
|             BigDecimal replaceFee = new BigDecimal(0);//补货扣款 | 
|             int lackNum = 0;//缺货数量 | 
|             BigDecimal lackFeeSupplier = new BigDecimal(0);//供应商缺货扣款 | 
|             BigDecimal lackFeePartner = new BigDecimal(0);//合伙人缺货扣款 | 
|             BigDecimal lackFeePlatform = new BigDecimal(0);//平台缺货扣款 | 
|             if (orderItemCheckList != null && orderItemCheckList.size() > 0) { | 
|                 for (OrderItemCheck c : orderItemCheckList) { | 
|                     Integer num = c.getNum(); | 
|                     BigDecimal amount = c.getDeductAmount(); | 
|                     String type = c.getType(); | 
|                     if (Constants.CHECK_TYPE.reduce.name().equals(type)) { | 
|                         checkNum = num == null ? 0 : num; | 
|                         checkFee = getAmount(amount); | 
|                     } else if (Constants.CHECK_TYPE.lack.name().equals(type)) { | 
|                         lackNum = num == null ? 0 : num; | 
|                         lackFeeSupplier = oi.getSupplierPrice().multiply(new BigDecimal(lackNum)); | 
|   | 
|                         BigDecimal markupPartner = getAmount(oi.getMarkupPartner()); | 
|                         lackFeePartner = markupPartner.multiply(new BigDecimal(lackNum)); | 
|   | 
|                         BigDecimal markupOne = getAmount(oi.getMarkupOne()); | 
|                         BigDecimal markupTwo = getAmount(oi.getMarkupTwo()); | 
|                         BigDecimal ppPrice = markupOne.add(markupTwo).subtract(getAmount(oi.getCouponAmount()));//1次加价+2次加价-优惠券金额 | 
|                         lackFeePlatform = lackFeePlatform.add(ppPrice.multiply(new BigDecimal(lackNum))); | 
|                     } else if (Constants.CHECK_TYPE.replace.name().equals(type)) { | 
|                         replaceNum = num == null ? 0 : num; | 
|                         replaceFee = getAmount(amount); | 
|                     } | 
|                 } | 
|             } | 
|             ois.setCheckNum(checkNum); | 
|             ois.setCheckFee(checkFee); | 
|             ois.setReplaceNum(replaceNum); | 
|             ois.setReplaceFee(replaceFee); | 
|             ois.setLackNum(lackNum); | 
|             ois.setLackFeePartner(lackFeePartner); | 
|             ois.setLackFeeSupplier(lackFeeSupplier); | 
|             ois.setLackFeePlatform(lackFeePlatform); | 
|   | 
|             Double serviceFeeRate = ois.getServiceFeeRate(); | 
|             if (serviceFeeRate == null) { | 
|                 ois.setServiceFeeRate(getFeeRate(oi)); | 
|             } | 
|             ois.setServiceFee(getServiceFee(oi, replaceNum, lackNum, ois.getServiceFeeRate()));//服务费 | 
|   | 
|             ois.setStationFee(getStationFee(oi, replaceNum, lackNum));//集货站运费 | 
|         } | 
|   | 
|         //售后计算 | 
|         if (Constants.S_TYPE.SALES.equals(sType) || Constants.S_TYPE.ALL.equals(sType)) { | 
|             List<OrderItemSales> ls = orderItemSalesMapper.selectList(new QueryWrapper<OrderItemSales>() | 
|                     .eq("order_item_id", oi.getId()) | 
|                     .eq("status", Constants.ORDER_SALES_STATUS.AGREED.name()) | 
|             ); | 
|             BigDecimal salesFeePlatform = new BigDecimal(0);//平台售后费用 | 
|             BigDecimal salesFeeSupplier = new BigDecimal(0);//供应商售后费用 | 
|             BigDecimal salesFeePartner = new BigDecimal(0);//合伙人售后费用 | 
|             if (ls != null && ls.size() > 0) { | 
|                 for (OrderItemSales s : ls) { | 
|                     BigDecimal feeSupplier = s.getFeeSupplier(); | 
|                     BigDecimal feePartner = s.getFeePartner(); | 
|                     BigDecimal feePlatform = s.getFeePlatform(); | 
|                     BigDecimal feePlatformPack = s.getFeePlatformPack(); | 
|                     BigDecimal feePlatformCheck = s.getFeePlatformCheck(); | 
|                     BigDecimal feePlatformTransport = s.getFeePlatformTransport(); | 
|                     salesFeePlatform = salesFeePlatform.add(feePlatform) | 
|                             .add(feePlatformPack).add(feePlatformCheck).add(feePlatformTransport); | 
|                     salesFeeSupplier = salesFeeSupplier.add(feeSupplier); | 
|                     salesFeePartner = salesFeePartner.add(feePartner); | 
|                 } | 
|             } | 
|             ois.setSalesFeePlatform(salesFeePlatform); | 
|             ois.setSalesFeeSupplier(salesFeeSupplier); | 
|             ois.setSalesFeePartner(salesFeePartner); | 
|         } | 
|   | 
|         setSupplierIncome(oi, ois); | 
|         setPartnerIncome(oi, ois); | 
|   | 
|         if(isCreate){ | 
|             ois.create(userId); | 
|             orderItemSettlementMapper.insert(ois); | 
|         } else { | 
|             ois.update(userId); | 
|             orderItemSettlementMapper.updateById(ois); | 
|         } | 
|     } | 
|   | 
|     private double getFeeRate(OrderItem oi){ | 
|         String yearMonth = format(LocalDateTime.now().plusMonths(-1), "yyyy-MM"); | 
|         FlowerSupplierSaleNum saleNum = saleNumMapper.selectOne(new QueryWrapper<FlowerSupplierSaleNum>() | 
|                 .eq("`year_month`", yearMonth).eq("supplier_id", oi.getSupplierId())); | 
|         double serviceFeeRate = 0D; | 
|         if (saleNum != null) { | 
|             serviceFeeRate = saleNum.getServiceFeeRate() == null ? 0D : saleNum.getServiceFeeRate(); | 
|         } | 
|   | 
|         return serviceFeeRate; | 
|     } | 
|   | 
|     private void setSupplierIncome(OrderItem oi, OrderItemSettlement ois){ | 
|         //供应商结算:商品价格-扣款-理赔-运费-服务费 = 结算金额 | 
|         //扣款包含:降级扣款、缺货扣款和补货扣款 | 
|         BigDecimal totalAmount = oi.getSupplierPrice().multiply(new BigDecimal(oi.getNum())); | 
|         BigDecimal settlementAmount = totalAmount.subtract(ois.getCheckFee()).subtract(ois.getLackFeeSupplier()) | 
|                 .subtract(ois.getReplaceFee()).subtract(ois.getSalesFeeSupplier()) | 
|                 .subtract(ois.getStationFee()).subtract(ois.getServiceFee());//结算金额 | 
|         if(settlementAmount.doubleValue() < 0){ | 
|             settlementAmount = new BigDecimal(0); | 
|         } | 
|         ois.setIncomeSupplier(settlementAmount); | 
|     } | 
|   | 
|     private void setPartnerIncome(OrderItem oi, OrderItemSettlement ois){ | 
|         //合伙人结算:合伙人加价-理赔-缺货扣款 = 结算金额 | 
|         BigDecimal markupPartner = getAmount(oi.getMarkupPartner()); | 
|         BigDecimal totalAmount = markupPartner.multiply(new BigDecimal(oi.getNum())); | 
|         BigDecimal settlementAmount = totalAmount.subtract(ois.getSalesFeePartner()).subtract(ois.getLackFeePartner());//结算金额 | 
|         if(settlementAmount.doubleValue() < 0){ | 
|             settlementAmount = new BigDecimal(0); | 
|         } | 
|         ois.setIncomePartner(settlementAmount); | 
|     } | 
|   | 
|     private BigDecimal getServiceFee(OrderItem oi, int replaceNum, int lackNum, double serviceFeeRate){ | 
|         int num = oi.getNum() - replaceNum - lackNum; | 
|         if(num <= 0){ | 
|             return new BigDecimal(0); | 
|         } | 
|         BigDecimal totalAmount = oi.getSupplierPrice().multiply(new BigDecimal(num)); | 
|   | 
|         return totalAmount.multiply(new BigDecimal(serviceFeeRate)) | 
|                 .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP); | 
|     } | 
|   | 
|     private BigDecimal getStationFee(OrderItem oi, int replaceNum, int lackNum){ | 
|         Long stationId = oi.getStationId(); | 
|         BigDecimal fee = new BigDecimal(0); | 
|         if(stationId != null) {//集货站运费按每扎算 | 
|             Station station = stationMapper.selectById(stationId); | 
|             if(station != null && station.getFreight() != null){ | 
|                 int num = oi.getNum() - replaceNum - lackNum; | 
|                 if(num > 0) { | 
|                     fee = station.getFreight().multiply(new BigDecimal(num)); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         return fee; | 
|     } | 
| } |