@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; }
@Transactional @Override public CommandProcessingResult create(final JsonCommand command) { this.accountTransfersDataValidator.validate(command); final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName); final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName); final Locale locale = command.extractLocale(); final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale); final Integer fromAccountTypeId = command.integerValueSansLocaleOfParameterNamed(fromAccountTypeParamName); final PortfolioAccountType fromAccountType = PortfolioAccountType.fromInt(fromAccountTypeId); final Integer toAccountTypeId = command.integerValueSansLocaleOfParameterNamed(toAccountTypeParamName); final PortfolioAccountType toAccountType = PortfolioAccountType.fromInt(toAccountTypeId); final PaymentDetail paymentDetail = null; Long fromSavingsAccountId = null; Long transferTransactionId = null; if (isSavingsToSavingsAccountTransfer(fromAccountType, toAccountType)) { fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName); final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId); final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal( fromSavingsAccount, fmt, transactionDate, transactionAmount, paymentDetail, fromSavingsAccount.isWithdrawalFeeApplicableForTransfer()); final Long toSavingsId = command.longValueOfParameterNamed(toAccountIdParamName); final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsId); final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit( toSavingsAccount, fmt, transactionDate, transactionAmount, paymentDetail); final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToSavingsTransfer( command, withdrawal, deposit); this.accountTransferRepository.saveAndFlush(transferTransaction); transferTransactionId = transferTransaction.getId(); } else if (isSavingsToLoanAccountTransfer(fromAccountType, toAccountType)) { // fromSavingsAccountId = command.longValueOfParameterNamed(fromAccountIdParamName); final SavingsAccount fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(fromSavingsAccountId); final SavingsAccountTransaction withdrawal = this.savingsAccountDomainService.handleWithdrawal( fromSavingsAccount, fmt, transactionDate, transactionAmount, paymentDetail, fromSavingsAccount.isWithdrawalFeeApplicableForTransfer()); final Long toLoanAccountId = command.longValueOfParameterNamed(toAccountIdParamName); final Loan toLoanAccount = this.loanAccountAssembler.assembleFrom(toLoanAccountId); final LoanTransaction loanRepaymentTransaction = this.loanAccountDomainService.makeRepayment( toLoanAccount, new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null); final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleSavingsToLoanTransfer( command, fromSavingsAccount, toLoanAccount, withdrawal, loanRepaymentTransaction); this.accountTransferRepository.saveAndFlush(transferTransaction); transferTransactionId = transferTransaction.getId(); } else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) { // FIXME - kw - ADD overpaid loan to savings account transfer // support. // final Long fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName); final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId); final LoanTransaction loanRefundTransaction = this.loanAccountDomainService.makeRefund( fromLoanAccountId, new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null); final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName); final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId); final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit( toSavingsAccount, fmt, transactionDate, transactionAmount, paymentDetail); final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleLoanToSavingsTransfer( command, fromLoanAccount, toSavingsAccount, deposit, loanRefundTransaction); this.accountTransferRepository.saveAndFlush(transferTransaction); transferTransactionId = transferTransaction.getId(); } else { } final CommandProcessingResultBuilder builder = new CommandProcessingResultBuilder().withEntityId(transferTransactionId); if (fromAccountType.isSavingsAccount()) { builder.withSavingsId(fromSavingsAccountId); } return builder.build(); }