chengf
2025-08-27 074caee550216dfd4bb676677ae33cbd837c5710
service-fee/src/main/java/com/java110/fee/bmo/impl/QueryOweFeeImpl.java
old mode 100644 new mode 100755
@@ -1,9 +1,11 @@
package com.java110.fee.bmo.impl;
import com.alibaba.fastjson.JSONArray;
import com.java110.core.factory.CommunitySettingFactory;
import com.java110.core.factory.Java110ThreadPoolFactory;
import com.java110.core.log.LoggerFactory;
import com.java110.core.smo.IComputeFeeSMO;
import com.java110.dto.RoomDto;
import com.java110.dto.room.RoomDto;
import com.java110.dto.fee.FeeConfigDto;
import com.java110.dto.fee.FeeDto;
import com.java110.dto.owner.OwnerCarDto;
@@ -19,24 +21,22 @@
import com.java110.utils.cache.MappingCache;
import com.java110.utils.constant.ResponseConstant;
import com.java110.utils.exception.ListenerExecuteException;
import com.java110.utils.util.Assert;
import com.java110.utils.util.DateUtil;
import com.java110.utils.util.StringUtil;
import com.java110.utils.util.*;
import com.java110.vo.ResultVo;
import com.java110.vo.api.fee.ApiFeeDataVo;
import com.java110.vo.api.fee.ApiFeeVo;
import com.java110.vo.api.feeConfig.ApiFeeConfigDataVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
@Service
public class QueryOweFeeImpl implements IQueryOweFee {
@@ -75,24 +75,58 @@
    //键
    public static final String RECEIVED_AMOUNT_SWITCH = "RECEIVED_AMOUNT_SWITCH";
    //禁用电脑端提交收费按钮
    public static final String OFFLINE_PAY_FEE_SWITCH = "OFFLINE_PAY_FEE_SWITCH";
    @Override
    public ResponseEntity<String> query(FeeDto feeDto) {
        //查询费用信息arrearsEndTime
        feeDto.setArrearsEndTime(DateUtil.getCurrentDate());
        // todo 这里考虑预付期的费用 所以查询全量再用费用
        feeDto.setState(FeeDto.STATE_DOING);
        List<FeeDto> feeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
        if (feeDtos == null || feeDtos.size() < 1) {
        if (ListUtil.isNull(feeDtos)) {
            feeDtos = new ArrayList<>();
            return ResultVo.createResponseEntity(feeDtos);
        }
        String val = CommunitySettingFactory.getValue(feeDtos.get(0).getCommunityId(), TOTAL_FEE_PRICE);
        if (StringUtil.isEmpty(val)) {
            val = MappingCache.getValue(DOMAIN_COMMON, TOTAL_FEE_PRICE);
        }
        List<FeeDto> tmpFeeDtos = new ArrayList<>();
        for (FeeDto tmpFeeDto : feeDtos) {
            computeFeeSMOImpl.computeEveryOweFee(tmpFeeDto);//计算欠费金额
            //如果金额为0 就排除
            if (tmpFeeDto.getFeePrice() > 0 && tmpFeeDto.getEndTime().getTime() <= DateUtil.getCurrentDate().getTime()) {
                tmpFeeDtos.add(tmpFeeDto);
            try {
                if (!StringUtil.isEmpty(tmpFeeDto.getAdditionalAmount())) {
                    tmpFeeDto.setAdditionalAmount(Double.parseDouble(tmpFeeDto.getAdditionalAmount()) + "");
                }
                if (!StringUtil.isEmpty(tmpFeeDto.getSquarePrice())) {
                    tmpFeeDto.setSquarePrice(Double.parseDouble(tmpFeeDto.getSquarePrice()) + "");
                }
                //todo 有目标结束时间,并且不是一次性费用
                if (!StringUtil.isEmpty(feeDto.getTargetEndTime())
                        && !FeeDto.FEE_FLAG_ONCE.equals(tmpFeeDto.getFeeFlag())
                ) {
                    computeFeeSMOImpl.computeEveryOweFeeByTargetEndTime(tmpFeeDto, feeDto.getTargetEndTime());//计算欠费金额
                } else {
                    computeFeeSMOImpl.computeEveryOweFee(tmpFeeDto);//计算欠费金额
                }
                //如果金额为0 就排除
                tmpFeeDto.setFeeTotalPrice(
                        MoneyUtil.computePriceScale(
                                tmpFeeDto.getFeeTotalPrice(),
                                tmpFeeDto.getScale(),
                                Integer.parseInt(tmpFeeDto.getDecimalPlace())
                        )
                );
                tmpFeeDto.setVal(val);
                if (tmpFeeDto.getFeeTotalPrice() != 0) {
                    tmpFeeDtos.add(tmpFeeDto);
                }
            } catch (Exception e) {
                logger.error("可能费用资料有问题导致算费失败", e);
            }
        }
@@ -121,11 +155,35 @@
        List<FeeDto> feeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
        if (feeDtos == null || feeDtos.size() < 1) {
        if (ListUtil.isNull(feeDtos)) {
            return ResultVo.success();
        }
        String cycel = null;
        String custEndTime = null;
        String customStartTime = "";
        String customEndTime = "";
        if (!StringUtil.isEmpty(feeDto.getCycle())) {
            cycel = feeDto.getCycle();
        }
        if (!StringUtil.isEmpty(feeDto.getCustEndTime())) {
            custEndTime = feeDto.getCustEndTime();
        }
        customStartTime = feeDto.getCustomStartTime();
        customEndTime = feeDto.getCustomEndTime();
        feeDto = feeDtos.get(0);
        //todo 考虑账单模式
        if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag()) && StringUtil.isNumber(feeDto.getMonthCycle())) {
            cycel = feeDto.getMonthCycle();
        }
        if (!StringUtil.isEmpty(cycel)) {
            feeDto.setCycle(cycel);
        }
        if (!StringUtil.isEmpty(custEndTime)) {
            feeDto.setCustEndTime(custEndTime);
        }
        feeDto.setCustomStartTime(customStartTime);
        feeDto.setCustomEndTime(customEndTime);
        if (FeeDto.PAYER_OBJ_TYPE_ROOM.equals(feeDto.getPayerObjType())) { //房屋相关
            RoomDto roomDto = new RoomDto();
@@ -136,11 +194,12 @@
                throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR, "未查到房屋信息,查询多条数据");
            }
            roomDto = roomDtos.get(0);
            feeDto.setPayerObjName(roomDto.getFloorNum() + "栋" + roomDto.getUnitNum() + "单元" + roomDto.getRoomNum() + "室");
            feeDto.setPayerObjName(roomDto.getFloorNum() + "-" + roomDto.getUnitNum() + "-" + roomDto.getRoomNum());
            feeDto.setBuiltUpArea(roomDto.getBuiltUpArea());
        } else if (FeeDto.PAYER_OBJ_TYPE_CAR.equals(feeDto.getPayerObjType())) {//车位相关
            OwnerCarDto ownerCarDto = new OwnerCarDto();
            ownerCarDto.setCarTypeCd("1001"); //业主车辆
            ownerCarDto.setCommunityId(feeDto.getCommunityId());
            ownerCarDto.setCarId(feeDto.getPayerObjId());
            List<OwnerCarDto> ownerCarDtos = ownerCarInnerServiceSMOImpl.queryOwnerCars(ownerCarDto);
@@ -149,7 +208,7 @@
            parkingSpaceDto.setCommunityId(feeDto.getCommunityId());
            parkingSpaceDto.setPsId(ownerCarDtos.get(0).getPsId());
            List<ParkingSpaceDto> parkingSpaceDtos = parkingSpaceInnerServiceSMOImpl.queryParkingSpaces(parkingSpaceDto);
            if (parkingSpaceDtos == null || parkingSpaceDtos.size() < 1) { //数据有问题
            if (ListUtil.isNull(parkingSpaceDtos)) { //数据有问题
                throw new ListenerExecuteException(ResponseConstant.RESULT_CODE_ERROR, "未查到停车位信息,查询多条数据");
            }
            ownerCarDto = ownerCarDtos.get(0);
@@ -157,18 +216,108 @@
            feeDto.setPayerObjName(ownerCarDto.getCarNum() + "(" + parkingSpaceDto.getAreaNum() + "停车场" + parkingSpaceDto.getNum() + "车位)");
            feeDto.setBuiltUpArea(parkingSpaceDto.getArea());
        }
        double feePrice = computeFeeSMOImpl.getFeePrice(feeDto);
        feeDto.setFeePrice(feePrice);
        Map feePriceAll = computeFeeSMOImpl.getFeePrice(feeDto);
        feeDto.setFeePrice(Double.parseDouble(feePriceAll.get("feePrice").toString()));
        feeDto.setFeeTotalPrice(
                MoneyUtil.computePriceScale(
                        Double.parseDouble(feePriceAll.get("feeTotalPrice").toString()),
                        feeDto.getScale(),
                        Integer.parseInt(feeDto.getDecimalPlace())
                )
        );
        if (!StringUtil.isEmpty(custEndTime)) {
            Date date = DateUtil.getDateFromStringB(custEndTime);
            computeFeeSMOImpl.dealRentRateCustEndTime(feeDto, date);
        } else {
            computeFeeSMOImpl.dealRentRateCycle(feeDto, NumberUtil.getDouble(feeDto.getCycle()));
        }
        //应收款取值
        String val = MappingCache.getValue(DOMAIN_COMMON, TOTAL_FEE_PRICE);
        //先取单小区的如果没有配置 取 全局的
        String val = CommunitySettingFactory.getValue(feeDto.getCommunityId(), TOTAL_FEE_PRICE);
        if (StringUtil.isEmpty(val)) {
            val = MappingCache.getValue(DOMAIN_COMMON, TOTAL_FEE_PRICE);
        }
        feeDto.setVal(val);
        String received_amount_switch = MappingCache.getValue(DOMAIN_COMMON, RECEIVED_AMOUNT_SWITCH);
        //先取单小区的如果没有配置 取 全局的
        String received_amount_switch = CommunitySettingFactory.getValue(feeDto.getCommunityId(), RECEIVED_AMOUNT_SWITCH);
        if (StringUtil.isEmpty(received_amount_switch)) {
            received_amount_switch = MappingCache.getValue(DOMAIN_COMMON, RECEIVED_AMOUNT_SWITCH);
        }
        //关闭 线下收银功能
        if (StringUtil.isEmpty(received_amount_switch)) {
            feeDto.setReceivedAmountSwitch("1");//默认启用实收款输入框
        } else {
            feeDto.setReceivedAmountSwitch(received_amount_switch);
        }
        return ResultVo.createResponseEntity(feeDto);
        //先取单小区的如果没有配置 取 全局的
        String offlinePayFeeSwitch = CommunitySettingFactory.getValue(feeDto.getCommunityId(), OFFLINE_PAY_FEE_SWITCH);
        if (StringUtil.isEmpty(offlinePayFeeSwitch)) {
            offlinePayFeeSwitch = MappingCache.getValue(DOMAIN_COMMON, OFFLINE_PAY_FEE_SWITCH);
        }
        feeDto.setOfflinePayFeeSwitch(offlinePayFeeSwitch);
        //去掉多余0
        feeDto.setSquarePrice(Double.parseDouble(feeDto.getSquarePrice()) + "");
        feeDto.setAdditionalAmount(Double.parseDouble(feeDto.getAdditionalAmount()) + "");
        ApiFeeDataVo apiFeeDataVo = BeanConvertUtil.covertBeanList(feeDtos, ApiFeeDataVo.class).get(0);
        apiFeeDataVo.setStartTime(apiFeeDataVo.getStartTime() == null ? null : apiFeeDataVo.getStartTime().split(" ")[0]);
        apiFeeDataVo.setEndTime(apiFeeDataVo.getEndTime() == null ? null : apiFeeDataVo.getEndTime().split(" ")[0]);
        apiFeeDataVo.setMaxEndTime(apiFeeDataVo.getMaxEndTime() == null ? null : apiFeeDataVo.getMaxEndTime().split(" ")[0]);
        apiFeeDataVo.setDeadlineTime(apiFeeDataVo.getDeadlineTime() == null ? null : apiFeeDataVo.getDeadlineTime().split(" ")[0]);
        if (cycel != null && !"105".equals(cycel)) { // 修正字符串比较方式
            Date date = feeDto.getEndTime();
            if (date != null) { // 增加空值检查
                LocalDateTime localDateTime;
                // 处理 java.sql.Date 不支持 toInstant() 的问题
                if (date instanceof java.sql.Date) {
                    // 对于 sql.Date,先转换为 LocalDate 再转为 LocalDateTime
                    LocalDate localDate = ((java.sql.Date) date).toLocalDate();
                    localDateTime = localDate.atStartOfDay();
                } else {
                    // 对于 util.Date,正常转换
                    localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
                }
                try {
                    // 增加x个月
                    int monthsToAdd = Integer.parseInt(cycel);
                    LocalDateTime newLocalDateTime = localDateTime.plusMonths(monthsToAdd).minusDays(1);
                    // 转换回Date
                    Date newDate = Date.from(newLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
                    apiFeeDataVo.setPayStartDate(feeDto.getEndTime());
                    apiFeeDataVo.setPayEndDate(newDate);
                } catch (NumberFormatException e) {
                    // 处理cycel无法转换为整数的异常
                    // 可以根据实际需求记录日志或抛出自定义异常
                    e.printStackTrace();
                }
            }
        }else{
            apiFeeDataVo.setPayStartDate(DateUtil.getDateFromStringB(feeDto.getCustomStartTime()));
            // 获取原始日期
            Date originalDate = DateUtil.getDateFromStringB(feeDto.getCustomEndTime());
            if (originalDate != null) {
                // 创建Calendar实例并设置日期
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(originalDate);
                // 减一天
                calendar.add(Calendar.DAY_OF_MONTH, -1);
                // 获取处理后的日期
                Date dateMinusOneDay = calendar.getTime();
                apiFeeDataVo.setPayEndDate(dateMinusOneDay);
            }
        }
        //计算MaxEndTime和payStartDate之间的月数
        int monthCount = DateUtil.calculateMonths(DateUtil.getFormatTimeStringB(apiFeeDataVo.getPayStartDate()), apiFeeDataVo.getMaxEndTime());
        apiFeeDataVo.setMonthCount(monthCount);
        return ResultVo.createResponseEntity(apiFeeDataVo);
    }
    @Override
@@ -183,20 +332,16 @@
        }
        //查询费用信息arrearsEndTime
        List<RoomDto> tmpRoomDtos = new ArrayList<>();
        //List<RoomDto> tempRooms = new ArrayList<>();
        List<RoomDto> tempRooms = new ArrayList<>();
        int threadNum = Java110ThreadPoolFactory.JAVA110_DEFAULT_THREAD_NUM;
        //for (int roomIndex = 0; roomIndex < roomDtos.size(); roomIndex++) {
        // tempRooms.add(roomDtos.get(roomIndex));
        //if (roomIndex % threadNum == 0 && roomIndex != 0) {
        //    tmpRoomDtos.addAll(doGetTmpRoomDto(tempRooms, feeDto, threadNum));
        //   tempRooms = new ArrayList();
        // }
        // }
//        if (tempRooms.size() > 0) {
//            tmpRoomDtos.addAll(doGetTmpRoomDto(tempRooms, feeDto, tempRooms.size()));
//        }
        tmpRoomDtos.addAll(doGetTmpRoomDto(roomDtos, feeDto, threadNum));
        tempRooms.addAll(doGetTmpRoomDto(roomDtos, feeDto, threadNum));
        for (RoomDto tmpRoomDto : tempRooms) {
            if (tmpRoomDto == null) {
                continue;
            }
            tmpRoomDtos.add(tmpRoomDto);
        }
        return ResultVo.createResponseEntity(tmpRoomDtos);
    }
