예제 #1
0
  public LoanScheduleModel assembleLoanScheduleFrom(
      final LoanApplicationTerms loanApplicationTerms,
      final boolean isHolidayEnabled,
      final List<Holiday> holidays,
      final WorkingDays workingDays,
      final JsonElement element) {

    final Set<LoanCharge> loanCharges = this.loanChargeAssembler.fromParsedJson(element);

    final LoanScheduleGenerator loanScheduleGenerator =
        this.loanScheduleFactory.create(loanApplicationTerms.getInterestMethod());

    final RoundingMode roundingMode = RoundingMode.HALF_EVEN;
    final MathContext mc = new MathContext(8, roundingMode);

    final MonetaryCurrency currency = loanApplicationTerms.getCurrency();
    final ApplicationCurrency applicationCurrency =
        this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);
    return loanScheduleGenerator.generate(
        mc,
        applicationCurrency,
        loanApplicationTerms,
        loanCharges,
        isHolidayEnabled,
        holidays,
        workingDays);
  }
예제 #2
0
  public LoanScheduleModel assembleLoanScheduleFrom(final JsonElement element) {
    // This method is getting called from calculate loan schedule.
    final LoanApplicationTerms loanApplicationTerms = assembleLoanTerms(element);
    // Get holiday details
    final boolean isHolidayEnabled =
        this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();

    final Long clientId = fromApiJsonHelper.extractLongNamed("clientId", element);
    final Long groupId = fromApiJsonHelper.extractLongNamed("groupId", element);

    Client client = null;
    Group group = null;
    Long officeId = null;
    if (clientId != null) {
      client = this.clientRepository.findOneWithNotFoundDetection(clientId);
      officeId = client.getOffice().getId();
    } else if (groupId != null) {
      group = this.groupRepository.findOneWithNotFoundDetection(groupId);
      officeId = group.getOffice().getId();
    }

    final LocalDate expectedDisbursementDate =
        this.fromApiJsonHelper.extractLocalDateNamed("expectedDisbursementDate", element);
    final List<Holiday> holidays =
        this.holidayRepository.findByOfficeIdAndGreaterThanDate(
            officeId, expectedDisbursementDate.toDate());
    final WorkingDays workingDays = this.workingDaysRepository.findOne();

    validateDisbursementDateIsOnNonWorkingDay(
        loanApplicationTerms.getExpectedDisbursementDate(), workingDays);
    validateDisbursementDateIsOnHoliday(
        loanApplicationTerms.getExpectedDisbursementDate(), isHolidayEnabled, holidays);

    return assembleLoanScheduleFrom(
        loanApplicationTerms, isHolidayEnabled, holidays, workingDays, element);
  }
예제 #3
0
 public LoanProductRelatedDetail assembleLoanProductRelatedDetail(final JsonElement element) {
   LoanApplicationTerms loanApplicationTerms = assembleLoanTerms(element);
   return loanApplicationTerms.toLoanProductRelatedDetail();
 }
