/*
* 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.calculator;
import org.apache.log4j.Logger;
import org.egov.commons.Installment;
import org.egov.commons.dao.InstallmentHibDao;
import org.egov.demand.model.EgDemandReasonDetails;
import org.egov.infra.admin.master.entity.Boundary;
import org.egov.infra.admin.master.service.ModuleService;
import org.egov.infstr.services.PersistenceService;
import org.egov.ptis.client.handler.TaxCalculationInfoXmlHandler;
import org.egov.ptis.client.model.calculator.APMiscellaneousTax;
import org.egov.ptis.client.model.calculator.APTaxCalculationInfo;
import org.egov.ptis.client.model.calculator.APUnitTaxCalculationInfo;
import org.egov.ptis.client.util.PropertyTaxUtil;
import org.egov.ptis.constants.PropertyTaxConstants;
import org.egov.ptis.domain.entity.property.BoundaryCategory;
import org.egov.ptis.domain.entity.property.Floor;
import org.egov.ptis.domain.entity.property.Property;
import org.egov.ptis.domain.entity.property.PropertyID;
import org.egov.ptis.domain.model.calculator.MiscellaneousTax;
import org.egov.ptis.domain.model.calculator.TaxCalculationInfo;
import org.egov.ptis.domain.model.calculator.UnitTaxCalculationInfo;
import org.egov.ptis.domain.service.calculator.PropertyTaxCalculator;
import org.egov.ptis.exceptions.TaxCalculatorExeption;
import org.egov.ptis.service.utils.PropertyTaxCommonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import static org.egov.ptis.constants.PropertyTaxConstants.*;
//TODO name class as client specific
public class APTaxCalculator implements PropertyTaxCalculator {
private static final Logger LOGGER = Logger.getLogger(APTaxCalculator.class);
private static BigDecimal RESD_OWNER_DEPRECIATION = new BigDecimal(40);
private static BigDecimal SEASHORE_RESD_OWNER_DEPRECIATION = new BigDecimal(45);
private BigDecimal BUIULDING_VALUE = new BigDecimal(2).divide(new BigDecimal(3), 5, BigDecimal.ROUND_HALF_UP);
private BigDecimal SITE_VALUE = new BigDecimal(1).divide(new BigDecimal(3), 5, BigDecimal.ROUND_HALF_UP);
private BigDecimal totalTaxPayable = BigDecimal.ZERO;
private Boolean isCorporation = Boolean.FALSE;
private Boolean isSeaShoreULB = Boolean.FALSE;
private Boolean isPrimaryServiceChrApplicable = Boolean.FALSE;
private String unAuthDeviationPerc = "";
private HashMap<Installment, TaxCalculationInfo> taxCalculationMap = new HashMap<Installment, TaxCalculationInfo>();
private Properties taxRateProps = null;
private Installment currInstallment = null;
@Autowired
@Qualifier("persistenceService")
private PersistenceService persistenceService;
@Autowired
private PropertyTaxUtil propertyTaxUtil;
@Autowired
private InstallmentHibDao installmentDAO;
@Autowired
private ModuleService moduleService;
@Autowired
private PropertyTaxCommonUtils propertyTaxCommonUtils;
/**
* @param property
* Property Object
* @param applicableTaxes
* List of Applicable Taxes
* @param occupationDate
* Minimum Occupancy Date among all the units
* @return
* @throws TaxCalculatorExeption
*/
@Override
public HashMap<Installment, TaxCalculationInfo> calculatePropertyTax(final Property property,
final Date occupationDate) throws TaxCalculatorExeption {
Boundary propertyZone = null;
BigDecimal totalNetArv = BigDecimal.ZERO;
BoundaryCategory boundaryCategory = null;
taxRateProps = propertyTaxUtil.loadTaxRates();
isCorporation = propertyTaxUtil.isCorporation();
isSeaShoreULB = propertyTaxUtil.isSeaShoreULB();
currInstallment = propertyTaxCommonUtils.getCurrentInstallment();
if (isCorporation)
isPrimaryServiceChrApplicable = propertyTaxUtil.isPrimaryServiceApplicable();
final List<String> applicableTaxes = prepareApplicableTaxes(property);
List<Installment> taxInstallments = propertyTaxUtil.getInstallmentsListByEffectiveDate(occupationDate);
propertyZone = property.getBasicProperty().getPropertyID().getZone();
for (final Installment installment : taxInstallments) {
totalTaxPayable = BigDecimal.ZERO;
totalNetArv = BigDecimal.ZERO;
final APTaxCalculationInfo taxCalculationInfo = addPropertyInfo(property);
if (betweenOrBefore(occupationDate, installment.getFromDate(), installment.getToDate())) {
if (property.getPropertyDetail().getPropertyTypeMaster().getCode().equals(OWNERSHIP_TYPE_VAC_LAND)
|| (property.getPropertyDetail().isAppurtenantLandChecked() != null && property
.getPropertyDetail().isAppurtenantLandChecked())) {
final APUnitTaxCalculationInfo unitTaxCalculationInfo = calculateVacantLandTax(property,
occupationDate, applicableTaxes, installment);
totalNetArv = totalNetArv.add(unitTaxCalculationInfo.getNetARV());
taxCalculationInfo.addUnitTaxCalculationInfo(unitTaxCalculationInfo);
totalTaxPayable = totalTaxPayable.add(unitTaxCalculationInfo.getTotalTaxPayable());
}
for (final Floor floorIF : property.getPropertyDetail().getFloorDetails()) {
// TODO think about, these beans to be client specific
if (betweenOrBefore(floorIF.getOccupancyDate(), installment.getFromDate(), installment.getToDate())) {
boundaryCategory = getBoundaryCategory(propertyZone, installment, floorIF.getPropertyUsage()
.getId(), occupationDate, floorIF.getStructureClassification().getId());
final APUnitTaxCalculationInfo unitTaxCalculationInfo = calculateNonVacantTax(property,
floorIF, boundaryCategory, applicableTaxes, installment);
totalNetArv = totalNetArv.add(unitTaxCalculationInfo.getNetARV());
totalTaxPayable = totalTaxPayable.add(unitTaxCalculationInfo.getTotalTaxPayable());
taxCalculationInfo.addUnitTaxCalculationInfo(unitTaxCalculationInfo);
}
}
taxCalculationInfo.setTotalNetARV(totalNetArv);
taxCalculationInfo.setTotalTaxPayable(totalTaxPayable);
taxCalculationInfo.setTaxCalculationInfoXML(generateTaxCalculationXML(taxCalculationInfo));
taxCalculationMap.put(installment, taxCalculationInfo);
}
}
return taxCalculationMap;
}
private APUnitTaxCalculationInfo calculateNonVacantTax(final Property property, final Floor floor,
final BoundaryCategory boundaryCategory, final List<String> applicableTaxes, final Installment installment) {
final APUnitTaxCalculationInfo unitTaxCalculationInfo = new APUnitTaxCalculationInfo();
BigDecimal builtUpArea = BigDecimal.ZERO;
BigDecimal floorMrv = BigDecimal.ZERO;
BigDecimal floorBuildingValue = BigDecimal.ZERO;
BigDecimal floorSiteValue = BigDecimal.ZERO;
BigDecimal floorGrossArv = BigDecimal.ZERO;
BigDecimal floorDepreciation = BigDecimal.ZERO;
BigDecimal floorNetArv = BigDecimal.ZERO;
builtUpArea = BigDecimal.valueOf(floor.getBuiltUpArea().getArea());
floorMrv = calculateFloorMrv(builtUpArea, boundaryCategory);
floorBuildingValue = calculateFloorBuildingValue(floorMrv);
floorSiteValue = calculateFloorSiteValue(floorMrv);
floorGrossArv = floorBuildingValue.multiply(new BigDecimal(12));
floorDepreciation = calculateFloorDepreciation(floorGrossArv, floor);
/*if (property.getPropertyDetail().isStructure())
floorNetArv = floorGrossArv.subtract(floorDepreciation);
else
floorNetArv = floorSiteValue.multiply(new BigDecimal(12)).add(floorGrossArv.subtract(floorDepreciation));*/
floorNetArv = floorSiteValue.multiply(new BigDecimal(12)).add(floorGrossArv.subtract(floorDepreciation));
unitTaxCalculationInfo.setFloorNumber(FLOOR_MAP.get(floor.getFloorNo()));
unitTaxCalculationInfo.setFloorArea(builtUpArea);
unitTaxCalculationInfo.setBaseRateEffectiveDate(boundaryCategory.getFromDate());
unitTaxCalculationInfo.setBaseRate(BigDecimal.valueOf(boundaryCategory.getCategory().getCategoryAmount()));
unitTaxCalculationInfo.setMrv(floorMrv);
unitTaxCalculationInfo.setBuildingValue(floorBuildingValue);
unitTaxCalculationInfo.setSiteValue(floorSiteValue);
unitTaxCalculationInfo.setGrossARV(floorGrossArv);
unitTaxCalculationInfo.setDepreciation(floorDepreciation);
unitTaxCalculationInfo.setUnitUsage(floor.getPropertyUsage().getUsageCode());
unitTaxCalculationInfo.setUnitOccupation(floor.getPropertyOccupation().getOccupancyCode());
unitTaxCalculationInfo.setUnitStructure(floor.getStructureClassification().getConstrTypeCode());
unitTaxCalculationInfo.setNetARV(floorNetArv.setScale(0, BigDecimal.ROUND_HALF_UP));
BigDecimal unAuthDeviationPerc = getUnAuthDeviationPerc(floor);
calculateApplicableTaxes(applicableTaxes, unitTaxCalculationInfo, installment, property.getPropertyDetail()
.getPropertyTypeMaster().getCode(), floor, unAuthDeviationPerc);
return unitTaxCalculationInfo;
}
private APTaxCalculationInfo addPropertyInfo(final Property property) {
final APTaxCalculationInfo taxCalculationInfo = new APTaxCalculationInfo();
// Add Property Info
PropertyID propertyId = property.getBasicProperty().getPropertyID();
taxCalculationInfo.setPropertyOwnerName(property.getBasicProperty().getFullOwnerName());
taxCalculationInfo.setPropertyAddress(property.getBasicProperty().getAddress().toString());
taxCalculationInfo.setHouseNumber(property.getBasicProperty().getAddress().getHouseNoBldgApt());
taxCalculationInfo.setZone(propertyId.getZone().getName());
taxCalculationInfo.setWard(propertyId.getWard().getName());
taxCalculationInfo.setBlock(propertyId.getArea() != null ? propertyId.getArea().getName() : "");
taxCalculationInfo.setLocality(property.getBasicProperty().getPropertyID().getLocality().getName());
if (property.getPropertyDetail().getSitalArea().getArea() != null)
taxCalculationInfo.setPropertyArea(new BigDecimal(property.getPropertyDetail().getSitalArea().getArea()
.toString()));
taxCalculationInfo.setPropertyType(property.getPropertyDetail().getPropertyTypeMaster().getType());
taxCalculationInfo.setPropertyId(property.getBasicProperty().getUpicNo());
return taxCalculationInfo;
}
public APUnitTaxCalculationInfo calculateApplicableTaxes(final List<String> applicableTaxes,
final APUnitTaxCalculationInfo unitTaxCalculationInfo, final Installment installment,
final String propTypeCode, final Floor floor, final BigDecimal unAuthDeviationPerc) {
BigDecimal totalHalfTaxPayable = BigDecimal.ZERO;
final BigDecimal alv = unitTaxCalculationInfo.getNetARV();
BigDecimal generalTax = BigDecimal.ZERO;
BigDecimal educationTax = BigDecimal.ZERO;
BigDecimal halfYearHeadTax = BigDecimal.ZERO;
BigDecimal taxRatePerc = BigDecimal.ZERO;
LOGGER.debug("calculateApplicableTaxes - ALV: " + alv);
LOGGER.debug("calculateApplicableTaxes - applicableTaxes: " + applicableTaxes);
for (final String applicableTax : applicableTaxes) {
halfYearHeadTax = BigDecimal.ZERO;
if (applicableTax.equals(DEMANDRSN_CODE_GENERAL_TAX) || applicableTax.equals(DEMANDRSN_CODE_VACANT_TAX)) {
if (applicableTax.equals(DEMANDRSN_CODE_VACANT_TAX)) {
taxRatePerc = getTaxRate(DEMANDRSN_CODE_VACANT_TAX);
halfYearHeadTax = getHalfYearTax(alv.multiply(taxRatePerc.divide(new BigDecimal("100"))).setScale(
2, BigDecimal.ROUND_HALF_UP));
} else {
if (floor != null && floor.getPropertyUsage().getIsResidential()) {
taxRatePerc = getTaxRate(DEMANDRSN_CODE_GENERAL_TAX + "_RESD");
} else {
taxRatePerc = getTaxRate(DEMANDRSN_CODE_GENERAL_TAX + "_NR");
}
halfYearHeadTax = alv.multiply(taxRatePerc.divide(new BigDecimal("100"))).setScale(2,
BigDecimal.ROUND_HALF_UP);
}
halfYearHeadTax = taxIfGovtProperty(propTypeCode, halfYearHeadTax);
generalTax = halfYearHeadTax;
}
if (applicableTax.equals(DEMANDRSN_CODE_EDUCATIONAL_CESS)) {
educationTax = alv.multiply(getTaxRate(DEMANDRSN_CODE_EDUCATIONAL_CESS).divide(new BigDecimal("100")))
.setScale(2, BigDecimal.ROUND_HALF_UP);
halfYearHeadTax = educationTax;
}
if (applicableTax.equals(DEMANDRSN_CODE_LIBRARY_CESS)) {
halfYearHeadTax = generalTax.add(educationTax)
.multiply(getTaxRate(DEMANDRSN_CODE_LIBRARY_CESS).divide(new BigDecimal("100")))
.setScale(2, BigDecimal.ROUND_HALF_UP);
}
if (halfYearHeadTax.compareTo(BigDecimal.ZERO) > 0) {
//halfYearHeadTax = roundOffToNearestEven(halfYearHeadTax);
totalHalfTaxPayable = totalHalfTaxPayable.add(halfYearHeadTax);
createMiscTax(applicableTax, halfYearHeadTax, unitTaxCalculationInfo);
}
}
// calculating Un Authorized Penalty
if (!propTypeCode.equalsIgnoreCase(OWNERSHIP_TYPE_VAC_LAND)) {
if (!(unAuthDeviationPerc == null || "0".equals(unAuthDeviationPerc) || "-1".equals(unAuthDeviationPerc) || (unAuthDeviationPerc != null && unAuthDeviationPerc.intValue() == 0))) {
halfYearHeadTax = BigDecimal.ZERO;
halfYearHeadTax = calculateUnAuthPenalty(unAuthDeviationPerc, totalHalfTaxPayable);
totalHalfTaxPayable = totalHalfTaxPayable.add(halfYearHeadTax);
createMiscTax(DEMANDRSN_CODE_UNAUTHORIZED_PENALTY, halfYearHeadTax, unitTaxCalculationInfo);
}
}
// calculating Public Service Charges
if (isPrimaryServiceChrApplicable) {
halfYearHeadTax = BigDecimal.ZERO;
halfYearHeadTax = roundOffToNearestEven(calcPublicServiceCharges(totalHalfTaxPayable));
totalHalfTaxPayable = totalHalfTaxPayable.add(halfYearHeadTax);
createMiscTax(DEMANDRSN_CODE_PRIMARY_SERVICE_CHARGES, halfYearHeadTax, unitTaxCalculationInfo);
}
unitTaxCalculationInfo.setTotalTaxPayable(totalHalfTaxPayable);
return unitTaxCalculationInfo;
}
/**
* Returns the applicable taxes for the given property
*
* @param property
* @return List of taxes
*/
private List<String> prepareApplicableTaxes(final Property property) {
LOGGER.debug("Entered into prepareApplTaxes");
LOGGER.debug("prepareApplTaxes: property: " + property);
final List<String> applicableTaxes = new ArrayList<String>();
if (!property.getPropertyDetail().getPropertyTypeMaster().getCode().equals(OWNERSHIP_TYPE_VAC_LAND)) {
applicableTaxes.add(DEMANDRSN_CODE_GENERAL_TAX);
applicableTaxes.add(DEMANDRSN_CODE_UNAUTHORIZED_PENALTY);
applicableTaxes.add(DEMANDRSN_CODE_EDUCATIONAL_CESS);
} else {
applicableTaxes.add(DEMANDRSN_CODE_VACANT_TAX);
}
applicableTaxes.add(DEMANDRSN_CODE_LIBRARY_CESS);
if (isCorporation)
applicableTaxes.add(DEMANDRSN_CODE_SEWERAGE_TAX);
if (isPrimaryServiceChrApplicable)
applicableTaxes.add(DEMANDRSN_CODE_PRIMARY_SERVICE_CHARGES);
LOGGER.debug("prepareApplTaxes: applicableTaxes: " + applicableTaxes);
LOGGER.debug("Exiting from prepareApplTaxes");
return applicableTaxes;
}
private BoundaryCategory getBoundaryCategory(final Boundary zone, final Installment installment,
final Long usageId, final Date occupancyDate, final Long classification) throws TaxCalculatorExeption {
List<BoundaryCategory> categories = new ArrayList<BoundaryCategory>();
categories = persistenceService.findAllByNamedQuery(QUERY_BASERATE_BY_OCCUPANCY_ZONE, zone.getId(), usageId,
classification, occupancyDate, installment.getToDate());
LOGGER.debug("baseRentOfUnit - Installment : " + installment);
if (categories.isEmpty()) {
throw new TaxCalculatorExeption("There are no Unit rates defined for chosen combinations, zone : "
+ zone.getName() + " usageId : " + usageId + " classification : " + classification
+ " occupancyDate : " + occupancyDate);
} else {
return categories.get(0);
}
}
private List<EgDemandReasonDetails> getDemandReasonDetails(final String demandReasonCode,
final BigDecimal grossAnnualRentAfterDeduction, final Installment installment) {
return persistenceService.findAllByNamedQuery(QUERY_DEMANDREASONDETAILS_BY_DEMANDREASON_AND_INSTALLMENT,
demandReasonCode, grossAnnualRentAfterDeduction, installment.getFromDate(), installment.getToDate());
}
public Map<String, BigDecimal> getMiscTaxesForProp(final List<UnitTaxCalculationInfo> unitTaxCalcInfos) {
final Map<String, BigDecimal> taxMap = new HashMap<String, BigDecimal>();
for (final UnitTaxCalculationInfo unitTaxCalcInfo : unitTaxCalcInfos)
for (final MiscellaneousTax miscTax : unitTaxCalcInfo.getMiscellaneousTaxes())
if (taxMap.get(miscTax.getTaxName()) == null)
taxMap.put(miscTax.getTaxName(), miscTax.getTotalCalculatedTax());
else
taxMap.put(miscTax.getTaxName(),
taxMap.get(miscTax.getTaxName()).add(miscTax.getTotalCalculatedTax()));
for (Map.Entry<String, BigDecimal> entry : taxMap.entrySet()) {
entry.setValue(entry.getValue().setScale(0, BigDecimal.ROUND_HALF_UP));
}
return taxMap;
}
private APUnitTaxCalculationInfo calculateVacantLandTax(final Property property, final Date occupancyDate,
final List<String> applicableTaxes, final Installment installment) {
final APUnitTaxCalculationInfo unitTaxCalculationInfo = new APUnitTaxCalculationInfo();
unitTaxCalculationInfo.setFloorNumber("VACANT");
unitTaxCalculationInfo.setBaseRateEffectiveDate(occupancyDate);
unitTaxCalculationInfo.setCapitalValue(new BigDecimal(property.getPropertyDetail().getCurrentCapitalValue()));
unitTaxCalculationInfo.setNetARV(unitTaxCalculationInfo.getCapitalValue());
calculateApplicableTaxes(applicableTaxes, unitTaxCalculationInfo, installment, property.getPropertyDetail()
.getPropertyTypeMaster().getCode(), null, null);
return unitTaxCalculationInfo;
}
public String generateTaxCalculationXML(final TaxCalculationInfo taxCalculationInfo) {
final TaxCalculationInfoXmlHandler handler = new TaxCalculationInfoXmlHandler();
String taxCalculationInfoXML = "";
if (taxCalculationInfo != null)
taxCalculationInfoXML = handler.toXML(taxCalculationInfo);
return taxCalculationInfoXML;
}
private Boolean between(final Date date, final Date fromDate, final Date toDate) {
return (date.after(fromDate) || date.equals(fromDate)) && date.before(toDate) || date.equals(toDate);
}
private Boolean betweenOrBefore(final Date date, final Date fromDate, final Date toDate) {
final Boolean result = between(date, fromDate, toDate) || date.before(fromDate);
return result;
}
private BigDecimal calculateFloorMrv(final BigDecimal builtUpArea, final BoundaryCategory boundaryCategory) {
return builtUpArea.multiply(BigDecimal.valueOf(boundaryCategory.getCategory().getCategoryAmount()));
}
private BigDecimal calculateFloorBuildingValue(final BigDecimal floorMrv) {
return floorMrv.multiply(BUIULDING_VALUE).setScale(2, BigDecimal.ROUND_HALF_UP);
}
private BigDecimal calculateFloorSiteValue(final BigDecimal floorMrv) {
return floorMrv.multiply(SITE_VALUE).setScale(2, BigDecimal.ROUND_HALF_UP);
}
private BigDecimal calculateFloorDepreciation(final BigDecimal grossArv, final Floor floor) {
BigDecimal depreciationPct = BigDecimal.ZERO;
if (isSeaShoreULB) {
if (floor.getPropertyOccupation().getOccupancyCode().equals(PropertyTaxConstants.OCC_OWNER)) {
depreciationPct = SEASHORE_RESD_OWNER_DEPRECIATION;
} else {
depreciationPct = BigDecimal.valueOf(floor.getDepreciationMaster().getDepreciationPct());
}
} else {
if (floor.getPropertyOccupation().getOccupancyCode().equals(PropertyTaxConstants.OCC_OWNER) && floor.getPropertyUsage().getUsageCode().equals(USAGE_RESIDENTIAL)) {
depreciationPct = RESD_OWNER_DEPRECIATION;
} else {
depreciationPct = BigDecimal.valueOf(floor.getDepreciationMaster().getDepreciationPct());
}
}
return grossArv.multiply(depreciationPct).divide(BigDecimal.valueOf(100));
}
public BigDecimal roundOffToNearestEven(final BigDecimal amount) {
BigDecimal roundedAmt;
final BigDecimal remainder = amount.remainder(new BigDecimal(2));
/*
* if reminder is less than 1, subtract reminder amount from passed
* amount else reminder is greater than 1, subtract reminder amount from
* passed amount and add 5 to result amount
*/
if (remainder.compareTo(new BigDecimal("1")) == 1)
roundedAmt = amount.subtract(remainder).add(new BigDecimal(2));
else
roundedAmt = amount.subtract(remainder);
return roundedAmt;
}
public BigDecimal convertYardToSquareMeters(final Float vacantLandArea) {
Float areaInSqMts = null;
areaInSqMts = new Float(vacantLandArea) * new Float(SQUARE_YARD_TO_SQUARE_METER_VALUE);
return new BigDecimal(areaInSqMts).setScale(2, BigDecimal.ROUND_HALF_UP);
}
private BigDecimal taxIfGovtProperty(String propTypeCode, BigDecimal tax) {
if (propTypeCode.equals(PropertyTaxConstants.OWNERSHIP_TYPE_CENTRAL_GOVT_335))
tax = tax.multiply(new BigDecimal(0.335));
if (propTypeCode.equals(PropertyTaxConstants.OWNERSHIP_TYPE_CENTRAL_GOVT_50))
tax = tax.multiply(new BigDecimal(0.5));
if (propTypeCode.equals(PropertyTaxConstants.OWNERSHIP_TYPE_CENTRAL_GOVT_75))
tax = tax.multiply(new BigDecimal(0.75));
return tax;
}
private BigDecimal getUnAuthDeviationPerc(Floor floor) {
BigDecimal deviationPerc = null;
BigDecimal diffArea = null;
BigDecimal plinthArea = new BigDecimal(floor.getBuiltUpArea().getArea()).setScale(2, BigDecimal.ROUND_HALF_UP);
BigDecimal buildingPlanPlinthArea = (floor.getBuildingPlanPlinthArea() != null && floor
.getBuildingPlanPlinthArea().getArea() != null) ? new BigDecimal(floor.getBuildingPlanPlinthArea()
.getArea()).setScale(2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO;
if (buildingPlanPlinthArea.compareTo(BigDecimal.ZERO) == 0) {
deviationPerc = new BigDecimal(100);
} else if (plinthArea.compareTo(buildingPlanPlinthArea) == 1) {
diffArea = plinthArea.subtract(buildingPlanPlinthArea);
deviationPerc = diffArea.divide(buildingPlanPlinthArea, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
}
return deviationPerc;
}
private BigDecimal calculateUnAuthPenalty(BigDecimal deviationPerc, BigDecimal totalPropertyTax) {
BigDecimal unAuthPenalty = BigDecimal.ZERO;
/*
* deviationPerc between 1-10, Penalty perc = 25%,
* deviationPerc > 10, Penalty perc = 50%,
* no Building plan details, Penalty perc = 100%
*/
if (deviationPerc != null && !deviationPerc.equals("0")) {
if (deviationPerc.compareTo(BigDecimal.ZERO) == 1 && deviationPerc.compareTo(BigDecimal.TEN) <=0) {
unAuthPenalty = totalPropertyTax.multiply(BPA_DEVIATION_TAXPERC_1_10);
} else if (deviationPerc.compareTo(BigDecimal.TEN) == 1
&& deviationPerc.compareTo(BIGDECIMAL_100) != 0) {
unAuthPenalty = totalPropertyTax.multiply(BPA_DEVIATION_TAXPERC_ABOVE_11);
} else {
unAuthPenalty = totalPropertyTax.multiply(BPA_DEVIATION_TAXPERC_NOT_DEFINED);
}
}
return unAuthPenalty;
}
private BigDecimal calcPublicServiceCharges(BigDecimal totalPropertyTax) {
BigDecimal publicServiceCharge = BigDecimal.ZERO;
return publicServiceCharge;
}
private void createMiscTax(String taxHead, BigDecimal tax, APUnitTaxCalculationInfo unitTaxCalculationInfo) {
APMiscellaneousTax miscellaneousTax = new APMiscellaneousTax();
miscellaneousTax.setTaxName(taxHead);
miscellaneousTax.setTotalCalculatedTax(tax);
unitTaxCalculationInfo.addMiscellaneousTaxes(miscellaneousTax);
}
private BigDecimal getTaxRate(String taxHead) {
BigDecimal taxRate = BigDecimal.ZERO;
if (taxRateProps != null) {
taxRate = new BigDecimal(taxRateProps.getProperty(taxHead));
}
return taxRate;
}
private BigDecimal getHalfYearTax(BigDecimal annualTax) {
return annualTax.divide(new BigDecimal(2)).setScale(2, BigDecimal.ROUND_HALF_UP);
}
}