package com.java110;
|
|
import static org.junit.Assert.assertTrue;
|
|
import com.java110.core.factory.PlutusFactory;
|
import com.java110.dto.fee.FeeDto;
|
import com.java110.dto.owner.OwnerCarDto;
|
import com.java110.utils.util.DateUtil;
|
import com.java110.utils.util.StringUtil;
|
import org.bouncycastle.util.encoders.Base64;
|
import org.junit.Test;
|
|
import java.math.BigDecimal;
|
import java.util.Calendar;
|
import java.util.Date;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
/**
|
* Unit test for simple App.
|
*/
|
public class AppTest
|
{
|
/**
|
* Rigorous Test :-)
|
*/
|
@Test
|
public void should()
|
{
|
//解密
|
FeeDto feeDto = new FeeDto();
|
feeDto.setStartTime(DateUtil.getDateFromStringB("2023-01-01"));
|
feeDto.setEndTime(DateUtil.getDateFromStringB("2023-01-12"));
|
feeDto.setPrepaymentPeriod("20");
|
feeDto.setState(FeeDto.STATE_DOING);
|
feeDto.setConfigEndTime(DateUtil.getDateFromStringB("2050-01-01"));
|
feeDto.setFeeFlag(FeeDto.FEE_FLAG_CYCLE);
|
feeDto.setPaymentCd("1200");
|
feeDto.setPaymentCycle("12");
|
getTargetEndDateAndOweMonth(feeDto,null);
|
}
|
|
public Map getTargetEndDateAndOweMonth(FeeDto feeDto, OwnerCarDto ownerCarDto) {
|
Date targetEndDate = null;
|
double oweMonth = 0.0;
|
|
Map<String, Object> targetEndDateAndOweMonth = new HashMap<>();
|
//todo 判断当前费用是否已结束
|
if (FeeDto.STATE_FINISH.equals(feeDto.getState())) {
|
targetEndDate = feeDto.getEndTime();
|
targetEndDateAndOweMonth.put("oweMonth", oweMonth);
|
targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
|
return targetEndDateAndOweMonth;
|
}
|
|
//todo 考虑费用项 费用提前生成
|
Calendar preEndTimeCal = Calendar.getInstance();
|
preEndTimeCal.setTime(feeDto.getEndTime());
|
if (StringUtil.isNumber(feeDto.getPrepaymentPeriod())) {
|
preEndTimeCal.add(Calendar.DAY_OF_MONTH, Integer.parseInt(feeDto.getPrepaymentPeriod()) * -1);
|
}
|
Date preEndTime = preEndTimeCal.getTime();
|
|
//todo 当前费用为一次性费用
|
Date maxEndTime = feeDto.getConfigEndTime();
|
if (FeeDto.FEE_FLAG_ONCE.equals(feeDto.getFeeFlag())) {
|
//先取 deadlineTime
|
if (feeDto.getDeadlineTime() != null) {
|
targetEndDate = feeDto.getDeadlineTime();
|
} else if (!StringUtil.isEmpty(feeDto.getCurDegrees())) {
|
targetEndDate = feeDto.getCurReadingTime();
|
} else if (feeDto.getImportFeeEndTime() == null) {
|
targetEndDate = maxEndTime;
|
} else {
|
targetEndDate = feeDto.getImportFeeEndTime();
|
}
|
//判断当前费用是不是导入费用
|
oweMonth = 1.0;
|
} else if (FeeDto.FEE_FLAG_CYCLE_ONCE.equals(feeDto.getFeeFlag())) {
|
if (feeDto.getDeadlineTime() != null) {
|
maxEndTime = feeDto.getDeadlineTime();
|
}
|
Date billEndTime = DateUtil.getCurrentDate();
|
//建账时间
|
Date startDate = feeDto.getStartTime();
|
//计费起始时间
|
Date endDate = feeDto.getEndTime();
|
//缴费周期
|
long paymentCycle = Long.parseLong(feeDto.getPaymentCycle());
|
// 当前时间 - 开始时间 = 月份
|
double mulMonth = 0.0;
|
mulMonth = 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);//目标结束时间
|
}
|
|
|
//todo 费用项的结束时间<缴费的结束时间 费用快结束了 取费用项的结束时间
|
if (maxEndTime.getTime() < targetEndDate.getTime()) {
|
targetEndDate = maxEndTime;
|
}
|
//说明欠费
|
if (endDate.getTime() < targetEndDate.getTime()) {
|
// 目标到期时间 - 到期时间 = 欠费月份
|
oweMonth = 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 = dayCompare(endDate, 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, endDate);//目标结束时间
|
|
//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 = dayCompare(endDate, targetEndDate);
|
}
|
|
if (feeDto.getEndTime().getTime() > targetEndDate.getTime()) {
|
targetEndDate = feeDto.getEndTime();
|
}
|
}
|
|
targetEndDateAndOweMonth.put("oweMonth", oweMonth);
|
targetEndDateAndOweMonth.put("targetEndDate", targetEndDate);
|
return targetEndDateAndOweMonth;
|
}
|
|
public Date getTargetEndTime(double month, Date startDate) {
|
Calendar endDate = Calendar.getInstance();
|
endDate.setTime(startDate);
|
|
Double intMonth = Math.floor(month);
|
endDate.add(Calendar.MONTH, intMonth.intValue());
|
double doubleMonth = month - intMonth;
|
if (doubleMonth <= 0) {
|
return endDate.getTime();
|
}
|
int futureDay = endDate.getActualMaximum(Calendar.DAY_OF_MONTH);
|
Double hour = doubleMonth * futureDay * 24;
|
endDate.add(Calendar.HOUR_OF_DAY, hour.intValue());
|
return endDate.getTime();
|
}
|
|
public double dayCompare(Date fromDate, Date toDate) {
|
double resMonth = 0.0;
|
Calendar from = Calendar.getInstance();
|
from.setTime(fromDate);
|
Calendar to = Calendar.getInstance();
|
to.setTime(toDate);
|
//比较月份差 可能有整数 也会负数
|
int result = to.get(Calendar.MONTH) - from.get(Calendar.MONTH);
|
//比较年差
|
int month = (to.get(Calendar.YEAR) - from.get(Calendar.YEAR)) * 12;
|
|
//真实 相差月份
|
result = result + month;
|
|
//开始时间 2021-06-01 2021-08-05 result = 2 2021-08-01
|
Calendar newFrom = Calendar.getInstance();
|
newFrom.setTime(fromDate);
|
newFrom.add(Calendar.MONTH, result);
|
//如果加月份后 大于了当前时间 默认加 月份 -1 情况 12-19 21-01-10
|
//这个是神的逻辑一定好好理解
|
if (newFrom.getTime().getTime() > toDate.getTime()) {
|
newFrom.setTime(fromDate);
|
result = result - 1;
|
newFrom.add(Calendar.MONTH, result);
|
}
|
|
// t1 2021-08-01 t2 2021-08-05
|
long t1 = newFrom.getTime().getTime();
|
long t2 = to.getTime().getTime();
|
//相差毫秒
|
double days = (t2 - t1) * 1.00 / (24 * 60 * 60 * 1000);
|
BigDecimal tmpDays = new BigDecimal(days); //相差天数
|
BigDecimal monthDay = null;
|
Calendar newFromMaxDay = Calendar.getInstance();
|
newFromMaxDay.set(newFrom.get(Calendar.YEAR), newFrom.get(Calendar.MONTH), 1, 0, 0, 0);
|
newFromMaxDay.add(Calendar.MONTH, 1); //下个月1号
|
//在当前月中 这块有问题
|
if (toDate.getTime() < newFromMaxDay.getTime().getTime()) {
|
monthDay = new BigDecimal(newFrom.getActualMaximum(Calendar.DAY_OF_MONTH));
|
return tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)).doubleValue();
|
}
|
// 上月天数
|
days = (newFromMaxDay.getTimeInMillis() - t1) * 1.00 / (24 * 60 * 60 * 1000);
|
tmpDays = new BigDecimal(days);
|
monthDay = new BigDecimal(newFrom.getActualMaximum(Calendar.DAY_OF_MONTH));
|
BigDecimal preRresMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP);
|
|
//下月天数
|
days = (t2 - newFromMaxDay.getTimeInMillis()) * 1.00 / (24 * 60 * 60 * 1000);
|
tmpDays = new BigDecimal(days);
|
monthDay = new BigDecimal(newFromMaxDay.getActualMaximum(Calendar.DAY_OF_MONTH));
|
resMonth = tmpDays.divide(monthDay, 4, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(result)).add(preRresMonth).doubleValue();
|
return resMonth;
|
}
|
|
}
|