wuxw
2022-07-19 05683f2b2bdbdbe21cf17ad523c21ab338bd1c54
java110-core/src/main/java/com/java110/core/smo/impl/ComputeFeeSMOImpl.java
@@ -20,6 +20,7 @@
import com.java110.intf.community.ICommunityInnerServiceSMO;
import com.java110.intf.community.IParkingSpaceInnerServiceSMO;
import com.java110.intf.community.IRoomInnerServiceSMO;
import com.java110.intf.fee.IFeeAttrInnerServiceSMO;
import com.java110.intf.fee.IFeeInnerServiceSMO;
import com.java110.intf.fee.ITempCarFeeConfigAttrInnerServiceSMO;
import com.java110.intf.fee.ITempCarFeeConfigInnerServiceSMO;
@@ -41,7 +42,12 @@
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
/**
@@ -59,6 +65,9 @@
    @Autowired(required = false)
    private IFeeInnerServiceSMO feeInnerServiceSMOImpl;
    @Autowired(required = false)
    private IFeeAttrInnerServiceSMO feeAttrInnerServiceSMOImpl;
    @Autowired(required = false)
    private IRoomInnerServiceSMO roomInnerServiceSMOImpl;
@@ -278,6 +287,9 @@
            } else if ("1101".equals(computingFormula)) { // 租金
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice(roomDto.getRoomRent());
            }  else if ("1102".equals(computingFormula)) { // 租金
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice(roomDto.getRoomRent());
            } else if ("4004".equals(computingFormula)) {
            } else if ("5005".equals(computingFormula)) {
                if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
@@ -313,7 +325,10 @@
            } else if ("1101".equals(computingFormula)) { //租金
                feeReceiptDetailPo.setArea(roomDtos.get(0).getBuiltUpArea());
                feeReceiptDetailPo.setSquarePrice(roomDtos.get(0).getRoomRent());
            } else {
            } else if ("1102".equals(computingFormula)) { //租金
                feeReceiptDetailPo.setArea(roomDtos.get(0).getBuiltUpArea());
                feeReceiptDetailPo.setSquarePrice(roomDtos.get(0).getRoomRent());
            }else {
            }
        } else if (FeeDto.PAYER_OBJ_TYPE_CAR.equals(feeDto.getPayerObjType())) {//车位相关
            String computingFormula = feeDto.getComputingFormula();
@@ -339,6 +354,9 @@
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice("0");
            } else if ("1101".equals(computingFormula)) { // 租金
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice("0");
            } else if ("1102".equals(computingFormula)) { // 租金(递增)
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice("0");
            } else if ("4004".equals(computingFormula)) {
@@ -416,9 +434,16 @@
                for (ContractRoomDto tmpContractRoomDto : contractRoomDtos) {
                    builtUpArea = builtUpArea.add(new BigDecimal(Double.parseDouble(tmpContractRoomDto.getRoomRent())));
                }
                feeReceiptDetailPo.setArea(builtUpArea.doubleValue() + "");
                feeReceiptDetailPo.setSquarePrice(feeDto.getSquarePrice() + "/" + feeDto.getAdditionalAmount());
            } else if ("4004".equals(computingFormula)) {
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice(builtUpArea.doubleValue() + "");
            } else if ("1102".equals(computingFormula)) { // 租金
                BigDecimal builtUpArea = new BigDecimal(0);
                for (ContractRoomDto tmpContractRoomDto : contractRoomDtos) {
                    builtUpArea = builtUpArea.add(new BigDecimal(Double.parseDouble(tmpContractRoomDto.getRoomRent())));
                }
                feeReceiptDetailPo.setArea("");
                feeReceiptDetailPo.setSquarePrice(builtUpArea.doubleValue() + "");
            }else if ("4004".equals(computingFormula)) {
            } else if ("5005".equals(computingFormula)) {
                if (StringUtil.isEmpty(feeDto.getCurDegrees())) {
                } else {
@@ -816,6 +841,9 @@
            } else if ("1101".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(tmpReportFeeDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
            }  else if ("1102".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(tmpReportFeeDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
            } else if ("4004".equals(computingFormula)) {
                feePrice = new BigDecimal(Double.parseDouble(tmpReportFeeDto.getAmount()));
            } else if ("5005".equals(computingFormula)) {
@@ -868,7 +896,9 @@
                feePrice = new BigDecimal(0);
            } else if ("1101".equals(computingFormula)) { // 租金
                feePrice = new BigDecimal(0);
            } else if ("4004".equals(computingFormula)) {
            }  else if ("1102".equals(computingFormula)) { // 租金
                feePrice = new BigDecimal(0);
            }else if ("4004".equals(computingFormula)) {
                feePrice = new BigDecimal(Double.parseDouble(tmpReportFeeDto.getAmount()));
            } else if ("5005".equals(computingFormula)) {
                if (StringUtil.isEmpty(tmpReportFeeDto.getCurDegrees())) {
@@ -938,9 +968,49 @@
                BigDecimal builtUpArea = new BigDecimal(Double.parseDouble(roomDto.getBuiltUpArea()));
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(feeDto.getAdditionalAmount()));
                feePrice = squarePrice.multiply(builtUpArea).add(additionalAmount).setScale(3, BigDecimal.ROUND_HALF_UP);
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
                if (!StringUtil.isEmpty(feeDto.getCycle()) && !"0".equals(feeDto.getCycle())) {
                    BigDecimal cycle = new BigDecimal(feeDto.getCycle());
                    feeTotalPrice = (squarePrice.multiply(builtUpArea).add(additionalAmount)).multiply(cycle).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
                if (!StringUtil.isEmpty(feeDto.getCycle()) && "0".equals(feeDto.getCycle()) && !StringUtil.isEmpty(feeDto.getCustEndTime())) {
                    //计算周期
                    Map<String, Object> cycleResults = dateDiff(feeDto.getEndTime(), feeDto.getCustEndTime());
                    //月份大于0
                    Integer months = Integer.valueOf(cycleResults.get("months").toString());
                    Integer days = Integer.valueOf(cycleResults.get("days").toString());
                    Integer startMonthDays = Integer.valueOf(cycleResults.get("startMonthDays").toString());
                    Integer endMonthDays = Integer.valueOf(cycleResults.get("endMonthDays").toString());
                    String isOneMonth = cycleResults.get("isOneMonth").toString();
                    //整数月
                    if (months > 0 && days == 0) {
                        BigDecimal cycle = new BigDecimal(months);
                        feeTotalPrice = (squarePrice.multiply(builtUpArea).add(additionalAmount)).multiply(cycle).setScale(3, BigDecimal.ROUND_HALF_UP);
                    }
                    //几个月几天   (单价*面积+附加费)*月份+((单价*面积+附加费)/总天数)*实际天数
                    if (months > 0 && days > 0) {
                        BigDecimal cycle = new BigDecimal(months);
                        BigDecimal endMonthDayss = new BigDecimal(endMonthDays);
                        BigDecimal dayss = new BigDecimal(days);
                        BigDecimal monthPrice = squarePrice.multiply(builtUpArea).add(additionalAmount);
                        feeTotalPrice = (monthPrice).multiply(cycle).add(monthPrice.divide(endMonthDayss).multiply(dayss)).setScale(3, BigDecimal.ROUND_HALF_UP);
                    }
                    //跨月份 不足一月  ((单价*面积+附加费)/开始月份总天数)*实际天数+((单价*面积+附加费)/结束月份总天数)*实际天数
                    if (months == 0 && days > 0 && "true".equals(isOneMonth)) {
                        BigDecimal startEndOfMonth = new BigDecimal(cycleResults.get("startEndOfMonth").toString());
                        BigDecimal endBeginningOfMonth = new BigDecimal(cycleResults.get("endBeginningOfMonth").toString());
                        BigDecimal endMonthDayss = new BigDecimal(endMonthDays);
                        BigDecimal startMonthDayss = new BigDecimal(startMonthDays);
                        BigDecimal monthPrice = squarePrice.multiply(builtUpArea).add(additionalAmount);
                        feeTotalPrice = monthPrice.divide(startMonthDayss, 4, BigDecimal.ROUND_HALF_UP).multiply(startEndOfMonth).add(monthPrice.divide(endMonthDayss, 4, BigDecimal.ROUND_HALF_UP).multiply(endBeginningOfMonth)).setScale(3, BigDecimal.ROUND_HALF_UP);
                    }
                    //不跨月份 不足一月  (单价*面积+附加费/开始月份总天数)*实际天数
                    if (months == 0 && days > 0 && "false".equals(isOneMonth)) {
                        BigDecimal cycle = new BigDecimal(days);
                        BigDecimal startMonthDayss = new BigDecimal(startMonthDays);
                        BigDecimal monthPrice = squarePrice.multiply(builtUpArea).add(additionalAmount);
                        feeTotalPrice = monthPrice.divide(startMonthDayss, 4, BigDecimal.ROUND_HALF_UP).multiply(cycle).setScale(3, BigDecimal.ROUND_HALF_UP);
                    }
                }
            } else if ("2002".equals(computingFormula)) { // 固定费用
                //feePrice = Double.parseDouble(feeDto.getAdditionalAmount());
@@ -960,6 +1030,13 @@
                    feeTotalPrice = (squarePrice.multiply(builtUpArea).add(additionalAmount)).multiply(cycle1).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            } else if ("1101".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(roomDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
                    BigDecimal cycle1 = new BigDecimal(feeDto.getCycle());
                    feeTotalPrice = additionalAmount.multiply(cycle1).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            }else if ("1102".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(roomDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
@@ -1080,7 +1157,14 @@
                    BigDecimal cycle1 = new BigDecimal(feeDto.getCycle());
                    feeTotalPrice = additionalAmount.multiply(cycle1).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            } else if ("4004".equals(computingFormula)) {
            }  else if ("1102".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(roomDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
                    BigDecimal cycle1 = new BigDecimal(feeDto.getCycle());
                    feeTotalPrice = additionalAmount.multiply(cycle1).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            }else if ("4004".equals(computingFormula)) {
                feePrice = new BigDecimal(Double.parseDouble(feeDto.getAmount()));
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
                    BigDecimal cycle1 = new BigDecimal(feeDto.getCycle());
@@ -1180,6 +1264,13 @@
                    feeTotalPrice = (squarePrice.multiply(builtUpArea).add(additionalAmount)).multiply(cycle1).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            } else if ("1101".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(roomDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
                    BigDecimal cycle1 = new BigDecimal(feeDto.getCycle());
                    feeTotalPrice = additionalAmount.multiply(cycle1).setScale(3, BigDecimal.ROUND_HALF_UP);
                }
            }else if ("1102".equals(computingFormula)) { // 租金
                BigDecimal additionalAmount = new BigDecimal(Double.parseDouble(roomDto.getRoomRent()));
                feePrice = additionalAmount.setScale(3, BigDecimal.ROUND_HALF_UP);
                if (!StringUtil.isEmpty(feeDto.getCycle())) {
@@ -1427,7 +1518,9 @@
            //判断当前费用是不是导入费用
            oweMonth = 1.0;
        }else if(FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeDto.getFeeFlag())){
            maxEndTime = feeDto.getDeadlineTime();
            if(feeDto.getDeadlineTime() != null) {
                maxEndTime = feeDto.getDeadlineTime();
            }
            Date billEndTime = DateUtil.getCurrentDate();
            //建账时间
            Date startDate = feeDto.getStartTime();
@@ -1647,16 +1740,16 @@
    }
    public static void main(String[] args) {
        BigDecimal squarePrice = new BigDecimal(Double.parseDouble("4.50"));
        BigDecimal builtUpArea = new BigDecimal(Double.parseDouble("52.69"));
        BigDecimal additionalAmount = new BigDecimal(Double.parseDouble("0"));
            BigDecimal cycle = new BigDecimal(Double.parseDouble("3"));
        BigDecimal  feeTotalPrice = (squarePrice.multiply(builtUpArea).add(additionalAmount)).multiply(cycle).setScale(3, BigDecimal.ROUND_HALF_DOWN);
        System.out.println(feeTotalPrice.doubleValue());
    }
//    public static void main(String[] args) {
//        BigDecimal squarePrice = new BigDecimal(Double.parseDouble("4.50"));
//        BigDecimal builtUpArea = new BigDecimal(Double.parseDouble("52.69"));
//        BigDecimal additionalAmount = new BigDecimal(Double.parseDouble("0"));
//            BigDecimal cycle = new BigDecimal(Double.parseDouble("3"));
//        BigDecimal  feeTotalPrice = (squarePrice.multiply(builtUpArea).add(additionalAmount)).multiply(cycle).setScale(3, BigDecimal.ROUND_HALF_DOWN);
//        System.out.println(feeTotalPrice.doubleValue());
//    }
    //    public static void main(String[] args) {
//        ComputeFeeSMOImpl computeFeeSMO = new ComputeFeeSMOImpl();
//        try {
//            Date startTime = DateUtil.getDateFromString("2020-12-31 00:00:00", DateUtil.DATE_FORMATE_STRING_A);
@@ -1669,4 +1762,216 @@
//            e.printStackTrace();
//        }
//    }
    static int[] getDiff(LocalDate start, LocalDate end) {
        if (!start.isBefore(end)) {
            throw new IllegalArgumentException("Start must not be before end.");
        }
        int year1 = start.getYear();
        int month1 = start.getMonthValue();
        int day1 = start.getDayOfMonth();
        int year2 = end.getYear();
        int month2 = end.getMonthValue();
        int day2 = end.getDayOfMonth();
        int yearDiff = year2 - year1;     // yearDiff >= 0
        int monthDiff = month2 - month1;
        int dayDiff = day2 - day1;
        if (dayDiff < 0) {
            LocalDate endMinusOneMonth = end.minusMonths(1);   // end 的上一个月
            int monthDays = endMinusOneMonth.lengthOfMonth();  // 该月的天数
            dayDiff += monthDays;  // 用上一个月的天数补上这个月差掉的日子
            if (monthDiff > 0) {   // eg. start is 2018-04-03, end is 2018-08-01
                monthDiff--;
            } else {  // eg. start is 2018-04-03, end is 2019-02-01
                monthDiff += 11;
                yearDiff--;
            }
        }
        int[] diff = new int[2];
        diff[0] = yearDiff * 12 + monthDiff;
        diff[1] = dayDiff;
        return diff;
    }
    /**
     * 计算两个日期的时间差
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public Map<String, Object> dateDiff(Date startDate, String endDate) {
        Map<String, Object> cycle = new HashMap<>();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date endDates = null;
        try {
            endDates = format.parse(endDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(endDates);
        calendar.add(calendar.DATE, 1);
        Date date = calendar.getTime();
        LocalDate end = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        int[] diff = getDiff(start, end);
        cycle.put("months", diff[0]);//几个月
        cycle.put("days", diff[1]);//几天
        String startDateString = format.format(startDate);
        String endDateString = format.format(endDates);
        cycle.put("startMonthDays", getDayOfMonth(startDateString));//开始月份天数
        cycle.put("endMonthDays", getDayOfMonth(endDateString));//结束月份天数
        cycle.put("isOneMonth", false);// false 不跨月 true月份
        if (diff[0] == 0) {
            //判断是否同一个月
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
            String date1 = sdf.format(startDate);
            String date2 = sdf.format(endDates);
            if (!date1.equals(date2)) {
                cycle.put("isOneMonth", true);
                //计算夸月分两个月分别是多少天
                SimpleDateFormat sdfday = new SimpleDateFormat("dd");
                Integer startDate1 = Integer.valueOf(sdfday.format(startDate));
                String endDates2 = sdfday.format(endDates);
                cycle.put("startEndOfMonth", getDayOfMonth(startDateString) - startDate1 + 1);//开始月份天数
                cycle.put("endBeginningOfMonth", Integer.valueOf(endDates2));//结束月份天数
            }
        }
        return cycle;
    }
    /**
     * 获取日期内的天数
     *
     * @param dateStr
     * @return
     */
    public int getDayOfMonth(String dateStr) {
        int year = Integer.parseInt(dateStr.substring(0, 4));
        int month = Integer.parseInt(dateStr.substring(5, 7));
        Calendar c = Calendar.getInstance();
        c.set(year, month, 0); //输入类型为int类型
        return c.get(Calendar.DAY_OF_MONTH);
    }
    /**
     *
     * @param feeDto
     * @param cycle
     */
    public void dealRentRateCycle(FeeDto feeDto,double cycle){
        Date endTime = feeDto.getEndTime();
        Date date = getTargetEndTime(cycle,endTime);
        feeDto.setDeadlineTime(date);
        dealRentRate(feeDto);
    }
    /**
     * 租金处理
     *
     * @param feeDto
     */
    public void dealRentRate(FeeDto feeDto) {
        if (!FeeConfigDto.COMPUTING_FORMULA_RANT_RATE.equals(feeDto.getComputingFormula())) {
            return;
        }
        //查询递增信息
        FeeAttrDto feeAttrDto = new FeeAttrDto();
        feeAttrDto.setFeeId(feeDto.getFeeId());
        feeAttrDto.setCommunityId(feeDto.getCommunityId());
        List<FeeAttrDto> feeAttrDtos = feeAttrInnerServiceSMOImpl.queryFeeAttrs(feeAttrDto);
        if (feeAttrDtos == null || feeAttrDtos.size() < 1) {
            return;
        }
        int rateCycle = 0;
        double rate = 0.0;
        Date rateStartTime = null;
        try {
            for (FeeAttrDto tmpFeeAttrDto : feeAttrDtos) {
                if (FeeAttrDto.SPEC_CD_RATE.equals(tmpFeeAttrDto.getSpecCd())) {
                    feeDto.setRate(tmpFeeAttrDto.getValue());
                    rate = Double.parseDouble(tmpFeeAttrDto.getValue());
                }
                if (FeeAttrDto.SPEC_CD_RATE_CYCLE.equals(tmpFeeAttrDto.getSpecCd())) {
                    feeDto.setRateCycle(tmpFeeAttrDto.getValue());
                    rateCycle = Integer.parseInt(tmpFeeAttrDto.getValue());
                }
                if (FeeAttrDto.SPEC_CD_RATE_START_TIME.equals(tmpFeeAttrDto.getSpecCd())) {
                    feeDto.setRateStartTime(tmpFeeAttrDto.getValue());
                    rateStartTime = DateUtil.getDateFromString(tmpFeeAttrDto.getValue(), DateUtil.DATE_FORMATE_STRING_B);
                }
            }
        } catch (Exception e) {
            logger.error("租金递增异常", e);
            return;
        }
        if (!FeeDto.STATE_DOING.equals(feeDto.getState())) {
            return;
        }
        if (rateCycle == 0 || rate == 0) {
            return;
        }
        if (feeDto.getDeadlineTime().getTime() <= rateStartTime.getTime()) {
            return;
        }
        BigDecimal oweAmountDec = new BigDecimal(0);
        //计算 计费起始时间 到 rateStartTime 时的费用
        double curOweMonth = 0;
        BigDecimal curFeePrice = new BigDecimal(feeDto.getFeePrice());
        if (feeDto.getEndTime().getTime() < rateStartTime.getTime()) {
            curOweMonth = dayCompare(feeDto.getEndTime(), rateStartTime);
            oweAmountDec = curFeePrice.multiply(new BigDecimal(curOweMonth)).setScale(2, BigDecimal.ROUND_HALF_UP);
        }
        curOweMonth = dayCompare(rateStartTime, feeDto.getDeadlineTime());
        double maxCycle = Math.floor(curOweMonth / rateCycle);
        //基准
        BigDecimal firstAmount = curFeePrice.multiply(new BigDecimal(rateCycle));
        BigDecimal preCycleAmount = firstAmount;
        BigDecimal rateDec = null; //递增周期所收费用
        BigDecimal lastRateAmountDec = null;
        double curCycle = 0;
        for (int cycleIndex = 0; cycleIndex < maxCycle; maxCycle++) {
            rateDec = preCycleAmount.multiply(new BigDecimal(rate)).setScale(2, BigDecimal.ROUND_HALF_UP);
            //增长周期的倍数
            curCycle = (cycleIndex + 1) * rateCycle;
            if (curCycle > curOweMonth) {
                rateDec = new BigDecimal(curOweMonth / rateCycle - Math.ceil(curOweMonth / rateCycle)).multiply(rateDec).setScale(2, BigDecimal.ROUND_HALF_UP);
                lastRateAmountDec = new BigDecimal(curOweMonth / rateCycle - Math.ceil(curOweMonth / rateCycle)).multiply(preCycleAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                firstAmount = firstAmount.add(rateDec).add(lastRateAmountDec);
                continue;
            }
            firstAmount = firstAmount.add(rateDec).add(preCycleAmount);
            preCycleAmount = preCycleAmount.add(rateDec);
        }
        firstAmount = firstAmount.add(oweAmountDec);
        feeDto.setAmountOwed(firstAmount.doubleValue() + "");
        feeDto.setFeeTotalPrice(firstAmount.doubleValue());
    }
}