wuxw
2024-05-31 8c066c39b9e5ebc39992f7152bf706acdae00f4a
java110-core/src/main/java/com/java110/core/smo/impl/ComputeFeeSMOImpl.java
@@ -127,13 +127,14 @@
    public void computeEveryOweFeeByTargetEndTime(FeeDto feeDto, String targetEndTime) {
        Date targetEndDate = DateUtil.getDateFromStringB(targetEndTime);
        double oweMonth = 1.0;
        double oweMonth = 0;
        if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) {
            targetEndDate = feeDto.getEndTime();
        }
        if (feeDto.getEndTime().getTime() < targetEndDate.getTime()) {
            // 目标到期时间 - 到期时间 = 欠费月份
            oweMonth = DateUtil.dayCompare(feeDto.getEndTime(), targetEndDate);
            oweMonth = DateUtil.dayCompare(feeDto.getEndTime(), targetEndDate, true);
        }
        String computingFormula = feeDto.getComputingFormula();
@@ -489,7 +490,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)) { //数据有问题
                return objName;
            }
            objName = objName + "-" + parkingSpaceDtos.get(0).getAreaNum() + "停车场" + "-" + parkingSpaceDtos.get(0).getNum() + "车位";
@@ -505,6 +506,19 @@
        }
        return objName;
    }
    @Override
    public OwnerDto getFeeOwnerDto(String feeId) {
        FeeDto feeDto = new FeeDto();
        feeDto.setFeeId(feeId);
        List<FeeDto> feeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
        Assert.listOnlyOne(feeDtos, "费用不存在");
        feeDtos.get(0).setFeeAttrDtos(null); // todo 这里设置为空,不要从属性中查以防数据有问题导致有问题
        return getFeeOwnerDto(feeDtos.get(0));
    }
    @Override
