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.constant.LockConstants; 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.entity.wallet.WalletBillRecordDO; import com.mzl.flower.entity.wallet.WalletDO; 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.mapper.wallet.WalletBillRecordDetailMapper; import com.mzl.flower.mapper.wallet.WalletBillRecordMapper; import com.mzl.flower.mapper.wallet.WalletMapper; import com.mzl.flower.service.BaseService; import com.mzl.flower.service.wallet.WalletService; import com.mzl.flower.utils.ExcelExportUtil; import com.mzl.flower.utils.UUIDGenerator; import lombok.extern.slf4j.Slf4j; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; import java.math.RoundingMode; import java.net.URLEncoder; import java.time.LocalDateTime; import java.util.*; import java.util.concurrent.TimeUnit; @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; @Autowired private WalletBillRecordMapper walletBillRecordMapper; @Autowired private WalletMapper walletMapper; @Autowired private WalletBillRecordDetailMapper walletBillRecordDetailMapper; @Autowired private WalletService walletService; @Autowired RedissonClient redissonClient; public Page selectSettlementList(Page page, OrderSettlementQueryDTO dto){ dto.setStartDate(parseLocalDateTime(dto.getStartDateStr(), true)); dto.setEndDate(parseLocalDateTime(dto.getEndDateStr(), false)); List 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() .eq("user_id", settlement.getUserId())); userName = s.getName(); } else { Partner p = partnerMapper.selectOne(new QueryWrapper() .eq("user_id", settlement.getUserId())); userName = p.getName(); } dto.setUserName(userName); List 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 type = settlement.getType(); //2024-10-23 //供应商新的结算逻辑不结算供应商的钱。 if (Constants.SETTLEMENT_TYPE.supplier.name().equals(type)) { 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 name = ""; if(Constants.SETTLEMENT_TYPE.supplier.name().equals(type)){ Supplier s = supplierMapper.selectOne(new QueryWrapper() .eq("user_id", settlement.getUserId())); name = "供应商" + s.getName(); } else { Partner p = partnerMapper.selectOne(new QueryWrapper() .eq("user_id", settlement.getUserId())); name = "合伙人" + p.getName(); } UserWechat wechat = wechatMapper.selectOne(new QueryWrapper() .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 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() .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 ls = orderMapper.getOrderForSettlement(); if(ls == null || ls.size() == 0){ return; } List stations = stationMapper.selectList(null); Map stationMap = new HashMap<>(); for(Station s : stations){ BigDecimal freight = s.getFreight(); stationMap.put(s.getId(), freight == null ? new BigDecimal(0) : freight); } List orderIdsAll = new ArrayList<>(); List orderIdsPartner = new ArrayList<>(); Map orderMap = new HashMap<>(); Set 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 partnerMap = new HashMap<>(); if(partnerIds.size() > 0){ List pLs = partnerMapper.selectBatchIds(partnerIds); for(Partner p : pLs){ partnerMap.put(p.getId(), p); } } List orderItems = orderItemMapper.selectList(new QueryWrapper() .in("order_id", orderIdsAll)); List itemIdsAll = new ArrayList<>(); Map orderItemMap = new HashMap<>(); Map> supplierItemMap = new HashMap<>(); Map> partnerItemMap = new HashMap<>(); Set 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 piIds = partnerItemMap.computeIfAbsent(partnerId, k -> new ArrayList<>()); piIds.add(id); } Long supplierId = oi.getSupplierId(); List siIds = supplierItemMap.computeIfAbsent(supplierId, k -> new ArrayList<>()); siIds.add(id); supplierIds.add(supplierId); } List orderItemCheckList = orderItemCheckMapper.selectList(new QueryWrapper() .in("order_id", orderIdsAll) .eq("audit_status", Constants.CHECK_AUDIT_STATUS.AGREED.name()) ); Map replaceMap = new HashMap<>(); Map reduceMap = new HashMap<>(); Map lackSupplierMap = new HashMap<>(); Map 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 suppliers = supplierMapper.selectBatchIds(supplierIds); Map supplierMap = new HashMap<>(); for(Supplier s : suppliers){ supplierMap.put(s.getId(), s); } String yearMonth = format(LocalDateTime.now().plusMonths(-1), "yyyy-MM"); List saleNumLs = saleNumMapper.selectList(new QueryWrapper() .eq("`year_month`", yearMonth).in("supplier_id", supplierIds)); Map preMonthNumMap = new HashMap<>(); if(saleNumLs != null && saleNumLs.size() > 0){ for (FlowerSupplierSaleNum ss : saleNumLs) { preMonthNumMap.put(ss.getSupplierId(), ss.getSaleNum()); } } List fees = feeServiceMapper.selectList(new QueryWrapper<>()); //售后结算 List sLs = orderItemSalesMapper.selectList(new QueryWrapper() .in("order_item_id", itemIdsAll)); Map supplierSalesMap = new HashMap<>(); Map 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 orderIds = new HashSet<>(); Set customerIds = new HashSet<>(); List 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 orderIds = new HashSet<>(); Set customerIds = new HashSet<>(); List 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 getOrders4Settlement(){ //结算完成收货的订单 return orderMapper.getOrderForSettlement(); } //这2个方法中间需要调用一下 OrderItemSettlementService.saveItemSettlementInfo(List orderIdsAll),以保证订单结算的准确性 public void doSettlementNew(List ls){ if(ls == null || ls.size() == 0){ return; } List orderIdsAll = new ArrayList<>(); List orderIdsPartner = new ArrayList<>(); Map orderMap = new HashMap<>(); Set 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 partnerMap = new HashMap<>(); if(partnerIds.size() > 0){ List pLs = partnerMapper.selectBatchIds(partnerIds); for(Partner p : pLs){ partnerMap.put(p.getId(), p); } } List orderItems = orderItemMapper.selectList(new QueryWrapper() .in("order_id", orderIdsAll)); Map orderItemMap = new HashMap<>(); Map> supplierItemMap = new HashMap<>(); Map> partnerItemMap = new HashMap<>(); Set 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 piIds = partnerItemMap.computeIfAbsent(partnerId, k -> new ArrayList<>()); piIds.add(id); } Long supplierId = oi.getSupplierId(); List siIds = supplierItemMap.computeIfAbsent(supplierId, k -> new ArrayList<>()); siIds.add(id); supplierIds.add(supplierId); } List orderItemSettlements = orderItemSettlementMapper.selectList(new QueryWrapper() .in("order_id", orderIdsAll)); Map orderItemSettlementMap = new HashMap<>(); for(OrderItemSettlement ois : orderItemSettlements){ orderItemSettlementMap.put(ois.getOrderItemId(), ois); } List suppliers = supplierMapper.selectBatchIds(supplierIds); Map 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 orderIds = new HashSet<>(); Set customerIds = new HashSet<>(); List 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); //2024-10-23 //copy信息到t_wallet_bill_record_detail // WalletBillRecordDetail walletBillRecordDetail = new WalletBillRecordDetail(); // BeanUtils.copyProperties(detail, walletBillRecordDetail, "id"); // walletBillRecordDetail.setBillRecordId(walletBillRecord.getId()); // walletBillRecordDetailMapper.insert(walletBillRecordDetail); 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()); WalletDO walletDO = walletService.getOrCreateBySupplierId(supplierId); RLock lock = redissonClient.getLock(String.format(LockConstants.WALLET_ID_KEY, walletDO.getId())); try { if (lock.tryLock(10, 30, TimeUnit.SECONDS)) { try { //2024-10-28 直接保存到walletBillRecord //新增WalletBillRecordDO if(ois.getIncomeSupplier().compareTo(BigDecimal.ZERO) > 0) { WalletBillRecordDO walletBillRecord = new WalletBillRecordDO(); walletBillRecord.setId(UUIDGenerator.getUUID()); WalletDO walletDOInfo = walletService.getBySupplierId(supplierId); //增加供应商结算金额保存到钱包 walletBillRecord.setSupplierId(supplierId); walletBillRecord.setWalletId(walletDOInfo.getId()); walletBillRecord.setSettlementId(settlement.getId()); walletBillRecord.setOrderItemId(detail.getOrderItemId()); //变动金额等于供应商收入 walletBillRecord.setTotalAmount(ois.getIncomeSupplier()); walletBillRecord.setType(Constants.BILL_CHANGE_TYPE.settlement.name()); walletBillRecord.setMethod(Constants.BILL_CHANGE_METHOD.add.name()); walletBillRecord.setOriginalAmount(walletDOInfo.getTotalAmount()); walletBillRecord.setChangeAmount(ois.getIncomeSupplier()); walletBillRecord.setBalance(walletDOInfo.getWithdrawableAmount().add(ois.getIncomeSupplier())); Order order = orderMapper.selectById(detail.getOrderId()); if (!ObjectUtils.isEmpty(order)) { walletBillRecord.setRemark("订单完成(订单号" + order.getOrderNo() + ")" + ",获得收入"); walletBillRecord.setOrderNo(order.getOrderNo()); } //更新钱包 //可提现金额=钱包余额=结算金额 walletDOInfo.setWithdrawableAmount(walletDOInfo.getWithdrawableAmount().add(ois.getIncomeSupplier())); walletDOInfo.setTotalAmount(walletDOInfo.getWithdrawableAmount()); //已结算金额 walletDOInfo.setSettledAmount(walletDOInfo.getSettledAmount().add(ois.getIncomeSupplier())); walletMapper.updateById(walletDOInfo); walletBillRecord.create(); walletBillRecordMapper.insert(walletBillRecord); } } finally { lock.unlock(); } } } catch (InterruptedException e) { throw new RuntimeException(e); } } 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(); //2024-10-23 //计算到钱包后订单状态变成已结算 //旧逻辑转账的时候才会标记状态为结算中 //新逻辑不是立即转账。不走结算后转账逻辑。此时没有转账时间、openID、转账ID、转账明细ID,直接标记结算状态完成,存金额到钱包中 settlement.setStatus(Constants.SETTLEMENT_STATUS.COMPLETED.name()); 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 orderIds = new HashSet<>(); Set customerIds = new HashSet<>(); List 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); } } public void exportSettlementList(HttpServletResponse response, OrderSettlementQueryDTO dto) { dto.setStartDate(parseLocalDateTime(dto.getStartDateStr(), true)); dto.setEndDate(parseLocalDateTime(dto.getEndDateStr(), false)); List ls = settlementMapper.selectSettlementListInfo(null, dto); String[] rowsName = new String[]{"序号","结算人", "结算金额(元)", "订单数量", "买家数量", "商品数量", "结算合计(元)", "结算均价(元)", "降级扣款(元)", "缺货扣款(元)", "补货扣款(元)", "售后理赔(元)", "服务费(元)", "集货站运费(元)", "结算类型", "结算状态", "结算时间"}; List dataList = new ArrayList<>(); int sn = 1; for (OrderSettlementListDTO o : ls) { Object[] objs = new Object[rowsName.length]; int a = 0; objs[a++] = sn; objs[a++] = o.getUserName(); objs[a++] = o.getSettlementAmount(); objs[a++] = o.getOrderNum(); objs[a++] = o.getCustomerNum(); objs[a++] = o.getFlowerNum(); objs[a++] = o.getTotalAmount(); objs[a++] = o.getPrice(); objs[a++] = o.getCheckFee(); objs[a++] = o.getLackFee(); objs[a++] = o.getReplaceFee(); objs[a++] = o.getSalesFee(); objs[a++] = o.getServiceFee(); objs[a++] = o.getStationFee(); objs[a++] = o.getTypeStr(); objs[a++] = o.getStatusStr(); objs[a++] = o.getTransferTime(); dataList.add(objs); sn++; } ExcelExportUtil excelExportUtil = new ExcelExportUtil("结算列表", rowsName, dataList, response); try { response.addHeader("filename", URLEncoder.encode("结算列表.xls", "UTF-8")); response.addHeader("Access-Control-Expose-Headers", "filename"); excelExportUtil.export(); } catch (Exception e) { log.error(e.getMessage(), e); } } }