예제 #4
0
  private LoanApplicationTerms assembleLoanApplicationTermsFrom(
      final JsonElement element, final LoanProduct loanProduct) {

    final MonetaryCurrency currency = loanProduct.getCurrency();
    final ApplicationCurrency applicationCurrency =
        this.applicationCurrencyRepository.findOneWithNotFoundDetection(currency);

    // loan terms
    final Integer loanTermFrequency =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("loanTermFrequency", element);
    final Integer loanTermFrequencyType =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("loanTermFrequencyType", element);
    final PeriodFrequencyType loanTermPeriodFrequencyType =
        PeriodFrequencyType.fromInt(loanTermFrequencyType);

    final Integer numberOfRepayments =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("numberOfRepayments", element);
    final Integer repaymentEvery =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentEvery", element);
    final Integer repaymentFrequencyType =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("repaymentFrequencyType", element);
    final PeriodFrequencyType repaymentPeriodFrequencyType =
        PeriodFrequencyType.fromInt(repaymentFrequencyType);

    final Integer amortizationType =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("amortizationType", element);
    final AmortizationMethod amortizationMethod = AmortizationMethod.fromInt(amortizationType);

    // interest terms
    final Integer interestType =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("interestType", element);
    final InterestMethod interestMethod = InterestMethod.fromInt(interestType);

    final Integer interestCalculationPeriodType =
        fromApiJsonHelper.extractIntegerWithLocaleNamed("interestCalculationPeriodType", element);
    final InterestCalculationPeriodMethod interestCalculationPeriodMethod =
        InterestCalculationPeriodMethod.fromInt(interestCalculationPeriodType);

    final BigDecimal interestRatePerPeriod =
        fromApiJsonHelper.extractBigDecimalWithLocaleNamed("interestRatePerPeriod", element);
    final PeriodFrequencyType interestRatePeriodFrequencyType =
        loanProduct.getInterestPeriodFrequencyType();

    final BigDecimal annualNominalInterestRate =
        this.aprCalculator.calculateFrom(interestRatePeriodFrequencyType, interestRatePerPeriod);

    // disbursement details
    final BigDecimal principal =
        this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("principal", element);
    final Money principalMoney = Money.of(currency, principal);

    final LocalDate expectedDisbursementDate =
        this.fromApiJsonHelper.extractLocalDateNamed("expectedDisbursementDate", element);
    final LocalDate repaymentsStartingFromDate =
        this.fromApiJsonHelper.extractLocalDateNamed("repaymentsStartingFromDate", element);
    LocalDate calculatedRepaymentsStartingFromDate = repaymentsStartingFromDate;
    final Boolean synchDisbursement =
        fromApiJsonHelper.extractBooleanNamed("syncDisbursementWithMeeting", element);
    final Long calendarId = this.fromApiJsonHelper.extractLongNamed("calendarId", element);
    Calendar calendar = null;
    if ((synchDisbursement != null && synchDisbursement.booleanValue())
        || (calendarId != null && calendarId != 0)) {
      calendar = this.calendarRepository.findOne(calendarId);
      if (calendar == null) {
        throw new CalendarNotFoundException(calendarId);
      }

      // validate repayment frequency and interval with meeting frequency and interval
      PeriodFrequencyType meetingPeriodFrequency =
          CalendarHelper.getMeetingPeriodFrequencyType(calendar.getRecurrence());
      validateRepaymentFrequencyIsSameAsMeetingFrequency(
          meetingPeriodFrequency.getValue(),
          repaymentFrequencyType,
          CalendarHelper.getInterval(calendar.getRecurrence()),
          repaymentEvery);
    }

    if (synchDisbursement != null && synchDisbursement.booleanValue()) {
      validateDisbursementDateWithMeetingDates(expectedDisbursementDate, calendar);
    }

    // if calendar is attached (not null) then reschedule repayment dates according to meeting
    if (null != calendar) {
      // TODO : AA - Is it require to reset repaymentsStartingFromDate or
      // set only if it is not provided (or null)
      // Currently provided repaymentsStartingFromDate takes precedence over system generated next
      // meeting date
      if (calculatedRepaymentsStartingFromDate == null) {
        // FIXME: AA - Possibility of having next meeting date immediately after disbursement date,
        // need to have minimum number of days gap between disbursement and first repayment date.
        final String frequency =
            CalendarHelper.getMeetingFrequencyFromPeriodFrequencyType(repaymentPeriodFrequencyType);
        calculatedRepaymentsStartingFromDate =
            CalendarHelper.getFirstRepaymentMeetingDate(
                calendar, expectedDisbursementDate, repaymentEvery, frequency);
      } else { // validate user provided repaymentsStartFromDate
        validateRepaymentsStartDateWithMeetingDates(repaymentsStartingFromDate, calendar);
      }
    }
    // grace details
    final Integer graceOnPrincipalPayment =
        this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnPrincipalPayment", element);
    final Integer graceOnInterestPayment =
        this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestPayment", element);
    final Integer graceOnInterestCharged =
        this.fromApiJsonHelper.extractIntegerWithLocaleNamed("graceOnInterestCharged", element);
    final LocalDate interestChargedFromDate =
        fromApiJsonHelper.extractLocalDateNamed("interestChargedFromDate", element);

    // other
    final BigDecimal inArrearsTolerance =
        this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed("inArrearsTolerance", element);
    final Money inArrearsToleranceMoney = Money.of(currency, inArrearsTolerance);

    return LoanApplicationTerms.assembleFrom(
        applicationCurrency,
        loanTermFrequency,
        loanTermPeriodFrequencyType,
        numberOfRepayments,
        repaymentEvery,
        repaymentPeriodFrequencyType,
        amortizationMethod,
        interestMethod,
        interestRatePerPeriod,
        interestRatePeriodFrequencyType,
        annualNominalInterestRate,
        interestCalculationPeriodMethod,
        principalMoney,
        expectedDisbursementDate,
        repaymentsStartingFromDate,
        calculatedRepaymentsStartingFromDate,
        graceOnPrincipalPayment,
        graceOnInterestPayment,
        graceOnInterestCharged,
        interestChargedFromDate,
        inArrearsToleranceMoney);
  }