java110
2023-05-11 672b30c82edac9bf0c0e6b63761aa4ca5b69d8cc
optimize pay fee to month
16个文件已修改
4个文件已添加
649 ■■■■ 已修改文件
java110-bean/src/main/java/com/java110/dto/payFeeDetailMonth/PayFeeDetailMonthDto.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-bean/src/main/java/com/java110/dto/payFeeDetailMonth/PayFeeDetailRefreshFeeMonthDto.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-bean/src/main/java/com/java110/po/payFeeDetailMonth/PayFeeDetailMonthPo.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-boot/src/main/java/com/java110/user/test.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-core/src/main/java/com/java110/core/smo/IComputeFeeSMO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-core/src/main/java/com/java110/core/smo/impl/ComputeFeeSMOImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-db/src/main/resources/mapper/fee/PayFeeDetailMonthServiceDaoImplMapper.xml 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-interface/src/main/java/com/java110/intf/fee/IPayFeeDetailMonthInnerServiceSMO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-interface/src/main/java/com/java110/intf/fee/IPayFeeMonthInnerServiceSMO.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-utils/src/main/java/com/java110/utils/util/DateUtil.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/dao/IPayFeeDetailMonthServiceDao.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/dao/impl/PayFeeDetailMonthServiceDaoImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/feeMonth/IPayFeeMonth.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/feeMonth/IPayFeeMonthHelp.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/feeMonth/PayFeeMonthHelp.java 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/feeMonth/PayFeeMonthImpl.java 149 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/smo/impl/PayFeeDetailMonthInnerServiceSMOImpl.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-fee/src/main/java/com/java110/fee/smo/impl/PayFeeMonthInnerServiceSMOImpl.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service-job/src/main/java/com/java110/job/adapt/fee/asyn/impl/PayFeeDetailToMonthIImpl.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
springboot/src/test/java/com/java110/AppTest.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
java110-bean/src/main/java/com/java110/dto/payFeeDetailMonth/PayFeeDetailMonthDto.java
@@ -43,6 +43,8 @@
    private String state;
    private String payFeeTime;
    private String curMonthTime;
    public String getDetailMonth() {
        return detailMonth;
@@ -196,4 +198,12 @@
    public void setPayFeeTime(String payFeeTime) {
        this.payFeeTime = payFeeTime;
    }
    public String getCurMonthTime() {
        return curMonthTime;
    }
    public void setCurMonthTime(String curMonthTime) {
        this.curMonthTime = curMonthTime;
    }
}
java110-bean/src/main/java/com/java110/dto/payFeeDetailMonth/PayFeeDetailRefreshFeeMonthDto.java
New file
@@ -0,0 +1,37 @@
package com.java110.dto.payFeeDetailMonth;
import java.io.Serializable;
/**
 * 缴费离散月对象
 *
 */
