/*
* 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.wtms.application.rest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.egov.collection.entity.ReceiptDetail;
import org.egov.collection.integration.models.BillAccountDetails.PURPOSE;
import org.egov.commons.CFinancialYear;
import org.egov.commons.dao.ChartOfAccountsHibernateDAO;
import org.egov.commons.dao.FinancialYearDAO;
import org.egov.commons.dao.FunctionHibernateDAO;
import org.egov.demand.model.EgBillDetails;
import org.egov.infra.validation.exception.ValidationError;
import org.egov.infra.validation.exception.ValidationException;
import org.egov.wtms.utils.constants.WaterTaxConstants;
public class CollectionApportioner {
public static final String STRING_FULLTAX = "FULLTAX";
public static final String STRING_ADVANCE = "ADVANCE";
private static final Logger LOGGER = Logger.getLogger(CollectionApportioner.class);
public CollectionApportioner() {
}
public void apportion(final BigDecimal amtPaid, final List<ReceiptDetail> receiptDetails,
final Map<String, BigDecimal> instDmdMap) {
LOGGER.info("receiptDetails before apportioning amount " + amtPaid + ": " + receiptDetails);
Amount balance = new Amount(amtPaid);
BigDecimal crAmountToBePaid = BigDecimal.ZERO;
for (final ReceiptDetail rd : receiptDetails) {
if (balance.isZero()) {
// nothing left to apportion
rd.zeroDrAndCrAmounts();
continue;
}
crAmountToBePaid = rd.getCramountToBePaid();
if (balance.isLessThanOrEqualTo(crAmountToBePaid)) {
// partial or exact payment
rd.setCramount(balance.amount);
balance = Amount.ZERO;
} else { // excess payment
rd.setCramount(crAmountToBePaid);
balance = balance.minus(crAmountToBePaid);
}
}
if (balance.isGreaterThanZero()) {
LOGGER.error("Apportioning failed: excess payment!");
throw new ValidationException(
Arrays.asList(new ValidationError("Paid Amount is greater than Total Amount to be paid",
"Paid Amount is greater than Total Amount to be paid")));
}
LOGGER.info("receiptDetails after apportioning: " + receiptDetails);
}
public List<ReceiptDetail> reConstruct(final BigDecimal amountPaid, final List<EgBillDetails> billDetails,
final FunctionHibernateDAO functionDAO, final ChartOfAccountsHibernateDAO chartOfAccountsDAO,
final FinancialYearDAO financialYearDAO) {
final List<ReceiptDetail> receiptDetails = new ArrayList<ReceiptDetail>(0);
LOGGER.info("receiptDetails before reApportion amount " + amountPaid + ": " + receiptDetails);
LOGGER.info("billDetails before reApportion " + billDetails);
Amount balance = new Amount(amountPaid);
final CFinancialYear finYear = financialYearDAO.getFinancialYearByDate(new Date());
BigDecimal crAmountToBePaid = BigDecimal.ZERO;
for (final EgBillDetails billDetail : billDetails) {
final String glCode = billDetail.getGlcode();
final ReceiptDetail receiptDetail = new ReceiptDetail();
if (billDetail.getDescription().contains(WaterTaxConstants.DEMANDRSN_REASON_ADVANCE))
receiptDetail.setPurpose(PURPOSE.ADVANCE_AMOUNT.toString());
else if (billDetail.getEgDemandReason().getEgInstallmentMaster().getToDate()
.compareTo(finYear.getStartingDate()) < 0)
receiptDetail.setPurpose(PURPOSE.ARREAR_AMOUNT.toString());
else if (billDetail.getEgDemandReason().getEgInstallmentMaster().getFromDate()
.compareTo(finYear.getStartingDate()) >= 0
&& billDetail.getEgDemandReason().getEgInstallmentMaster().getFromDate()
.compareTo(finYear.getEndingDate()) < 0)
receiptDetail.setPurpose(PURPOSE.CURRENT_AMOUNT.toString());
else
receiptDetail.setPurpose(PURPOSE.OTHERS.toString());
receiptDetail.setOrdernumber(Long.valueOf(billDetail.getOrderNo()));
receiptDetail.setDescription(billDetail.getDescription());
receiptDetail.setIsActualDemand(true);
if (billDetail.getFunctionCode() != null)
receiptDetail.setFunction(functionDAO.getFunctionByCode(billDetail.getFunctionCode()));
receiptDetail.setAccounthead(chartOfAccountsDAO.getCChartOfAccountsByGlCode(glCode));
receiptDetail.setCramountToBePaid(balance.amount);
receiptDetail.setDramount(BigDecimal.ZERO);
if (balance.isZero()) {
// nothing left to apportion
receiptDetail.zeroDrAndCrAmounts();
receiptDetails.add(receiptDetail);
continue;
}
crAmountToBePaid = billDetail.getCrAmount();
if (balance.isLessThanOrEqualTo(crAmountToBePaid)) {
// partial or exact payment
receiptDetail.setCramount(balance.amount);
receiptDetail.setCramountToBePaid(balance.amount);
balance = Amount.ZERO;
} else { // excess payment
receiptDetail.setCramount(crAmountToBePaid);
receiptDetail.setCramountToBePaid(crAmountToBePaid);
balance = balance.minus(crAmountToBePaid);
}
receiptDetails.add(receiptDetail);
}
if (balance.isGreaterThanZero()) {
LOGGER.error("reApportion failed: excess payment!");
throw new ValidationException(
Arrays.asList(new ValidationError("Paid Amount is greater than Total Amount to be paid",
"Paid Amount is greater than Total Amount to be paid")));
}
LOGGER.info("receiptDetails after reApportion: " + receiptDetails);
return receiptDetails;
}
private static class Amount {
private final BigDecimal amount;
private static Amount ZERO = new Amount(BigDecimal.ZERO);
private Amount(final BigDecimal amount) {
this.amount = amount;
}
private boolean isZero() {
return amount.compareTo(BigDecimal.ZERO) == 0;
}
private boolean isGreaterThan(final BigDecimal bd) {
return amount.compareTo(bd) > 0;
}
private boolean isGreaterThanZero() {
return isGreaterThan(BigDecimal.ZERO);
}
private boolean isLessThanOrEqualTo(final BigDecimal bd) {
return amount.compareTo(bd) <= 0;
}
private Amount minus(final BigDecimal bd) {
return new Amount(amount.subtract(bd));
}
}
}