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<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 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<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);
|
|
//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<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);
|
}
|
}
|
|
public void exportSettlementList(HttpServletResponse response, OrderSettlementQueryDTO dto) {
|
dto.setStartDate(parseLocalDateTime(dto.getStartDateStr(), true));
|
dto.setEndDate(parseLocalDateTime(dto.getEndDateStr(), false));
|
List<OrderSettlementListDTO> ls = settlementMapper.selectSettlementListInfo(null, dto);
|
|
String[] rowsName = new String[]{"序号","结算人", "结算金额(元)", "订单数量", "买家数量", "商品数量", "结算合计(元)", "结算均价(元)", "降级扣款(元)",
|
"缺货扣款(元)", "补货扣款(元)", "售后理赔(元)", "服务费(元)", "集货站运费(元)", "结算类型", "结算状态", "结算时间"};
|
List<Object[]> 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);
|
}
|
|
}
|
}
|