adamsaghy commented on code in PR #4046:
URL: https://github.com/apache/fineract/pull/4046#discussion_r1744131009
##########
fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java:
##########
@@ -295,6 +303,139 @@ public CommandProcessingResult disburseLoan(Long loanId,
JsonCommand command, Bo
return disburseLoan(loanId, command, isAccountTransfer, false);
}
+ @Transactional
+ @Override
+ public CommandProcessingResult disburseLoanToLinkedAccount(Long loanId,
JsonCommand command, Boolean isAccountTransfer) {
+ Boolean isWithoutAutoPayment = false;
+ boolean isPaymentHubIntegrationEnabled =
configurationDomainService.isPaymentHubIntegrationEnabled();
+ if (!isPaymentHubIntegrationEnabled) {
+ throw new
GlobalConfigurationNotEnabledException("enable-payment-hub-integration");
+ }
+ loanTransactionValidator.validateDisbursement(command,
isAccountTransfer, loanId);
+
+ Loan loan = loanAssembler.assembleFrom(loanId);
+
+ if (loan.loanProduct().isDisallowExpectedDisbursements()) {
+ List<LoanDisbursementDetails> filteredList =
loan.getDisbursementDetails().stream()
+ .filter(disbursementDetails ->
disbursementDetails.actualDisbursementDate() == null).toList();
+ // Check whether a new LoanDisbursementDetails is required
+ if (filteredList.isEmpty()) {
+ // create artificial 'tranche/expected disbursal' as current
disburse code expects it for
+ // multi-disbursal products
+ final LocalDate artificialExpectedDate =
loan.getExpectedDisbursedOnLocalDate();
+ LoanDisbursementDetails disbursementDetail = new
LoanDisbursementDetails(artificialExpectedDate, null,
+ loan.getDisbursedAmount(), null, false);
+ disbursementDetail.updateLoan(loan);
+ loan.getAllDisbursementDetails().add(disbursementDetail);
+ }
+ }
+
+ final LocalDate nextPossibleRepaymentDate =
loan.getNextPossibleRepaymentDateForRescheduling();
+ final LocalDate rescheduledRepaymentDate =
command.localDateValueOfParameterNamed("adjustRepaymentDate");
+ final LocalDate actualDisbursementDate =
command.localDateValueOfParameterNamed("actualDisbursementDate");
+ if (!loan.isMultiDisburmentLoan()) {
+ loan.setActualDisbursementDate(actualDisbursementDate);
+ }
+
+ // validate actual disbursement date against meeting date
+ ScheduleGeneratorDTO scheduleGeneratorDTO =
this.loanUtilService.buildScheduleGeneratorDTO(loan, null);
+
+ final AppUser currentUser = getAppUserIfPresent();
+ final Map<String, Object> changes = new LinkedHashMap<>();
+
+ final PaymentDetail paymentDetail =
this.paymentDetailWritePlatformService.createAndPersistPaymentDetail(command,
changes);
+ if (paymentDetail != null && paymentDetail.getPaymentType() != null &&
paymentDetail.getPaymentType().getIsCashPayment()) {
+ BigDecimal transactionAmount =
command.bigDecimalValueOfParameterNamed("transactionAmount");
+
this.cashierTransactionDataValidator.validateOnLoanDisbursal(currentUser,
loan.getCurrencyCode(), transactionAmount);
+ }
+ final boolean isPaymentTypeApplicableForDisbursementCharge =
configurationDomainService
+ .isPaymentTypeApplicableForDisbursementCharge();
+
+ Money amountBeforeAdjust = loan.getPrincipal();
+ final Locale locale = command.extractLocale();
+ final DateTimeFormatter fmt =
DateTimeFormatter.ofPattern(command.dateFormat()).withLocale(locale);
+
+ if (loan.canDisburse()) {
+ // Get netDisbursalAmount from disbursal screen field.
+ final BigDecimal netDisbursalAmount = command
+
.bigDecimalValueOfParameterNamed(LoanApiConstants.disbursementNetDisbursalAmountParameterName);
+ if (netDisbursalAmount != null) {
+ loan.setNetDisbursalAmount(netDisbursalAmount);
+ }
+ Money disburseAmount = loan.adjustDisburseAmount(command,
actualDisbursementDate);
+ boolean recalculateSchedule =
amountBeforeAdjust.isNotEqualTo(loan.getPrincipal());
+ final ExternalId txnExternalId =
externalIdFactory.createFromCommand(command,
LoanApiConstants.externalIdParameterName);
+
+ if (loan.isTopup() && loan.getClientId() != null) {
+ final Long loanIdToClose =
loan.getTopupLoanDetails().getLoanIdToClose();
+ final Loan loanToClose =
this.loanRepositoryWrapper.findNonClosedLoanThatBelongsToClient(loanIdToClose,
loan.getClientId());
+ if (loanToClose == null) {
+ throw new
GeneralPlatformDomainRuleException("error.msg.loan.to.be.closed.with.topup.is.not.active",
+ "Loan to be closed with this topup is not
active.");
+ }
+ final LocalDate lastUserTransactionOnLoanToClose =
loanToClose.getLastUserTransactionDate();
+ if (DateUtils.isBefore(loan.getDisbursementDate(),
lastUserTransactionOnLoanToClose)) {
+ throw new GeneralPlatformDomainRuleException(
+
"error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
+ "Disbursal date of this loan application " +
loan.getDisbursementDate()
+ + " should be after last transaction date
of loan to be closed " + lastUserTransactionOnLoanToClose);
+ }
+
+ BigDecimal loanOutstanding = this.loanReadPlatformService
+
.retrieveLoanPrePaymentTemplate(LoanTransactionType.REPAYMENT, loanIdToClose,
actualDisbursementDate).getAmount();
+ final BigDecimal firstDisbursalAmount =
loan.getFirstDisbursalAmount();
+ if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) {
+ throw new
GeneralPlatformDomainRuleException("error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
+ "Topup loan amount should be greater than
outstanding amount of loan to be closed.");
+ }
+ }
+ if (loan.getRepaymentScheduleInstallments().isEmpty()) {
+ /*
+ * If no schedule, generate one (applicable to non-tranche
multi-disbursal loans)
+ */
+ recalculateSchedule = true;
+ }
+
+ regenerateScheduleOnDisbursement(command, loan,
recalculateSchedule, scheduleGeneratorDTO, nextPossibleRepaymentDate,
+ rescheduledRepaymentDate);
+ boolean downPaymentEnabled =
loan.repaymentScheduleDetail().isEnableDownPayment();
+ if
(loan.repaymentScheduleDetail().isInterestRecalculationEnabled() ||
downPaymentEnabled) {
+ createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
+ }
+ }
+
+ final PortfolioAccountData portfolioAccountData =
this.accountAssociationsReadPlatformService
+ .retriveLoanLinkedAssociation(loan.getId());
+ if (portfolioAccountData == null) {
+ final String errorMessage = "Disburse Loan with id:" +
loan.getId() + " requires linked savings account for payment";
+ throw new
LinkedAccountRequiredException("loan.disburse.to.savings", errorMessage,
loan.getId());
+ }
+
Review Comment:
Please rename it: `identifier1` is way too vague and not descriptive
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]