public class PayFeeDetailRefreshFeeMonthDto implements Serializable {
    private String communityId;
    private String feeId;
    private String detailId;
    public String getCommunityId() {
        return communityId;
    }
    public void setCommunityId(String communityId) {
        this.communityId = communityId;
    }
    public String getFeeId() {
        return feeId;
    }
    public void setFeeId(String feeId) {
        this.feeId = feeId;
    }
    public String getDetailId() {
        return detailId;
    }
    public void setDetailId(String detailId) {
        this.detailId = detailId;
    }
}
java110-bean/src/main/java/com/java110/po/payFeeDetailMonth/PayFeeDetailMonthPo.java
@@ -25,6 +25,12 @@
    private String state;
    private String payFeeTime;
    private String curMonthTime;
    private String curMonthStartTime;
    private String curMonthEndTime;
    public String getDetailMonth() {
        return detailMonth;
@@ -169,4 +175,28 @@
    public void setPayFeeTime(String payFeeTime) {
        this.payFeeTime = payFeeTime;
    }
    public String getCurMonthTime() {
        return curMonthTime;
    }
    public void setCurMonthTime(String curMonthTime) {
        this.curMonthTime = curMonthTime;
    }
    public String getCurMonthStartTime() {
        return curMonthStartTime;
    }
    public void setCurMonthStartTime(String curMonthStartTime) {
        this.curMonthStartTime = curMonthStartTime;
    }
    public String getCurMonthEndTime() {
        return curMonthEndTime;
    }
    public void setCurMonthEndTime(String curMonthEndTime) {
        this.curMonthEndTime = curMonthEndTime;
    }
}
java110-boot/src/main/java/com/java110/user/test.java
New file
@@ -0,0 +1,14 @@
package com.java110.user;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class test {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.YEAR,2023);
        calendar.set(Calendar.MONTH,12);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.printf(dateFormat.format(calendar.getTime())+"");
    }
}
java110-core/src/main/java/com/java110/core/smo/IComputeFeeSMO.java
@@ -35,6 +35,13 @@
    Date getFeeEndTime();
    /**
     * 获取 deadlineTime
     * @param feeDto
     * @return
     */
    Date getDeadlineTime(FeeDto feeDto);
    /**
     * 计算欠费金额
     *
     * @param tmpFeeDto
java110-core/src/main/java/com/java110/core/smo/impl/ComputeFeeSMOImpl.java
@@ -1793,6 +1793,12 @@
    }
    @Override
    public Date getDeadlineTime(FeeDto feeDto){
        Map info = getTargetEndDateAndOweMonth(feeDto);
        return (Date)info.get("targetEndDate");
    }
    /**
     * 计算 计费结束时间和 欠费月份(可能存在小数点)
     *
@@ -1907,14 +1913,6 @@
    }
    public Map getTargetEndDateAndOweMonth(FeeDto feeDto) {
//        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);
//            return getTargetEndDateAndOweMonth(feeDto, ownerCarDtos == null || ownerCarDtos.size() < 1 ? null : ownerCarDtos.get(0));
//        }
        return getTargetEndDateAndOweMonth(feeDto, null);
    }
java110-db/src/main/resources/mapper/fee/PayFeeDetailMonthServiceDaoImplMapper.xml
@@ -151,6 +151,10 @@
        <if test="detailId !=null and detailId != ''">
            and t.detail_id= #{detailId}
        </if>
        <if test="curMonthStartTime !=null and curMonthStartTime != ''">
            and t.cur_month_time &gt;= #{curMonthStartTime}
            and t.cur_month_time &lt;= #{curMonthEndTime}
        </if>
    </update>
    <!-- 查询月缴费表数量 add by wuxw 2018-07-03 -->
@@ -209,7 +213,71 @@
        <if test="payFeeTime !=null and payFeeTime != ''">
            and t.pay_fee_time= #{payFeeTime}
        </if>
    </select>
    <select id="queryPayFeeDetailMaxMonths" parameterType="Map" resultType="Map">
        select t.detail_month,t.detail_month detailMonth,t.detail_year,t.detail_year detailYear,t.detail_id,t.detail_id
        detailId,t.receivable_amount,t.receivable_amount receivableAmount,t.discount_amount,t.discount_amount
        discountAmount,t.remark,t.status_cd,t.status_cd statusCd,t.received_amount,t.received_amount
        receivedAmount,t.community_id,t.community_id communityId,t.fee_id,t.fee_id feeId,t.month_id,t.month_id monthId,
        t.obj_name objName,t.obj_id objId,t.owner_name ownerName,t.owner_id ownerId,t.link,t.state,t.pay_fee_time payFeeTime
        from pay_fee_detail_month t
        where 1 =1
        <if test="detailMonth !=null and detailMonth != ''">
            and t.detail_month= #{detailMonth}
        </if>
        <if test="detailYear !=null and detailYear != ''">
            and t.detail_year= #{detailYear}
        </if>
        <if test="detailId !=null and detailId != ''">
            and t.detail_id= #{detailId}
        </if>
        <if test="receivableAmount !=null and receivableAmount != ''">
            and t.receivable_amount= #{receivableAmount}
        </if>
        <if test="discountAmount !=null and discountAmount != ''">
            and t.discount_amount= #{discountAmount}
        </if>
        <if test="remark !=null and remark != ''">
            and t.remark= #{remark}
        </if>
        <if test="statusCd !=null and statusCd != ''">
            and t.status_cd= #{statusCd}
        </if>
        <if test="receivedAmount !=null and receivedAmount != ''">
            and t.received_amount= #{receivedAmount}
        </if>
        <if test="communityId !=null and communityId != ''">
            and t.community_id= #{communityId}
        </if>
        <if test="feeId !=null and feeId != ''">
            and t.fee_id= #{feeId}
        </if>
        <if test="monthId !=null and monthId != ''">
            and t.month_id= #{monthId}
        </if>
        <if test="objName !=null and objName != ''">
            and t.obj_name= #{objName}
        </if>
        <if test="objId !=null and objId != ''">
            and t.obj_id= #{objId}
        </if>
        <if test="ownerName !=null and ownerName != ''">
            and t.owner_name= #{ownerName}
        </if>
        <if test="ownerId !=null and ownerId != ''">
            and t.owner_id= #{ownerId}
        </if>
        <if test="state !=null and state != ''">
            and t.state= #{state}
        </if>
        <if test="payFeeTime !=null and payFeeTime != ''">
            and t.pay_fee_time= #{payFeeTime}
        </if>
        order by t.detail_year ,t.detail_month
        <if test="page != -1 and page != null ">
            limit #{page}, #{row}
        </if>
    </select>
java110-interface/src/main/java/com/java110/intf/fee/IPayFeeDetailMonthInnerServiceSMO.java
@@ -54,4 +54,7 @@
     */
    @RequestMapping(value = "/queryPayFeeDetailMonthsCount", method = RequestMethod.POST)
    int queryPayFeeDetailMonthsCount(@RequestBody PayFeeDetailMonthDto payFeeDetailMonthDto);
    @RequestMapping(value = "/queryPayFeeDetailMaxMonths", method = RequestMethod.POST)
    List<PayFeeDetailMonthDto> queryPayFeeDetailMaxMonths(@RequestBody PayFeeDetailMonthDto payFeeDetailMonthDto);
}
java110-interface/src/main/java/com/java110/intf/fee/IPayFeeMonthInnerServiceSMO.java
New file
@@ -0,0 +1,38 @@
package com.java110.intf.fee;
import com.java110.config.feign.FeignConfiguration;
import com.java110.dto.payFeeDetailMonth.PayFeeDetailMonthDto;
import com.java110.dto.payFeeDetailMonth.PayFeeDetailRefreshFeeMonthDto;
import com.java110.po.payFeeDetailMonth.PayFeeDetailMonthPo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.util.List;
/**
 * @ClassName IPayFeeDetailMonthInnerServiceSMO
 * @Description 月缴费表接口类
 * @Author wuxw
 * @Date 2019/4/24 9:04
 * @Version 1.0
 * add by wuxw 2019/4/24
 **/
