diff --git a/mallinkAdmin/src/main/resources/db/migration/V202409000000004.sql b/mallinkAdmin/src/main/resources/db/migration/V202409000000004.sql index bcba33337..ee49baceb 100644 --- a/mallinkAdmin/src/main/resources/db/migration/V202409000000004.sql +++ b/mallinkAdmin/src/main/resources/db/migration/V202409000000004.sql @@ -97,4 +97,8 @@ ALTER TABLE wx_all_bill_95 ADD COLUMN rent_contract_agile_fees_type INT(1) ALTER TABLE wx_all_bill_96 ADD COLUMN rent_contract_agile_fees_type INT(1) COMMENT '自定义合同费用类型'; ALTER TABLE wx_all_bill_97 ADD COLUMN rent_contract_agile_fees_type INT(1) COMMENT '自定义合同费用类型'; ALTER TABLE wx_all_bill_98 ADD COLUMN rent_contract_agile_fees_type INT(1) COMMENT '自定义合同费用类型'; -ALTER TABLE wx_all_bill_99 ADD COLUMN rent_contract_agile_fees_type INT(1) COMMENT '自定义合同费用类型'; \ No newline at end of file +ALTER TABLE wx_all_bill_99 ADD COLUMN rent_contract_agile_fees_type INT(1) COMMENT '自定义合同费用类型'; + + +ALTER TABLE wx_rent_contract_agile_un_deposit ADD COLUMN time_period INT(3) COMMENT '计费周期' AFTER price_unit; + diff --git a/mallinkService/src/main/java/com/iformall/domain/po/WxRentContractAgileUnDeposit.java b/mallinkService/src/main/java/com/iformall/domain/po/WxRentContractAgileUnDeposit.java index d7b84b18b..c27e1ff93 100644 --- a/mallinkService/src/main/java/com/iformall/domain/po/WxRentContractAgileUnDeposit.java +++ b/mallinkService/src/main/java/com/iformall/domain/po/WxRentContractAgileUnDeposit.java @@ -61,7 +61,10 @@ public class WxRentContractAgileUnDeposit extends TenantEntity { return null; } - @io.swagger.annotations.ApiModelProperty(value="计费周期EnumRentContractAgilTimeUnit",name="timeUnit") + @io.swagger.annotations.ApiModelProperty(value="计费周期",name="timePeriod") + private Integer timePeriod; + + @io.swagger.annotations.ApiModelProperty(value="计费周期单位EnumRentContractAgilTimeUnit",name="timeUnit") private Integer timeUnit; @TableField(exist = false) private String timeUnitName; @@ -79,7 +82,7 @@ public class WxRentContractAgileUnDeposit extends TenantEntity { private Integer feesCreateRule; @TableField(exist = false) private String feesCreateRuleName; - public String getFeesCreateRule() { + public String getFeesCreateRuleName() { if (null != feesCreateRule) { return EnumFeesShopTimeType.getEnum(feesCreateRule).getMessage(); } diff --git a/mallinkService/src/main/java/com/iformall/enums/EnumRentContractAgilTimeUnit.java b/mallinkService/src/main/java/com/iformall/enums/EnumRentContractAgilTimeUnit.java index 3d60f3e69..76e9a88ad 100644 --- a/mallinkService/src/main/java/com/iformall/enums/EnumRentContractAgilTimeUnit.java +++ b/mallinkService/src/main/java/com/iformall/enums/EnumRentContractAgilTimeUnit.java @@ -1,12 +1,16 @@ package com.iformall.enums; +import java.util.Calendar; +import java.util.Date; + +import com.iformall.utils.DateUtils; /** */ public enum EnumRentContractAgilTimeUnit { MONTH(1, "月"), - QUATOR(2,"季度"), + QUATOR(2,"自然季度"), HALF_YEAR(3,"半年"), YEAR(4,"年"), RENT_PERIOD(5,"租赁期"), @@ -36,4 +40,91 @@ public enum EnumRentContractAgilTimeUnit { public String getMessage() { return message; } + + //截止到后几个季度的时间 + public static Calendar getAfterCalendarDay(Calendar instance,int time,EnumRentContractAgilTimeUnit timeUnit) { + if (timeUnit == MONTH) { + instance.add(Calendar.MONTH, time); + instance.add(Calendar.SECOND, -1); + instance.set(Calendar.MILLISECOND, 0); + //几个季度之后 + }else if (timeUnit == QUATOR) { + instance = DateUtils.getAfterQuaterStartDay(instance.getTime(), time); + instance.add(Calendar.SECOND, -1); + instance.set(Calendar.MILLISECOND, 0); + }else if (timeUnit == HALF_YEAR) { + instance.add(Calendar.MONTH, time*6); + instance.add(Calendar.SECOND, -1); + instance.set(Calendar.MILLISECOND, 0); + }else if (timeUnit == YEAR) { + instance.add(Calendar.MONTH, time*12); + instance.add(Calendar.SECOND, -1); + instance.set(Calendar.MILLISECOND, 0); + }else if (timeUnit == RENT_PERIOD) { + return instance; + } + return instance; + } + + //截止到后几个季度的时间,自然天 + public static Date getAfterCalendarNarDay(Date date,int time,EnumRentContractAgilTimeUnit timeUnit) { + if (timeUnit == MONTH) { + if (time <= 1) { + return DateUtils.getLastDayForMonth(date); + }else { + Date firstDay = DateUtils.getFirstDayForCurrMonth(date); + Calendar instance = Calendar.getInstance(); + instance.setTime(firstDay); + instance.add(Calendar.MONTH, time); + //instance.add(Calendar.DAY_OF_MONTH, -1); + instance.add(Calendar.SECOND, -1); + instance.set(Calendar.MILLISECOND, 0); + return instance.getTime(); + } + //几个季度之后 + }else if (timeUnit == QUATOR) { + Calendar instance = DateUtils.getAfterQuaterStartDay(date, time); + instance.add(Calendar.SECOND, -1); + instance.set(Calendar.MILLISECOND, 0); + return instance.getTime(); + }else if (timeUnit == HALF_YEAR) { + Date enddate = DateUtils.getTimeAfterMonths(time*6, date); + Date endYearDate = DateUtils.getLastDayForYear(enddate); + if (enddate.equals(endYearDate)) { + return endYearDate; + }else { + Calendar endc = Calendar.getInstance(); + endc.setTime(enddate); + endc.set(Calendar.MONTH, 5); + endc.set(Calendar.DAY_OF_MONTH,30);//设置为1号,当前日期既为本月第一天 + endc.set(Calendar.HOUR_OF_DAY, 23); //将小时至0 + endc.set(Calendar.MINUTE, 59); //将分钟至0 + endc.set(Calendar.SECOND,59); //将秒至0 + endc.set(Calendar.MILLISECOND, 0); + if (enddate.after(endc.getTime())) { + return endc.getTime(); + }else { + //如果结束时间年终都没到,则返回上一年年底 + endc.add(Calendar.YEAR, -1); + return DateUtils.getLastDayForYear(endc.getTime()); + } + } + }else if (timeUnit == YEAR) { + Calendar endc = Calendar.getInstance(); + endc.setTime(date); + endc.add(Calendar.YEAR, time); + + Date endYearDate = DateUtils.getLastDayForYear(endc.getTime()); + if (endYearDate.equals(endc.getTime())) { + return endYearDate; + }else { + //如果结束时间年终都没到,则返回上一年年底 + endc.add(Calendar.YEAR, -1); + return DateUtils.getLastDayForYear(endc.getTime()); + } + }else if (timeUnit == RENT_PERIOD) { + return date; + } + return date; + } } diff --git a/mallinkService/src/main/java/com/iformall/service/helper/WxRentContractAgileHelper.java b/mallinkService/src/main/java/com/iformall/service/helper/WxRentContractAgileHelper.java new file mode 100644 index 000000000..6ab85447e --- /dev/null +++ b/mallinkService/src/main/java/com/iformall/service/helper/WxRentContractAgileHelper.java @@ -0,0 +1,506 @@ +package com.iformall.service.helper; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.Months; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.iformall.domain.dto.NeedPayDTO; +import com.iformall.domain.po.WxEnergyFees; +import com.iformall.domain.po.WxPropertyContract; +import com.iformall.domain.po.WxRentContract; +import com.iformall.domain.vo.BillTimeVo; +import com.iformall.domain.vo.WxBillFeesStandardsListVo; +import com.iformall.enums.EnumFeesShopTimeType; +import com.iformall.enums.EnumFeesStandardsCalcuteUnit; +import com.iformall.enums.EnumPriceUnit; +import com.iformall.enums.EnumRentContractAdjustPeriod; +import com.iformall.enums.EnumRentContractAdjustRatioWay; +import com.iformall.enums.EnumRentContractAgilPriceUnit; +import com.iformall.enums.EnumRentContractAgilTimeUnit; +import com.iformall.enums.EnumRentContractRentInputWay; +import com.iformall.enums.EnumRentContractType; +import com.iformall.enums.EnumRentDayPriceCalcute; +import com.iformall.enums.EnumYesOrNo; +import com.iformall.service.impl.WxRentContractServiceImpl; +import com.iformall.utils.Constant; +import com.iformall.utils.DateUtils; + +public class WxRentContractAgileHelper { + + + public static List getYearsBeginList(Date startDate,Date endDate ) { + int years = DateUtils.getBetweenYears(startDate,endDate); + List yearList = new ArrayList(); + for (int i = 0; i < years; i++) { + Calendar instance = Calendar.getInstance(); + instance.setTime(startDate); + instance.set(Calendar.MILLISECOND, 0); + instance.add(Calendar.MONTH, 12 * i); + Date _startDate = instance.getTime(); + yearList.add(_startDate); + } + return yearList; + } + + public static List initBillTimeList(List yearList,Date start,Date end,EnumFeesShopTimeType calcuteRule, + EnumRentContractAgilTimeUnit timeUnit,int time,int payPeriod){ + List list = new ArrayList<>(); + int count = 0; + List yearsBeginList = new ArrayList(); + yearsBeginList.addAll(yearList); + if (yearsBeginList.size() > 0) { + yearsBeginList.remove(0); + } + BillTimeVo receiveDate = null; + while (true) { + BillTimeVo timeVo = new BillTimeVo(); + + //账单日 + Calendar instance = Calendar.getInstance(); + instance.setTime(start); + instance.set(Calendar.MILLISECOND, 0); + //开始时间 + timeVo.setStartDate(instance.getTime()); + + //结束时间 + instance.clear(); + instance.setTime(start); + instance.set(Calendar.MILLISECOND, 0); + instance = EnumRentContractAgilTimeUnit.getAfterCalendarDay(instance, time, timeUnit); + //instance.add(dayType, receivePeriod); + //instance.add(Calendar.DATE, -1); + timeVo.setEndDate(instance.getTime()); + + //自然月,应该是从本月开始到本月结束 + if(calcuteRule == EnumFeesShopTimeType.NATURE_PERIOD){ + timeVo.setEndDate(EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(timeVo.getStartDate(), time, timeUnit)); + } + + //如果是到了每年的截止时间,第一年忽略(是开始时间) + boolean isYearCut = false;//是不是有截断 + if (null != yearsBeginList && yearsBeginList.size() > 0 ) { + Date yearStartDate = yearsBeginList.get(0); + //如果开始时间到了年的截止 + if (timeVo.getStartDate().equals(yearStartDate)) { + yearsBeginList.remove(yearStartDate); + }else if (timeVo.getStartDate().after(yearStartDate)) { + //do nothing + }else if (timeVo.getStartDate().before(yearStartDate)) { + Date yearStartDateEnd = DateUtils.getDayEnd(yearStartDate); + if (timeVo.getEndDate().after(yearStartDateEnd)) { + timeVo.setEndDate(DateUtils.getDaySet(yearStartDateEnd,Calendar.DATE,-1)); + yearsBeginList.remove(yearStartDate); + isYearCut = true; + }else if(timeVo.getEndDate().equals(yearStartDateEnd)) { + yearsBeginList.remove(yearStartDate); + } + } + } + + if(timeVo.getEndDate().after(end)){ + Calendar endinstance = Calendar.getInstance(); + endinstance.setTime(end); + endinstance.set(Calendar.MILLISECOND, 0); + timeVo.setEndDate(endinstance.getTime()); + } + + list.add(timeVo); + + receiveDate = getReceiveDate(receiveDate,timeVo.getStartDate(), timeVo.getEndDate(), payPeriod,calcuteRule,time,timeUnit); + timeVo.setReceiveDate(receiveDate.getStartDate()); + + + //next + start = DateUtils.getDaySet(timeVo.getEndDate(),Calendar.SECOND,1); + + if(start.after(end)) { + break; + } + count ++; + + //预警 + if(count >= 1000){ + Logger logger = LoggerFactory.getLogger(WxRentContractServiceImpl.class); + logger.error("initBillTimeList() warnCount max error !!!"); + break; + } + } + return list; + } + + public static BillTimeVo getReceiveDate(BillTimeVo currentReceiveDate,Date start,Date end,int payPeriodRate, + EnumFeesShopTimeType calcuteRule,Integer time,EnumRentContractAgilTimeUnit timeUnit) { + if (null != currentReceiveDate) { + if ((currentReceiveDate.getStartDate().equals(start) || currentReceiveDate.getStartDate().before(start) ) && + (currentReceiveDate.getEndDate().equals(end) || currentReceiveDate.getEndDate().after(end) )) { + return currentReceiveDate; + } + } + + Calendar instance = Calendar.getInstance(); + instance.setTime(start); + instance.set(Calendar.MILLISECOND, 0); + BillTimeVo vo = new BillTimeVo(); + //按月计租 + if (calcuteRule == EnumFeesShopTimeType.PERIOD) { + //按月 + if (timeUnit == EnumRentContractAgilTimeUnit.MONTH) { + vo.setStartDate(instance.getTime()); + Date endDate = EnumRentContractAgilTimeUnit.getAfterCalendarDay(instance, time*payPeriodRate, EnumRentContractAgilTimeUnit.MONTH).getTime(); + vo.setEndDate(endDate); + return vo; + //自然季度 + }else if(timeUnit == EnumRentContractAgilTimeUnit.QUATOR){ + //如果开始日期是1号,则从开始日期算起,,如果不是,则从结束日期算起 + int day = instance.get(Calendar.DAY_OF_MONTH); + if (day == 1) { + vo.setStartDate(instance.getTime()); + Date endDate = EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(instance.getTime(), time*payPeriodRate, EnumRentContractAgilTimeUnit.QUATOR); + vo.setEndDate(endDate); + return vo; + }else { + Date startDate = null; + //如果是第一期,则取当前的周期 + if (null == currentReceiveDate) { + startDate = EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(end, 0, EnumRentContractAgilTimeUnit.QUATOR); + startDate = DateUtils.getSecondsTimeAfter(1, startDate); + }else { + startDate = EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(end, -1*time*payPeriodRate, EnumRentContractAgilTimeUnit.QUATOR); + } + startDate = DateUtils.getFirstDayForCurrMonth(startDate); + vo.setStartDate(startDate); + vo.setEndDate(end); + return vo; + } + }else if(timeUnit == EnumRentContractAgilTimeUnit.HALF_YEAR) { + vo.setStartDate(instance.getTime()); + Date endDate = EnumRentContractAgilTimeUnit.getAfterCalendarDay(instance, 6*time*payPeriodRate, EnumRentContractAgilTimeUnit.MONTH).getTime(); + vo.setEndDate(endDate); + return vo; + }else if(timeUnit == EnumRentContractAgilTimeUnit.YEAR) { + vo.setStartDate(instance.getTime()); + Date endDate = EnumRentContractAgilTimeUnit.getAfterCalendarDay(instance, 12*time*payPeriodRate, EnumRentContractAgilTimeUnit.MONTH).getTime(); + vo.setEndDate(endDate); + return vo; + }else { + vo.setStartDate(start); + vo.setEndDate(end); + return vo; + } + }else if (calcuteRule == EnumFeesShopTimeType.NATURE_PERIOD) { + //自然月 + int day = instance.get(Calendar.DAY_OF_MONTH); + if (day == 1) { + vo.setStartDate(instance.getTime()); + Date endDate = EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(instance.getTime(), time*payPeriodRate, timeUnit); + vo.setEndDate(endDate); + return vo; + }else { + Date startDate = null; + //如果是第一期,则取当前的周期 + if (null == currentReceiveDate) { + startDate = EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(end, 0, timeUnit); + startDate = DateUtils.getSecondsTimeAfter(1, startDate); + }else { + startDate = EnumRentContractAgilTimeUnit.getAfterCalendarNarDay(end, -1*time*payPeriodRate, timeUnit); + } + startDate = DateUtils.getFirstDayForCurrMonth(start); + vo.setStartDate(startDate); + vo.setEndDate(end); + return vo; + } + }else { + vo.setStartDate(start); + vo.setEndDate(end); + return vo; + } + } + + + //查询月账单需要支付的金额 + public static String getNeedPayMoney(List freeDays,Integer decimalSize,EnumRentContractAgilPriceUnit priceUnit, + String price,String rentArea,Date startDate,Date endDate,EnumRentDayPriceCalcute dayPriceRule,Integer monthAverageDays, + Integer time,EnumRentContractAgilTimeUnit timeUnit){ + String needpay; + if (priceUnit == EnumRentContractAgilPriceUnit.RENT_PERIOD){ + return price; + }else if (priceUnit == EnumRentContractAgilPriceUnit.DAY){ + BigDecimal priceD = new BigDecimal(price); + String needpayD = WxRentContractHelper.getNeedPay(freeDays,Constant.default_long_decimal_size,priceD,startDate,endDate,dayPriceRule,monthAverageDays); + needpay = new BigDecimal(needpayD).setScale(decimalSize, RoundingMode.HALF_UP).toPlainString(); + }else if (priceUnit == EnumRentContractAgilPriceUnit.MM_DAY) { + BigDecimal priceD = new BigDecimal(price).multiply(new BigDecimal(rentArea)); + String needpayD = WxRentContractHelper.getNeedPay(freeDays,Constant.default_long_decimal_size,priceD,startDate,endDate,dayPriceRule,monthAverageDays); + needpay = new BigDecimal(needpayD).setScale(decimalSize, RoundingMode.HALF_UP).toPlainString(); + }else{ + BigDecimal priceD = new BigDecimal(price); + if (priceUnit == EnumRentContractAgilPriceUnit.MM_MONTH) { + priceD = priceD.multiply(new BigDecimal(rentArea)); + }else if (priceUnit == EnumRentContractAgilPriceUnit.QUATOR) { + priceD = new BigDecimal(price).divide(new BigDecimal(3),Constant.default_long_decimal_size,RoundingMode.HALF_UP); + }else if (priceUnit == EnumRentContractAgilPriceUnit.HALF_YEAR) { + priceD = new BigDecimal(price).divide(new BigDecimal(6),Constant.default_long_decimal_size,RoundingMode.HALF_UP); + }else if (priceUnit == EnumRentContractAgilPriceUnit.YEAR) { + priceD = new BigDecimal(price).divide(new BigDecimal(12),Constant.default_long_decimal_size,RoundingMode.HALF_UP); + } + //判断是否满足整月 + needpay = new BigDecimal(getMonthNeedPay(freeDays,Constant.default_long_decimal_size,priceD, startDate, endDate, + timeUnit,time,dayPriceRule,monthAverageDays)).setScale(decimalSize, RoundingMode.HALF_UP).toPlainString(); + } + return needpay; + } + + /** + * 按月计租 根据每月的日期总数计算needpay + * @param monthPrice + * @param start + * @param end + * @return + */ + private static String getMonthNeedPay(List freeDays,Integer decimalSize,BigDecimal price,Date start,Date end, + EnumRentContractAgilTimeUnit timeUnit,int time,EnumRentDayPriceCalcute dayPriceRule,Integer monthAvageDays){ + SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat sdM = new SimpleDateFormat("yyyy-MM"); + SimpleDateFormat sdD = new SimpleDateFormat("d"); + BigDecimal total = new BigDecimal(0); + int[] diff; + + //同一天 + if(sd.format(start).equals(sd.format(end))){ + List validDays = getValidDays(start,end,freeDays); + if (null == validDays || validDays.size() <= 0 ) { + return "0"; + } + if (validDays.contains(start)) { + int dayCount = getRealDays(dayPriceRule.getCode(), monthAvageDays, start); + return price.divide(new BigDecimal(dayCount),decimalSize,BigDecimal.ROUND_HALF_UP).toPlainString(); + }else { + return "0"; + } + } + + //同月 + if(sdM.format(start).equals(sdM.format(end))){ + List validDays = getValidDays(start,end,freeDays); + if (null == validDays || validDays.size() <= 0 ) { + return "0"; + } + NeedPayDTO np = getCurrentMonthPay(start, end, price, decimalSize, validDays, dayPriceRule.getCode(), monthAvageDays); + return np.getMoney().toPlainString(); + } + + //正好是一个周期开始 + boolean isPeriodStart = false; + //如果是按自然季度,如果start不是1号,则也不是一个周期 + if (timeUnit == EnumRentContractAgilTimeUnit.QUATOR) { + String startday = sdD.format(start); + if ("1".equals(startday)) { + isPeriodStart = true; + } + }else { + isPeriodStart = true; + } + if (isPeriodStart) { + Calendar instance = Calendar.getInstance(); + instance.setTime(start); + instance = EnumRentContractAgilTimeUnit.getAfterCalendarDay(instance, time, timeUnit); + if(sd.format(instance.getTime()).equals(sd.format(end))){ + List validDays = getValidDays(start,end,freeDays); + if (null == validDays || validDays.size() <= 0 ) { + return "0"; + } + //如果该周期内是全部有效的,则用月份*金额 + int allDays = DateUtils.daysBetween(start,end)+1; + boolean isFull = false; + if (allDays == validDays.size()) { + isFull = true; + } + //不是一个月的。但是按整月算的 + int months = getMonths(sdM.format(start)+"-01",sdM.format(DateUtils.getDaySet(end,Calendar.DATE,1))+"-01"); + if (isFull) { + return price.multiply(new BigDecimal(months)).toPlainString(); + } + //计费每个周期开始时间 + Calendar periodStart = Calendar.getInstance(); + periodStart.setTime(start); + for (int i = 0 ; i < months; i++) { + //每个计费1个月结束时间,可能是跨月的 + Date periodEnd = EnumRentContractAgilTimeUnit.getAfterCalendarDay(periodStart, i+1, EnumRentContractAgilTimeUnit.MONTH).getTime(); + + //当前开始时间到当前月底 + Date currentMonthEnd = DateUtils.getLastDayForMonth(start); + NeedPayDTO np = getCurrentMonthPay(start, currentMonthEnd, price, decimalSize, validDays, dayPriceRule.getCode(), monthAvageDays); + total = total.add(np.getMoney()); + + if(periodEnd.after(currentMonthEnd)) { + start = DateUtils.getDaySet(currentMonthEnd,Calendar.DATE,1); + NeedPayDTO lnp = getCurrentMonthPay(start, periodEnd, price, decimalSize, validDays, dayPriceRule.getCode(), monthAvageDays); + total = total.add(lnp.getMoney()); + }else { + start = DateUtils.getDaySet(currentMonthEnd,Calendar.DATE,1); + periodStart.setTime(start); + } + + } + return total.toPlainString(); + } + } + + //开始到这个月底 + Date lastMonthDay = DateUtils.getLastDayForMonth(start); + List currValidDays = getValidDays(start,lastMonthDay,freeDays); + if (null == currValidDays || currValidDays.size() <= 0 ) { + }else { + NeedPayDTO np = getCurrentMonthPay(start, lastMonthDay, price, decimalSize, currValidDays, dayPriceRule.getCode(), monthAvageDays); + total = total.add(np.getMoney()); + System.out.println("首1月>>>>"+DateUtils.date2String(start)+">>>"+DateUtils.date2String(lastMonthDay)+">>>>"+total.toPlainString()); + } + + //中间月份 + Date newStartDate = DateUtils.getDaySet(lastMonthDay,Calendar.SECOND,1); + int months = getMonths(sdM.format(newStartDate)+"-01",sdM.format(end)+"-01"); + for (int i = 0 ; i < months; i++) { + Date currentMonthEnd = DateUtils.getLastDayForMonth(newStartDate); + List _validDays = getValidDays(newStartDate,currentMonthEnd,freeDays); + if (null == _validDays ||_validDays.size() <= 0 ) { + }else { + NeedPayDTO _np = getCurrentMonthPay(newStartDate, currentMonthEnd, price, decimalSize, _validDays, dayPriceRule.getCode(), monthAvageDays); + System.out.println(i+2+"月>>>>"+DateUtils.date2String(newStartDate)+">>>>"+DateUtils.date2String(currentMonthEnd)+">>>>"+_np.getMoney().toPlainString()); + newStartDate = DateUtils.getDaySet(currentMonthEnd,Calendar.SECOND,1); + total = total.add(_np.getMoney()); + } + } + + //最后一个月 + if (newStartDate.before(end)) { + List lastValidDays = getValidDays(newStartDate,end,freeDays); + if (null == lastValidDays || lastValidDays.size() <= 0 ) { + }else { + NeedPayDTO enp = getCurrentMonthPay(newStartDate, end, price, decimalSize, lastValidDays, dayPriceRule.getCode(), monthAvageDays); + total = total.add(enp.getMoney()); + System.out.println("末月>>>>"+DateUtils.date2String(newStartDate)+">>>"+DateUtils.date2String(end)+">>>>"+enp.getMoney().toPlainString()); + } + } + return total.toPlainString(); + } + + public static List getValidDays(Date start,Date end,List freeDays) { + List allDays = DateUtils.getAllDays(start, end); + if (null == allDays) { + return null; + } + List validDays = new ArrayList(); + validDays.addAll(allDays); + if (null != freeDays) { + List currfreeDays = (List) CollectionUtils.intersection(allDays, freeDays); + if (null != currfreeDays) { + validDays.removeAll(currfreeDays); + } + } + return validDays; + } + + //查询当前月内的金额 + private static NeedPayDTO getCurrentMonthPay(Date start,Date end, BigDecimal priceMonth,Integer decimalSize,List validDays,Integer dayPriceCalcute,Integer monthAvageDays) { + NeedPayDTO np = new NeedPayDTO(); + //当月实际天数 + int md = DateUtils.getMonthDayCount(start);; + //在有效的时间里面有多少天 + int ms = getDays(start,end,validDays); + + //计算天数 + int dayCount = getRealDays(dayPriceCalcute, monthAvageDays, start); + int sed = DateUtils.daysBetween(start,end)+1; + + //满月 + if (md == sed) { + //如果有免租的,则按天算 + if (ms == md) { + np.setFullMonth(true); + np.setMoney(priceMonth); + }else { + np.setFullMonth(false); + np.setMoney(new BigDecimal(ms).multiply(priceMonth).divide(new BigDecimal(dayCount),decimalSize,BigDecimal.ROUND_HALF_UP)); + } + }else { + np.setFullMonth(false); + np.setMoney(new BigDecimal(ms).multiply(priceMonth).divide(new BigDecimal(dayCount),decimalSize,BigDecimal.ROUND_HALF_UP)); + } + return np; + } + + private static int getRealDays(Integer dayPriceCalcute,Integer monthAvageDays,Date start) { + //是不是按实际天数来计算 + boolean isRealDays = true; + if (dayPriceCalcute.intValue() == EnumRentDayPriceCalcute.REAL_DAYS.getCode().intValue()) { + }else { + isRealDays = false; + } + if (isRealDays) { + return DateUtils.getMonthDayCount(start); + }else { + return monthAvageDays; + } + + } + + private static int getDays(Date start,Date end,List allDays) { + if (null == allDays || allDays.size() <= 0 ) { + return 0; + } + + //如果可用区间的最大比start小 + if (start.after(allDays.get(allDays.size()-1))) { + return 0; + } + + List _tempList = new ArrayList(); + _tempList.addAll(allDays); + Date _end = DateUtils.getDayBegin(end); + + //如果可用区间的最大闭end小,相当于这一期是尾 + Date allDayEnd = DateUtils.getDayBegin(allDays.get(allDays.size()-1)); + if (end.after(allDayEnd)) { + int ret = allDays.size(); + allDays.clear(); + return ret; + } + + + for (int i = 0 ; i < _tempList.size(); i ++) { + Date a = _tempList.get(i); + if (a.equals(_end)) { + allDays.remove(a); + return i+1; + }else if (a.after(_end)) { + return i; + }else { + allDays.remove(a); + } + } + return 0; + } + + public static int getMonths(String startStr,String endStr){ + DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd"); + DateTime start = formatter.parseDateTime(startStr); + DateTime end = formatter.parseDateTime(endStr); + int months = Months.monthsBetween(start, end).getMonths(); + return months; + } +} diff --git a/mallinkService/src/main/java/com/iformall/service/impl/WxAgileContractServiceImpl.java b/mallinkService/src/main/java/com/iformall/service/impl/WxAgileContractServiceImpl.java index f57743954..9891f41a1 100644 --- a/mallinkService/src/main/java/com/iformall/service/impl/WxAgileContractServiceImpl.java +++ b/mallinkService/src/main/java/com/iformall/service/impl/WxAgileContractServiceImpl.java @@ -18,12 +18,17 @@ import com.iformall.domain.po.WxRentContractAgileDepositShop; import com.iformall.domain.po.WxRentContractAgileUnDeposit; import com.iformall.domain.po.WxRentContractAgileUnDepositItem; import com.iformall.domain.po.WxShop; +import com.iformall.domain.vo.BillTimeVo; import com.iformall.enums.EnumBillAllType; import com.iformall.enums.EnumBillExtraCreateFrom; +import com.iformall.enums.EnumFeesShopTimeType; import com.iformall.enums.EnumRentContractAdjustPeriod; +import com.iformall.enums.EnumRentContractAgilPriceUnit; +import com.iformall.enums.EnumRentContractAgilTimeUnit; import com.iformall.enums.EnumRentContractAgileFeesType; import com.iformall.enums.EnumRentContractAppStatus; import com.iformall.enums.EnumRentContractStatus; +import com.iformall.enums.EnumRentDayPriceCalcute; import com.iformall.enums.EnumYesOrNo; import com.iformall.exception.MallinkException; import com.iformall.mapper.WxAllBillMapper; @@ -42,6 +47,7 @@ import com.iformall.service.WxEnergyService; import com.iformall.service.WxFlowRecordService; import com.iformall.service.WxMallService; import com.iformall.service.WxMerchantService; +import com.iformall.service.helper.WxRentContractAgileHelper; import com.iformall.service.helper.WxRentContractHelper; import com.iformall.utils.DateUtils; @@ -326,7 +332,7 @@ public class WxAgileContractServiceImpl implements WxAgileContractService { wxBillDeposit.setId(idWorker.nextId()); wxBillDeposit.updateTenantInfo(wxRentContract); wxBillDeposit.setRentContractId(wxRentContract.getId()); - wxBillDeposit.setBillType(EnumBillAllType.RENT_DEPOSIT.getCode()); + wxBillDeposit.setBillType(fees.getBillType()); wxBillDeposit.setIsPreview(EnumYesOrNo.YES.getCode()); wxBillDeposit.setCanEdit(EnumYesOrNo.NO.getCode()); wxBillDeposit.setPriceDetail(fees.getName()); @@ -376,7 +382,80 @@ public class WxAgileContractServiceImpl implements WxAgileContractService { @Override public void createUnDepositBill(WxRentContractAgileUnDeposit unDeposit,MallUserInfo user) { + //删除未生效的账单。 + WxAllBill wxBillDel = new WxAllBill(); + wxBillDel.updateTenantInfo(unDeposit); + wxBillDel.setRentContractId(unDeposit.getRentContractId()); + wxBillDel.setIsPreview(EnumYesOrNo.YES.getCode()); + wxBillDel.setRentContractAgileFeesType(EnumRentContractAgileFeesType.UN_DEPOSIT.getCode()); + wxBillDel.setEnergyFeesId(unDeposit.getFeesId()); + wxAllBillMapper.deletePreviewBill(wxBillDel); + if (null == unDeposit.getItems() || unDeposit.getItems().size() <= 0 ) { + return; + } + WxEnergyFees fees = wxEnergyService.getFeesById(unDeposit.getFeesId(), unDeposit.getTenantId()); + EnumFeesShopTimeType creatRule = EnumFeesShopTimeType.getEnum(unDeposit.getFeesCreateRule()); + WxRentContract contract = wxRentContractMapper.selectById(unDeposit.getRentContractId()); + List yearsBeginList = WxRentContractAgileHelper.getYearsBeginList(contract.getRentalStartDate(), contract.getRentalEndDate()); + + List insertList = new ArrayList(); + final IdWorker idWorker = IdWorker.get(); + for (int i = 0 ; i < unDeposit.getItems().size(); i++) { + WxRentContractAgileUnDepositItem item = unDeposit.getItems().get(i); + if (item.getIsFree() == EnumYesOrNo.NO.getCode()) { + String shopNumber = item.getShopNumber(); + if (StringUtils.isBlank(shopNumber)) { + shopNumber = contract.getShopName(); + } + //根据每一个的开始日期,结束日期来生成账单 + List timeVoList = WxRentContractAgileHelper.initBillTimeList(yearsBeginList, item.getBeginTime(), item.getEndTime(), creatRule, null, i, i); + for (int j = 0 ; j < timeVoList.size() ; j ++) { + BillTimeVo timeVo = timeVoList.get(j); + String needpay = WxRentContractAgileHelper.getNeedPayMoney(null, contract.getDecimalSize(), + EnumRentContractAgilPriceUnit.getEnum(item.getPriceUnit()),item.getPrice(), item.getRentArea(), + item.getBeginTime(), item.getEndTime(), EnumRentDayPriceCalcute.getEnum(contract.getDayPriceCalcute()), + contract.getMonthAverageDays(), unDeposit.getTimePeriod(), EnumRentContractAgilTimeUnit.getEnum(unDeposit.getTimeUnit())); + WxAllBill wxBillRent = new WxAllBill(); + wxBillRent.setIsPreview(EnumYesOrNo.YES.getCode()); + wxBillRent.setId(idWorker.nextId()); + wxBillRent.setRentContractId(unDeposit.getRentContractId()); + wxBillRent.setBillType(fees.getBillType()); + wxBillRent.setPay("0"); + wxBillRent.setStarttime(timeVo.getStartDate()); + wxBillRent.setEndtime(timeVo.getEndDate()); + wxBillRent.setReceiveDate(timeVo.getReceiveDate()); + wxBillRent.setPeriod(WxRentContractHelper.getPeriod(timeVo.getReceiveDate())); + wxBillRent.setCanEdit(EnumYesOrNo.NO.getCode());; + wxBillRent.setNeedPay(needpay); + wxBillRent.setReceivePay(needpay); + //截止收租日在当前时间之前 + Date date = new Date(); + wxBillRent.updateTenantInfo(unDeposit); + wxBillRent.setMerchantId(unDeposit.getMerchantId()); + wxBillRent.setShopId(item.getShopId()); + wxBillRent.setShopNumber(shopNumber); + wxBillRent.setRentArea(item.getRentArea()); + wxBillRent.setCreatetime(date); + wxBillRent.setCreateBy(user.getId()); + wxBillRent.setCreateByName(user.getName()); + wxBillRent.setUpdatetime(date); + wxBillRent.setUpdateBy(user.getId()); + wxBillRent.setUpdateByName(user.getName());; + wxBillRent.setEnergyFeesId(fees.getId()); + insertList.add(wxBillRent); + } + } + } + + try { + if (insertList.size() > 0 ) { + wxAllBillMapper.insertBills(unDeposit.getTenantId(),insertList); + } + } catch (Exception e) { + logger.error("添加押金账单失败,e:" + e.getMessage()); + throw new MallinkException(ErrorCode.DB_FAIL.getCode(), "DB FAILD " + e.getMessage()); + } } } diff --git a/mallinkService/src/main/java/com/iformall/utils/DateUtils.java b/mallinkService/src/main/java/com/iformall/utils/DateUtils.java index efe63165b..ba5ce4ef3 100755 --- a/mallinkService/src/main/java/com/iformall/utils/DateUtils.java +++ b/mallinkService/src/main/java/com/iformall/utils/DateUtils.java @@ -1464,6 +1464,24 @@ public class DateUtils { int year = cal.get(Calendar.YEAR); return year; } + + public static int getBetweenYears(Date start,Date end) { + Calendar startc = Calendar.getInstance(); + startc.setTime(start); + int startYear = startc.get(Calendar.YEAR); + + Calendar endc = Calendar.getInstance(); + endc.setTime(end); + int endYear = endc.get(Calendar.YEAR); + int diffYear = endYear - startYear; + + startc.set(Calendar.YEAR, endYear); + if (startc.before(endc)) { + diffYear ++; + } + + return diffYear; + } /** * 判断生日 @@ -1689,5 +1707,8 @@ public class DateUtils { public static void main(String[] args) { System.out.println(DateUtils.getLastDayForYear(new Date())); + Date start = DateUtils.stringToDate("2021-09-20"); + Date end = DateUtils.stringToDate("2024-09-20"); + System.out.println(DateUtils.getBetweenYears(start, end)); } } diff --git a/mallinkService/src/main/resources/mapper/WxAllBillMapper.xml b/mallinkService/src/main/resources/mapper/WxAllBillMapper.xml index f86bbe8f4..c56db72cc 100644 --- a/mallinkService/src/main/resources/mapper/WxAllBillMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxAllBillMapper.xml @@ -297,6 +297,9 @@ and rent_contract_agile_fees_type = #{rentContractAgileFeesType} + + and energy_fees_id = #{energyFeesId} + diff --git a/mallinkService/src/main/resources/mapper/WxRentContractAgileUnDepositMapper.xml b/mallinkService/src/main/resources/mapper/WxRentContractAgileUnDepositMapper.xml index 4338250d7..19c20f57a 100644 --- a/mallinkService/src/main/resources/mapper/WxRentContractAgileUnDepositMapper.xml +++ b/mallinkService/src/main/resources/mapper/WxRentContractAgileUnDepositMapper.xml @@ -11,6 +11,7 @@ + @@ -20,7 +21,7 @@ `id`,`tenant_id`,`parent_tenant_id`,`rent_contract_id`,`merchant_id`,`setting_method`,`fees_id`,`price`,`price_unit`, - `time_unit`,`calcute_time`,`fees_create_rule`,`createtime`,`updatetime` + `time_period`,`time_unit`,`calcute_time`,`fees_create_rule`,`createtime`,`updatetime`