@@ -236,7 +381,8 @@
            computeFeeSMOImpl.computeEveryOweFee(tempFeeDto, tmpRoomDto);//计算欠费金额
            //如果金额为0 就排除
            if (tempFeeDto.getFeePrice() > 0 && tempFeeDto.getEndTime().getTime() <= DateUtil.getCurrentDate().getTime()) {
            //if (tempFeeDto.getFeePrice() > 0 && tempFeeDto.getEndTime().getTime() <= DateUtil.getCurrentDate().getTime()) {
            if (tempFeeDto.getFeePrice() > 0) {
                tmpFeeDtos.add(tempFeeDto);
            }
        }
@@ -392,7 +538,7 @@
    private void dealFeePs(ParkingSpaceDto tmpParkingSpaceDto, FeeDto feeDto) {
        // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间
        Map<String, Object> targetEndDateAndOweMonth = getTargetEndDateAndOweMonth(feeDto);
        Map<String, Object> targetEndDateAndOweMonth = computeFeeSMOImpl.getTargetEndDateAndOweMonth(feeDto);
        Date targetEndDate = (Date) targetEndDateAndOweMonth.get("targetEndDate");
        double oweMonth = (double) targetEndDateAndOweMonth.get("oweMonth");
        if (!tmpParkingSpaceDto.getPsId().equals(feeDto.getPayerObjId())) {
@@ -411,6 +557,12 @@
            BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
            feePrice = additionalAmount.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
        } else if ("3003".equals(computingFormula)) { // 固定费用
            feePrice = 0.0;
        } else if ("1101".equals(computingFormula)) { // 租金
            feePrice = 0.0;
        } else if ("1102".equals(computingFormula)) { // 租金
            feePrice = 0.0;
        } else if ("4004".equals(computingFormula)) {
            feePrice = Double.parseDouble(feeDto.getAmount());
        } else if ("5005".equals(computingFormula)) {
@@ -420,6 +572,19 @@
                BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
                BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
                BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
                BigDecimal sub = curDegree.subtract(preDegree);
                feePrice = sub.multiply(squarePrice)
                        .add(additionalAmount)
                        .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
            }
        } else if ("9009".equals(computingFormula)) {  //(本期度数-上期度数)*动态单价+附加费
            if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
                feePrice = -1.00;
            } else {
                BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
                BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
                BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getMwPrice()));
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
                BigDecimal sub = curDegree.subtract(preDegree);
                feePrice = sub.multiply(squarePrice)