@FeignClient(name = "${java110.fee-service}", configuration = {FeignConfiguration.class})
@RequestMapping("/payFeeMonthApi")
public interface IPayFeeMonthInnerServiceSMO {
    /**
     * 缴费处理离散表
     * @param payFeeDetailRefreshFeeMonthDto
     * @return
     */
    @RequestMapping(value = "/payFeeDetailRefreshFeeMonth", method = RequestMethod.POST)
    int payFeeDetailRefreshFeeMonth(PayFeeDetailRefreshFeeMonthDto payFeeDetailRefreshFeeMonthDto);
}
java110-utils/src/main/java/com/java110/utils/util/DateUtil.java
@@ -123,6 +123,21 @@
        }
    }
    public static String getFormatTimeStringA(Date date) {
        SimpleDateFormat sDateFormat = getDateFormat(DateUtil.DATE_FORMATE_STRING_A);
        synchronized (sDateFormat) {
            return sDateFormat.format(date);
        }
    }
    public static String getFormatTimeStringB(Date date) {
        SimpleDateFormat sDateFormat = getDateFormat(DateUtil.DATE_FORMATE_STRING_B);
        synchronized (sDateFormat) {
            return sDateFormat.format(date);
        }
    }
    public static String getDefaultFormateTimeString(Date date) {
        return getFormatTimeString(date, "yyyyMMddHHmmss");
    }
