/**
  * @param pmv
  * @return
  */
 private List<Map<String, String>> getResultsFromMv(final PropertyMaterlizeView pmv) {
   if (LOGGER.isDebugEnabled()) {
     LOGGER.debug("Entered into getSearchResults method");
     LOGGER.debug("Assessment Number : " + pmv.getPropertyId());
   }
   BasicProperty basicProperty =
       basicPropertyDAO.getBasicPropertyByPropertyID(pmv.getPropertyId());
   Property property = basicProperty.getProperty();
   if (basicProperty != null) {
     checkIsDemandActive(basicProperty.getProperty());
   }
   if (pmv.getPropertyId() != null
       || org.apache.commons.lang.StringUtils.isNotEmpty(pmv.getPropertyId()))
     if (pmv != null) {
       final Map<String, String> searchResultMap = new HashMap<String, String>();
       searchResultMap.put("assessmentNum", pmv.getPropertyId());
       searchResultMap.put("ownerName", pmv.getOwnerName());
       searchResultMap.put("parcelId", pmv.getGisRefNo());
       searchResultMap.put("address", pmv.getPropertyAddress());
       searchResultMap.put("source", pmv.getSource().toString());
       searchResultMap.put("isDemandActive", String.valueOf(isDemandActive));
       searchResultMap.put(
           "propType", property.getPropertyDetail().getPropertyTypeMaster().getCode());
       searchResultMap.put("isTaxExempted", String.valueOf(property.getIsExemptedFromTax()));
       searchResultMap.put("isUnderWorkflow", String.valueOf(basicProperty.isUnderWorkflow()));
       searchResultMap.put(
           "enableVacancyRemission",
           String.valueOf(propertyTaxUtil.enableVacancyRemission(basicProperty.getUpicNo())));
       searchResultMap.put(
           "enableMonthlyUpdate",
           String.valueOf(propertyTaxUtil.enableMonthlyUpdate(basicProperty.getUpicNo())));
       searchResultMap.put(
           "enableVRApproval",
           String.valueOf(propertyTaxUtil.enableVRApproval(basicProperty.getUpicNo())));
       if (pmv.getIsExempted()) {
         searchResultMap.put("currDemand", "0");
         searchResultMap.put("arrDemandDue", "0");
         searchResultMap.put("currDemandDue", "0");
       } else {
         searchResultMap.put("currDemand", pmv.getAggrCurrDmd().toString());
         searchResultMap.put(
             "currDemandDue", pmv.getAggrCurrDmd().subtract(pmv.getAggrCurrColl()).toString());
         searchResultMap.put(
             "arrDemandDue", pmv.getAggrArrDmd().subtract(pmv.getAggrArrColl()).toString());
       }
       searchList.add(searchResultMap);
     }
   if (LOGGER.isDebugEnabled()) {
     LOGGER.debug("Search list : " + (searchList != null ? searchList : ZERO));
     LOGGER.debug("Exit from getSearchResults method");
   }
   return searchList;
 }
  /**
   * 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);
    else applicableTaxes.add(DEMANDRSN_CODE_VACANT_TAX);
    applicableTaxes.add(DEMANDRSN_CODE_EDUCATIONAL_CESS);
    applicableTaxes.add(DEMANDRSN_CODE_LIBRARY_CESS);
    if (property.getPropertyDetail().isToilets()) applicableTaxes.add(DEMANDRSN_CODE_SEWERAGE_TAX);

    LOGGER.debug("prepareApplTaxes: applicableTaxes: " + applicableTaxes);
    LOGGER.debug("Exiting from prepareApplTaxes");
    return applicableTaxes;
  }
 /** @param property */
 private void checkIsDemandActive(final Property property) {
   if (LOGGER.isDebugEnabled()) LOGGER.debug("Entered into checkIsDemandActive");
   if (property.getStatus().equals(PropertyTaxConstants.STATUS_DEMAND_INACTIVE))
     isDemandActive = false;
   else isDemandActive = true;
   if (LOGGER.isDebugEnabled()) {
     LOGGER.debug("checkIsDemandActive - Is demand active? : " + isDemandActive);
     LOGGER.debug("Exiting from checkIsDemandActive");
   }
 }
  private APUnitTaxCalculationInfo calculateVacantLandTax(
      final Property property, final Date occupancyDate) {
    final APUnitTaxCalculationInfo unitTaxCalculationInfo = new APUnitTaxCalculationInfo();

    unitTaxCalculationInfo.setFloorNumber("0");
    unitTaxCalculationInfo.setBaseRateEffectiveDate(occupancyDate);
    unitTaxCalculationInfo.setCapitalValue(
        new BigDecimal(property.getPropertyDetail().getCurrentCapitalValue()));
    unitTaxCalculationInfo.setNetARV(unitTaxCalculationInfo.getCapitalValue());
    return unitTaxCalculationInfo;
  }
  private APUnitTaxCalculationInfo prepareUnitCalcInfo(
      final Property property, final Floor floor, final BoundaryCategory boundaryCategory) {
    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));
    unitTaxCalculationInfo.setFloorNumber(FLOOR_MAP.get(floor.getFloorNo()));
    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.setNetARV(floorNetArv.setScale(0, BigDecimal.ROUND_HALF_UP));
    return unitTaxCalculationInfo;
  }
  /**
   * @param property Property Object
   * @param applicableTaxes List of Applicable Taxes
   * @param occupationDate Minimum Occupancy Date among all the units
   * @return
   */
  @Override
  public HashMap<Installment, TaxCalculationInfo> calculatePropertyTax(
      final Property property, final Date occupationDate) {

    Boundary propertyZone = null;
    BigDecimal totalNetArv = BigDecimal.ZERO;
    BoundaryCategory boundaryCategory = null;
    // TODO move method prepareApplicableTaxes to tax calculator
    final List<String> applicableTaxes = prepareApplicableTaxes(property);
    final List<Installment> taxInstallments = getInstallmentListByStartDate(occupationDate);
    propertyZone = property.getBasicProperty().getPropertyID().getZone();

    for (final Installment installment : taxInstallments) {
      totalTaxPayable = BigDecimal.ZERO;
      final APTaxCalculationInfo taxCalculationInfo = addPropertyInfo(property);

      if (betweenOrBefore(occupationDate, installment.getFromDate(), installment.getToDate())) {
        if (property
            .getPropertyDetail()
            .getPropertyTypeMaster()
            .getCode()
            .equals(OWNERSHIP_TYPE_VAC_LAND)) {
          final APUnitTaxCalculationInfo unitTaxCalculationInfo =
              calculateVacantLandTax(property, occupationDate);
          totalNetArv = totalNetArv.add(unitTaxCalculationInfo.getNetARV());
          taxCalculationInfo.addUnitTaxCalculationInfo(unitTaxCalculationInfo);
          calculateApplicableTaxes(
              applicableTaxes,
              unitTaxCalculationInfo,
              installment,
              property.getPropertyDetail().getPropertyTypeMaster().getCode());
          totalTaxPayable = totalTaxPayable.add(unitTaxCalculationInfo.getTotalTaxPayable());
        } else
          for (final Floor floorIF : property.getPropertyDetail().getFloorDetails())
            if (floorIF != null) {
              // TODO think about, these beans to be client
              // specific
              boundaryCategory =
                  getBoundaryCategory(
                      propertyZone,
                      installment,
                      floorIF.getPropertyUsage().getId(),
                      occupationDate);
              final APUnitTaxCalculationInfo unitTaxCalculationInfo =
                  prepareUnitCalcInfo(property, floorIF, boundaryCategory);
              totalNetArv = totalNetArv.add(unitTaxCalculationInfo.getNetARV());

              calculateApplicableTaxes(
                  applicableTaxes,
                  unitTaxCalculationInfo,
                  installment,
                  property.getPropertyDetail().getPropertyTypeMaster().getCode());

              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 APTaxCalculationInfo addPropertyInfo(final Property property) {
   final APTaxCalculationInfo taxCalculationInfo = new APTaxCalculationInfo();
   // Add Property Info
   taxCalculationInfo.setPropertyOwnerName(property.getBasicProperty().getFullOwnerName());
   taxCalculationInfo.setPropertyAddress(property.getBasicProperty().getAddress().toString());
   taxCalculationInfo.setHouseNumber(property.getBasicProperty().getAddress().getHouseNoBldgApt());
   taxCalculationInfo.setZone(property.getBasicProperty().getPropertyID().getZone().getName());
   taxCalculationInfo.setWard(property.getBasicProperty().getPropertyID().getWard().getName());
   taxCalculationInfo.setBlock(property.getBasicProperty().getPropertyID().getArea().getName());
   taxCalculationInfo.setLocality(
       property.getBasicProperty().getPropertyID().getLocality().getName());
   if (property.getPropertyDetail().getSitalArea().getArea() != null)
     if (property
         .getPropertyDetail()
         .getPropertyTypeMaster()
         .getCode()
         .equals(OWNERSHIP_TYPE_VAC_LAND))
       taxCalculationInfo.setPropertyArea(
           convertYardToSquareMeters(property.getPropertyDetail().getSitalArea().getArea()));
     else
       taxCalculationInfo.setPropertyArea(
           new BigDecimal(property.getPropertyDetail().getSitalArea().getArea().toString()));
   taxCalculationInfo.setPropertyType(
       property.getPropertyDetail().getPropertyTypeMaster().getType());
   taxCalculationInfo.setPropertyId(property.getBasicProperty().getUpicNo());
   return taxCalculationInfo;
 }
  /**
   * @param assessmentNumber
   * @return
   */
  private List<Map<String, String>> getSearchResults(final String assessmentNumber) {
    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("Entered into getSearchResults method");
      LOGGER.debug("Assessment Number : " + assessmentNumber);
    }
    if (assessmentNumber != null
        || org.apache.commons.lang.StringUtils.isNotEmpty(assessmentNumber)) {

      final BasicProperty basicProperty =
          basicPropertyDAO.getBasicPropertyByPropertyID(assessmentNumber);
      if (LOGGER.isDebugEnabled()) LOGGER.debug("BasicProperty : " + basicProperty);
      if (basicProperty != null) {
        final Property property = basicProperty.getProperty();
        if (LOGGER.isDebugEnabled()) LOGGER.debug("Property : " + property);

        checkIsDemandActive(property);

        final Map<String, BigDecimal> demandCollMap = ptDemandDAO.getDemandCollMap(property);

        final Map<String, String> searchResultMap = new HashMap<String, String>();
        searchResultMap.put("assessmentNum", assessmentNumber);
        searchResultMap.put("ownerName", basicProperty.getFullOwnerName());
        searchResultMap.put("address", basicProperty.getAddress().toString());
        searchResultMap.put("source", basicProperty.getSource().toString());
        searchResultMap.put("isDemandActive", String.valueOf(isDemandActive));
        searchResultMap.put(
            "propType", property.getPropertyDetail().getPropertyTypeMaster().getCode());
        searchResultMap.put("isTaxExempted", String.valueOf(property.getIsExemptedFromTax()));
        searchResultMap.put("isUnderWorkflow", String.valueOf(basicProperty.isUnderWorkflow()));
        searchResultMap.put(
            "enableVacancyRemission",
            String.valueOf(propertyTaxUtil.enableVacancyRemission(basicProperty.getUpicNo())));
        searchResultMap.put(
            "enableMonthlyUpdate",
            String.valueOf(propertyTaxUtil.enableMonthlyUpdate(basicProperty.getUpicNo())));
        searchResultMap.put(
            "enableVRApproval",
            String.valueOf(propertyTaxUtil.enableVRApproval(basicProperty.getUpicNo())));
        if (!property.getIsExemptedFromTax()) {
          searchResultMap.put("currDemand", demandCollMap.get(CURR_DMD_STR).toString());
          searchResultMap.put(
              "arrDemandDue",
              demandCollMap.get(ARR_DMD_STR).subtract(demandCollMap.get(ARR_COLL_STR)).toString());
          searchResultMap.put(
              "currDemandDue",
              demandCollMap
                  .get(CURR_DMD_STR)
                  .subtract(demandCollMap.get(CURR_COLL_STR))
                  .toString());
        } else {
          searchResultMap.put("currDemand", "0");
          searchResultMap.put("arrDemandDue", "0");
          searchResultMap.put("currDemandDue", "0");
        }
        if (LOGGER.isDebugEnabled())
          LOGGER.debug(
              "Assessment Number : "
                  + searchResultMap.get("assessmentNum")
                  + ", "
                  + "Owner Name : "
                  + searchResultMap.get("ownerName")
                  + ", "
                  + "Parcel id : "
                  + searchResultMap.get("parcelId")
                  + ", "
                  + "Address : "
                  + searchResultMap.get("address")
                  + ", "
                  + "Current Demand : "
                  + searchResultMap.get("currDemand")
                  + ", "
                  + "Arrears Demand Due : "
                  + searchResultMap.get("arrDemandDue")
                  + ", "
                  + "Current Demand Due : "
                  + searchResultMap.get("currDemandDue"));
        searchList.add(searchResultMap);
      }
    }
    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("Search list : " + (searchList != null ? searchList : ZERO));
      LOGGER.debug("Exit from getSearchResults method");
    }
    return searchList;
  }