| package com.mzl.flower.service.payment; | 
|   | 
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
| import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | 
| import com.mzl.flower.config.PyamentV3Configurer; | 
| import com.mzl.flower.config.exception.ValidationException; | 
| import com.mzl.flower.config.security.SecurityUtils; | 
| import com.mzl.flower.constant.Constants; | 
| import com.mzl.flower.dto.request.payment.*; | 
| import com.mzl.flower.dto.response.payment.OrderSettlementDTO; | 
| import com.mzl.flower.dto.response.payment.OrderSettlementDetailDTO; | 
| import com.mzl.flower.dto.response.payment.OrderSettlementListDTO; | 
| import com.mzl.flower.entity.flower.FlowerSupplierSaleNum; | 
| import com.mzl.flower.entity.partner.Partner; | 
| import com.mzl.flower.entity.payment.*; | 
| import com.mzl.flower.entity.supplier.Station; | 
| import com.mzl.flower.entity.supplier.Supplier; | 
| import com.mzl.flower.entity.system.UserWechat; | 
| import com.mzl.flower.mapper.flower.FlowerSupplierSaleNumMapper; | 
| import com.mzl.flower.mapper.payment.*; | 
| import com.mzl.flower.mapper.supplier.StationMapper; | 
| import com.mzl.flower.mapper.system.UserWechatMapper; | 
| import com.mzl.flower.service.BaseService; | 
| import com.mzl.flower.utils.UUIDGenerator; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.beans.BeanUtils; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| 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.*; | 
|   | 
| @Slf4j | 
| @Service | 
| @Transactional | 
| public class OrderSettlementService extends BaseService { | 
|   | 
|     @Autowired | 
|     private OrderSettlementMapper settlementMapper; | 
|   | 
|     @Autowired | 
|     private OrderSettlementDetailMapper settlementDetailMapper; | 
|   | 
|     @Autowired | 
|     private OrderMapper orderMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemMapper orderItemMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemCheckMapper orderItemCheckMapper; | 
|   | 
|     @Autowired | 
|     private UserWechatMapper wechatMapper; | 
|   | 
|     @Autowired | 
|     private FeeServiceMapper feeServiceMapper; | 
|   | 
|     @Autowired | 
|     private OrderItemSalesMapper orderItemSalesMapper; | 
|   | 
|     @Autowired | 
|     private StationMapper stationMapper; | 
|   | 
|     @Autowired | 
|     private FlowerSupplierSaleNumMapper saleNumMapper; | 
|   | 
|     @Autowired | 
|     private UserPaymentV3Service paymentV3Service; | 
|   | 
|     @Autowired | 
|     private OrderItemSettlementMapper orderItemSettlementMapper; | 
|   | 
|     @Autowired | 
|     private TransferMapper transferMapper; | 
|   | 
|     @Autowired | 
|     private TransferDetailMapper transferDetailMapper; | 
|   | 
|     public Page<OrderSettlementListDTO> selectSettlementList(Page page, OrderSettlementQueryDTO dto){ | 
|         dto.setStartDate(parseLocalDateTime(dto.getStartDateStr(), true)); | 
|         dto.setEndDate(parseLocalDateTime(dto.getEndDateStr(), false)); | 
|   | 
|         List<OrderSettlementListDTO> ls = settlementMapper.selectSettlementList(page, dto); | 
|   | 
|         page.setRecords(ls); | 
|         return page; | 
|     } | 
|   | 
|     public OrderSettlementDTO getSettlement(String id){ | 
|         OrderSettlementDTO dto = new OrderSettlementDTO(); | 
|         OrderSettlement settlement = settlementMapper.selectById(id); | 
|         if(settlement == null){ | 
|             throw new ValidationException("结算单不存在"); | 
|         } | 
|         BeanUtils.copyProperties(settlement, dto); | 
|   | 
|         String userName; | 
|         if(Constants.SETTLEMENT_TYPE.supplier.name().equals(dto.getType())){ | 
|             Supplier s = supplierMapper.selectOne(new QueryWrapper<Supplier>() | 
|                     .eq("user_id", settlement.getUserId())); | 
|             userName = s.getName(); | 
|         } else { | 
|             Partner p = partnerMapper.selectOne(new QueryWrapper<Partner>() | 
|                     .eq("user_id", settlement.getUserId())); | 
|             userName = p.getName(); | 
|         } | 
|         dto.setUserName(userName); | 
|   | 
|         List<OrderSettlementDetailDTO> details = settlementDetailMapper.selectSettlementDetailList(id); | 
|         dto.setDetails(details); | 
|   | 
|         return dto; | 
|     } | 
|   | 
|     public void doSettlementTransfer(String id){ | 
|         OrderSettlement settlement = settlementMapper.selectById(id); | 
|         if(settlement == null){ | 
|             throw new ValidationException("结算单不存在"); | 
|         } | 
|         String status = settlement.getStatus(); | 
|         if(Constants.SETTLEMENT_STATUS.PROCESSING.name().equals(status)){ | 
|             throw new ValidationException("结算中,不用重复结算"); | 
|         } | 
|         if(Constants.SETTLEMENT_STATUS.COMPLETED.name().equals(status)){ | 
|             throw new ValidationException("结算成功,不用重复结算"); | 
|         } | 
|         String type = settlement.getType(); | 
|   | 
|         String name = ""; | 
|         if(Constants.SETTLEMENT_TYPE.supplier.name().equals(type)){ | 
|             Supplier s = supplierMapper.selectOne(new QueryWrapper<Supplier>() | 
|                     .eq("user_id", settlement.getUserId())); | 
|             name = "供应商" + s.getName(); | 
|         } else { | 
|             Partner p = partnerMapper.selectOne(new QueryWrapper<Partner>() | 
|                     .eq("user_id", settlement.getUserId())); | 
|             name = "合伙人" + p.getName(); | 
|         } | 
|   | 
|         UserWechat wechat = wechatMapper.selectOne(new QueryWrapper<UserWechat>() | 
|                 .eq("user_id", settlement.getUserId())); | 
|         if(wechat == null){ | 
|             String msg = name + "未绑定账号无法结算"; | 
|             log.error(msg); | 
|             throw new ValidationException(msg); | 
|         } | 
|         settlement.setOpenId(wechat.getOpenId()); | 
|   | 
|         LocalDateTime now = LocalDateTime.now(); | 
|         String day = format(now, "yyyy-MM-dd"); | 
|   | 
|         String remarks = name + "账单结算"; | 
|   | 
|         String appId = Constants.SETTLEMENT_TYPE.supplier.name().equals(type) | 
|                 ? PyamentV3Configurer.supplier_app_id : PyamentV3Configurer.partner_app_id; | 
|   | 
|         TransferReqDTO transferReqDTO = new TransferReqDTO(); | 
|         transferReqDTO.setId(UUIDGenerator.getUUID()); | 
|         transferReqDTO.setAppId(appId); | 
|         transferReqDTO.setName(day + "日" + remarks); | 
|         transferReqDTO.setRemarks(remarks); | 
|   | 
|         settlement.setTransferId(transferReqDTO.getId()); | 
|   | 
|         BigDecimal settlementAmount = settlement.getSettlementAmount(); | 
|         if(settlementAmount.doubleValue() > 0) {//结算金额>0时才去转账 | 
|             TransferDetailReqDTO dr = new TransferDetailReqDTO(); | 
|             dr.setId(UUIDGenerator.getUUID()); | 
|             dr.setAmount(settlementAmount.multiply(new BigDecimal(100)).longValue()); | 
|             dr.setOpenId(settlement.getOpenId()); | 
|             dr.setRemarks(remarks); | 
|             if (settlementAmount.doubleValue() >= 2000) { | 
|                 dr.setUserName(wechat.getRealName()); | 
|             } | 
|   | 
|             List<TransferDetailReqDTO> details = new ArrayList<>(); | 
|             details.add(dr); | 
|   | 
|             settlement.setTransferDetailId(dr.getId()); | 
|   | 
|             log.info("发起转账"); | 
|             transferReqDTO.setDetails(details); | 
|             paymentV3Service.doBatchTransfer(transferReqDTO, SecurityUtils.getUserId()); //发起转账 | 
|         } | 
|   | 
|         settlement.setTransferTime(LocalDateTime.now()); | 
|         settlement.setStatus(Constants.SETTLEMENT_STATUS.PROCESSING.name()); | 
|         settlement.update(SecurityUtils.getUserId()); | 
|   | 
|         settlementMapper.updateById(settlement); | 
|     } | 
|   | 
|     public void updateSettlementStatus(String transferId){ | 
|         Transfer t  = transferMapper.selectById(transferId); | 
|         if("FINISHED".equals(t.getStatus())){ | 
|             OrderSettlement settlement = settlementMapper.selectOne(new QueryWrapper<OrderSettlement>() | 
|                     .eq("transfer_id", transferId)); | 
|             if(settlement == null){ | 
|                 return; | 
|             } | 
|             String transferDetailId = settlement.getTransferDetailId(); | 
|             TransferDetail td = transferDetailMapper.selectById(transferDetailId); | 
|             if(td == null){ | 
|                 log.warn("未找到对应明细"); | 
|                 return; | 
|             } | 
|             String dStatus = td.getStatus(); | 
|             if("SUCCESS".equals(dStatus)){ | 
|                 settlement.setStatus(Constants.SETTLEMENT_STATUS.COMPLETED.name()); | 
|                 settlement.update("sys"); | 
|                 settlementMapper.updateById(settlement); | 
|             } else if ("FAIL".equals(dStatus)){ | 
|                 settlement.setStatus(Constants.SETTLEMENT_STATUS.FAILED.name()); | 
|                 settlement.update("sys"); | 
|                 settlementMapper.updateById(settlement); | 
|             } | 
|         } | 
|     } | 
|   | 
|     public void doSettlement(){//弃用 | 
|         //结算完成收货的订单 | 
|         List<Order> ls = orderMapper.getOrderForSettlement(); | 
|         if(ls == null || ls.size() == 0){ | 
|             return; | 
|         } | 
|   | 
|         List<Station> stations = stationMapper.selectList(null); | 
|         Map<Long, BigDecimal> stationMap = new HashMap<>(); | 
|         for(Station s : stations){ | 
|             BigDecimal freight = s.getFreight(); | 
|             stationMap.put(s.getId(), freight == null ? new BigDecimal(0) : freight); | 
|         } | 
|   | 
|         List<String> orderIdsAll = new ArrayList<>(); | 
|         List<String> orderIdsPartner = new ArrayList<>(); | 
|         Map<String, Order> orderMap = new HashMap<>(); | 
|         Set<Long> partnerIds = new HashSet<>(); | 
|         for(Order o : ls){ | 
|             String orderId = o.getId(); | 
|             orderIdsAll.add(orderId); | 
|             orderMap.put(orderId, o); | 
|             Long partnerId = o.getPartnerId(); | 
|             if(partnerId != null){ | 
|                 orderIdsPartner.add(orderId); | 
|                 partnerIds.add(partnerId); | 
|             } | 
|         } | 
|   | 
|         Map<Long, Partner> partnerMap = new HashMap<>(); | 
|   | 
|         if(partnerIds.size() > 0){ | 
|             List<Partner> pLs = partnerMapper.selectBatchIds(partnerIds); | 
|             for(Partner p : pLs){ | 
|                 partnerMap.put(p.getId(), p); | 
|             } | 
|         } | 
|   | 
|         List<OrderItem> orderItems = orderItemMapper.selectList(new QueryWrapper<OrderItem>() | 
|                 .in("order_id", orderIdsAll)); | 
|         List<String> itemIdsAll = new ArrayList<>(); | 
|         Map<String, OrderItem> orderItemMap = new HashMap<>(); | 
|         Map<Long, List<String>> supplierItemMap = new HashMap<>(); | 
|         Map<Long, List<String>> partnerItemMap = new HashMap<>(); | 
|         Set<Long> supplierIds = new HashSet<>(); | 
|         for(OrderItem oi : orderItems){ | 
|             String id = oi.getId(); | 
|             itemIdsAll.add(id); | 
|             orderItemMap.put(id, oi); | 
|             if(orderIdsPartner.contains(oi.getOrderId())){ | 
|                 Order o = orderMap.get(oi.getOrderId()); | 
|                 Long partnerId = o.getPartnerId(); | 
|                 List<String> piIds = partnerItemMap.computeIfAbsent(partnerId, k -> new ArrayList<>()); | 
|                 piIds.add(id); | 
|             } | 
|             Long supplierId = oi.getSupplierId(); | 
|             List<String> siIds = supplierItemMap.computeIfAbsent(supplierId, k -> new ArrayList<>()); | 
|             siIds.add(id); | 
|             supplierIds.add(supplierId); | 
|         } | 
|   | 
|         List<OrderItemCheck> orderItemCheckList = orderItemCheckMapper.selectList(new QueryWrapper<OrderItemCheck>() | 
|                 .in("order_id", orderIdsAll) | 
|                 .eq("audit_status", Constants.CHECK_AUDIT_STATUS.AGREED.name()) | 
|         ); | 
|         Map<String, BigDecimal> replaceMap = new HashMap<>(); | 
|         Map<String, BigDecimal> reduceMap = new HashMap<>(); | 
|         Map<String, BigDecimal> lackSupplierMap = new HashMap<>(); | 
|         Map<String, BigDecimal> lackPartnerMap = new HashMap<>(); | 
|         if(orderItemCheckList != null && orderItemCheckList.size() > 0){ | 
|             for(OrderItemCheck c : orderItemCheckList){ | 
|                 String orderItemId = c.getOrderItemId(); | 
|                 BigDecimal amount = c.getDeductAmount(); | 
|                 String type = c.getType(); | 
|                 if(Constants.CHECK_TYPE.reduce.name().equals(type)){ | 
|                     BigDecimal ra = reduceMap.get(orderItemId); | 
|                     if(ra == null){ | 
|                         ra = new BigDecimal(0); | 
|                     } | 
|                     ra = ra.add(amount); | 
|                     reduceMap.put(orderItemId, ra); | 
|                 } else if(Constants.CHECK_TYPE.lack.name().equals(type)){ | 
|                     OrderItem oi = orderItemMap.get(orderItemId); | 
|                     int lackNum = c.getNum() == null ? 0 : c.getNum(); | 
|                     BigDecimal lackFeeSupplier = oi.getSupplierPrice().multiply(new BigDecimal(lackNum)); | 
|                     BigDecimal ra = lackSupplierMap.get(orderItemId); | 
|                     if(ra == null){ | 
|                         ra = new BigDecimal(0); | 
|                     } | 
|                     ra = ra.add(lackFeeSupplier); | 
|                     lackSupplierMap.put(orderItemId, ra); | 
|   | 
|                     BigDecimal lackFeePartner = oi.getMarkupPartner().multiply(new BigDecimal(lackNum)); | 
|                     BigDecimal pa = lackPartnerMap.get(orderItemId); | 
|                     if(pa == null){ | 
|                         pa = new BigDecimal(0); | 
|                     } | 
|                     pa = pa.add(lackFeePartner); | 
|                     lackPartnerMap.put(orderItemId, pa); | 
|                 } else if(Constants.CHECK_TYPE.replace.name().equals(type)){ | 
|                     BigDecimal ra = replaceMap.get(orderItemId); | 
|                     if(ra == null){ | 
|                         ra = new BigDecimal(0); | 
|                     } | 
|                     ra = ra.add(amount); | 
|                     replaceMap.put(orderItemId, ra); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         List<Supplier> suppliers = supplierMapper.selectBatchIds(supplierIds); | 
|         Map<Long, Supplier> supplierMap = new HashMap<>(); | 
|         for(Supplier s : suppliers){ | 
|             supplierMap.put(s.getId(), s); | 
|         } | 
|   | 
|         String yearMonth = format(LocalDateTime.now().plusMonths(-1), "yyyy-MM"); | 
|         List<FlowerSupplierSaleNum> saleNumLs = saleNumMapper.selectList(new QueryWrapper<FlowerSupplierSaleNum>() | 
|                 .eq("`year_month`", yearMonth).in("supplier_id", supplierIds)); | 
|         Map<Long, Integer> preMonthNumMap = new HashMap<>(); | 
|         if(saleNumLs != null && saleNumLs.size() > 0){ | 
|             for (FlowerSupplierSaleNum ss : saleNumLs) { | 
|                 preMonthNumMap.put(ss.getSupplierId(), ss.getSaleNum()); | 
|             } | 
|         } | 
|   | 
|         List<FeeService> fees = feeServiceMapper.selectList(new QueryWrapper<>()); | 
|   | 
|         //售后结算 | 
|         List<OrderItemSales> sLs = orderItemSalesMapper.selectList(new QueryWrapper<OrderItemSales>() | 
|                 .in("order_item_id", itemIdsAll)); | 
|         Map<String, BigDecimal> supplierSalesMap = new HashMap<>(); | 
|         Map<String, BigDecimal> partnerSalesMap = new HashMap<>(); | 
|         if(sLs != null && sLs.size() > 0){ | 
|             for(OrderItemSales s : sLs){//同一个订单的同一个商品可能会多次理赔 | 
|                 prepareSalesAmount(s, supplierSalesMap, partnerSalesMap, null); | 
|             } | 
|         } | 
|   | 
|         LocalDateTime now = LocalDateTime.now(); | 
|   | 
|         for(Long supplierId : supplierItemMap.keySet()){ | 
|             Supplier s = supplierMap.get(supplierId); | 
|   | 
|             OrderSettlement settlement = new OrderSettlement(); | 
|             settlement.setId(UUIDGenerator.getUUID()); | 
|             settlement.setType(Constants.SETTLEMENT_TYPE.supplier.name()); | 
|             settlement.setUserId(s.getUserId()); | 
|             settlement.setStatus(Constants.SETTLEMENT_STATUS.PENDING.name()); | 
|   | 
|             Integer flowerNum = 0;//商品数量 | 
|             BigDecimal totalAmount = new BigDecimal(0);//交易合计 | 
|             BigDecimal checkFee = new BigDecimal(0);//降级扣款 | 
|             BigDecimal lackFee = new BigDecimal(0);//缺货扣款 | 
|             BigDecimal replaceFee = new BigDecimal(0);//补货扣款 | 
|             BigDecimal stationFee = new BigDecimal(0);//集货站运费 | 
|             BigDecimal salesFee = new BigDecimal(0);//售后理赔 | 
|   | 
|             Set<String> orderIds = new HashSet<>(); | 
|             Set<String> customerIds = new HashSet<>(); | 
|             List<String> itemIds = supplierItemMap.get(supplierId); | 
|             for(String itemId : itemIds){ | 
|                 OrderSettlementDetail detail = new OrderSettlementDetail(); | 
|                 detail.setId(UUIDGenerator.getUUID()); | 
|                 detail.setSettlementId(settlement.getId()); | 
|   | 
|                 OrderItem oi = orderItemMap.get(itemId); | 
|   | 
|                 orderIds.add(oi.getOrderId()); | 
|                 customerIds.add(oi.getCreateBy()); | 
|   | 
|                 detail.setOrderId(oi.getOrderId()); | 
|                 detail.setOrderItemId(itemId); | 
|                 detail.setPrice(oi.getSupplierPrice()); | 
|                 detail.setNum(oi.getNum()); | 
|                 detail.setTotalAmount(detail.getPrice().multiply(new BigDecimal(detail.getNum()))); | 
|   | 
|                 BigDecimal ra = reduceMap.get(itemId); | 
|                 detail.setCheckFee(ra == null ? new BigDecimal(0) : ra);//降级扣款 | 
|   | 
|                 BigDecimal la = lackSupplierMap.get(itemId); | 
|                 detail.setLackFee(la == null ? new BigDecimal(0) : la);//缺货扣款 | 
|   | 
|                 BigDecimal rpa = replaceMap.get(itemId); | 
|                 detail.setReplaceFee(rpa == null ? new BigDecimal(0) : rpa);//补货扣款 | 
|   | 
|                 detail.setStationFee(new BigDecimal(0)); | 
|                 Long stationId = oi.getStationId(); | 
|                 if(stationId != null) {//集货站运费按每扎算 | 
|                     BigDecimal sa = stationMap.get(stationId); | 
|                     if(sa != null){ | 
|                         detail.setStationFee(sa.multiply(new BigDecimal(detail.getNum()))); | 
|                     } | 
|                 } | 
|   | 
|                 BigDecimal sf = supplierSalesMap.get(itemId); | 
|                 detail.setSalesFee(sf == null ? new BigDecimal(0) : sf); | 
|                 detail.create(); | 
|                 settlementDetailMapper.insert(detail); | 
|   | 
|                 flowerNum += oi.getNum(); | 
|                 totalAmount = totalAmount.add(detail.getTotalAmount()); | 
|                 checkFee = checkFee.add(detail.getCheckFee()); | 
|                 lackFee = lackFee.add(detail.getLackFee()); | 
|                 replaceFee = replaceFee.add(detail.getReplaceFee()); | 
|                 stationFee = stationFee.add(detail.getStationFee()); | 
|                 salesFee = salesFee.add(detail.getSalesFee()); | 
|             } | 
|   | 
|             settlement.setFlowerNum(flowerNum); | 
|             settlement.setTotalAmount(totalAmount); | 
|             settlement.setCheckFee(checkFee); | 
|             settlement.setLackFee(lackFee); | 
|             settlement.setReplaceFee(replaceFee); | 
|             settlement.setStationFee(stationFee); | 
|             settlement.setSalesFee(salesFee); | 
|   | 
|             Integer orderNum = orderIds.size();//订单数量 | 
|             settlement.setOrderNum(orderNum); | 
|   | 
|             Integer customerNum = customerIds.size();//买家数量 | 
|             settlement.setCustomerNum(customerNum); | 
|   | 
|             BigDecimal price = totalAmount.divide(new BigDecimal(flowerNum), 2, RoundingMode.HALF_UP);//结算单价/均价 | 
|             settlement.setPrice(price); | 
|   | 
|             Integer preNum = preMonthNumMap.get(supplierId); | 
|             double serviceFeeRate = getServiceFeeRate(fees, preNum); | 
|             settlement.setServiceFeeRate(serviceFeeRate); | 
|   | 
|             BigDecimal serviceFee = totalAmount.multiply(new BigDecimal(serviceFeeRate)) | 
|                     .divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);//服务费 | 
|             settlement.setServiceFee(serviceFee); | 
|   | 
|             //供应商结算:商品价格-扣款-理赔-运费-服务费 = 结算金额 | 
|             //扣款包含:降级扣款、缺货扣款和补货扣款 | 
|             BigDecimal settlementAmount = totalAmount.subtract(checkFee).subtract(lackFee).subtract(replaceFee) | 
|                     .subtract(salesFee).subtract(stationFee).subtract(serviceFee);//结算金额 | 
|             if(settlementAmount.doubleValue() < 0){ | 
|                 settlementAmount = new BigDecimal(0); | 
|             } | 
|             settlement.setSettlementAmount(settlementAmount); | 
|             settlement.create(); | 
|   | 
|             settlementMapper.insert(settlement); | 
|         } | 
|   | 
|         /* ******************************************************************** */ | 
|         for(Long partnerId : partnerItemMap.keySet()){ | 
|             Partner p = partnerMap.get(partnerId); | 
|   | 
|             OrderSettlement settlement = new OrderSettlement(); | 
|             settlement.setId(UUIDGenerator.getUUID()); | 
|             settlement.setType(Constants.SETTLEMENT_TYPE.partner.name()); | 
|             settlement.setUserId(p.getUserId()); | 
|             settlement.setStatus(Constants.SETTLEMENT_STATUS.PENDING.name()); | 
|   | 
|             Integer flowerNum = 0;//商品数量 | 
|             BigDecimal totalAmount = new BigDecimal(0);//交易合计 | 
|             BigDecimal checkFee = new BigDecimal(0);//降级扣款 | 
|             BigDecimal lackFee = new BigDecimal(0);//缺货扣款 | 
|             BigDecimal replaceFee = new BigDecimal(0);//补货扣款 | 
|             BigDecimal stationFee = new BigDecimal(0);//集货站运费 | 
|             BigDecimal salesFee = new BigDecimal(0);//售后理赔 | 
|   | 
|             Set<String> orderIds = new HashSet<>(); | 
|             Set<String> customerIds = new HashSet<>(); | 
|             List<String> itemIds = partnerItemMap.get(partnerId); | 
|             for(String itemId : itemIds){ | 
|                 OrderSettlementDetail detail = new OrderSettlementDetail(); | 
|                 detail.setId(UUIDGenerator.getUUID()); | 
|                 detail.setSettlementId(settlement.getId()); | 
|   | 
|                 OrderItem oi = orderItemMap.get(itemId); | 
|   | 
|                 orderIds.add(oi.getOrderId()); | 
|                 customerIds.add(oi.getCreateBy()); | 
|   | 
|                 detail.setOrderId(oi.getOrderId()); | 
|                 detail.setOrderItemId(itemId); | 
|                 detail.setPrice(oi.getMarkupPartner()); | 
|                 detail.setNum(oi.getNum()); | 
|                 detail.setTotalAmount(detail.getPrice().multiply(new BigDecimal(detail.getNum()))); | 
|                 detail.setCheckFee(new BigDecimal(0)); | 
|   | 
|                 BigDecimal la = lackPartnerMap.get(itemId); | 
|                 detail.setLackFee(la == null ? new BigDecimal(0) : la);//缺货扣款 | 
|   | 
|                 detail.setReplaceFee(new BigDecimal(0)); | 
|                 detail.setStationFee(new BigDecimal(0)); | 
|   | 
|                 BigDecimal sf = partnerSalesMap.get(itemId); | 
|                 detail.setSalesFee(sf == null ? new BigDecimal(0) : sf); | 
|                 detail.create(); | 
|                 settlementDetailMapper.insert(detail); | 
|   | 
|                 flowerNum += oi.getNum(); | 
|                 totalAmount = totalAmount.add(detail.getTotalAmount()); | 
|                 salesFee = salesFee.add(detail.getSalesFee()); | 
|                 lackFee = lackFee.add(detail.getLackFee()); | 
|             } | 
|   | 
|             settlement.setFlowerNum(flowerNum); | 
|             settlement.setTotalAmount(totalAmount); | 
|             settlement.setCheckFee(checkFee); | 
|             settlement.setLackFee(lackFee); | 
|             settlement.setReplaceFee(replaceFee); | 
|             settlement.setStationFee(stationFee); | 
|             settlement.setSalesFee(salesFee); | 
|   | 
|             Integer orderNum = orderIds.size();//订单数量 | 
|             settlement.setOrderNum(orderNum); | 
|   | 
|             Integer customerNum = customerIds.size();//买家数量 | 
|             settlement.setCustomerNum(customerNum); | 
|   | 
|             BigDecimal price = totalAmount.divide(new BigDecimal(flowerNum), 2, RoundingMode.HALF_UP);//结算单价/均价 | 
|             settlement.setPrice(price); | 
|   | 
|             settlement.setServiceFee(new BigDecimal(0)); | 
|   | 
|             //合伙人结算:合伙人加价-理赔-缺货扣款 = 结算金额 | 
|             BigDecimal settlementAmount = totalAmount.subtract(salesFee).subtract(lackFee);//结算金额 | 
|             if(settlementAmount.doubleValue() < 0){ | 
|                 settlementAmount = new BigDecimal(0); | 
|             } | 
|             settlement.setSettlementAmount(settlementAmount); | 
|             settlement.create(); | 
|   | 
|             settlementMapper.insert(settlement); | 
|         } | 
|   | 
|         //更新订单状态 | 
|         for(Order o : ls){ | 
|             o.setStatus(Constants.ORDER_STATUS.COMPLETED.name()); | 
|             o.setStatusBackend(Constants.ORDER_STATUS_BACKEND.COMPLETED.name()); | 
|             o.setCompleteTime(now); | 
|             o.update("sys"); | 
|             orderMapper.updateById(o); | 
|         } | 
|     } | 
|   | 
|     //新的结算,每一笔订单的商品都会独立结算,结算单只是汇总 | 
|     public List<Order> getOrders4Settlement(){ | 
|         //结算完成收货的订单 | 
|         return orderMapper.getOrderForSettlement(); | 
|     } | 
|     //这2个方法中间需要调用一下 OrderItemSettlementService.saveItemSettlementInfo(List<String> orderIdsAll),以保证订单结算的准确性 | 
|     public void doSettlementNew(List<Order> ls){ | 
|         if(ls == null || ls.size() == 0){ | 
|             return; | 
|         } | 
|   | 
|         List<String> orderIdsAll = new ArrayList<>(); | 
|         List<String> orderIdsPartner = new ArrayList<>(); | 
|         Map<String, Order> orderMap = new HashMap<>(); | 
|         Set<Long> partnerIds = new HashSet<>(); | 
|         for(Order o : ls){ | 
|             String orderId = o.getId(); | 
|             orderIdsAll.add(orderId); | 
|             orderMap.put(orderId, o); | 
|             Long partnerId = o.getPartnerId(); | 
|             if(partnerId != null){ | 
|                 orderIdsPartner.add(orderId); | 
|                 partnerIds.add(partnerId); | 
|             } | 
|         } | 
|   | 
|         Map<Long, Partner> partnerMap = new HashMap<>(); | 
|         if(partnerIds.size() > 0){ | 
|             List<Partner> pLs = partnerMapper.selectBatchIds(partnerIds); | 
|             for(Partner p : pLs){ | 
|                 partnerMap.put(p.getId(), p); | 
|             } | 
|         } | 
|   | 
|         List<OrderItem> orderItems = orderItemMapper.selectList(new QueryWrapper<OrderItem>() | 
|                 .in("order_id", orderIdsAll)); | 
|         Map<String, OrderItem> orderItemMap = new HashMap<>(); | 
|         Map<Long, List<String>> supplierItemMap = new HashMap<>(); | 
|         Map<Long, List<String>> partnerItemMap = new HashMap<>(); | 
|         Set<Long> supplierIds = new HashSet<>(); | 
|         for(OrderItem oi : orderItems){ | 
|             String id = oi.getId(); | 
|             orderItemMap.put(id, oi); | 
|             if(orderIdsPartner.contains(oi.getOrderId())){ | 
|                 Order o = orderMap.get(oi.getOrderId()); | 
|                 Long partnerId = o.getPartnerId(); | 
|                 List<String> piIds = partnerItemMap.computeIfAbsent(partnerId, k -> new ArrayList<>()); | 
|                 piIds.add(id); | 
|             } | 
|             Long supplierId = oi.getSupplierId(); | 
|             List<String> siIds = supplierItemMap.computeIfAbsent(supplierId, k -> new ArrayList<>()); | 
|             siIds.add(id); | 
|             supplierIds.add(supplierId); | 
|         } | 
|   | 
|         List<OrderItemSettlement> orderItemSettlements = orderItemSettlementMapper.selectList(new QueryWrapper<OrderItemSettlement>() | 
|                 .in("order_id", orderIdsAll)); | 
|         Map<String, OrderItemSettlement> orderItemSettlementMap = new HashMap<>(); | 
|         for(OrderItemSettlement ois : orderItemSettlements){ | 
|             orderItemSettlementMap.put(ois.getOrderItemId(), ois); | 
|         } | 
|   | 
|         List<Supplier> suppliers = supplierMapper.selectBatchIds(supplierIds); | 
|         Map<Long, Supplier> supplierMap = new HashMap<>(); | 
|         for(Supplier s : suppliers){ | 
|             supplierMap.put(s.getId(), s); | 
|         } | 
|   | 
|         LocalDateTime now = LocalDateTime.now(); | 
|   | 
|         for(Long supplierId : supplierItemMap.keySet()){ | 
|             Supplier s = supplierMap.get(supplierId); | 
|   | 
|             OrderSettlement settlement = new OrderSettlement(); | 
|             settlement.setId(UUIDGenerator.getUUID()); | 
|             settlement.setType(Constants.SETTLEMENT_TYPE.supplier.name()); | 
|             settlement.setUserId(s.getUserId()); | 
|             settlement.setStatus(Constants.SETTLEMENT_STATUS.PENDING.name()); | 
|   | 
|             Integer flowerNum = 0;//商品数量 | 
|             BigDecimal totalAmount = new BigDecimal(0);//交易合计 | 
|             BigDecimal checkFee = new BigDecimal(0);//降级扣款 | 
|             BigDecimal lackFee = new BigDecimal(0);//缺货扣款 | 
|             BigDecimal replaceFee = new BigDecimal(0);//补货扣款 | 
|             BigDecimal stationFee = new BigDecimal(0);//集货站运费 | 
|             BigDecimal salesFee = new BigDecimal(0);//售后理赔 | 
|             BigDecimal serviceFee = new BigDecimal(0);//服务费 | 
|             double serviceFeeRate = 0d; | 
|             BigDecimal settlementAmount = new BigDecimal(0);//结算费用 | 
|   | 
|             Set<String> orderIds = new HashSet<>(); | 
|             Set<String> customerIds = new HashSet<>(); | 
|             List<String> itemIds = supplierItemMap.get(supplierId); | 
|             for(String itemId : itemIds){ | 
|                 OrderSettlementDetail detail = new OrderSettlementDetail(); | 
|                 detail.setId(UUIDGenerator.getUUID()); | 
|                 detail.setSettlementId(settlement.getId()); | 
|   | 
|                 OrderItem oi = orderItemMap.get(itemId); | 
|                 OrderItemSettlement ois = orderItemSettlementMap.get(itemId); | 
|   | 
|                 orderIds.add(oi.getOrderId()); | 
|                 customerIds.add(oi.getCreateBy()); | 
|   | 
|                 detail.setOrderId(oi.getOrderId()); | 
|                 detail.setOrderItemId(itemId); | 
|                 detail.setPrice(oi.getSupplierPrice()); | 
|                 detail.setNum(oi.getNum()); | 
|                 detail.setTotalAmount(detail.getPrice().multiply(new BigDecimal(detail.getNum()))); | 
|   | 
|                 detail.setCheckFee(ois.getCheckFee());//降级扣款 | 
|                 detail.setLackFee(ois.getLackFeeSupplier());//缺货扣款 | 
|                 detail.setReplaceFee(ois.getReplaceFee());//补货扣款 | 
|   | 
|                 detail.setStationFee(ois.getStationFee()); | 
|                 detail.setSalesFee(ois.getSalesFeeSupplier()); | 
|                 detail.create(); | 
|                 settlementDetailMapper.insert(detail); | 
|   | 
|                 flowerNum += oi.getNum(); | 
|                 totalAmount = totalAmount.add(detail.getTotalAmount()); | 
|                 checkFee = checkFee.add(detail.getCheckFee()); | 
|                 lackFee = lackFee.add(detail.getLackFee()); | 
|                 replaceFee = replaceFee.add(detail.getReplaceFee()); | 
|                 stationFee = stationFee.add(detail.getStationFee()); | 
|                 salesFee = salesFee.add(detail.getSalesFee()); | 
|                 serviceFee = serviceFee.add(ois.getServiceFee()); | 
|                 serviceFeeRate = ois.getServiceFeeRate(); | 
|                 settlementAmount = settlementAmount.add(ois.getIncomeSupplier()); | 
|             } | 
|   | 
|             settlement.setFlowerNum(flowerNum); | 
|             settlement.setTotalAmount(totalAmount); | 
|             settlement.setCheckFee(checkFee); | 
|             settlement.setLackFee(lackFee); | 
|             settlement.setReplaceFee(replaceFee); | 
|             settlement.setStationFee(stationFee); | 
|             settlement.setSalesFee(salesFee); | 
|   | 
|             Integer orderNum = orderIds.size();//订单数量 | 
|             settlement.setOrderNum(orderNum); | 
|   | 
|             Integer customerNum = customerIds.size();//买家数量 | 
|             settlement.setCustomerNum(customerNum); | 
|   | 
|             BigDecimal price = totalAmount.divide(new BigDecimal(flowerNum), 2, RoundingMode.HALF_UP);//结算单价/均价 | 
|             settlement.setPrice(price); | 
|   | 
|             settlement.setServiceFeeRate(serviceFeeRate); | 
|             settlement.setServiceFee(serviceFee); | 
|   | 
|             //供应商结算:商品价格-扣款-理赔-运费-服务费 = 结算金额 | 
|             //扣款包含:降级扣款、缺货扣款和补货扣款 | 
|             settlement.setSettlementAmount(settlementAmount); | 
|             settlement.create(); | 
|   | 
|             settlementMapper.insert(settlement); | 
|         } | 
|   | 
|         /* ******************************************************************** */ | 
|         for(Long partnerId : partnerItemMap.keySet()){ | 
|             Partner p = partnerMap.get(partnerId); | 
|   | 
|             OrderSettlement settlement = new OrderSettlement(); | 
|             settlement.setId(UUIDGenerator.getUUID()); | 
|             settlement.setType(Constants.SETTLEMENT_TYPE.partner.name()); | 
|             settlement.setUserId(p.getUserId()); | 
|             settlement.setStatus(Constants.SETTLEMENT_STATUS.PENDING.name()); | 
|   | 
|             Integer flowerNum = 0;//商品数量 | 
|             BigDecimal totalAmount = new BigDecimal(0);//交易合计 | 
|             BigDecimal checkFee = new BigDecimal(0);//降级扣款 | 
|             BigDecimal lackFee = new BigDecimal(0);//缺货扣款 | 
|             BigDecimal replaceFee = new BigDecimal(0);//补货扣款 | 
|             BigDecimal stationFee = new BigDecimal(0);//集货站运费 | 
|             BigDecimal salesFee = new BigDecimal(0);//售后理赔 | 
|             BigDecimal settlementAmount = new BigDecimal(0);//结算费用 | 
|   | 
|             Set<String> orderIds = new HashSet<>(); | 
|             Set<String> customerIds = new HashSet<>(); | 
|             List<String> itemIds = partnerItemMap.get(partnerId); | 
|             for(String itemId : itemIds){ | 
|                 OrderSettlementDetail detail = new OrderSettlementDetail(); | 
|                 detail.setId(UUIDGenerator.getUUID()); | 
|                 detail.setSettlementId(settlement.getId()); | 
|   | 
|                 OrderItem oi = orderItemMap.get(itemId); | 
|                 OrderItemSettlement ois = orderItemSettlementMap.get(itemId); | 
|   | 
|                 orderIds.add(oi.getOrderId()); | 
|                 customerIds.add(oi.getCreateBy()); | 
|   | 
|                 detail.setOrderId(oi.getOrderId()); | 
|                 detail.setOrderItemId(itemId); | 
|                 detail.setPrice(getAmount(oi.getMarkupPartner())); | 
|                 detail.setNum(oi.getNum()); | 
|                 detail.setTotalAmount(detail.getPrice().multiply(new BigDecimal(detail.getNum()))); | 
|                 detail.setCheckFee(new BigDecimal(0)); | 
|   | 
|                 detail.setLackFee(ois.getLackFeePartner());//缺货扣款 | 
|   | 
|                 detail.setReplaceFee(new BigDecimal(0)); | 
|                 detail.setStationFee(new BigDecimal(0)); | 
|   | 
|                 detail.setSalesFee(ois.getSalesFeePartner()); | 
|                 detail.create(); | 
|                 settlementDetailMapper.insert(detail); | 
|   | 
|                 flowerNum += oi.getNum(); | 
|                 totalAmount = totalAmount.add(detail.getTotalAmount()); | 
|                 salesFee = salesFee.add(detail.getSalesFee()); | 
|                 lackFee = lackFee.add(detail.getLackFee()); | 
|                 settlementAmount = settlementAmount.add(ois.getIncomePartner()); | 
|             } | 
|   | 
|             settlement.setFlowerNum(flowerNum); | 
|             settlement.setTotalAmount(totalAmount); | 
|             settlement.setCheckFee(checkFee); | 
|             settlement.setLackFee(lackFee); | 
|             settlement.setReplaceFee(replaceFee); | 
|             settlement.setStationFee(stationFee); | 
|             settlement.setSalesFee(salesFee); | 
|   | 
|             Integer orderNum = orderIds.size();//订单数量 | 
|             settlement.setOrderNum(orderNum); | 
|   | 
|             Integer customerNum = customerIds.size();//买家数量 | 
|             settlement.setCustomerNum(customerNum); | 
|   | 
|             BigDecimal price = totalAmount.divide(new BigDecimal(flowerNum), 2, RoundingMode.HALF_UP);//结算单价/均价 | 
|             settlement.setPrice(price); | 
|   | 
|             settlement.setServiceFee(new BigDecimal(0)); | 
|   | 
|             //合伙人结算:合伙人加价-理赔-缺货扣款 = 结算金额 | 
|             settlement.setSettlementAmount(settlementAmount); | 
|             settlement.create(); | 
|   | 
|             settlementMapper.insert(settlement); | 
|         } | 
|   | 
|         //更新订单状态 | 
|         for(Order o : ls){ | 
|             o.setStatus(Constants.ORDER_STATUS.COMPLETED.name()); | 
|             o.setStatusBackend(Constants.ORDER_STATUS_BACKEND.COMPLETED.name()); | 
|             o.setCompleteTime(now); | 
|             o.update("sys"); | 
|             orderMapper.updateById(o); | 
|         } | 
|     } | 
| } |