service-fee/src/main/java/com/java110/fee/dao/IPayFeeDetailMonthServiceDao.java
@@ -61,4 +61,5 @@
    int queryPayFeeDetailMonthsCount(Map info);
    List<Map> queryPayFeeDetailMaxMonths(Map info);
}
service-fee/src/main/java/com/java110/fee/dao/impl/PayFeeDetailMonthServiceDaoImpl.java
@@ -102,5 +102,14 @@
        return Integer.parseInt(businessPayFeeDetailMonthInfos.get(0).get("count").toString());
    }
    @Override
    public List<Map> queryPayFeeDetailMaxMonths(Map info) {
        logger.debug("查询queryPayFeeDetailMaxMonths信息 入参 info : {}", info);
        List<Map> businessPayFeeDetailMonthInfos = sqlSessionTemplate.selectList("payFeeDetailMonthServiceDaoImpl.queryPayFeeDetailMaxMonths", info);
        return businessPayFeeDetailMonthInfos;
    }
}
service-fee/src/main/java/com/java110/fee/feeMonth/IPayFeeMonth.java
@@ -22,4 +22,12 @@
     */
    void doGeneratorOrRefreshAllFeeMonth(String communityId);
    /**
     * 缴费 离散数据
     * @param feeId
     * @param detailId
     * @param communityId
     */
    void payFeeDetailRefreshFeeMonth(String feeId,String detailId,String communityId);
}
service-fee/src/main/java/com/java110/fee/feeMonth/IPayFeeMonthHelp.java
@@ -1,11 +1,37 @@
package com.java110.fee.feeMonth;
import com.java110.dto.fee.FeeDetailDto;
import com.java110.dto.fee.FeeDto;
import com.java110.dto.payFeeDetailMonth.PayFeeMonthOwnerDto;
import java.util.Date;
import java.util.List;
public interface IPayFeeMonthHelp {
    PayFeeMonthOwnerDto generatorOwnerRoom(FeeDto feeDto);
    Double getMonthFeePrice(FeeDto feeDto);
    Double getReceivableAmount(List<FeeDetailDto> feeDetailDtos, Double feePrice, Date curDate, FeeDto feeDto);
    /**
     * 计算实收
     * @param feeDetailDtos
     * @param feePrice
     * @return
     */
    Double getReceivedAmount(List<FeeDetailDto> feeDetailDtos, Double feePrice, Date curDate, FeeDto feeDto);
    Double getDiscountAmount(Double feePrice, double parseDouble, Date curDate, FeeDto feeDto);
    /**
     * 计算缴费DetailId
     * @param feeDetailDtos
     * @param time
     * @return
     */
    String getFeeDetailId(List<FeeDetailDto> feeDetailDtos, Date time);
}
service-fee/src/main/java/com/java110/fee/feeMonth/PayFeeMonthHelp.java
@@ -1,8 +1,8 @@
package com.java110.fee.feeMonth;
import com.java110.core.smo.IComputeFeeSMO;
import com.java110.dto.RoomDto;
import com.java110.dto.fee.FeeAttrDto;
import com.java110.dto.fee.FeeDetailDto;
import com.java110.dto.fee.FeeDto;
import com.java110.dto.payFeeDetailMonth.PayFeeMonthOwnerDto;
import com.java110.intf.community.IRoomInnerServiceSMO;
@@ -10,6 +10,7 @@
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -59,4 +60,86 @@
    }
    public Double getReceivableAmount(List<FeeDetailDto> feeDetailDtos, Double feePrice, Date curDate, FeeDto feeDto) {
        FeeDetailDto feeDetailDto = getCurFeeDetail(feeDetailDtos, curDate);
        if (feeDetailDto == null && curDate.getTime() < feeDto.getEndTime().getTime()) {
            return 0.00;
        }
        return feePrice;
    }
    @Override
    public Double getReceivedAmount(List<FeeDetailDto> feeDetailDtos, Double feePrice, Date curDate, FeeDto feeDto) {
        //todo 这种情况下应该 实收为0
        if (curDate.getTime() >= feeDto.getEndTime().getTime()) {
            return 0.00;
        }
        //todo 如果 fee 为空
        if (feeDetailDtos == null) {
            return feePrice;
        }
        FeeDetailDto feeDetailDto = getCurFeeDetail(feeDetailDtos, curDate);
        if (feeDetailDto == null && curDate.getTime() < feeDto.getEndTime().getTime()) {
            return 0.00;
        }
        if (feeDetailDto == null) {
            return feePrice;
        }
        double maxMonth = Math.ceil(computeFeeSMOImpl.dayCompare(feeDetailDto.getStartTime(), feeDetailDto.getEndTime()));
        if (maxMonth < 1) {
            return Double.parseDouble(feeDetailDto.getReceivedAmount());
        }
        BigDecimal totalRecDec = new BigDecimal(feeDetailDto.getReceivedAmount());
        //每月平均值
        BigDecimal priRecDec = totalRecDec.divide(new BigDecimal(maxMonth), 2, BigDecimal.ROUND_HALF_EVEN);
        return priRecDec.doubleValue();
    }
    @Override
    public Double getDiscountAmount(Double feePrice, double parseDouble, Date curDate, FeeDto feeDto) {
        //todo 这种情况下应该 优惠为0
        if (curDate.getTime() >= feeDto.getEndTime().getTime()) {
            return 0.00;
        }
        BigDecimal discountAmountDec = new BigDecimal(feePrice).subtract(new BigDecimal(parseDouble)).setScale(2, BigDecimal.ROUND_HALF_UP);
        return discountAmountDec.doubleValue();
    }
    @Override
    public String getFeeDetailId(List<FeeDetailDto> feeDetailDtos, Date curDate) {
        FeeDetailDto feeDetailDto = getCurFeeDetail(feeDetailDtos, curDate);
        if (feeDetailDto == null) {
            return "-1";
        }
        return feeDetailDto.getDetailId();
    }
    /**
     * 获取当前缴费记录
     *
     * @param feeDetailDtos
     * @param curDate
     * @return
     */
    private FeeDetailDto getCurFeeDetail(List<FeeDetailDto> feeDetailDtos, Date curDate) {
        for (FeeDetailDto feeDetailDto : feeDetailDtos) {
            if (feeDetailDto.getStartTime().getTime() < curDate.getTime() && feeDetailDto.getEndTime().getTime() > curDate.getTime()) {
                return feeDetailDto;
            }
        }
        return null;
    }
}
service-fee/src/main/java/com/java110/fee/feeMonth/PayFeeMonthImpl.java
@@ -4,21 +4,19 @@
import com.java110.core.factory.GenerateCodeFactory;
import com.java110.core.log.LoggerFactory;
import com.java110.core.smo.IComputeFeeSMO;
import com.java110.dto.fee.FeeDetailDto;
import com.java110.dto.fee.FeeDto;
import com.java110.dto.payFeeDetailMonth.PayFeeDetailMonthDto;
import com.java110.dto.payFeeDetailMonth.PayFeeMonthOwnerDto;
import com.java110.dto.report.ReportRoomDto;
import com.java110.intf.fee.IFeeInnerServiceSMO;
import com.java110.intf.fee.IPayFeeConfigV1InnerServiceSMO;
import com.java110.intf.fee.IPayFeeDetailMonthInnerServiceSMO;
import com.java110.intf.fee.*;
import com.java110.po.payFeeDetailMonth.PayFeeDetailMonthPo;
import com.java110.utils.util.Assert;
import com.java110.utils.util.DateUtil;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.*;
/**
@@ -38,6 +36,9 @@
    private IPayFeeDetailMonthInnerServiceSMO payFeeDetailMonthInnerServiceSMOImpl;
    @Autowired
    private IFeeDetailInnerServiceSMO feeDetailInnerServiceSMOImpl;
    @Autowired
    private IPayFeeMonthHelp payFeeMonthHelp;
    @Autowired
@@ -48,6 +49,7 @@
    /**
     * 生成单个费用 并 离散到月
     *
     * @param feeId
     * @param communityId
     */
