/*
* 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.works.services.impl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.egov.commons.Accountdetailtype;
import org.egov.commons.CFinancialYear;
import org.egov.commons.dao.FinancialYearHibernateDAO;
import org.egov.dao.budget.BudgetDetailsDAO;
import org.egov.egf.commons.EgovCommon;
import org.egov.infra.validation.exception.ValidationError;
import org.egov.infra.validation.exception.ValidationException;
import org.egov.infstr.services.PersistenceService;
import org.egov.model.budget.BudgetUsage;
import org.egov.works.abstractestimate.entity.AbstractEstimate;
import org.egov.works.abstractestimate.entity.AbstractEstimateAppropriation;
import org.egov.works.abstractestimate.entity.FinancialDetail;
import org.egov.works.models.estimate.DepositWorksUsage;
import org.egov.works.revisionestimate.entity.RevisionAbstractEstimate;
import org.egov.works.services.AbstractEstimateService;
import org.egov.works.services.DepositWorksUsageService;
import org.egov.works.services.RevisionEstimateService;
import org.egov.works.services.WorksService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* This class will expose all Revision Estimate related operations.
*/
public class RevisionEstimateServiceImpl extends BaseServiceImpl<RevisionAbstractEstimate, Long> implements
RevisionEstimateService {
private AbstractEstimateService abstractEstimateService;
private WorksService worksService;
private EgovCommon egovCommon;
private DepositWorksUsageService depositWorksUsageService;
private PersistenceService<AbstractEstimateAppropriation, Long> estimateAppropriationService;
private BudgetDetailsDAO budgetDetailsDAO;
@Autowired
private FinancialYearHibernateDAO finHibernateDao;
private static final String MODULE_NAME = "Works";
private static final String KEY_NAME = "SKIP_BUDGET_CHECK";
public RevisionEstimateServiceImpl(final PersistenceService<RevisionAbstractEstimate, Long> persistenceService) {
super(persistenceService);
}
@Override
public void consumeBudget(final RevisionAbstractEstimate revisionEstimate) {
final AbstractEstimate parentEstimate = revisionEstimate.getParent();
final String appropriationNumber = abstractEstimateService.getBudgetAppropriationNumber(parentEstimate);
if (isDepositWorksType(parentEstimate))
checkForBudgetaryAppropriationForDepositWorks(revisionEstimate, appropriationNumber);
else
consumeBudgetForNormalWorks(revisionEstimate, appropriationNumber);
}
@Override
public void releaseBudget(final RevisionAbstractEstimate revisionEstimate) {
final AbstractEstimate parentEstimate = revisionEstimate.getParent();
final String appropriationNumber = abstractEstimateService.getLatestEstimateAppropriationNumber(revisionEstimate);
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("BC/");
stringBuilder.append(appropriationNumber);
final String budgetRejectionNumber = stringBuilder.toString();
// Financial details of the parent
final FinancialDetail financialDetail = parentEstimate.getFinancialDetails().get(0);
if (isDepositWorksType(parentEstimate))
releaseDepositWorksAmountOnReject(revisionEstimate, financialDetail, budgetRejectionNumber);
else
releaseBudgetOnReject(revisionEstimate, financialDetail, budgetRejectionNumber);
}
private boolean releaseDepositWorksAmountOnReject(final RevisionAbstractEstimate revisionEstimate,
final FinancialDetail financialDetail, final String budgetRejectionNumber) throws ValidationException {
boolean flag = false;
final Accountdetailtype accountdetailtype = worksService.getAccountdetailtypeByName("DEPOSITCODE");
final AbstractEstimateAppropriation estimateAppropriation = estimateAppropriationService.findByNamedQuery(
"getLatestDepositWorksUsageForEstimate", revisionEstimate.getId());
// No budget appropriation was done in the first place
if (estimateAppropriation == null)
return flag;
final BigDecimal creditBalance = egovCommon.getDepositAmountForDepositCode(new Date(), financialDetail.getCoa()
.getGlcode(), financialDetail.getFund().getCode(), accountdetailtype.getId(), financialDetail
.getAbstractEstimate().getDepositCode().getId().intValue());
final double releaseAmount = estimateAppropriation.getDepositWorksUsage().getConsumedAmount().doubleValue();
DepositWorksUsage depositWorksUsage = new DepositWorksUsage();
depositWorksUsage.setTotalDepositAmount(creditBalance);
depositWorksUsage.setConsumedAmount(BigDecimal.ZERO);
depositWorksUsage.setReleasedAmount(new BigDecimal(releaseAmount));
depositWorksUsage.setAppropriationNumber(budgetRejectionNumber);
depositWorksUsage.setAbstractEstimate(revisionEstimate);
depositWorksUsage.setAppropriationDate(new Date());
depositWorksUsage.setFinancialYear(estimateAppropriation.getDepositWorksUsage().getFinancialYear());
depositWorksUsage.setCoa(financialDetail.getCoa());
depositWorksUsage.setDepositCode(financialDetail.getAbstractEstimate().getDepositCode());
depositWorksUsage = depositWorksUsageService.persist(depositWorksUsage);
persistReleaseDepositWorksAmountDetails(revisionEstimate, financialDetail, depositWorksUsage);
flag = true;
return flag;
}
private void persistReleaseDepositWorksAmountDetails(final RevisionAbstractEstimate revisionEstimate,
final FinancialDetail financialDetail, final DepositWorksUsage depositWorksUsage) {
AbstractEstimateAppropriation estimateAppropriation = null;
final BigDecimal creditBalance = depositWorksUsage.getTotalDepositAmount();
final BigDecimal utilizedAmt = depositWorksUsageService.getTotalUtilizedAmountForDepositWorks(financialDetail,
new Date());
final BigDecimal balance = creditBalance.subtract(utilizedAmt);
estimateAppropriation = estimateAppropriationService.findByNamedQuery("getLatestDepositWorksUsageForEstimate",
revisionEstimate.getId());
estimateAppropriation.setBalanceAvailable(balance);
estimateAppropriation.setDepositWorksUsage(depositWorksUsage);
estimateAppropriationService.persist(estimateAppropriation);
}
private boolean consumeBudgetForNormalWorks(final RevisionAbstractEstimate revisionEstimate,
final String appropriationNumber) {
boolean flag = false;
final Long finYearId = finHibernateDao.getFinYearByDate(new Date()).getId();
final List<Long> budgetHeadId = new ArrayList<Long>();
final FinancialDetail financialDetail = revisionEstimate.getParent().getFinancialDetails().get(0);
budgetHeadId.add(financialDetail.getBudgetGroup().getId());
final BudgetUsage budgetUsage = budgetDetailsDAO.consumeEncumbranceBudget(
appropriationNumber == null ? null : appropriationNumber,
finYearId,
Integer.valueOf(11),
revisionEstimate.getEstimateNumber(),
Integer.parseInt(financialDetail.getAbstractEstimate().getUserDepartment().getId().toString()),
financialDetail.getFunction() == null ? null : financialDetail.getFunction().getId(),
financialDetail.getFunctionary() == null ? null : financialDetail.getFunctionary().getId(),
financialDetail.getScheme() == null ? null : financialDetail.getScheme().getId(),
financialDetail.getSubScheme() == null ? null : financialDetail.getSubScheme().getId(),
financialDetail.getAbstractEstimate().getWard() == null ? null : Integer.parseInt(financialDetail
.getAbstractEstimate().getWard().getId().toString()),
financialDetail.getBudgetGroup() == null ? null : budgetHeadId,
financialDetail.getFund() == null ? null : financialDetail.getFund().getId(), revisionEstimate
.getTotalAmount().getValue());
if (budgetUsage == null)
throw new ValidationException(Arrays.asList(new ValidationError("changeFDHeader.budget.consumption.failed",
"Insufficient funds available")));
persistBudgetAppropriationDetails(revisionEstimate, revisionEstimate.getParent(), budgetUsage);
flag = true;
return flag;
}
private void persistBudgetAppropriationDetails(final RevisionAbstractEstimate revisionEstimate,
final AbstractEstimate parentEstimate, final BudgetUsage budgetUsage) {
AbstractEstimateAppropriation estimateAppropriation = null;
final Integer finYearId = budgetUsage.getFinancialYearId();
final Date endingDate = finHibernateDao.getFinancialYearById(finYearId.longValue()).getEndingDate();
estimateAppropriation = estimateAppropriationService.findByNamedQuery("getBudgetUsageForEstimateByFinYear",
revisionEstimate.getId(), finYearId.intValue());
if (estimateAppropriation != null) {
estimateAppropriation.setBalanceAvailable(abstractEstimateService.getBudgetAvailable(parentEstimate,
endingDate));
estimateAppropriation.setBudgetUsage(budgetUsage);
} else {
estimateAppropriation = new AbstractEstimateAppropriation();
estimateAppropriation.setAbstractEstimate(revisionEstimate);
estimateAppropriation.setBalanceAvailable(abstractEstimateService.getBudgetAvailable(parentEstimate,
endingDate));
estimateAppropriation.setBudgetUsage(budgetUsage);
}
estimateAppropriationService.persist(estimateAppropriation);
}
private boolean checkForBudgetaryAppropriationForDepositWorks(final RevisionAbstractEstimate revisionEstimate,
final String appropriationNumber)
throws ValidationException {
boolean flag = false;
final Date appDate = new Date();
double depApprAmnt = 0.0;
final Accountdetailtype accountdetailtype = worksService.getAccountdetailtypeByName("DEPOSITCODE");
depApprAmnt = revisionEstimate.getTotalAmount().getValue();
final FinancialDetail financialDetail = revisionEstimate.getParent().getFinancialDetails().get(0);
final BigDecimal creditBalance = egovCommon.getDepositAmountForDepositCode(new Date(), financialDetail.getCoa()
.getGlcode(), financialDetail.getFund().getCode(), accountdetailtype.getId(), financialDetail
.getAbstractEstimate().getDepositCode().getId().intValue());
BigDecimal utilizedAmt = depositWorksUsageService.getTotalUtilizedAmountForDepositWorks(financialDetail,
appDate);
BigDecimal balance = BigDecimal.ZERO;
if (utilizedAmt == null) {
balance = creditBalance;
utilizedAmt = BigDecimal.ZERO;
} else
balance = creditBalance.subtract(utilizedAmt);
if (balance.doubleValue() >= depApprAmnt) {
DepositWorksUsage depositWorksUsage = new DepositWorksUsage();
final CFinancialYear budgetApprDate_finYear = finHibernateDao.getFinYearByDate(appDate);
depositWorksUsage.setTotalDepositAmount(creditBalance);
depositWorksUsage.setConsumedAmount(new BigDecimal(depApprAmnt));
depositWorksUsage.setReleasedAmount(BigDecimal.ZERO);
depositWorksUsage.setAppropriationNumber(appropriationNumber);
depositWorksUsage.setAbstractEstimate(revisionEstimate);
depositWorksUsage.setAppropriationDate(appDate);
depositWorksUsage.setFinancialYear(budgetApprDate_finYear);
depositWorksUsage.setDepositCode(financialDetail.getAbstractEstimate().getDepositCode());
depositWorksUsage.setCoa(financialDetail.getCoa());
depositWorksUsage = depositWorksUsageService.persist(depositWorksUsage);
persistDepositCodeAppDetails(depositWorksUsage, financialDetail);
flag = true;
}
if (!flag)
throw new ValidationException(Arrays.asList(new ValidationError(
"reEstimate.estimate.validate.budget.amount", "Insufficient funds available")));
return flag;
}
private void persistDepositCodeAppDetails(final DepositWorksUsage depositWorksUsage,
final FinancialDetail financialDetail) {
AbstractEstimateAppropriation estimateAppropriation = null;
final int finYearId = finHibernateDao.getFinYearByDate(new Date()).getId().intValue();
final BigDecimal creditBalance = depositWorksUsage.getTotalDepositAmount();
final AbstractEstimate abstractEstimate = depositWorksUsage.getAbstractEstimate();
BigDecimal utilizedAmt = depositWorksUsageService.getTotalUtilizedAmountForDepositWorks(financialDetail,
depositWorksUsage.getCreatedDate());
BigDecimal balance = BigDecimal.ZERO;
if (utilizedAmt == null) {
balance = creditBalance;
utilizedAmt = BigDecimal.ZERO;
} else
balance = creditBalance.subtract(utilizedAmt);
estimateAppropriation = estimateAppropriationService.findByNamedQuery(
"getDepositWorksUsageForEstimateByFinYear", abstractEstimate.getId(), finYearId);
if (estimateAppropriation != null) {
estimateAppropriation.setBalanceAvailable(balance);
estimateAppropriation.setDepositWorksUsage(depositWorksUsage);
} else {
estimateAppropriation = new AbstractEstimateAppropriation();
estimateAppropriation.setAbstractEstimate(abstractEstimate);
estimateAppropriation.setBalanceAvailable(balance);
estimateAppropriation.setDepositWorksUsage(depositWorksUsage);
}
estimateAppropriationService.persist(estimateAppropriation);
}
private boolean releaseBudgetOnReject(final RevisionAbstractEstimate revisionEstimate,
final FinancialDetail financialDetail, final String budgetRejectionNumber) throws ValidationException {
boolean flag = false;
final AbstractEstimateAppropriation estimateAppropriation = estimateAppropriationService.findByNamedQuery(
"getLatestBudgetUsageForEstimate", revisionEstimate.getId());
// No budget appropriation was done for this revision estimate
if (estimateAppropriation == null)
return flag;
final List<Long> budgetheadid = new ArrayList<Long>();
budgetheadid.add(financialDetail.getBudgetGroup().getId());
BudgetUsage budgetUsage = null;
budgetUsage = budgetDetailsDAO.releaseEncumbranceBudget(
budgetRejectionNumber == null ? null : budgetRejectionNumber,
estimateAppropriation.getBudgetUsage().getFinancialYearId().longValue(),
Integer.valueOf(11),
revisionEstimate.getEstimateNumber(),
Integer.parseInt(financialDetail.getAbstractEstimate().getUserDepartment().getId().toString()),
financialDetail.getFunction() == null ? null : financialDetail.getFunction().getId(),
financialDetail.getFunctionary() == null ? null : financialDetail.getFunctionary().getId(),
financialDetail.getScheme() == null ? null : financialDetail.getScheme().getId(),
financialDetail.getSubScheme() == null ? null : financialDetail.getSubScheme().getId(),
financialDetail.getAbstractEstimate().getWard() == null ? null : Integer.parseInt(financialDetail
.getAbstractEstimate().getWard().getId().toString()),
financialDetail.getBudgetGroup() == null ? null : budgetheadid,
financialDetail.getFund() == null ? null : financialDetail.getFund().getId(), estimateAppropriation
.getBudgetUsage().getConsumedAmount());
if (financialDetail.getAbstractEstimate() != null)
persistBudgetReleaseDetails(revisionEstimate, financialDetail.getAbstractEstimate(), budgetUsage);
flag = true;
return flag;
}
private void persistBudgetReleaseDetails(final RevisionAbstractEstimate revisionEstimate,
final AbstractEstimate parentEstimate, final BudgetUsage budgetUsage) {
AbstractEstimateAppropriation estimateAppropriation = null;
estimateAppropriation = estimateAppropriationService.findByNamedQuery("getLatestBudgetUsageForEstimate",
revisionEstimate.getId());
final Integer finYearId = estimateAppropriation.getBudgetUsage().getFinancialYearId();
final Date endingDate = finHibernateDao.getFinancialYearById(finYearId.longValue()).getEndingDate();
estimateAppropriation.setBalanceAvailable(abstractEstimateService
.getBudgetAvailable(parentEstimate, endingDate));
estimateAppropriation.setBudgetUsage(budgetUsage);
estimateAppropriationService.persist(estimateAppropriation);
}
@Override
public boolean isDepositWorksType(final AbstractEstimate estimate) {
boolean isDepositWorks = false;
final List<String> depositTypeList = getAppConfigValuesToSkipBudget();
for (final String type : depositTypeList)
if (type.equals(estimate.getNatureOfWork().getName()))
isDepositWorks = true;
return isDepositWorks;
}
@Override
public boolean getShowBudgetFolio(final AbstractEstimate revisionEstimate) {
if (revisionEstimate != null && revisionEstimate.getEgwStatus() != null && revisionEstimate.getParent() != null
&& !isDepositWorksType(revisionEstimate.getParent()))
return estimateAppropriationService.findByNamedQuery("getLatestBudgetUsageForEstimate",
revisionEstimate.getId()) != null ? true : false;
else
return false;
}
@Override
public boolean getShowDepositFolio(final AbstractEstimate revisionEstimate) {
if (revisionEstimate != null && revisionEstimate.getEgwStatus() != null && revisionEstimate.getParent() != null
&& isDepositWorksType(revisionEstimate.getParent()))
return estimateAppropriationService.findByNamedQuery("getLatestDepositWorksUsageForEstimate",
revisionEstimate.getId()) != null ? true : false;
else
return false;
}
private List<String> getAppConfigValuesToSkipBudget() {
return worksService.getNatureOfWorkAppConfigValues(MODULE_NAME, KEY_NAME);
}
public void setAbstractEstimateService(final AbstractEstimateService abstractEstimateService) {
this.abstractEstimateService = abstractEstimateService;
}
public void setWorksService(final WorksService worksService) {
this.worksService = worksService;
}
public void setEgovCommon(final EgovCommon egovCommon) {
this.egovCommon = egovCommon;
}
public void setDepositWorksUsageService(final DepositWorksUsageService depositWorksUsageService) {
this.depositWorksUsageService = depositWorksUsageService;
}
public void setEstimateAppropriationService(
final PersistenceService<AbstractEstimateAppropriation, Long> estimateAppropriationService) {
this.estimateAppropriationService = estimateAppropriationService;
}
public void setBudgetDetailsDAO(final BudgetDetailsDAO budgetDetailsDAO) {
this.budgetDetailsDAO = budgetDetailsDAO;
}
}