@@ -558,7 +572,7 @@
    private OwnerDto getOwnerDtoByFeeAttr(FeeDto feeDto) {
        List<FeeAttrDto> feeAttrDtos = feeDto.getFeeAttrDtos();
        if (feeAttrDtos == null || feeAttrDtos.size() < 1) {
        if (ListUtil.isNull(feeAttrDtos)) {
            return null;
        }
@@ -762,16 +776,15 @@
            } else {
                endCalender.setTime(feeDto.getImportFeeEndTime());
            }
        } else if (FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeDto.getFeeFlag())) {
            if (feeDto.getDeadlineTime() == null) {
                throw new IllegalArgumentException("间接性费用未设置结束时间");
            }
            if ((endCalender.getTime()).after(feeDto.getDeadlineTime())) {
                endCalender.setTime(feeDto.getDeadlineTime());
            }
        } else {
            if ((endCalender.getTime()).after(feeDto.getConfigEndTime())) {
                endCalender.setTime(feeDto.getConfigEndTime());
            Date deadLineTime = feeDto.getDeadlineTime();
            if (deadLineTime == null) {
                deadLineTime = feeDto.getConfigEndTime();
            }
            if ((endCalender.getTime()).after(deadLineTime)) {
                endCalender.setTime(feeDto.getDeadlineTime());
            } else {
                endCalender.add(Calendar.SECOND, -1);
            }
        }
@@ -1665,7 +1678,10 @@
        Date preEndTime = preEndTimeCal.getTime();
        //todo 当前费用为一次性费用
        Date maxEndTime = feeDto.getConfigEndTime();
        Date maxEndTime = feeDto.getDeadlineTime();
        if (maxEndTime == null) {
            maxEndTime = feeDto.getConfigEndTime();
        }
        if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())) {
            //先取 deadlineTime
            if (feeDto.getDeadlineTime() != null) {
@@ -1687,11 +1703,7 @@
            if (StringUtil.isNumber(feeDto.getMonthCycle())) {
                oweMonth = Integer.parseInt(feeDto.getMonthCycle());
            }
        } else if (FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeDto.getFeeFlag())) {
            if (feeDto.getDeadlineTime() != null) {
                maxEndTime = feeDto.getDeadlineTime();
            }
        } else {
            Date billEndTime = DateUtil.getCurrentDate();
            //建账时间
            Date startDate = feeDto.getStartTime();
@@ -1719,7 +1731,6 @@
            ) {
                targetEndDate = getTargetEndTime((round + 1) * paymentCycle, startDate);//目标结束时间
            }
            //todo 费用项的结束时间<缴费的结束时间  费用快结束了   取费用项的结束时间
            if (maxEndTime.getTime() < targetEndDate.getTime()) {
@@ -1728,50 +1739,7 @@
            //说明欠费
            if (endDate.getTime() < targetEndDate.getTime()) {
                // 目标到期时间 - 到期时间 = 欠费月份
                oweMonth = DateUtil.dayCompare(endDate, targetEndDate);
            }
            if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) {
                targetEndDate = feeDto.getEndTime();
            }
        } else { // todo 周期性费用
            //当前时间
            Date billEndTime = DateUtil.getCurrentDate();
            //建账时间
            Date startDate = feeDto.getStartTime();
            //计费起始时间
            Date endDate = feeDto.getEndTime();
            //缴费周期
            long paymentCycle = Long.parseLong(feeDto.getPaymentCycle());
            // 当前时间 - 开始时间  = 月份
            double mulMonth = 0.0;
            mulMonth = DateUtil.dayCompare(startDate, billEndTime);
            // 月份/ 周期 = 轮数(向上取整)
            double round = 0.0;
            if ("1200".equals(feeDto.getPaymentCd())) { // 1200预付费
                round = Math.floor(mulMonth / paymentCycle) + 1;
            } else { //2100后付费
                round = Math.floor(mulMonth / paymentCycle);
            }
            // 轮数 * 周期 * 30 + 开始时间 = 目标 到期时间
            targetEndDate = getTargetEndTime(round * paymentCycle, startDate);//目标结束时间
            //todo 如果 到了 预付期 产生下个周期的费用
            if (DateUtil.getFormatTimeStringB(targetEndDate).equals(DateUtil.getFormatTimeStringB(endDate))
                    && DateUtil.getCurrentDate().getTime() > preEndTime.getTime()
            ) {
                targetEndDate = getTargetEndTime((round + 1) * paymentCycle, startDate);//目标结束时间
            }
            //费用项的结束时间<缴费的结束时间  费用快结束了   取费用项的结束时间
            if (maxEndTime.getTime() < targetEndDate.getTime()) {
                targetEndDate = maxEndTime;
            }
            //说明欠费
            if (endDate.getTime() < targetEndDate.getTime()) {
                // 目标到期时间 - 到期时间 = 欠费月份
                oweMonth = DateUtil.dayCompare(endDate, targetEndDate);
                oweMonth = DateUtil.dayCompare(endDate, targetEndDate, true);
            }
            if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) {
@@ -1885,11 +1853,13 @@
        endDate.add(Calendar.MONTH, intMonth.intValue());
        double doubleMonth = month - intMonth;
        if (doubleMonth <= 0) {
            endDate.add(Calendar.SECOND, -1);
            return endDate.getTime();
        }
        int futureDay = endDate.getActualMaximum(Calendar.DAY_OF_MONTH);
        Double hour = doubleMonth * futureDay * 24;
        endDate.add(Calendar.HOUR_OF_DAY, hour.intValue());
        endDate.add(Calendar.SECOND, -1);
        return endDate.getTime();
    }
@@ -2126,7 +2096,7 @@
        feeAttrDto.setCommunityId(feeDto.getCommunityId());
        List<FeeAttrDto> feeAttrDtos = feeAttrInnerServiceSMOImpl.queryFeeAttrs(feeAttrDto);
        if (feeAttrDtos == null || feeAttrDtos.size() < 1) {
        if (ListUtil.isNull(feeAttrDtos)) {
            return;
        }
        int rateCycle = 0;
@@ -2164,8 +2134,9 @@
            return;
        }
        Date oRateStartTime = rateStartTime;
        //todo 递增时间 不是 费用建账时间的倍数时,修正一下
        rateStartTime = correctByFeeStartTime(rateStartTime,feeDto.getStartTime());
        rateStartTime = correctByFeeStartTime(rateStartTime, feeDto.getStartTime());
        BigDecimal addTotalAmount = new BigDecimal("0");
        double curOweMonth = 0;