@@ -70,75 +72,81 @@
        //todo 计算每月单价
        Double feePrice = payFeeMonthHelp.getMonthFeePrice(feeDto);
        // 准备离散的基础数据
        // todo 准备离散的基础数据
        PayFeeMonthOwnerDto payFeeMonthOwnerDto = payFeeMonthHelp.generatorOwnerRoom(feeDto);
        //todo 检查费用是否离散过,如果没有离散过,先离散 start_time 到 end_time 的数据
        ifHasNoMonthData(feeDto,payFeeMonthOwnerDto,feePrice);
        //todo 离散start_time 或者 pay_fee_detail_month 最大月份 到  deadlineTime 的数据
        maxMonthDateToDeadlineTimeData(feeDto, payFeeMonthOwnerDto, feePrice);
    }
    /**
     * 如果费用没有month 数据,则直接离散 start_time 到end_time 数据
     * 离散最大 离散月到 deadlineTime 的数据
     *
     * @param feeDto
     * @param payFeeMonthOwnerDto
     * @param feePrice
     */
    private void ifHasNoMonthData(FeeDto feeDto,PayFeeMonthOwnerDto payFeeMonthOwnerDto,Double feePrice) {
        //todo 分析建账时间 和开始时间
        Date startTime = feeDto.getStartTime();
        if(startTime == null){
            throw new IllegalArgumentException("数据错误,未包含开始时间");
        }
        Calendar calendar = Calendar.getInstance();
        int startYear = calendar.get(Calendar.YEAR);
        int startMonth = calendar.get(Calendar.MONTH)+1;
    private void maxMonthDateToDeadlineTimeData(FeeDto feeDto, PayFeeMonthOwnerDto payFeeMonthOwnerDto, Double feePrice) {
        PayFeeDetailMonthDto payFeeDetailMonthDto = new PayFeeDetailMonthDto();
        payFeeDetailMonthDto.setCommunityId(feeDto.getCommunityId());
        payFeeDetailMonthDto.setFeeId(feeDto.getFeeId());
        payFeeDetailMonthDto.setDetailYear(startYear+"");
        payFeeDetailMonthDto.setDetailMonth(startMonth+"");
        int count = payFeeDetailMonthInnerServiceSMOImpl.queryPayFeeDetailMonthsCount(payFeeDetailMonthDto);
        // todo 说明这个费用已经第一次离散过
        if(count > 0){
            return ;
        List<PayFeeDetailMonthDto> payFeeDetailMonthDtos = payFeeDetailMonthInnerServiceSMOImpl.queryPayFeeDetailMaxMonths(payFeeDetailMonthDto);
        Date startTime = null;
        Date deadlineTime = computeFeeSMOImpl.getDeadlineTime(feeDto);
        if (payFeeDetailMonthDtos == null || payFeeDetailMonthDtos.size() < 1) {
            startTime = feeDto.getStartTime();
        } else {
            int detailYear = Integer.parseInt(payFeeDetailMonthDtos.get(0).getDetailYear());
            int detailMonth = Integer.parseInt(payFeeDetailMonthDtos.get(0).getDetailMonth());
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.YEAR, detailYear);
            calendar.set(Calendar.MONTH, detailMonth); //这里不用加1
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            startTime = calendar.getTime();
        }
        double maxMonth = Math.ceil(computeFeeSMOImpl.dayCompare(startTime, feeDto.getEndTime()));
        // todo 生成一段时间内的数据
        doGeneratorTimeMonthData(feeDto, payFeeMonthOwnerDto, feePrice, startTime, deadlineTime);
    }
    private void doGeneratorTimeMonthData(FeeDto feeDto, PayFeeMonthOwnerDto payFeeMonthOwnerDto, Double feePrice, Date startTime, Date endTime) {
        double maxMonth = Math.ceil(computeFeeSMOImpl.dayCompare(startTime, endTime));
        if (maxMonth < 1) {
            return;
        }
        //todo 查询 缴费明细
        FeeDetailDto feeDetailDto = new FeeDetailDto();
        feeDetailDto.setCommunityId(feeDto.getCommunityId());
        feeDetailDto.setFeeId(feeDto.getFeeId());
        List<FeeDetailDto> feeDetailDtos = feeDetailInnerServiceSMOImpl.queryFeeDetails(feeDetailDto);
        //todo 生成 月离散数据
        PayFeeDetailMonthPo tmpPayFeeDetailMonthPo;
        String detailId = "";
        String discountAmount = "";
        String receivedAmount = "";
        List<PayFeeDetailMonthPo> payFeeDetailMonthPos = new ArrayList<>();
        for (int month = 0; month < maxMonth; month++) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startTime);
            calendar.add(Calendar.MONTH, month);
            calendar.set(Calendar.DAY_OF_MONTH, 1);
            tmpPayFeeDetailMonthPo = new PayFeeDetailMonthPo();
            tmpPayFeeDetailMonthPo.setFeeId(feeDto.getFeeId());
            tmpPayFeeDetailMonthPo.setCommunityId(feeDto.getCommunityId());
            tmpPayFeeDetailMonthPo.setDetailId(detailId);
            tmpPayFeeDetailMonthPo.setDetailMonth((calendar.get(Calendar.MONTH) + 1) + "");
            tmpPayFeeDetailMonthPo.setDetailId(payFeeMonthHelp.getFeeDetailId(feeDetailDtos, calendar.getTime()));
            tmpPayFeeDetailMonthPo.setDetailYear(calendar.get(Calendar.YEAR) + "");
            tmpPayFeeDetailMonthPo.setDiscountAmount(discountAmount);
            tmpPayFeeDetailMonthPo.setDetailMonth((calendar.get(Calendar.MONTH) + 1) + "");
            tmpPayFeeDetailMonthPo.setReceivableAmount(payFeeMonthHelp.getReceivableAmount(feeDetailDtos, feePrice, calendar.getTime(), feeDto) + "");
            tmpPayFeeDetailMonthPo.setReceivedAmount(payFeeMonthHelp.getReceivedAmount(feeDetailDtos, feePrice, calendar.getTime(), feeDto) + "");
            tmpPayFeeDetailMonthPo.setDiscountAmount(payFeeMonthHelp.getDiscountAmount(feePrice, Double.parseDouble(tmpPayFeeDetailMonthPo.getReceivedAmount()), calendar.getTime(), feeDto) + "");
            tmpPayFeeDetailMonthPo.setMonthId(GenerateCodeFactory.getGeneratorId(GenerateCodeFactory.CODE_PREFIX_monthId));
            tmpPayFeeDetailMonthPo.setReceivableAmount(feePrice + "");
            tmpPayFeeDetailMonthPo.setReceivedAmount(receivedAmount);
            tmpPayFeeDetailMonthPo.setRemark("程序计算生成");
            tmpPayFeeDetailMonthPo.setObjName(payFeeMonthOwnerDto.getObjName());
            tmpPayFeeDetailMonthPo.setObjId(payFeeMonthOwnerDto.getObjId());
            tmpPayFeeDetailMonthPo.setOwnerId(payFeeMonthOwnerDto.getOwnerId());
            tmpPayFeeDetailMonthPo.setOwnerName(payFeeMonthOwnerDto.getOwnerName());
            tmpPayFeeDetailMonthPo.setCurMonthTime(DateUtil.getFormatTimeStringB(calendar.getTime()));
            payFeeDetailMonthPos.add(tmpPayFeeDetailMonthPo);
        }
        payFeeDetailMonthInnerServiceSMOImpl.savePayFeeDetailMonths(payFeeDetailMonthPos);
