/* * eGov suite of products aim to improve the internal efficiency,transparency, * accountability and the service delivery of the government organizations. * * Copyright (C) <2015> eGovernments Foundation * * The updated version of eGov suite of products as by eGovernments Foundation * is available at http://www.egovernments.org * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/ or * http://www.gnu.org/licenses/gpl.html . * * In addition to the terms of the GPL license to be adhered to in using this * program, the following additional terms are to be complied with: * * 1) All versions of this program, verbatim or modified must carry this * Legal Notice. * * 2) Any misrepresentation of the origin of the material is prohibited. It * is required that all modified versions of this material be marked in * reasonable ways as different from the original version. * * 3) This license does not grant any rights to any user of the program * with regards to rights under trademark law for use of the trade names * or trademarks of eGovernments Foundation. * * In case of any queries, you can reach eGovernments Foundation at contact@egovernments.org. */ package org.egov.ptis.client.service; import org.egov.commons.Installment; import org.egov.demand.model.EgDemand; import org.egov.demand.model.EgDemandDetails; import org.egov.infra.exception.ApplicationRuntimeException; import org.egov.infra.utils.DateUtils; import org.egov.infra.utils.MoneyUtils; import org.egov.infra.validation.exception.ValidationException; import org.egov.ptis.client.bill.PenaltyBill; import org.egov.ptis.client.util.PropertyTaxUtil; import org.egov.ptis.constants.PropertyTaxConstants; import org.egov.ptis.domain.entity.demand.Ptdemand; import org.egov.ptis.domain.entity.property.BasicProperty; import org.egov.ptis.domain.entity.property.Property; import org.egov.ptis.domain.entity.property.RebatePeriod; import org.egov.ptis.domain.service.property.RebatePeriodService; import org.egov.ptis.notice.PtNotice; import org.egov.ptis.service.utils.PropertyTaxCommonUtils; import org.hibernate.Session; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import java.math.BigDecimal; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; import static org.egov.ptis.constants.PropertyTaxConstants.ARR_LP_DATE_BREAKUP; import static org.egov.ptis.constants.PropertyTaxConstants.ARR_LP_DATE_CONSTANT; import static org.egov.ptis.constants.PropertyTaxConstants.BILLTYPE_MANUAL; import static org.egov.ptis.constants.PropertyTaxConstants.DEMANDRSN_CODE_PENALTY_FINES; import static org.egov.ptis.constants.PropertyTaxConstants.LP_PERCENTAGE_CONSTANT; import static org.egov.ptis.constants.PropertyTaxConstants.NOTICE127; import static org.egov.ptis.constants.PropertyTaxConstants.NOTICE134; import static org.egov.ptis.constants.PropertyTaxConstants.NOTICE_PRATIVRUTTA; import static org.egov.ptis.constants.PropertyTaxConstants.NOTICE_TYPE_BILL; /** * Provieds api's for penalty calculation * * @author nayeem */ @Service @Transactional(readOnly = true) public class PenaltyCalculationService { private Logger LOGGER = LoggerFactory.getLogger(PenaltyCalculationService.class); @Autowired private PropertyTaxUtil propertyTaxUtil; private SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy"); private static final BigDecimal VALUE_HUNDRED = new BigDecimal(100); private BasicProperty basicProperty; private Map<Installment, BigDecimal> installmentWiseDemand; private Map<Installment, BigDecimal> installmentWiseCollection; private Map<String, Date> installmentAndLatestCollDate; private Map<Installment, EgDemandDetails> installmentWisePenaltyDemandDetail; @Autowired private RebatePeriodService rebatePeriodService; @PersistenceContext private EntityManager entityManager; @Autowired private PropertyTaxCommonUtils propertyTaxCommonUtils; public PenaltyCalculationService() { } public PenaltyCalculationService(BasicProperty basicProperty, Map<Installment, BigDecimal> installmentWiseDemand, Map<Installment, BigDecimal> installmentWiseCollection, Map<String, Date> installmentAndLatestCollDate, Map<Installment, EgDemandDetails> installmentWisePenaltyDemandDetail) { this.basicProperty = basicProperty; this.installmentWiseDemand = installmentWiseDemand; this.installmentWiseCollection = installmentWiseCollection; this.installmentAndLatestCollDate = installmentAndLatestCollDate; this.installmentWisePenaltyDemandDetail = installmentWisePenaltyDemandDetail; } public Map<Installment, BigDecimal> getInstallmentWisePenalty() throws ValidationException { LOGGER.debug("Entered into getInstallmentWisePenalty, basicProperty={}", basicProperty); Map<Installment, BigDecimal> installmentWisePenalty = new TreeMap<Installment, BigDecimal>(); Map<Installment, Date> installmentWisePenaltyEffectiveDates = getPenaltyEffectiveDates(basicProperty, new ArrayList<Installment>(installmentWiseDemand.keySet())); if (installmentWisePenaltyEffectiveDates.isEmpty()) { LOGGER.debug("getInstallmentWisePenalty - installmentWisePenaltyEffectiveDates is empty"); return null; } LOGGER.debug("getInstallmentWisePenalty - installmentWisePenaltyEffectiveDates={}", installmentWisePenaltyEffectiveDates); Installment installment = null; BigDecimal penalty = BigDecimal.ZERO; BigDecimal balancePenalty = BigDecimal.ZERO; EgDemandDetails penaltyDemandDetail = null; Amount balance = null; Amount installmentDemand = null; Amount installmentCollection = null; DateTime installmentLatestCollectionDate = null; DateTime today = new DateTime(); for (Map.Entry<Installment, Date> mapEntry : installmentWisePenaltyEffectiveDates.entrySet()) { installment = mapEntry.getKey(); penalty = BigDecimal.ZERO; installmentDemand = new Amount(installmentWiseDemand.get(installment)); installmentCollection = new Amount(installmentWiseCollection.get(installment)); installmentLatestCollectionDate = new DateTime(installmentAndLatestCollDate.get(installment)); if (!installmentWisePenaltyDemandDetail.isEmpty()) { penaltyDemandDetail = installmentWisePenaltyDemandDetail.get(installment); } if (mapEntry.getValue() != null) { balance = installmentDemand.minus(installmentWiseCollection.get(installment)); if (balance.isGreaterThanZero()) { /* * if (installmentCollection.isZero()) { penalty = * calculatePenalty(mapEntry.getValue(), * balance.getAmount()); } else { */ if (penaltyDemandDetail == null || installmentLatestCollectionDate == null) { LOGGER.debug( "getInstallmentWisePenalty - Penalty demand detail / collection date is null for {} ", installment); penalty = calculatePenalty(mapEntry.getValue(), balance.getAmount()); } else { if (penaltyDemandDetail.getAmtCollected().compareTo(BigDecimal.ZERO) > 0) { balancePenalty = penaltyDemandDetail.getAmount().subtract( penaltyDemandDetail.getAmtCollected()); } if (installmentLatestCollectionDate.getMonthOfYear() == today.getMonthOfYear() && installmentLatestCollectionDate.getYear() == today.getYear()) { penalty = balancePenalty.compareTo(BigDecimal.ZERO) > 0 ? balancePenalty : calculatePenalty(mapEntry.getValue(), balance.getAmount()); } else { penalty = calculatePenalty(mapEntry.getValue(), balance.getAmount()).add(balancePenalty); } } // } } } installmentWisePenalty.put(mapEntry.getKey(), penalty); } LOGGER.debug("getInstallmentWisePenalty, installmentWisePenalty={}", installmentWisePenalty); LOGGER.debug("Exiting from getInstallmentWisePenalty"); return installmentWisePenalty; } /** * Excludes if there is water tax before the installment 2011-12 * (exclusive). * <p> * Water tax must be considered only after 01/01/2012 for penalty * calculation * </p> * * @param installment * @param balanceDemand * @param waterTax * @return */ private BigDecimal excludeWaterTax(Installment installment, BigDecimal balanceDemand, BigDecimal waterTax) { BigDecimal demand = balanceDemand; Date waterTaxEffectiveDate = PropertyTaxUtil.getWaterTaxEffectiveDateForPenalty(); if (installment.getFromDate().before(waterTaxEffectiveDate) && !propertyTaxUtil.between(waterTaxEffectiveDate, installment.getFromDate(), installment.getToDate())) { demand = demand.subtract(waterTax); } return demand; } /** * Calculates the penalty from the effective date to the current date * * @param effectiveFrom * @param tax * @return */ public BigDecimal calculatePenalty(Date effectiveFrom, BigDecimal tax) { LOGGER.debug("Entered into calculatePenalty, effectiveFrom={} , tax={} ", effectiveFrom, tax); Integer noOfMonths = PropertyTaxUtil.getMonthsBetweenDates(effectiveFrom, new Date()); BigDecimal penalty = BigDecimal.ZERO; if (noOfMonths > 0) { penalty = tax.multiply(LP_PERCENTAGE_CONSTANT).divide(VALUE_HUNDRED) .multiply(BigDecimal.valueOf(noOfMonths)); } LOGGER.debug("calcPanalty - before rounding - noOfMonths={}, penalty={}", noOfMonths, penalty); penalty = MoneyUtils.roundOff(penalty); LOGGER.debug("calcPanalty - after rounding - noOfMonths={}, penalty={}", noOfMonths, penalty); LOGGER.debug("Exiting from calculatePenalty"); return penalty; } /** * True if the 90 days notice after bill generation is over * * @return */ private Map<Installment, Date> getPenaltyEffectiveDates(BasicProperty basicProperty, List<Installment> installments) throws ValidationException { LOGGER.debug("Entered into getPenaltyEffectiveDates, basicProperty={}, installments={}", basicProperty, installments); Map<Installment, Date> installmentWisePenaltyEffectiveDate = new TreeMap<Installment, Date>(); // get the 22nd day after expiry of 21 days notice for basicProperty Date date22ndDay = get22ndDayDateAfter21DaysNoticeExpiry(basicProperty.getUpicNo()); if (date22ndDay == null) { LOGGER.debug(" getPenaltyEffectiveDates, date22ndDay is null "); } Date earliestModificationDate = null; if (!basicProperty.getSource().equals(PropertyTaxConstants.SOURCEOFDATA_APPLICATION)) { earliestModificationDate = propertyTaxUtil.getEarliestModificationDate(basicProperty.getUpicNo()); LOGGER.debug(" getPenaltyEffectiveDates, earliestModificationDate={}", earliestModificationDate); } // get the bill dates installment wise Map<Installment, Date> installmentAndBillDate = getAllBillGenerationDates(basicProperty, installments); if (installmentAndBillDate != null && !installmentAndBillDate.isEmpty()) { // take the later date of 22nd date or bill date Map<Installment, Date> installmentAnd90DaysDate = get90DaysDate(installmentAndBillDate, date22ndDay); LOGGER.debug("getPenaltyEffectiveDates - installmentAndLatestCollDate={}", installmentAndLatestCollDate); // payment date should not be between the 90 days period Date latestCollectionDate = null; Installment installment = null; Date dateOn91stDay = null; Date penaltyEffectiveDate = null; for (Map.Entry<Installment, Date> mapEntry : installmentAnd90DaysDate.entrySet()) { installment = mapEntry.getKey(); dateOn91stDay = mapEntry.getValue(); penaltyEffectiveDate = null; if (earliestModificationDate != null && installment.getFromDate().before(earliestModificationDate) && installment.getToDate().before(earliestModificationDate)) { continue; } latestCollectionDate = installmentAndLatestCollDate.get(installment.getDescription()); if (dateOn91stDay == null) { if (isRolloverInstallment(installment)) { penaltyEffectiveDate = getPenaltyEffectiveForRolloverInstallment(latestCollectionDate, installment.getFromDate()); } } else { if (latestCollectionDate != null && latestCollectionDate.after(dateOn91stDay)) { penaltyEffectiveDate = getPenaltyEffectiveForRolloverInstallment(latestCollectionDate, installment.getFromDate()); } else { penaltyEffectiveDate = getPenaltyEffectiveDate(dateOn91stDay); } } installmentWisePenaltyEffectiveDate.put(installment, penaltyEffectiveDate); } } LOGGER.debug("getPenaltyEffectiveDates - installmentWisePenaltyEffectiveDate={}", installmentWisePenaltyEffectiveDate); LOGGER.debug("Exiting from getPenaltyEffectiveDates"); return installmentWisePenaltyEffectiveDate; } /** * Gives installment wise bill generation date * * @param basicProperty * @return map of installment and bill generation date pair */ @SuppressWarnings("unchecked") public Map<Installment, Date> getAllBillGenerationDates(BasicProperty basicProperty, List<Installment> installments) throws ValidationException { Map<Installment, Date> installmentAndBillDate = new TreeMap<Installment, Date>(); String upicNo = basicProperty.getUpicNo(); String noBillMessage = "Bill is not available penalty calculation for " + upicNo; String query = "select notice from EgBill bill, PtNotice notice left join notice.basicProperty bp " + "where bill.is_Cancelled = 'N' and bill.egBillType.code = :billTypeCode and bill.billNo = notice.noticeNo " + "and notice.noticeType = :noticeType and bp.upicNo = :upicNo order by notice.noticeDate"; List<PtNotice> demandBills = entityManager.unwrap(Session.class).createQuery(query) .setString("billTypeCode", BILLTYPE_MANUAL).setString("noticeType", NOTICE_TYPE_BILL) .setString("upicNo", upicNo).list(); if (demandBills.isEmpty()) { LOGGER.debug("getAllBillGenerationDates - {}", noBillMessage); // throw new ValidationException(Arrays.asList(new // ValidationError(noBillMessage , noBillMessage))); } Map<Date, Date> propertyCreatedAndOccupancyDate = new TreeMap<Date, Date>(); List<Date> propertySystemCreatedDates = new ArrayList<Date>(); List<Date> occupancyDates = new ArrayList<Date>(); for (Map.Entry<Date, Property> entry : propertyTaxUtil.getPropertiesForPenlatyCalculation(basicProperty) .entrySet()) { propertySystemCreatedDates.add(entry.getValue().getCreatedDate()); propertyCreatedAndOccupancyDate.put(entry.getValue().getCreatedDate(), entry.getKey()); } occupancyDates = new ArrayList<Date>(propertyCreatedAndOccupancyDate.values()); // Collections.sort(propertySystemCreatedDates); // Collections.sort(occupancyDates); LOGGER.info("getAllBillGenerationDates - propertySystemCreatedDates=" + propertySystemCreatedDates + ", occupancyDates=" + occupancyDates); int noOfEffects = propertySystemCreatedDates.size(); Date createdDate = null; Date occupancyDate = null; Date nextOccupancyDate = null; Date nextCreatedDate = null; Date billDate = null; int j = 0; List<PenaltyBill> billDetails = new ArrayList<PenaltyBill>(); Calendar fromDateCalendar = Calendar.getInstance(); Calendar billDateCalendar = Calendar.getInstance(); fromDateCalendar.set(Calendar.DAY_OF_MONTH, 1); fromDateCalendar.set(Calendar.MONTH, 3); fromDateCalendar.set(Calendar.HOUR_OF_DAY, 00); fromDateCalendar.set(Calendar.MINUTE, 00); fromDateCalendar.set(Calendar.SECOND, 00); fromDateCalendar.set(Calendar.MILLISECOND, 0); if (!demandBills.isEmpty()) { for (int i = 0; i < noOfEffects; i++) { createdDate = propertySystemCreatedDates.get(i); occupancyDate = occupancyDates.get(i); nextCreatedDate = i != (noOfEffects - 1) ? propertySystemCreatedDates.get(i + 1) : null; if (demandBills.isEmpty()) { break; } else { billDate = demandBills.get(j).getNoticeDate(); } if (billDate.before(createdDate)) { // bill needs to be skipped as there was modification // effective from same previous modification effective // date demandBills.remove(j); i--; continue; } else if (PropertyTaxUtil.afterOrEqual(billDate, createdDate) && (nextCreatedDate == null || billDate.before(nextCreatedDate))) { billDetails.add(new PenaltyBill(createdDate, occupancyDate, billDate, false)); demandBills.remove(j); } } } j = 0; // if there are more bills as compared to bills generated after // modification if (!demandBills.isEmpty()) { for (j = 0; j < demandBills.size(); j++) { billDate = demandBills.get(j).getNoticeDate(); billDateCalendar.setTime(billDate); fromDateCalendar.set(Calendar.YEAR, billDateCalendar.get(Calendar.YEAR)); billDetails .add(new PenaltyBill(fromDateCalendar.getTime(), fromDateCalendar.getTime(), billDate, true)); } } Collections.sort(billDetails, new Comparator<PenaltyBill>() { @Override public int compare(PenaltyBill bill1, PenaltyBill bill2) { return bill1.getBillDate().compareTo(bill2.getBillDate()); } }); int totalBills = billDetails.size(); DateFormat dateFormat = new SimpleDateFormat(PropertyTaxConstants.DATE_FORMAT_DDMMYYY); for (int i = 0; i < totalBills; i++) { createdDate = billDetails.get(i).getCreatedDate(); occupancyDate = billDetails.get(i).getOccupancyDate(); nextOccupancyDate = i == (totalBills - 1) ? null : billDetails.get(i + 1).getOccupancyDate(); for (Installment installment : installments) { if (billDetails.get(i).getIsBillGeneratedAfterRollover()) { if (dateFormat.format(installment.getFromDate()).equalsIgnoreCase(dateFormat.format(createdDate))) { installmentAndBillDate.put(installment, null); } } else { if (nextOccupancyDate != null && propertyTaxUtil.between(nextOccupancyDate, installment.getFromDate(), installment.getToDate())) { break; } if (PropertyTaxUtil.afterOrEqual(createdDate, installment.getFromDate()) && !billDetails.get(i).getIsBillGeneratedAfterRollover()) { if ((propertyTaxUtil.between(occupancyDate, installment.getFromDate(), installment.getToDate()) || PropertyTaxUtil .afterOrEqual(installment.getFromDate(), occupancyDate)) && (nextOccupancyDate == null || installment.getFromDate().before(nextOccupancyDate))) { installmentAndBillDate.put(installment, billDetails.get(i).getBillDate()); } } } } } // this is the for the installments for which bills not there, ex. after // rollover, if no bill is generated for (Installment installment : installments) { if (installmentAndBillDate.get(installment) == null) { installmentAndBillDate.put(installment, null); } } LOGGER.info("getAllBillGenerationDates - installmentAndBillDate={}", installmentAndBillDate); return installmentAndBillDate; } /** * Gives the applicable demand bill for penalty calculation * * @param demandBills * @param createdDate * @param nextCreatedDate * @param billToRemoved * @param billIndex * @param bill * @return */ private Date getApplicableBillDate(int i, int j, Installment installment, List<Date> createdDates, List<Date> occupancyDates, List<PtNotice> demandBills) { Date applicableBillDate = null; Date createdDate = createdDates.get(i); Date nextCreatedDate = i != (createdDates.size() - 1) ? createdDates.get(i + 1) : null; Date occupancyDate = occupancyDates.get(i); Date nextOccupancyDate = nextCreatedDate == null ? null : occupancyDates.get(i + 1); Date billDate = demandBills.get(j).getNoticeDate(); Date nextBillDate = j != (demandBills.size() - 1) ? demandBills.get(j + 1).getNoticeDate() : null; if (nextBillDate == null) { applicableBillDate = billDate; } else { if (!propertyTaxUtil.between(nextBillDate, installment.getFromDate(), installment.getToDate())) { if (PropertyTaxUtil.afterOrEqual(billDate, createdDate) && billDate.before(nextCreatedDate)) { if (installment.getFromDate().before(billDate) || propertyTaxUtil.between(billDate, installment.getFromDate(), installment.getToDate())) { if (PropertyTaxUtil.afterOrEqual(installment.getFromDate(), occupancyDate) && (nextOccupancyDate == null || installment.getFromDate().before(nextOccupancyDate))) { applicableBillDate = billDate; createdDates.remove(i); occupancyDates.remove(i); demandBills.remove(j); } } } } } return applicableBillDate; } public Map<Installment, Date> get90DaysDate(Map<Installment, Date> installmentAndBillDate, Date dateAfter21Days) { Map<Installment, Date> installmentAnd90DaysDate = new TreeMap<Installment, Date>(); Date date = null; Date dateOn91stDay = null; for (Map.Entry<Installment, Date> mapEntry : installmentAndBillDate.entrySet()) { date = mapEntry.getValue(); dateOn91stDay = null; if (date != null) { date = dateAfter21Days == null ? date : dateAfter21Days.after(date) ? dateAfter21Days : date; dateOn91stDay = DateUtils.add(date, Calendar.DAY_OF_MONTH, 91); } installmentAnd90DaysDate.put(mapEntry.getKey(), dateOn91stDay); } return installmentAnd90DaysDate; } /** * @param basicProperty * @return */ public Date get22ndDayDateAfter21DaysNoticeExpiry(String propertyId) { LOGGER.debug("Entered into get22ndDayDateAfter21DaysNoticeExpiry, propertyId={}", propertyId); String notice127And134 = "'" + NOTICE127 + "', '" + NOTICE134 + "'"; String stringQuery = "select to_char(n.noticeDate, 'dd/mm/yyyy'), to_char(pvr.noticeDate, 'dd/mm/yyyy'), to_char(p.createdDate, 'dd/mm/yyyy') " + "from PtNotice n, PtNotice pvr, PropertyImpl p left join p.basicProperty bp " + "where n.basicProperty = bp " + "and pvr.basicProperty = bp " + "and (p.status = 'A' or p.status = 'I') " + "and bp.upicNo = :upicNo " + "and bp.status.statusCode <> :bpStatus " + "and n.noticeType in (" + notice127And134 + ") " + "and pvr.noticeType = :noticePVR " + "and n.noticeDate > p.createdDate " + "and pvr.noticeDate > p.createdDate " + " and n.noticeDate is not null " + "and pvr.noticeDate is not null "; List result = entityManager.unwrap(Session.class).createQuery(stringQuery).setString("upicNo", propertyId) .setString("bpStatus", PropertyTaxConstants.STATUS_OBJECTED_STR) .setString("noticePVR", NOTICE_PRATIVRUTTA).list(); if (result.isEmpty()) { return null; } Date noticeDate = null; Date pvrDate = null; Object row = result.get(0); Object[] columnValues = (Object[]) row; try { noticeDate = dateFormatter.parse((String) columnValues[0]); pvrDate = dateFormatter.parse((String) columnValues[1]); } catch (ParseException pe) { LOGGER.error("Error while parsing notice/pvr date", pe); throw new ApplicationRuntimeException("Error while parsing notice/pvr date", pe); } Date dateOn22ndDay = DateUtils.add((noticeDate.before(pvrDate) ? pvrDate : noticeDate), Calendar.DAY_OF_MONTH, 21); LOGGER.debug("get22ndDayDateAfter21DaysNoticeExpiry, dateOn22ndDay={}", dateOn22ndDay); LOGGER.debug("Exiting from get22ndDayDateAfter21DaysNoticeExpiry"); return dateOn22ndDay; } public Date getPenaltyEffectiveDate(Date dateAfterNoticeDaysExpiry) { LOGGER.debug("Entered into getPenaltyEffectiveDate, dateAfterNoticeDaysExpiry={}", dateAfterNoticeDaysExpiry); Date penaltyEffectiveDate = null; Calendar calendar = Calendar.getInstance(); calendar.setTime(dateAfterNoticeDaysExpiry); if (calendar.get(Calendar.DAY_OF_MONTH) <= 15) { penaltyEffectiveDate = dateAfterNoticeDaysExpiry; } else { calendar.add(Calendar.MONTH, 1); penaltyEffectiveDate = calendar.getTime(); } LOGGER.debug("getPenaltyEffectiveDate, penaltyEffectiveDate={}", penaltyEffectiveDate); LOGGER.debug("Exting from getPenaltyEffectiveDate"); return penaltyEffectiveDate; } /** * Gives the date to calculate the penalty from. * * @param latestCollReceiptDate * @param fromDate * @return date from which penalty will be applied */ public Date getPenaltyEffectiveForRolloverInstallment(Date latestCollReceiptDate, Date fromDate) { LOGGER.info("Enter into calcPanalty - latestCollReceiptDate: " + latestCollReceiptDate + ", fromDate " + fromDate); Calendar fromDateCalendar = Calendar.getInstance(); fromDateCalendar.setTime(fromDate); Calendar arrearsPenaltyApplicableDate = Calendar.getInstance(); arrearsPenaltyApplicableDate.set(Calendar.DAY_OF_MONTH, 1); arrearsPenaltyApplicableDate.set(Calendar.MONTH, Calendar.JANUARY); arrearsPenaltyApplicableDate.set(Calendar.HOUR_OF_DAY, 00); arrearsPenaltyApplicableDate.set(Calendar.MINUTE, 00); arrearsPenaltyApplicableDate.set(Calendar.SECOND, 00); Calendar latestCollRcptCalendar = Calendar.getInstance(); if (latestCollReceiptDate != null) { latestCollRcptCalendar.setTime(latestCollReceiptDate); } DateFormat dateFormat = new SimpleDateFormat(PropertyTaxConstants.DATE_FORMAT_DDMMYYY); Date arrearlpDate = null; Date arrearlpDateBreakup = null; Date frmDate = null; try { arrearlpDate = dateFormat.parse(ARR_LP_DATE_CONSTANT); arrearlpDateBreakup = dateFormat.parse(ARR_LP_DATE_BREAKUP); frmDate = dateFormat.parse(dateFormat.format(fromDate)); } catch (ParseException e) { LOGGER.error("Error while parsing Arrear Late Payment penalty dates", e); } Date penaltyFromDate = null; if (latestCollReceiptDate != null && latestCollReceiptDate.after(frmDate) && latestCollReceiptDate.after(arrearlpDateBreakup)) { latestCollRcptCalendar.add(Calendar.MONTH, 1); arrearsPenaltyApplicableDate.setTime(latestCollRcptCalendar.getTime()); penaltyFromDate = arrearsPenaltyApplicableDate.getTime(); } else if (frmDate.after(arrearlpDateBreakup) || frmDate.equals(arrearlpDateBreakup)) { arrearsPenaltyApplicableDate.set(Calendar.YEAR, (fromDateCalendar.get(Calendar.YEAR) + 1)); penaltyFromDate = arrearsPenaltyApplicableDate.getTime(); } else { penaltyFromDate = arrearlpDate; } LOGGER.info("calcPanalty - penaltyFromDate: " + penaltyFromDate); return penaltyFromDate; } /** * Returns true if the installment passed is a rollover installment else * returns false * * @param installment * @return true if the installment passed is a rollover installment */ private boolean isRolloverInstallment(Installment installment) { Date systemCreatedDate = basicProperty.getProperty().getCreatedDate(); return propertyTaxUtil.between(new Date(), installment.getFromDate(), installment.getToDate()) && !propertyTaxUtil.between(systemCreatedDate, installment.getFromDate(), installment.getToDate()); } public Map<String, Map<Installment, BigDecimal>> getInstallmentDemandAndCollection(BasicProperty basicProperty, EgDemand currentDemand) { Map<String, Map<Installment, BigDecimal>> installmentDemandAndCollection = new TreeMap<String, Map<Installment, BigDecimal>>(); Property property = null; property = basicProperty.getProperty(); final Installment currentInstall = currentDemand.getEgInstallmentMaster(); installmentDemandAndCollection = propertyTaxUtil.prepareReasonWiseDenandAndCollection(property, currentInstall); return installmentDemandAndCollection; } public Map<Installment, EgDemandDetails> getInstallmentWisePenaltyDemandDetails(final Property property, EgDemand currentDemand) { final Map<Installment, EgDemandDetails> installmentWisePenaltyDemandDetails = new TreeMap<Installment, EgDemandDetails>(); for (final EgDemandDetails dmdDet : currentDemand.getEgDemandDetails()) { if (dmdDet.getEgDemandReason().getEgDemandReasonMaster().getCode() .equalsIgnoreCase(DEMANDRSN_CODE_PENALTY_FINES) && dmdDet.getAmount().compareTo(BigDecimal.ZERO) > 0) installmentWisePenaltyDemandDetails.put(dmdDet.getEgDemandReason().getEgInstallmentMaster(), dmdDet); } return installmentWisePenaltyDemandDetails; } public boolean isEarlyPayRebateActive() { boolean value = false; final Installment currentInstallment = propertyTaxCommonUtils.getCurrentInstallment(); final RebatePeriod rebatePeriod = rebatePeriodService.getRebateForCurrInstallment(currentInstallment.getId()); if (rebatePeriod != null) if (rebatePeriod.getRebateDate().compareTo(new Date()) > 0) value = true; return value; } public void setPropertyTaxUtil(PropertyTaxUtil propertyTaxUtil) { this.propertyTaxUtil = propertyTaxUtil; } }