@Transactional
  @Override
  public CommandProcessingResult rejectApplication(
      final Long savingsId, final JsonCommand command) {

    final AppUser currentUser = this.context.authenticatedUser();

    this.savingsAccountApplicationTransitionApiJsonValidator.validateRejection(command.json());

    final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(savingsId);
    checkClientOrGroupActive(savingsAccount);

    final Map<String, Object> changes =
        savingsAccount.rejectApplication(currentUser, command, DateUtils.getLocalDateOfTenant());
    if (!changes.isEmpty()) {
      this.savingAccountRepository.save(savingsAccount);

      final String noteText = command.stringValueOfParameterNamed("note");
      if (StringUtils.isNotBlank(noteText)) {
        final Note note = Note.savingNote(savingsAccount, noteText);
        changes.put("note", noteText);
        this.noteRepository.save(note);
      }
    }

    return new CommandProcessingResultBuilder() //
        .withCommandId(command.commandId()) //
        .withEntityId(savingsId) //
        .withOfficeId(savingsAccount.officeId()) //
        .withClientId(savingsAccount.clientId()) //
        .withGroupId(savingsAccount.groupId()) //
        .withSavingsId(savingsId) //
        .with(changes) //
        .build();
  }
  @Transactional
  @Override
  public LoanTransaction makeRepayment(
      final Long accountId,
      final CommandProcessingResultBuilder builderResult,
      final LocalDate transactionDate,
      final BigDecimal transactionAmount,
      final PaymentDetail paymentDetail,
      final String noteText,
      final String txnExternalId) {

    final Loan loan = this.loanAccountAssembler.assembleFrom(accountId);
    checkClientOrGroupActive(loan);

    // TODO: Is it required to validate transaction date with meeting dates
    // if repayments is synced with meeting?
    /*
     * if(loan.isSyncDisbursementWithMeeting()){ // validate actual
     * disbursement date against meeting date CalendarInstance
     * calendarInstance =
     * this.calendarInstanceRepository.findCalendarInstaneByLoanId
     * (loan.getId(), CalendarEntityType.LOANS.getValue());
     * this.loanEventApiJsonValidator
     * .validateRepaymentDateWithMeetingDate(transactionDate,
     * calendarInstance); }
     */

    final List<Long> existingTransactionIds = new ArrayList<Long>();
    final List<Long> existingReversedTransactionIds = new ArrayList<Long>();

    final Money repaymentAmount = Money.of(loan.getCurrency(), transactionAmount);
    final LoanTransaction newRepaymentTransaction =
        LoanTransaction.repayment(repaymentAmount, paymentDetail, transactionDate, txnExternalId);
    final boolean allowTransactionsOnHoliday =
        this.configurationDomainService.allowTransactionsOnHolidayEnabled();
    final List<Holiday> holidays =
        this.holidayRepository.findByOfficeIdAndGreaterThanDate(
            loan.getOfficeId(), transactionDate.toDate());
    final WorkingDays workingDays = this.workingDaysRepository.findOne();
    final boolean allowTransactionsOnNonWorkingDay =
        this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled();

    final ChangedTransactionDetail changedTransactionDetail =
        loan.makeRepayment(
            newRepaymentTransaction,
            defaultLoanLifecycleStateMachine(),
            existingTransactionIds,
            existingReversedTransactionIds,
            allowTransactionsOnHoliday,
            holidays,
            workingDays,
            allowTransactionsOnNonWorkingDay);

    this.loanTransactionRepository.save(newRepaymentTransaction);

    /**
     * * TODO Vishwas Batch save is giving me a HibernateOptimisticLockingFailureException, looping
     * and saving for the time being, not a major issue for now as this loop is entered only in edge
     * cases (when a payment is made before the latest payment recorded against the loan) *
     */
    if (changedTransactionDetail != null) {
      for (final LoanTransaction loanTransaction : changedTransactionDetail.getNewTransactions()) {
        this.loanTransactionRepository.save(loanTransaction);
      }
    }
    this.loanRepository.save(loan);

    if (StringUtils.isNotBlank(noteText)) {
      final Note note = Note.loanTransactionNote(loan, newRepaymentTransaction, noteText);
      this.noteRepository.save(note);
    }

    postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);

    builderResult
        .withEntityId(newRepaymentTransaction.getId()) //
        .withOfficeId(loan.getOfficeId()) //
        .withClientId(loan.getClientId()) //
        .withGroupId(loan.getGroupId()); //

    return newRepaymentTransaction;
  }