@@ -171,6 +179,65 @@
            doTmpFeeDtoMonths(communityId, tmpFeeDtos);
        }
    }
    /**
     * 物业缴费时离散 报表数据
     *
     * @param feeId
     * @param detailId
     * @param communityId
     */
    @Async
    @Override
    public void payFeeDetailRefreshFeeMonth(String feeId, String detailId, String communityId) {
        // todo 查询费用
        FeeDto feeDto = new FeeDto();
        feeDto.setCommunityId(communityId);
        feeDto.setFeeId(feeId);
        List<FeeDto> tmpFeeDtos = feeInnerServiceSMOImpl.queryFees(feeDto);
        Assert.listOnlyOne(tmpFeeDtos, "费用不存在");
        //todo 查询 缴费明细
        FeeDetailDto feeDetailDto = new FeeDetailDto();
        feeDetailDto.setCommunityId(feeDto.getCommunityId());
        feeDetailDto.setFeeId(feeDto.getFeeId());
        feeDetailDto.setDetailId(detailId);
        List<FeeDetailDto> feeDetailDtos = feeDetailInnerServiceSMOImpl.queryFeeDetails(feeDetailDto);
        Assert.listOnlyOne(feeDetailDtos, "缴费记录不存在");
        //todo 计算每月单价
        Double feePrice = payFeeMonthHelp.getMonthFeePrice(feeDto);
        // todo 准备离散的基础数据
        PayFeeMonthOwnerDto payFeeMonthOwnerDto = payFeeMonthHelp.generatorOwnerRoom(feeDto);
        // todo 删除缴费时间范围内的数据
        doDeletePayFeeDetailInMonth(feeDto, feeDetailDtos.get(0));
        // todo 生成一段时间内的数据
        doGeneratorTimeMonthData(feeDto, payFeeMonthOwnerDto, feePrice, feeDetailDtos.get(0).getStartTime(), feeDetailDtos.get(0).getEndTime());
    }
    /**
     * 删除缴费范围内的数据
     *
     * @param feeDto
     * @param feeDetailDto
     */
    private void doDeletePayFeeDetailInMonth(FeeDto feeDto, FeeDetailDto feeDetailDto) {
        PayFeeDetailMonthPo payFeeDetailMonthPo = new PayFeeDetailMonthPo();
        payFeeDetailMonthPo.setFeeId(feeDto.getFeeId());
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(feeDetailDto.getStartTime());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        payFeeDetailMonthPo.setCurMonthTime(DateUtil.getFormatTimeStringB(calendar.getTime()));
        payFeeDetailMonthPo.setCurMonthEndTime(DateUtil.getFormatTimeStringB(feeDetailDto.getEndTime()));
        payFeeDetailMonthInnerServiceSMOImpl.deletePayFeeDetailMonth(payFeeDetailMonthPo);
    }
    private void doTmpFeeDtoMonths(String communityId, List<FeeDto> tmpFeeDtos) {
service-fee/src/main/java/com/java110/fee/smo/impl/PayFeeDetailMonthInnerServiceSMOImpl.java
@@ -84,6 +84,19 @@
        return payFeeDetailMonthServiceDaoImpl.queryPayFeeDetailMonthsCount(BeanConvertUtil.beanCovertMap(payFeeDetailMonthDto));
    }
    @Override
    public List<PayFeeDetailMonthDto> queryPayFeeDetailMaxMonths(@RequestBody PayFeeDetailMonthDto payFeeDetailMonthDto) {
        int page = payFeeDetailMonthDto.getPage();
        if (page != PageDto.DEFAULT_PAGE) {
            payFeeDetailMonthDto.setPage((page - 1) * payFeeDetailMonthDto.getRow());
        }
        List<PayFeeDetailMonthDto> payFeeDetailMonths = BeanConvertUtil.covertBeanList(payFeeDetailMonthServiceDaoImpl.queryPayFeeDetailMaxMonths(BeanConvertUtil.beanCovertMap(payFeeDetailMonthDto)), PayFeeDetailMonthDto.class);
        return payFeeDetailMonths;
    }
    public IPayFeeDetailMonthServiceDao getPayFeeDetailMonthServiceDaoImpl() {
        return payFeeDetailMonthServiceDaoImpl;
    }