@@ -437,7 +602,9 @@
        feeDto.setAmountOwed(price.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue() + "");
        feeDto.setDeadlineTime(targetEndDate);
        //动态费用
        if ("4004".equals(computingFormula)) {
        if ("4004".equals(computingFormula)
                && FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())
        ) {
            feeDto.setAmountOwed(feeDto.getFeePrice() + "");
            feeDto.setDeadlineTime(DateUtil.getCurrentDate());
        }
@@ -489,7 +656,7 @@
    }
    private void dealFeeRoom(RoomDto tmpRoomDto, FeeDto feeDto) {
        Map<String, Object> targetEndDateAndOweMonth = getTargetEndDateAndOweMonth(feeDto);
        Map<String, Object> targetEndDateAndOweMonth = computeFeeSMOImpl.getTargetEndDateAndOweMonth(feeDto);
        Date targetEndDate = (Date) targetEndDateAndOweMonth.get("targetEndDate");
        double oweMonth = (double) targetEndDateAndOweMonth.get("oweMonth");
        if (!tmpRoomDto.getRoomId().equals(feeDto.getPayerObjId())) {
@@ -507,6 +674,17 @@
        } else if ("2002".equals(computingFormula)) { // 固定费用
            BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
            feePrice = additionalAmount.setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
        } else if ("3003".equals(computingFormula)) { // 固定费用
            BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
            BigDecimal builtUpArea = new BigDecimal(Double.parseDouble(tmpRoomDto.getRoomArea()));
            BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
            feePrice = squarePrice.multiply(builtUpArea).add(additionalAmount).setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
        } else if ("1101".equals(computingFormula)) { // 租金
            BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(tmpRoomDto.getRoomRent()));
            feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
        } else if ("1102".equals(computingFormula)) { // 租金
            BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(tmpRoomDto.getRoomRent()));
            feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_EVEN).doubleValue();
        } else if ("4004".equals(computingFormula)) {
            feePrice = Double.parseDouble(feeDto.getAmount());
        } else if ("5005".equals(computingFormula)) {
@@ -517,6 +695,20 @@
                BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
                BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
                BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getSquarePrice()));
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
                BigDecimal sub = curDegree.subtract(preDegree);
                feePrice = sub.multiply(squarePrice)
                        .add(additionalAmount)
                        .setScale(2, BigDecimal.ROUND_HALF_EVEN).doubleValue();
            }
        } else if ("9009".equals(computingFormula)) {
            if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
                feePrice = -1.00;
            } else {
                BigDecimal curDegree = new BigDecimal(Double.parseDouble(feeDto.getCurDegrees()));
                BigDecimal preDegree = new BigDecimal(Double.parseDouble(feeDto.getPreDegrees()));
                BigDecimal squarePrice = new BigDecimal(Double.parseDouble(feeDto.getMwPrice()));
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
                BigDecimal sub = curDegree.subtract(preDegree);
                feePrice = sub.multiply(squarePrice)
@@ -542,121 +734,6 @@
    }
    /**
     * 计算2个日期之间相差的  以年、月、日为单位,各自计算结果是多少
     * 比如:2011-02-02 到  2017-03-02
     * 以年为单位相差为:6年
     * 以月为单位相差为:73个月
     * 以日为单位相差为:2220天
     *
     * @param fromDate
     * @param toDate
     * @return
     */
    public static double dayCompare(Date fromDate, Date toDate) {
        Calendar from = Calendar.getInstance();
        from.setTime(fromDate);
        Calendar to = Calendar.getInstance();
        to.setTime(toDate);
        long t1 = from.getTimeInMillis();
        long t2 = to.getTimeInMillis();
        double days = (t2 - t1) * 1.00 / (24 * 60 * 60 * 1000);
        BigDecimal tmpDays = new BigDecimal(days);
        BigDecimal monthDay = new BigDecimal(30);
        return tmpDays.divide(monthDay, 2, RoundingMode.HALF_UP).doubleValue();
    }
    private Map getTargetEndDateAndOweMonth(FeeDto feeDto) {
        Date targetEndDate = null;
        double oweMonth = 0.0;
        Map<String, Object> targetEndDateAndOweMonth = new HashMap<>();
        if (FeeDto.STATE_FINISH.equals(feeDto.getState())) {
            targetEndDate = feeDto.getEndTime();
            targetEndDateAndOweMonth.put("oweMonth", oweMonth);
            targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
            return targetEndDateAndOweMonth;
        }
        if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())) {
            if (!StringUtil.isEmpty(feeDto.getCurDegrees())) {
                targetEndDate = feeDto.getCurReadingTime();
            } else if (feeDto.getImportFeeEndTime() == null) {
                targetEndDate = feeDto.getConfigEndTime();
            } else {
                targetEndDate = feeDto.getImportFeeEndTime();
            }
            //判断当前费用是不是导入费用
            oweMonth = 1.0;
        } else {
            //当前时间
            Date billEndTime = DateUtil.getCurrentDate();
            //开始时间
            Date startDate = feeDto.getStartTime();
            //到期时间
            Date endDate = feeDto.getEndTime();
            if (FeeDto.PAYER_OBJ_TYPE_CAR.equals(feeDto.getPayerObjType())) {
                OwnerCarDto ownerCarDto = new OwnerCarDto();
                ownerCarDto.setCommunityId(feeDto.getCommunityId());
                ownerCarDto.setCarId(feeDto.getPayerObjId());
                List<OwnerCarDto> ownerCarDtos = ownerCarInnerServiceSMOImpl.queryOwnerCars(ownerCarDto);
                if (ownerCarDtos == null || ownerCarDtos.size() != 1) {
                    targetEndDateAndOweMonth.put("oweMonth", 0);
                    targetEndDateAndOweMonth.put("targetEndDate", "");
                    return targetEndDateAndOweMonth;
                }
                targetEndDate = ownerCarDtos.get(0).getEndTime();
                //说明没有欠费
                if (endDate.getTime() >= targetEndDate.getTime()) {
                    // 目标到期时间 - 到期时间 = 欠费月份
                    oweMonth = 0;
                    targetEndDateAndOweMonth.put("oweMonth", oweMonth);
                    targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
                    return targetEndDateAndOweMonth;
                }
            }
            //缴费周期
            long paymentCycle = Long.parseLong(feeDto.getPaymentCycle());
            // 当前时间 - 开始时间  = 月份
            double mulMonth = 0.0;
            mulMonth = dayCompare(startDate, billEndTime);
            // 月份/ 周期 = 轮数(向上取整)
            double round = 0.0;
            if ("1200".equals(feeDto.getPaymentCd())) { // 预付费
                round = Math.floor(mulMonth / paymentCycle) + 1;
            } else { //后付费
                round = Math.floor(mulMonth / paymentCycle);
            }
            // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间
            targetEndDate = getTargetEndTime(round * paymentCycle, startDate);
            //费用 快结束了
            if (feeDto.getConfigEndTime().getTime() < targetEndDate.getTime()) {
                targetEndDate = feeDto.getConfigEndTime();
            }
            //说明没有欠费
            if (endDate.getTime() < targetEndDate.getTime()) {
                // 目标到期时间 - 到期时间 = 欠费月份
                oweMonth = dayCompare(endDate, targetEndDate);
            }
            if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) {
                targetEndDate = feeDto.getEndTime();
            }
        }
        targetEndDateAndOweMonth.put("oweMonth", oweMonth);
        targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
        return targetEndDateAndOweMonth;
    }
    private Date getTargetEndTime(double v, Date startDate) {
        Calendar endDate = Calendar.getInstance();