@Override
    public SavingsAccountAnnualFeeData mapRow(
        final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {

      final Long id = rs.getLong("id");
      final Long accountId = rs.getLong("accountId");
      final String accountNo = rs.getString("accountNo");
      final LocalDate annualFeeNextDueDate = JdbcSupport.getLocalDate(rs, "dueDate");

      return SavingsAccountAnnualFeeData.instance(id, accountId, accountNo, annualFeeNextDueDate);
    }
    @Override
    public SavingsAccountChargeData mapRow(
        final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {

      final Long id = rs.getLong("id");
      final Long chargeId = rs.getLong("chargeId");
      final Long accountId = rs.getLong("accountId");
      final String name = rs.getString("name");
      final BigDecimal amount = rs.getBigDecimal("amountDue");
      final BigDecimal amountPaid = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPaid");
      final BigDecimal amountWaived =
          JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountWaived");
      final BigDecimal amountWrittenOff =
          JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountWrittenOff");
      final BigDecimal amountOutstanding = rs.getBigDecimal("amountOutstanding");

      final BigDecimal percentageOf =
          JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "percentageOf");
      final BigDecimal amountPercentageAppliedTo =
          JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "amountPercentageAppliedTo");

      final String currencyCode = rs.getString("currencyCode");
      final String currencyName = rs.getString("currencyName");
      final String currencyNameCode = rs.getString("currencyNameCode");
      final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
      final Integer currencyDecimalPlaces = JdbcSupport.getInteger(rs, "currencyDecimalPlaces");
      final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");

      final CurrencyData currency =
          new CurrencyData(
              currencyCode,
              currencyName,
              currencyDecimalPlaces,
              inMultiplesOf,
              currencyDisplaySymbol,
              currencyNameCode);

      final int chargeTime = rs.getInt("chargeTime");
      final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(chargeTime);

      final LocalDate dueAsOfDate = JdbcSupport.getLocalDate(rs, "dueAsOfDate");
      final Integer feeInterval = JdbcSupport.getInteger(rs, "feeInterval");
      MonthDay feeOnMonthDay = null;
      final Integer feeOnMonth = JdbcSupport.getInteger(rs, "feeOnMonth");
      final Integer feeOnDay = JdbcSupport.getInteger(rs, "feeOnDay");
      if (feeOnDay != null) {
        feeOnMonthDay = new MonthDay(feeOnMonth, feeOnDay);
      }

      final int chargeCalculation = rs.getInt("chargeCalculation");
      final EnumOptionData chargeCalculationType =
          ChargeEnumerations.chargeCalculationType(chargeCalculation);
      final boolean penalty = rs.getBoolean("penalty");

      final Collection<ChargeData> chargeOptions = null;

      return SavingsAccountChargeData.instance(
          id,
          chargeId,
          accountId,
          name,
          currency,
          amount,
          amountPaid,
          amountWaived,
          amountWrittenOff,
          amountOutstanding,
          chargeTimeType,
          dueAsOfDate,
          chargeCalculationType,
          percentageOf,
          amountPercentageAppliedTo,
          chargeOptions,
          penalty,
          feeOnMonthDay,
          feeInterval);
    }
    @Override
    public AccountTransferData mapRow(
        final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {

      final Long id = rs.getLong("id");
      final boolean reversed = rs.getBoolean("isReversed");

      final LocalDate transferDate = JdbcSupport.getLocalDate(rs, "transferDate");
      final BigDecimal transferAmount =
          JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "transferAmount");
      final String transferDescription = rs.getString("transferDescription");

      final String currencyCode = rs.getString("currencyCode");
      final String currencyName = rs.getString("currencyName");
      final String currencyNameCode = rs.getString("currencyNameCode");
      final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
      final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
      final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
      final CurrencyData currency =
          new CurrencyData(
              currencyCode,
              currencyName,
              currencyDigits,
              inMultiplesOf,
              currencyDisplaySymbol,
              currencyNameCode);

      final Long fromOfficeId = JdbcSupport.getLong(rs, "fromOfficeId");
      final String fromOfficeName = rs.getString("fromOfficeName");
      final OfficeData fromOffice = OfficeData.dropdown(fromOfficeId, fromOfficeName, null);

      final Long toOfficeId = JdbcSupport.getLong(rs, "toOfficeId");
      final String toOfficeName = rs.getString("toOfficeName");
      final OfficeData toOffice = OfficeData.dropdown(toOfficeId, toOfficeName, null);

      final Long fromClientId = JdbcSupport.getLong(rs, "fromClientId");
      final String fromClientName = rs.getString("fromClientName");
      final ClientData fromClient =
          ClientData.lookup(fromClientId, fromClientName, fromOfficeId, fromOfficeName);

      final Long toClientId = JdbcSupport.getLong(rs, "toClientId");
      final String toClientName = rs.getString("toClientName");
      final ClientData toClient =
          ClientData.lookup(toClientId, toClientName, toOfficeId, toOfficeName);

      final Long fromSavingsAccountId = JdbcSupport.getLong(rs, "fromSavingsAccountId");
      final String fromSavingsAccountNo = rs.getString("fromSavingsAccountNo");
      final Long fromLoanAccountId = JdbcSupport.getLong(rs, "fromLoanAccountId");
      final String fromLoanAccountNo = rs.getString("fromLoanAccountNo");
      PortfolioAccountData fromAccount = null;
      EnumOptionData fromAccountType = null;
      if (fromSavingsAccountId != null) {
        fromAccount = PortfolioAccountData.lookup(fromSavingsAccountId, fromSavingsAccountNo);
        fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
      } else if (fromLoanAccountId != null) {
        fromAccount = PortfolioAccountData.lookup(fromLoanAccountId, fromLoanAccountNo);
        fromAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
      }

      PortfolioAccountData toAccount = null;
      EnumOptionData toAccountType = null;
      final Long toSavingsAccountId = JdbcSupport.getLong(rs, "toSavingsAccountId");
      final String toSavingsAccountNo = rs.getString("toSavingsAccountNo");
      final Long toLoanAccountId = JdbcSupport.getLong(rs, "toLoanAccountId");
      final String toLoanAccountNo = rs.getString("toLoanAccountNo");

      if (toSavingsAccountId != null) {
        toAccount = PortfolioAccountData.lookup(toSavingsAccountId, toSavingsAccountNo);
        toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS);
      } else if (toLoanAccountId != null) {
        toAccount = PortfolioAccountData.lookup(toLoanAccountId, toLoanAccountNo);
        toAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN);
      }

      return AccountTransferData.instance(
          id,
          reversed,
          transferDate,
          currency,
          transferAmount,
          transferDescription,
          fromOffice,
          toOffice,
          fromClient,
          toClient,
          fromAccountType,
          fromAccount,
          toAccountType,
          toAccount);
    }
    @Override
    @SuppressWarnings("unused")
    public LoanRescheduleRequestData mapRow(final ResultSet rs, final int rowNum)
        throws SQLException {
      final Long id = rs.getLong("id");
      final Long loanId = rs.getLong("loanId");
      final Integer statusEnumId = JdbcSupport.getInteger(rs, "statusEnum");
      final LoanRescheduleRequestStatusEnumData statusEnum =
          LoanRescheduleRequestEnumerations.status(statusEnumId);
      final String clientName = rs.getString("clientName");
      final String loanAccountNumber = rs.getString("loanAccountNumber");
      final Long clientId = rs.getLong("clientId");
      final Integer rescheduleFromInstallment =
          JdbcSupport.getInteger(rs, "rescheduleFromInstallment");
      final Integer graceOnPrincipal = JdbcSupport.getInteger(rs, "graceOnPrincipal");
      final Integer graceOnInterest = JdbcSupport.getInteger(rs, "graceOnInterest");
      final LocalDate rescheduleFromDate = JdbcSupport.getLocalDate(rs, "rescheduleFromDate");
      final LocalDate adjustedDueDate = JdbcSupport.getLocalDate(rs, "adjustedDueDate");
      final Integer extraTerms = JdbcSupport.getInteger(rs, "extraTerms");
      final BigDecimal interestRate = rs.getBigDecimal("interestRate");
      final Long rescheduleReasonCvId = JdbcSupport.getLong(rs, "rescheduleReasonCvId");
      final String rescheduleReasonCvValue = rs.getString("rescheduleReasonCvValue");
      final CodeValueData rescheduleReasonCodeValue =
          CodeValueData.instance(rescheduleReasonCvId, rescheduleReasonCvValue);
      final String rescheduleReasonComment = rs.getString("rescheduleReasonComment");
      final Boolean recalculateInterest = rs.getBoolean("recalculateInterest");

      final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
      final String submittedByUsername = rs.getString("submittedByUsername");
      final String submittedByFirstname = rs.getString("submittedByFirstname");
      final String submittedByLastname = rs.getString("submittedByLastname");

      final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedOnDate");
      final String approvedByUsername = rs.getString("approvedByUsername");
      final String approvedByFirstname = rs.getString("approvedByFirstname");
      final String approvedByLastname = rs.getString("approvedByLastname");

      final LocalDate rejectedOnDate = JdbcSupport.getLocalDate(rs, "rejectedOnDate");
      final String rejectedByUsername = rs.getString("rejectedByUsername");
      final String rejectedByFirstname = rs.getString("rejectedByFirstname");
      final String rejectedByLastname = rs.getString("rejectedByLastname");

      final LoanRescheduleRequestTimelineData timeline =
          new LoanRescheduleRequestTimelineData(
              submittedOnDate,
              submittedByUsername,
              submittedByFirstname,
              submittedByLastname,
              approvedOnDate,
              approvedByUsername,
              approvedByFirstname,
              approvedByLastname,
              rejectedOnDate,
              rejectedByUsername,
              rejectedByFirstname,
              rejectedByLastname);

      return LoanRescheduleRequestData.instance(
          id,
          loanId,
          statusEnum,
          rescheduleFromInstallment,
          graceOnPrincipal,
          graceOnInterest,
          rescheduleFromDate,
          adjustedDueDate,
          extraTerms,
          interestRate,
          rescheduleReasonCodeValue,
          rescheduleReasonComment,
          timeline,
          clientName,
          loanAccountNumber,
          clientId,
          recalculateInterest);
    }
    @Override
    public LoanAccountSummaryData mapRow(
        final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {

      final Long id = JdbcSupport.getLong(rs, "id");
      final String accountNo = rs.getString("accountNo");
      final String externalId = rs.getString("externalId");
      final Long productId = JdbcSupport.getLong(rs, "productId");
      final String loanProductName = rs.getString("productName");
      final Integer loanStatusId = JdbcSupport.getInteger(rs, "statusId");
      final LoanStatusEnumData loanStatus = LoanEnumerations.status(loanStatusId);
      final Integer loanTypeId = JdbcSupport.getInteger(rs, "loanType");
      final EnumOptionData loanType = AccountEnumerations.loanType(loanTypeId);
      final Integer loanCycle = JdbcSupport.getInteger(rs, "loanCycle");

      final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
      final String submittedByUsername = rs.getString("submittedByUsername");
      final String submittedByFirstname = rs.getString("submittedByFirstname");
      final String submittedByLastname = rs.getString("submittedByLastname");

      final LocalDate rejectedOnDate = JdbcSupport.getLocalDate(rs, "rejectedOnDate");
      final String rejectedByUsername = rs.getString("rejectedByUsername");
      final String rejectedByFirstname = rs.getString("rejectedByFirstname");
      final String rejectedByLastname = rs.getString("rejectedByLastname");

      final LocalDate withdrawnOnDate = JdbcSupport.getLocalDate(rs, "withdrawnOnDate");
      final String withdrawnByUsername = rs.getString("withdrawnByUsername");
      final String withdrawnByFirstname = rs.getString("withdrawnByFirstname");
      final String withdrawnByLastname = rs.getString("withdrawnByLastname");

      final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedOnDate");
      final String approvedByUsername = rs.getString("approvedByUsername");
      final String approvedByFirstname = rs.getString("approvedByFirstname");
      final String approvedByLastname = rs.getString("approvedByLastname");

      final LocalDate expectedDisbursementDate =
          JdbcSupport.getLocalDate(rs, "expectedDisbursementDate");
      final LocalDate actualDisbursementDate =
          JdbcSupport.getLocalDate(rs, "actualDisbursementDate");
      final String disbursedByUsername = rs.getString("disbursedByUsername");
      final String disbursedByFirstname = rs.getString("disbursedByFirstname");
      final String disbursedByLastname = rs.getString("disbursedByLastname");

      final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
      final String closedByUsername = rs.getString("closedByUsername");
      final String closedByFirstname = rs.getString("closedByFirstname");
      final String closedByLastname = rs.getString("closedByLastname");

      final LocalDate writtenOffOnDate = JdbcSupport.getLocalDate(rs, "writtenOffOnDate");

      final LocalDate expectedMaturityDate = JdbcSupport.getLocalDate(rs, "expectedMaturityDate");

      final LocalDate overdueSinceDate = JdbcSupport.getLocalDate(rs, "overdueSinceDate");
      Boolean inArrears = true;
      if (overdueSinceDate == null) {
        inArrears = false;
      }

      final LoanApplicationTimelineData timeline =
          new LoanApplicationTimelineData(
              submittedOnDate,
              submittedByUsername,
              submittedByFirstname,
              submittedByLastname,
              rejectedOnDate,
              rejectedByUsername,
              rejectedByFirstname,
              rejectedByLastname,
              withdrawnOnDate,
              withdrawnByUsername,
              withdrawnByFirstname,
              withdrawnByLastname,
              approvedOnDate,
              approvedByUsername,
              approvedByFirstname,
              approvedByLastname,
              expectedDisbursementDate,
              actualDisbursementDate,
              disbursedByUsername,
              disbursedByFirstname,
              disbursedByLastname,
              closedOnDate,
              closedByUsername,
              closedByFirstname,
              closedByLastname,
              expectedMaturityDate,
              writtenOffOnDate,
              closedByUsername,
              closedByFirstname,
              closedByLastname);

      return new LoanAccountSummaryData(
          id,
          accountNo,
          externalId,
          productId,
          loanProductName,
          loanStatus,
          loanType,
          loanCycle,
          timeline,
          inArrears);
    }
    @Override
    public SavingsAccountSummaryData mapRow(
        final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {

      final Long id = JdbcSupport.getLong(rs, "id");
      final String accountNo = rs.getString("accountNo");
      final String externalId = rs.getString("externalId");
      final Long productId = JdbcSupport.getLong(rs, "productId");
      final String productName = rs.getString("productName");
      final Integer statusId = JdbcSupport.getInteger(rs, "statusEnum");
      final BigDecimal accountBalance =
          JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "accountBalance");
      final SavingsAccountStatusEnumData status = SavingsEnumerations.status(statusId);
      final Integer accountType = JdbcSupport.getInteger(rs, "accountType");
      final EnumOptionData accountTypeData = AccountEnumerations.loanType(accountType);

      final String currencyCode = rs.getString("currencyCode");
      final String currencyName = rs.getString("currencyName");
      final String currencyNameCode = rs.getString("currencyNameCode");
      final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
      final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
      final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");
      final CurrencyData currency =
          new CurrencyData(
              currencyCode,
              currencyName,
              currencyDigits,
              inMultiplesOf,
              currencyDisplaySymbol,
              currencyNameCode);

      final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate");
      final String submittedByUsername = rs.getString("submittedByUsername");
      final String submittedByFirstname = rs.getString("submittedByFirstname");
      final String submittedByLastname = rs.getString("submittedByLastname");

      final LocalDate rejectedOnDate = JdbcSupport.getLocalDate(rs, "rejectedOnDate");
      final String rejectedByUsername = rs.getString("rejectedByUsername");
      final String rejectedByFirstname = rs.getString("rejectedByFirstname");
      final String rejectedByLastname = rs.getString("rejectedByLastname");

      final LocalDate withdrawnOnDate = JdbcSupport.getLocalDate(rs, "withdrawnOnDate");
      final String withdrawnByUsername = rs.getString("withdrawnByUsername");
      final String withdrawnByFirstname = rs.getString("withdrawnByFirstname");
      final String withdrawnByLastname = rs.getString("withdrawnByLastname");

      final LocalDate approvedOnDate = JdbcSupport.getLocalDate(rs, "approvedOnDate");
      final String approvedByUsername = rs.getString("approvedByUsername");
      final String approvedByFirstname = rs.getString("approvedByFirstname");
      final String approvedByLastname = rs.getString("approvedByLastname");

      final LocalDate activatedOnDate = JdbcSupport.getLocalDate(rs, "activatedOnDate");
      final String activatedByUsername = rs.getString("activatedByUsername");
      final String activatedByFirstname = rs.getString("activatedByFirstname");
      final String activatedByLastname = rs.getString("activatedByLastname");

      final LocalDate closedOnDate = JdbcSupport.getLocalDate(rs, "closedOnDate");
      final String closedByUsername = rs.getString("closedByUsername");
      final String closedByFirstname = rs.getString("closedByFirstname");
      final String closedByLastname = rs.getString("closedByLastname");

      final SavingsAccountApplicationTimelineData timeline =
          new SavingsAccountApplicationTimelineData(
              submittedOnDate,
              submittedByUsername,
              submittedByFirstname,
              submittedByLastname,
              rejectedOnDate,
              rejectedByUsername,
              rejectedByFirstname,
              rejectedByLastname,
              withdrawnOnDate,
              withdrawnByUsername,
              withdrawnByFirstname,
              withdrawnByLastname,
              approvedOnDate,
              approvedByUsername,
              approvedByFirstname,
              approvedByLastname,
              activatedOnDate,
              activatedByUsername,
              activatedByFirstname,
              activatedByLastname,
              closedOnDate,
              closedByUsername,
              closedByFirstname,
              closedByLastname);

      return new SavingsAccountSummaryData(
          id,
          accountNo,
          externalId,
          productId,
          productName,
          status,
          currency,
          accountBalance,
          accountTypeData,
          timeline);
    }
    @Override
    public LoanProductData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum)
        throws SQLException {

      final Long id = JdbcSupport.getLong(rs, "id");
      final String name = rs.getString("name");
      final String shortName = rs.getString("shortName");
      final String description = rs.getString("description");
      final Long fundId = JdbcSupport.getLong(rs, "fundId");
      final String fundName = rs.getString("fundName");
      final Long transactionStrategyId = JdbcSupport.getLong(rs, "transactionStrategyId");
      final String transactionStrategyName = rs.getString("transactionStrategyName");

      final String currencyCode = rs.getString("currencyCode");
      final String currencyName = rs.getString("currencyName");
      final String currencyNameCode = rs.getString("currencyNameCode");
      final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol");
      final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits");
      final Integer inMultiplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf");

      final CurrencyData currency =
          new CurrencyData(
              currencyCode,
              currencyName,
              currencyDigits,
              inMultiplesOf,
              currencyDisplaySymbol,
              currencyNameCode);

      final BigDecimal principal = rs.getBigDecimal("principal");
      final BigDecimal minPrincipal = rs.getBigDecimal("minPrincipal");
      final BigDecimal maxPrincipal = rs.getBigDecimal("maxPrincipal");
      final BigDecimal tolerance = rs.getBigDecimal("tolerance");

      final Integer numberOfRepayments = JdbcSupport.getInteger(rs, "numberOfRepayments");
      final Integer minNumberOfRepayments = JdbcSupport.getInteger(rs, "minNumberOfRepayments");
      final Integer maxNumberOfRepayments = JdbcSupport.getInteger(rs, "maxNumberOfRepayments");
      final Integer repaymentEvery = JdbcSupport.getInteger(rs, "repaidEvery");

      final Integer graceOnPrincipalPayment =
          JdbcSupport.getIntegerDefaultToNullIfZero(rs, "graceOnPrincipalPayment");
      final Integer graceOnInterestPayment =
          JdbcSupport.getIntegerDefaultToNullIfZero(rs, "graceOnInterestPayment");
      final Integer graceOnInterestCharged =
          JdbcSupport.getIntegerDefaultToNullIfZero(rs, "graceOnInterestCharged");
      final Integer graceOnArrearsAgeing =
          JdbcSupport.getIntegerDefaultToNullIfZero(rs, "graceOnArrearsAgeing");
      final Integer overdueDaysForNPA =
          JdbcSupport.getIntegerDefaultToNullIfZero(rs, "overdueDaysForNPA");
      final Integer minimumDaysBetweenDisbursalAndFirstRepayment =
          JdbcSupport.getInteger(rs, "minimumDaysBetweenDisbursalAndFirstRepayment");

      final Integer accountingRuleId = JdbcSupport.getInteger(rs, "accountingType");
      final EnumOptionData accountingRuleType =
          AccountingEnumerations.accountingRuleType(accountingRuleId);

      final BigDecimal interestRatePerPeriod = rs.getBigDecimal("interestRatePerPeriod");
      final BigDecimal minInterestRatePerPeriod = rs.getBigDecimal("minInterestRatePerPeriod");
      final BigDecimal maxInterestRatePerPeriod = rs.getBigDecimal("maxInterestRatePerPeriod");
      final BigDecimal annualInterestRate = rs.getBigDecimal("annualInterestRate");

      final int repaymentFrequencyTypeId = JdbcSupport.getInteger(rs, "repaymentPeriodFrequency");
      final EnumOptionData repaymentFrequencyType =
          LoanEnumerations.repaymentFrequencyType(repaymentFrequencyTypeId);

      final int amortizationTypeId = JdbcSupport.getInteger(rs, "amortizationMethod");
      final EnumOptionData amortizationType = LoanEnumerations.amortizationType(amortizationTypeId);

      final int interestRateFrequencyTypeId =
          JdbcSupport.getInteger(rs, "interestRatePerPeriodFreq");
      final EnumOptionData interestRateFrequencyType =
          LoanEnumerations.interestRateFrequencyType(interestRateFrequencyTypeId);

      final int interestTypeId = JdbcSupport.getInteger(rs, "interestMethod");
      final EnumOptionData interestType = LoanEnumerations.interestType(interestTypeId);

      final int interestCalculationPeriodTypeId =
          JdbcSupport.getInteger(rs, "interestCalculationInPeriodMethod");
      final EnumOptionData interestCalculationPeriodType =
          LoanEnumerations.interestCalculationPeriodType(interestCalculationPeriodTypeId);

      final boolean includeInBorrowerCycle = rs.getBoolean("includeInBorrowerCycle");
      final boolean useBorrowerCycle = rs.getBoolean("useBorrowerCycle");
      final LocalDate startDate = JdbcSupport.getLocalDate(rs, "startDate");
      final LocalDate closeDate = JdbcSupport.getLocalDate(rs, "closeDate");
      String status = "";
      if (closeDate != null && closeDate.isBefore(DateUtils.getLocalDateOfTenant())) {
        status = "loanProduct.inActive";
      } else {
        status = "loanProduct.active";
      }
      final String externalId = rs.getString("externalId");
      final Collection<LoanProductBorrowerCycleVariationData> principalVariationsForBorrowerCycle =
          new ArrayList<>();
      final Collection<LoanProductBorrowerCycleVariationData>
          interestRateVariationsForBorrowerCycle = new ArrayList<>();
      final Collection<LoanProductBorrowerCycleVariationData>
          numberOfRepaymentVariationsForBorrowerCycle = new ArrayList<>();
      if (this.borrowerCycleVariationDatas != null) {
        for (final LoanProductBorrowerCycleVariationData borrowerCycleVariationData :
            this.borrowerCycleVariationDatas) {
          final LoanProductParamType loanProductParamType =
              borrowerCycleVariationData.getParamType();
          if (loanProductParamType.isParamTypePrincipal()) {
            principalVariationsForBorrowerCycle.add(borrowerCycleVariationData);
          } else if (loanProductParamType.isParamTypeInterestTate()) {
            interestRateVariationsForBorrowerCycle.add(borrowerCycleVariationData);
          } else if (loanProductParamType.isParamTypeRepayment()) {
            numberOfRepaymentVariationsForBorrowerCycle.add(borrowerCycleVariationData);
          }
        }
      }

      final Boolean multiDisburseLoan = rs.getBoolean("multiDisburseLoan");
      final Integer maxTrancheCount = rs.getInt("maxTrancheCount");
      final BigDecimal outstandingLoanBalance = rs.getBigDecimal("outstandingLoanBalance");

      final int daysInMonth = JdbcSupport.getInteger(rs, "daysInMonth");
      final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(daysInMonth);
      final int daysInYear = JdbcSupport.getInteger(rs, "daysInYear");
      final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(daysInYear);
      final boolean isInterestRecalculationEnabled =
          rs.getBoolean("isInterestRecalculationEnabled");

      LoanProductInterestRecalculationData interestRecalculationData = null;
      if (isInterestRecalculationEnabled) {

        final Long lprId = JdbcSupport.getLong(rs, "lprId");
        final Long productId = JdbcSupport.getLong(rs, "productId");
        final int compoundTypeEnumValue = JdbcSupport.getInteger(rs, "compoundType");
        final EnumOptionData interestRecalculationCompoundingType =
            LoanEnumerations.interestRecalculationCompoundingType(compoundTypeEnumValue);
        final int rescheduleStrategyEnumValue = JdbcSupport.getInteger(rs, "rescheduleStrategy");
        final EnumOptionData rescheduleStrategyType =
            LoanEnumerations.rescheduleStrategyType(rescheduleStrategyEnumValue);
        final int restFrequencyEnumValue = JdbcSupport.getInteger(rs, "restFrequencyEnum");
        final EnumOptionData restFrequencyType =
            LoanEnumerations.interestRecalculationFrequencyType(restFrequencyEnumValue);
        final int restFrequencyInterval = JdbcSupport.getInteger(rs, "restFrequencyInterval");
        final LocalDate restFrequencyDate = JdbcSupport.getLocalDate(rs, "restFrequencyDate");

        interestRecalculationData =
            new LoanProductInterestRecalculationData(
                lprId,
                productId,
                interestRecalculationCompoundingType,
                rescheduleStrategyType,
                restFrequencyType,
                restFrequencyInterval,
                restFrequencyDate);
      }

      final boolean holdGuaranteeFunds = rs.getBoolean("holdGuaranteeFunds");
      LoanProductGuaranteeData loanProductGuaranteeData = null;
      if (holdGuaranteeFunds) {
        final Long lpgId = JdbcSupport.getLong(rs, "lpgId");
        final BigDecimal mandatoryGuarantee = rs.getBigDecimal("mandatoryGuarantee");
        final BigDecimal minimumGuaranteeFromOwnFunds =
            rs.getBigDecimal("minimumGuaranteeFromOwnFunds");
        final BigDecimal minimumGuaranteeFromGuarantor =
            rs.getBigDecimal("minimumGuaranteeFromGuarantor");
        loanProductGuaranteeData =
            LoanProductGuaranteeData.instance(
                lpgId,
                id,
                mandatoryGuarantee,
                minimumGuaranteeFromOwnFunds,
                minimumGuaranteeFromGuarantor);
      }

      return new LoanProductData(
          id,
          name,
          shortName,
          description,
          currency,
          principal,
          minPrincipal,
          maxPrincipal,
          tolerance,
          numberOfRepayments,
          minNumberOfRepayments,
          maxNumberOfRepayments,
          repaymentEvery,
          interestRatePerPeriod,
          minInterestRatePerPeriod,
          maxInterestRatePerPeriod,
          annualInterestRate,
          repaymentFrequencyType,
          interestRateFrequencyType,
          amortizationType,
          interestType,
          interestCalculationPeriodType,
          fundId,
          fundName,
          transactionStrategyId,
          transactionStrategyName,
          graceOnPrincipalPayment,
          graceOnInterestPayment,
          graceOnInterestCharged,
          this.charges,
          accountingRuleType,
          includeInBorrowerCycle,
          useBorrowerCycle,
          startDate,
          closeDate,
          status,
          externalId,
          principalVariationsForBorrowerCycle,
          interestRateVariationsForBorrowerCycle,
          numberOfRepaymentVariationsForBorrowerCycle,
          multiDisburseLoan,
          maxTrancheCount,
          outstandingLoanBalance,
          graceOnArrearsAgeing,
          overdueDaysForNPA,
          daysInMonthType,
          daysInYearType,
          isInterestRecalculationEnabled,
          interestRecalculationData,
          minimumDaysBetweenDisbursalAndFirstRepayment,
          holdGuaranteeFunds,
          loanProductGuaranteeData);
    }