service-fee/src/main/java/com/java110/fee/smo/impl/PayFeeMonthInnerServiceSMOImpl.java
New file
@@ -0,0 +1,43 @@
package com.java110.fee.smo.impl;
import com.java110.core.base.smo.BaseServiceSMO;
import com.java110.dto.PageDto;
import com.java110.dto.payFeeDetailMonth.PayFeeDetailMonthDto;
import com.java110.dto.payFeeDetailMonth.PayFeeDetailRefreshFeeMonthDto;
import com.java110.fee.dao.IPayFeeDetailMonthServiceDao;
import com.java110.fee.feeMonth.IPayFeeMonth;
import com.java110.intf.fee.IPayFeeDetailMonthInnerServiceSMO;
import com.java110.intf.fee.IPayFeeMonthInnerServiceSMO;
import com.java110.po.payFeeDetailMonth.PayFeeDetailMonthPo;
import com.java110.utils.util.BeanConvertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @ClassName FloorInnerServiceSMOImpl
 * @Description 月缴费表内部服务实现类
 * @Author wuxw
 * @Date 2019/4/24 9:20
 * @Version 1.0
 * add by wuxw 2019/4/24
 **/
@RestController
public class PayFeeMonthInnerServiceSMOImpl extends BaseServiceSMO implements IPayFeeMonthInnerServiceSMO {
    @Autowired
    private IPayFeeMonth payFeeMonthImpl;
    @Override
    public int payFeeDetailRefreshFeeMonth(@RequestBody PayFeeDetailRefreshFeeMonthDto payFeeDetailRefreshFeeMonthDto) {
        payFeeMonthImpl.payFeeDetailRefreshFeeMonth(payFeeDetailRefreshFeeMonthDto.getFeeId(),
                payFeeDetailRefreshFeeMonthDto.getDetailId(),
                payFeeDetailRefreshFeeMonthDto.getCommunityId());
        return 1;
    }
}
service-job/src/main/java/com/java110/job/adapt/fee/asyn/impl/PayFeeDetailToMonthIImpl.java
@@ -7,10 +7,12 @@
import com.java110.dto.fee.FeeConfigDto;
import com.java110.dto.fee.FeeDto;
import com.java110.dto.owner.OwnerRoomRelDto;
import com.java110.dto.payFeeDetailMonth.PayFeeDetailRefreshFeeMonthDto;
import com.java110.dto.reportOweFee.ReportOweFeeDto;
import com.java110.entity.order.Business;
import com.java110.intf.fee.IFeeInnerServiceSMO;
import com.java110.intf.fee.IPayFeeDetailMonthInnerServiceSMO;
import com.java110.intf.fee.IPayFeeMonthInnerServiceSMO;
import com.java110.intf.report.IGeneratorOweFeeInnerServiceSMO;
import com.java110.intf.user.IOwnerRoomRelV1InnerServiceSMO;
import com.java110.job.adapt.fee.asyn.IPayFeeDetailToMonth;
@@ -30,6 +32,10 @@
import java.text.ParseException;
import java.util.*;
/**
 * 主要用于处理费用离散月 适配器
 * add by wuxw 2023-05-11
 */