@@ -2193,8 +2164,10 @@
        BigDecimal rateDec = new BigDecimal(rate + "");
        BigDecimal oweAmountDec = null;
        //todo 递增轮数 循环 curFeePrice 这个是 原始租金
        BigDecimal oldFeePrice = null;
        for (int cycleIndex = 0; cycleIndex < maxCycle; cycleIndex++) {
            //todo 递增月单价
            oldFeePrice = curFeePrice;
            curFeePrice = new BigDecimal("1").add(rateDec).multiply(curFeePrice).setScale(FeeConfigConstant.FEE_SCALE, BigDecimal.ROUND_HALF_UP);
            //todo 计算 curCycleRateEneTime 本轮递增结束时间
@@ -2205,20 +2178,31 @@
                continue;
            }
            //todo 本轮 欠费开始时间大于 deadlineTime 跳过
            if(curOweStartTime.getTime() >= feeDto.getDeadlineTime().getTime()){
            if (curOweStartTime.getTime() >= feeDto.getDeadlineTime().getTime()) {
                continue;
            }
            boolean hasInRateMonth = false;
            //todo 本轮递增时间未到 费用deadlineTime
            if (curCycleRateEneTime.getTime() < feeDto.getDeadlineTime().getTime()) {
                curOweMonth = DateUtil.dayCompare(curOweStartTime, curCycleRateEneTime);
                hasInRateMonth = rateStartMonthIn(oRateStartTime, curOweStartTime, curCycleRateEneTime);
                curOweStartTime = curCycleRateEneTime;
            } else {
                curOweMonth = DateUtil.dayCompare(curOweStartTime, feeDto.getDeadlineTime());
                hasInRateMonth = rateStartMonthIn(oRateStartTime, curOweStartTime, feeDto.getDeadlineTime());
                curOweStartTime = feeDto.getDeadlineTime();
            }
            oweAmountDec = curFeePrice.multiply(new BigDecimal(curOweMonth)).setScale(FeeConfigConstant.FEE_SCALE, BigDecimal.ROUND_HALF_UP);
            if (hasInRateMonth) {
                //todo 递增月如果建账时间和递增日期不一致,那么减去建账时间日至 递增日的递增部分
                int moreComputeDay = getRateDay(feeDto.getStartTime(), oRateStartTime);
                BigDecimal moreComputeAmountDec = oldFeePrice.multiply(rateDec).divide(new BigDecimal(DateUtil.getMonthDay(oRateStartTime)), FeeConfigConstant.FEE_SCALE, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(moreComputeDay));
                oweAmountDec = oweAmountDec.subtract(moreComputeAmountDec);
            }
            addTotalAmount = addTotalAmount.add(oweAmountDec);
        }
@@ -2229,8 +2213,60 @@
    }
    /**
     * 递增月在这个之间
     *
     * @param oRateStartTime
     * @param startTime
     * @param endTime
     * @return
     */
    private boolean rateStartMonthIn(Date oRateStartTime, Date startTime, Date endTime) {
        Calendar calendarStartTime = Calendar.getInstance();
        calendarStartTime.setTime(startTime);
        calendarStartTime.set(Calendar.DAY_OF_MONTH, 1);
        Calendar calendarEndTime = Calendar.getInstance();
        calendarEndTime.setTime(endTime);
        //calendarEndTime.set(Calendar.DAY_OF_MONTH,1);
        Calendar calendarOrate = Calendar.getInstance();
        calendarOrate.setTime(oRateStartTime);
        calendarOrate.set(Calendar.YEAR, calendarStartTime.get(Calendar.YEAR));
        if (calendarStartTime.getTime().before(calendarOrate.getTime()) && calendarEndTime.getTime().after(calendarOrate.getTime())) {
            return true;
        }
        calendarOrate.set(Calendar.YEAR, calendarEndTime.get(Calendar.YEAR));
        if (calendarStartTime.getTime().before(calendarOrate.getTime()) && calendarEndTime.getTime().after(calendarOrate.getTime())) {
            return true;
        }
        return false;
    }
    private int getRateDay(Date startTime, Date rateStartTime) {
        Calendar rateCalendar = Calendar.getInstance();
        rateCalendar.setTime(rateStartTime);
        int rateDay = rateCalendar.get(Calendar.DAY_OF_MONTH);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        if (rateDay == day || rateDay < day) {
            return 0;
        }
        return rateDay - day;
    }
    /**
     * 修正递增 开始时间
     * 如果设置的 递增开始时间和建账时间不是同一天 强制修正下
     *
     * @param rateStartTime
     * @param startTime
     * @return
@@ -2242,14 +2278,14 @@
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        if(rateDay == day){
        if (rateDay == day) {
            return rateStartTime;
        }
        rateCalendar = Calendar.getInstance();
        rateCalendar.setTime(rateStartTime);
        rateCalendar.add(Calendar.MONTH,1);
        rateCalendar.set(Calendar.DAY_OF_MONTH,day);
        //rateCalendar.add(Calendar.MONTH, 1);
        rateCalendar.set(Calendar.DAY_OF_MONTH, day);
        return rateCalendar.getTime();
    }