@Service
public class PayFeeDetailToMonthIImpl implements IPayFeeDetailToMonth {
@@ -40,7 +46,6 @@
    @Autowired
    private IComputeFeeSMO computeFeeSMOImpl;
    @Autowired
    private IPayFeeDetailMonthInnerServiceSMO payFeeDetailMonthInnerServiceSMOImpl;
@@ -49,6 +54,9 @@
    @Autowired
    private IGeneratorOweFeeInnerServiceSMO generatorOweFeeInnerServiceSMOImpl;
    @Autowired
    private IPayFeeMonthInnerServiceSMO payFeeMonthInnerServiceSMOImpl;
    @Override
    @Async
@@ -62,22 +70,16 @@
        Assert.listOnlyOne(feeDtos, "未查询到费用信息");
        feeDto = feeDtos.get(0);
        Date startTime = null;
        Date endTime = null;
        Date createTime = null;
        try {
            startTime = DateUtil.getDateFromString(businessPayFeeDetail.getString("startTime"), DateUtil.DATE_FORMATE_STRING_B);
            endTime = DateUtil.getDateFromString(businessPayFeeDetail.getString("endTime"), DateUtil.DATE_FORMATE_STRING_B);
            createTime = DateUtil.getDateFromString(businessPayFeeDetail.getString("createTime"), DateUtil.DATE_FORMATE_STRING_B);
        } catch (ParseException e) {
            throw new IllegalArgumentException("时间格式错误");
        }
        Date endTime = DateUtil.getDateFromStringB(businessPayFeeDetail.getString("endTime"));
        //todo 转换为月(优化版)
        toPayFeeDetailMonth(businessPayFeeDetail, feeDto);
        //todo 转换为月
        toMonth(businessPayFeeDetail, feeDto, startTime, endTime, createTime);
        //toMonth(businessPayFeeDetail, feeDto, startTime, endTime, createTime);
        //todo 如果是租金 则延长房屋租期
        toAddRoomRentTime(feeDtos.get(0),endTime);
        toAddRoomRentTime(feeDtos.get(0), endTime);
        //todo 修改欠费
        toDeleteOweFee(feeDtos.get(0));
@@ -85,22 +87,36 @@
    }
    /**
     * 调用fee 模块 处理 离散
     * @param businessPayFeeDetail
     * @param feeDto
     */
    private void toPayFeeDetailMonth(JSONObject businessPayFeeDetail, FeeDto feeDto) {
        PayFeeDetailRefreshFeeMonthDto payFeeDetailRefreshFeeMonthDto = new PayFeeDetailRefreshFeeMonthDto();
        payFeeDetailRefreshFeeMonthDto.setCommunityId(feeDto.getCommunityId());
        payFeeDetailRefreshFeeMonthDto.setDetailId(businessPayFeeDetail.getString("detailId"));
        payFeeDetailRefreshFeeMonthDto.setFeeId(feeDto.getFeeId());
        //todo 调用费用模块 处理
        payFeeMonthInnerServiceSMOImpl.payFeeDetailRefreshFeeMonth(payFeeDetailRefreshFeeMonthDto);
    }
    /**
     * 处理欠费
     *
     * @param feeDto
     */
    private void toDeleteOweFee(FeeDto feeDto) {
        generatorOweFeeInnerServiceSMOImpl.computeOweFee(feeDto);
    }
    private void toAddRoomRentTime(FeeDto feeDto,Date endTime) {
    private void toAddRoomRentTime(FeeDto feeDto, Date endTime) {
        //todo 不是租金直接返回
        if (!FeeConfigDto.FEE_TYPE_CD_RENT.equals(feeDto.getFeeTypeCd())) {
            return;
        }
        //todo 不是房屋直接返回
        if(!FeeDto.PAYER_OBJ_TYPE_ROOM.equals(feeDto.getPayerObjType())){
        if (!FeeDto.PAYER_OBJ_TYPE_ROOM.equals(feeDto.getPayerObjType())) {
            return;
        }
@@ -109,23 +125,21 @@
        ownerRoomRelDto.setCommunityId(feeDto.getCommunityId());
        List<OwnerRoomRelDto> ownerRoomRelDtos = ownerRoomRelV1InnerServiceSMOImpl.queryOwnerRoomRels(ownerRoomRelDto);
        if(ownerRoomRelDtos == null || ownerRoomRelDtos.size()< 1){
        if (ownerRoomRelDtos == null || ownerRoomRelDtos.size() < 1) {
            return;
        }
        Date rentEndDate = ownerRoomRelDtos.get(0).getEndTime();
        if(endTime.getTime()< rentEndDate.getTime()){
            return ;
        if (endTime.getTime() < rentEndDate.getTime()) {
            return;
        }
        OwnerRoomRelPo ownerRoomRelPo = new OwnerRoomRelPo();
        ownerRoomRelPo.setEndTime(DateUtil.getFormatTimeString(endTime,DateUtil.DATE_FORMATE_STRING_B));
        ownerRoomRelPo.setEndTime(DateUtil.getFormatTimeString(endTime, DateUtil.DATE_FORMATE_STRING_B));
        ownerRoomRelPo.setRelId(ownerRoomRelDtos.get(0).getRelId());
        ownerRoomRelV1InnerServiceSMOImpl.updateOwnerRoomRel(ownerRoomRelPo);
    }
    private void toMonth(JSONObject businessPayFeeDetail, FeeDto feeDto, Date startTime, Date endTime, Date createTime) {
@@ -148,15 +162,8 @@
        List<PayFeeDetailMonthPo> payFeeDetailMonthPos = new ArrayList<>();
        Calendar calendar = Calendar.getInstance();
        PayFeeDetailMonthPo tmpPayFeeDetailMonthPo = null;
        BigDecimal discountAmount = new BigDecimal(0.0);
//        if("bailefu".equals(MappingCache.getValue("payFeeDetailToMonth"))){
//            bailefuPropertyCode(businessPayFeeDetail, feeDto, startTime, createTime, maxMonth, feePrice, priRecDec, payFeeDetailMonthPos, calendar);
//        }else{
        commonPropertyCode(businessPayFeeDetail, feeDto, startTime, createTime, maxMonth, feePrice, priRecDec, payFeeDetailMonthPos, calendar);
//        }
        payFeeDetailMonthInnerServiceSMOImpl.savePayFeeDetailMonths(payFeeDetailMonthPos);
    }
springboot/src/test/java/com/java110/AppTest.java
@@ -28,15 +28,9 @@
    public void should()
    {
       JSONObject param = new JSONObject();
       param.put("tel","18909715555");
       param.put("passwd","admin");
        try {
            String accessToken = Base64Convert.byteToBase64(param.toJSONString().getBytes("UTF-8"));
            System.out.printf("accessToken="+accessToken);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
     Calendar calendar = Calendar.getInstance();
     calendar.set(Calendar.YEAR,2023);
     calendar.set(Calendar.MONTH,11);
        System.out.printf(DateUtil.getFormatTimeString(calendar.getTime(),DateUtil.DATE_FORMATE_STRING_A));
    }
}