From 51203b173f788ab60ffda089d82b7060daa6501a Mon Sep 17 00:00:00 2001 From: Adam Saghy Date: Tue, 7 Feb 2023 17:02:59 +0100 Subject: [PATCH] FINERACT-1694: Fix missing payment details data for events --- .../api/LoanChargesApiResourceSwagger.java | 14 +++++++ .../data/LoanTransactionEnumData.java | 13 ------ .../portfolio/loanaccount/domain/Loan.java | 2 - .../domain/LoanAccountDomainService.java | 2 +- .../domain/LoanAccountDomainServiceJpa.java | 8 ++-- .../loanaccount/domain/LoanTransaction.java | 13 +++--- .../LoanChargeApiJsonValidator.java | 8 +++- .../LoanChargeWritePlatformServiceImpl.java | 40 ++++++++++++++----- .../service/LoanReadPlatformServiceImpl.java | 25 ++++++------ ...WritePlatformServiceJpaRepositoryImpl.java | 21 ++++++---- .../paymentdetail/domain/PaymentDetail.java | 1 + .../LoanDelinquencyDomainServiceTest.java | 2 +- .../ClientLoanIntegrationTest.java | 8 ++-- ...tCreditRefundPayoutWithChargebackTest.java | 8 +++- 14 files changed, 102 insertions(+), 63 deletions(-) diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanChargesApiResourceSwagger.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanChargesApiResourceSwagger.java index 17ee409a3..d222ff72d 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanChargesApiResourceSwagger.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoanChargesApiResourceSwagger.java @@ -261,6 +261,20 @@ final class LoanChargesApiResourceSwagger { public Double amount; @Schema(example = "786444UUUYYH7") public String externalId; + @Schema(example = "An optional note") + public String note; + @Schema(example = "3") + public Long paymentTypeId; + @Schema(example = "acc123") + public String accountNumber; + @Schema(example = "che123") + public String checkNumber; + @Schema(example = "rou123") + public String routingCode; + @Schema(example = "rec123") + public String receiptNumber; + @Schema(example = "ban123") + public String bankNumber; } @Schema(description = "PostLoansLoanIdChargesChargeIdResponse") diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java index e11dcb6ea..e86183190 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java @@ -83,19 +83,6 @@ public class LoanTransactionEnumData { this.chargeAdjustment = Long.valueOf(26).equals(this.id); } - /** - * Returns true if the transaction involves either a payment (disbursement) or a receipt (repayments, repayments - * during disbursement etc) - * - * @return - */ - public boolean isPaymentOrReceipt() { - if (isDisbursement() || isRepaymentType() || isRepaymentAtDisbursement() || isRecoveryRepayment()) { - return true; - } - return false; - } - public boolean isRepaymentType() { if (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || isGoodwillCredit() || isChargeRefund() || isChargeAdjustment()) { diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java index 3e443586c..497e2c441 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java @@ -6272,8 +6272,6 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom { public void handleChargebackTransaction(final LoanTransaction chargebackTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine) { - chargebackTransaction.updateLoan(this); - if (!chargebackTransaction.isChargeback()) { final String errorMessage = "A transaction of type chargeback was expected but not received."; throw new InvalidLoanTransactionTypeException("transaction", "is.not.a.chargeback.transaction", errorMessage); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java index d378ffc2c..e10c3a841 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainService.java @@ -97,5 +97,5 @@ public interface LoanAccountDomainService { void recalculateAccruals(Loan loan, boolean isInterestCalcualtionHappened); LoanTransaction creditBalanceRefund(Loan loan, LocalDate transactionDate, BigDecimal transactionAmount, String noteText, - ExternalId externalId); + ExternalId externalId, PaymentDetail paymentDetail); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 114040a0c..7fadb8e01 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -632,19 +632,19 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { @Override public LoanTransaction creditBalanceRefund(final Loan loan, final LocalDate transactionDate, final BigDecimal transactionAmount, - final String noteText, final ExternalId externalId) { + final String noteText, final ExternalId externalId, PaymentDetail paymentDetail) { businessEventNotifierService.notifyPreBusinessEvent(new LoanCreditBalanceRefundPreBusinessEvent(loan)); final List existingTransactionIds = new ArrayList<>(); final List existingReversedTransactionIds = new ArrayList<>(); final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount); - final LoanTransaction newCreditBalanceRefundTransaction = LoanTransaction.creditBalanceRefund(loan, loan.getOffice(), refundAmount, - transactionDate, externalId); + LoanTransaction newCreditBalanceRefundTransaction = LoanTransaction.creditBalanceRefund(loan, loan.getOffice(), refundAmount, + transactionDate, externalId, paymentDetail); loan.creditBalanceRefund(newCreditBalanceRefundTransaction, defaultLoanLifecycleStateMachine, existingTransactionIds, existingReversedTransactionIds); - this.loanTransactionRepository.saveAndFlush(newCreditBalanceRefundTransaction); + newCreditBalanceRefundTransaction = this.loanTransactionRepository.saveAndFlush(newCreditBalanceRefundTransaction); if (StringUtils.isNotBlank(noteText)) { final Note note = Note.loanTransactionNote(loan, newCreditBalanceRefundTransaction, noteText); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java index 2ae376090..3faf4c9ee 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java @@ -159,9 +159,9 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom { return new LoanTransaction(null, office, LoanTransactionType.REPAYMENT, paymentDetail, amount.getAmount(), paymentDate, externalId); } - public static LoanTransaction chargeback(final Office office, final Money amount, final PaymentDetail paymentDetail, + public static LoanTransaction chargeback(final Loan loan, final Money amount, final PaymentDetail paymentDetail, final LocalDate paymentDate, final ExternalId externalId) { - LoanTransaction loanTransaction = new LoanTransaction(null, office, LoanTransactionType.CHARGEBACK, paymentDetail, + LoanTransaction loanTransaction = new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGEBACK, paymentDetail, amount.getAmount(), paymentDate, externalId); loanTransaction.principalPortion = amount.getAmount(); return loanTransaction; @@ -175,8 +175,9 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom { } public static LoanTransaction chargeAdjustment(final Loan loan, final BigDecimal amount, final LocalDate transactionDate, - final ExternalId externalId) { - return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_ADJUSTMENT, amount, transactionDate, externalId); + final ExternalId externalId, PaymentDetail paymentDetail) { + return new LoanTransaction(loan, loan.getOffice(), LoanTransactionType.CHARGE_ADJUSTMENT, paymentDetail, amount, transactionDate, + externalId); } public void setLoanTransactionToRepaymentScheduleMappings(final Integer installmentId, final BigDecimal chargePerInstallment) { @@ -290,9 +291,9 @@ public class LoanTransaction extends AbstractAuditableWithUTCDateTimeCustom { } public static LoanTransaction creditBalanceRefund(final Loan loan, final Office office, final Money amount, final LocalDate paymentDate, - final ExternalId externalId) { + final ExternalId externalId, PaymentDetail paymentDetail) { return new LoanTransaction(loan, office, LoanTransactionType.CREDIT_BALANCE_REFUND.getValue(), paymentDate, amount.getAmount(), - null, null, null, null, amount.getAmount(), false, null, externalId); + null, null, null, null, amount.getAmount(), false, paymentDetail, externalId); } public static LoanTransaction refundForActiveLoan(final Office office, final Money amount, final PaymentDetail paymentDetail, diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanChargeApiJsonValidator.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanChargeApiJsonValidator.java index 2de7cb129..f9149a9e0 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanChargeApiJsonValidator.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/serialization/LoanChargeApiJsonValidator.java @@ -184,13 +184,14 @@ public final class LoanChargeApiJsonValidator { throwExceptionIfValidationWarningsExist(dataValidationErrors); } - public void validateLoanAdjustmentRequest(final Long loanId, final Long loanChargeId, final String json) { + public void validateLoanChargeAdjustmentRequest(final Long loanId, final Long loanChargeId, final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } - Set transactionParameters = new HashSet<>(List.of("amount", "externalId", "locale")); + Set transactionParameters = new HashSet<>(List.of("amount", "externalId", "locale", "paymentTypeId", "accountNumber", + "checkNumber", "routingCode", "receiptNumber", "bankNumber", "note")); final Type typeOfMap = new TypeToken>() { @@ -208,6 +209,9 @@ public final class LoanChargeApiJsonValidator { baseDataValidator.reset().parameter("loanId").value(loanId).notNull().positiveAmount(); baseDataValidator.reset().parameter("loanChargeId").value(loanChargeId).notNull().positiveAmount(); + final String note = this.fromApiJsonHelper.extractStringNamed("note", element); + baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000); + throwExceptionIfValidationWarningsExist(dataValidationErrors); } diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java index 493ec971d..bd4fbb614 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanChargeWritePlatformServiceImpl.java @@ -123,6 +123,10 @@ import org.apache.fineract.portfolio.loanaccount.serialization.LoanChargeApiJson import org.apache.fineract.portfolio.loanproduct.data.LoanOverdueDTO; import org.apache.fineract.portfolio.loanproduct.exception.InvalidCurrencyException; import org.apache.fineract.portfolio.loanproduct.exception.LinkedAccountRequiredException; +import org.apache.fineract.portfolio.note.domain.Note; +import org.apache.fineract.portfolio.note.domain.NoteRepository; +import org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail; +import org.apache.fineract.portfolio.paymentdetail.service.PaymentDetailWritePlatformService; import org.apache.fineract.portfolio.savings.domain.SavingsAccount; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -154,6 +158,8 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo private final AccountTransferDetailRepository accountTransferDetailRepository; private final LoanChargeAssembler loanChargeAssembler; private final ReplayedTransactionBusinessEventService replayedTransactionBusinessEventService; + private final PaymentDetailWritePlatformService paymentDetailWritePlatformService; + private final NoteRepository noteRepository; private static boolean isPartOfThisInstallment(LoanCharge loanCharge, LoanRepaymentScheduleInstallment e) { return e.getFromDate().isBefore(loanCharge.getDueDate()) && !loanCharge.getDueDate().isAfter(e.getDueDate()); @@ -640,7 +646,7 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo @Transactional @Override public CommandProcessingResult adjustmentForLoanCharge(Long loanId, Long loanChargeId, JsonCommand command) { - this.loanChargeApiJsonValidator.validateLoanAdjustmentRequest(loanId, loanChargeId, command.json()); + this.loanChargeApiJsonValidator.validateLoanChargeAdjustmentRequest(loanId, loanChargeId, command.json()); final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId); final LocalDate transactionDate = DateUtils.getBusinessLocalDate(); @@ -648,12 +654,22 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo final ExternalId externalId = externalIdFactory.createFromCommand(command, "externalId"); final String locale = command.locale(); + Map changes = new HashMap<>(); + changes.put("externalId", externalId); + changes.put("amount", transactionAmount); + changes.put("transactionDate", transactionDate); + changes.put("locale", locale); + loanChargeAdjustmentEntranceValidation(loanCharge, transactionAmount); final Loan loan = loanAssembler.assembleFrom(loanId); final CommandProcessingResultBuilder commandProcessingResultBuilder = new CommandProcessingResultBuilder(); - - LoanTransaction loanTransaction = applyChargeAdjustment(loan, loanCharge, transactionAmount, transactionDate, externalId); + PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createPaymentDetail(command, changes); + if (paymentDetail != null) { + paymentDetail = this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); + } + LoanTransaction loanTransaction = applyChargeAdjustment(loan, loanCharge, transactionAmount, transactionDate, externalId, + paymentDetail); // Update loan transaction on repayment. if (AccountType.fromInt(loan.getLoanType()).isIndividualAccount()) { @@ -671,13 +687,17 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo } this.loanAccountDomainService.updateLoanCollateralTransaction(loanCollateralManagements); } + + final String noteText = command.stringValueOfParameterNamed("note"); + if (StringUtils.isNotBlank(noteText)) { + final Note note = Note.loanNote(loan, noteText); + changes.put("note", noteText); + this.noteRepository.save(note); + } + businessEventNotifierService.notifyPostBusinessEvent(new LoanBalanceChangedBusinessEvent(loan)); businessEventNotifierService.notifyPostBusinessEvent(new LoanChargeAdjustmentPostBusinessEvent(loanTransaction)); - Map changes = new HashMap<>(); - changes.put("externalId", externalId); - changes.put("amount", transactionAmount); - changes.put("transactionDate", transactionDate); - changes.put("locale", locale); + return commandProcessingResultBuilder.withCommandId(command.commandId()) // .withLoanId(loanId) // .withEntityId(loanChargeId) // @@ -753,13 +773,13 @@ public class LoanChargeWritePlatformServiceImpl implements LoanChargeWritePlatfo } private LoanTransaction applyChargeAdjustment(final Loan loan, final LoanCharge loanCharge, final BigDecimal transactionAmount, - final LocalDate transactionDate, final ExternalId txnExternalId) { + final LocalDate transactionDate, final ExternalId txnExternalId, PaymentDetail paymentDetail) { businessEventNotifierService.notifyPreBusinessEvent(new LoanChargeAdjustmentPreBusinessEvent(loan)); final List existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds()); final List existingReversedTransactionIds = new ArrayList<>(loan.findExistingReversedTransactionIds()); LoanTransaction loanChargeAdjustmentTransaction = LoanTransaction.chargeAdjustment(loan, transactionAmount, transactionDate, - txnExternalId); + txnExternalId, paymentDetail); LoanTransactionRelation loanTransactionRelation = LoanTransactionRelation.linkToCharge(loanChargeAdjustmentTransaction, loanCharge, LoanTransactionRelationTypeEnum.CHARGE_ADJUSTMENT); loanChargeAdjustmentTransaction.getLoanTransactionRelations().add(loanTransactionRelation); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java index 7b587c043..0cf51c28e 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanReadPlatformServiceImpl.java @@ -1386,20 +1386,19 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService { PaymentDetailData paymentDetailData = null; - if (transactionType.isPaymentOrReceipt()) { - final Long paymentTypeId = JdbcSupport.getLong(rs, "paymentType"); - if (paymentTypeId != null) { - final String typeName = rs.getString("paymentTypeName"); - final PaymentTypeData paymentType = PaymentTypeData.instance(paymentTypeId, typeName); - final String accountNumber = rs.getString("accountNumber"); - final String checkNumber = rs.getString("checkNumber"); - final String routingCode = rs.getString("routingCode"); - final String receiptNumber = rs.getString("receiptNumber"); - final String bankNumber = rs.getString("bankNumber"); - paymentDetailData = new PaymentDetailData(id, paymentType, accountNumber, checkNumber, routingCode, receiptNumber, - bankNumber); - } + final Long paymentTypeId = JdbcSupport.getLong(rs, "paymentType"); + if (paymentTypeId != null) { + final String typeName = rs.getString("paymentTypeName"); + final PaymentTypeData paymentType = PaymentTypeData.instance(paymentTypeId, typeName); + final String accountNumber = rs.getString("accountNumber"); + final String checkNumber = rs.getString("checkNumber"); + final String routingCode = rs.getString("routingCode"); + final String receiptNumber = rs.getString("receiptNumber"); + final String bankNumber = rs.getString("bankNumber"); + paymentDetailData = new PaymentDetailData(id, paymentType, accountNumber, checkNumber, routingCode, receiptNumber, + bankNumber); } + final LocalDate date = JdbcSupport.getLocalDate(rs, "date"); final LocalDate submittedOnDate = JdbcSupport.getLocalDate(rs, "submittedOnDate"); final BigDecimal totalAmount = JdbcSupport.getBigDecimalDefaultToZeroIfNull(rs, "total"); diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index a6a358fdb..53400439a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -1256,20 +1256,21 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf changes.put("paymentTypeId", command.longValueOfParameterNamed(LoanApiConstants.PAYMENT_TYPE_PARAMNAME)); final Money transactionAmountAsMoney = Money.of(loan.getCurrency(), transactionAmount); - final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createPaymentDetail(command, changes); - LoanTransaction newTransaction = LoanTransaction.chargeback(loan.getOffice(), transactionAmountAsMoney, paymentDetail, - transactionDate, txnExternalId); + PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createPaymentDetail(command, changes); + if (paymentDetail != null) { + paymentDetail = this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); + } + LoanTransaction newTransaction = LoanTransaction.chargeback(loan, transactionAmountAsMoney, paymentDetail, transactionDate, + txnExternalId); validateLoanTransactionAmountChargeBack(loanTransaction, newTransaction); - this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); - // Store the Loan Transaction Relation LoanTransactionRelation loanTransactionRelation = LoanTransactionRelation.linkToTransaction(loanTransaction, newTransaction, LoanTransactionRelationTypeEnum.CHARGEBACK); this.loanTransactionRelationRepository.save(loanTransactionRelation); - this.loanTransactionRepository.save(newTransaction); + newTransaction = this.loanTransactionRepository.saveAndFlush(newTransaction); loan.handleChargebackTransaction(newTransaction, defaultLoanLifecycleStateMachine); @@ -2439,9 +2440,15 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf if (!externalId.isEmpty()) { changes.put(LoanApiConstants.externalIdParameterName, externalId); } + changes.put("paymentTypeId", command.longValueOfParameterNamed(LoanApiConstants.PAYMENT_TYPE_PARAMNAME)); + + PaymentDetail paymentDetail = this.paymentDetailWritePlatformService.createPaymentDetail(command, changes); + if (paymentDetail != null) { + paymentDetail = this.paymentDetailWritePlatformService.persistPaymentDetail(paymentDetail); + } final LoanTransaction loanTransaction = this.loanAccountDomainService.creditBalanceRefund(loan, transactionDate, transactionAmount, - noteText, externalId); + noteText, externalId, paymentDetail); return new CommandProcessingResultBuilder() // .withEntityId(loanTransaction.getId()) // diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java index b737c7631..f110c6841 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/paymentdetail/domain/PaymentDetail.java @@ -82,6 +82,7 @@ public final class PaymentDetail extends AbstractPersistableCustom { if (StringUtils.isNotBlank(bankNumber)) { changes.put(PaymentDetailConstants.bankNumberParamName, bankNumber); } + changes.put("paymentTypeId", paymentType.getId()); final PaymentDetail paymentDetail = new PaymentDetail(paymentType, accountNumber, checkNumber, routingCode, receiptNumber, bankNumber); return paymentDetail; diff --git a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java index ef48eb58a..09dfeb1fe 100644 --- a/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java +++ b/fineract-provider/src/test/java/org/apache/fineract/portfolio/deliquency/LoanDelinquencyDomainServiceTest.java @@ -163,7 +163,7 @@ public class LoanDelinquencyDomainServiceTest { final Money zeroMoney = Money.zero(currency); LoanRepaymentScheduleInstallment installment = new LoanRepaymentScheduleInstallment(loan, 1, fromDate, dueDate, principal, zeroAmount, zeroAmount, zeroAmount, false, new HashSet<>(), zeroAmount); - LoanTransaction loanTransaction = LoanTransaction.chargeback(null, Money.of(currency, principal), paymentDetail, transactionDate, + LoanTransaction loanTransaction = LoanTransaction.chargeback(loan, Money.of(currency, principal), paymentDetail, transactionDate, null); installment.getLoanTransactionToRepaymentScheduleMappings().add(LoanTransactionToRepaymentScheduleMapping .createFrom(loanTransaction, installment, zeroMoney, zeroMoney, zeroMoney, zeroMoney)); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java index 3aa41f676..4745dee28 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ClientLoanIntegrationTest.java @@ -6169,7 +6169,8 @@ public class ClientLoanIntegrationTest { String externalId = UUID.randomUUID().toString(); PostLoansLoanIdChargesChargeIdResponse chargeAdjustmentResponse = this.loanTransactionHelper.chargeAdjustment((long) loanID, - (long) penalty1LoanChargeId, new PostLoansLoanIdChargesChargeIdRequest().amount(10.0).externalId(externalId)); + (long) penalty1LoanChargeId, + new PostLoansLoanIdChargesChargeIdRequest().amount(10.0).externalId(externalId).paymentTypeId(1L)); loanSchedule = this.loanTransactionHelper.getLoanRepaymentSchedule(requestSpec, responseSpec, loanID); assertEquals(2, loanSchedule.size()); @@ -6196,6 +6197,7 @@ public class ClientLoanIntegrationTest { assertEquals(chargeAdjustmentResponse.getSubResourceId(), transactionRelation.getFromLoanTransaction()); assertEquals((long) penalty1LoanChargeId, transactionRelation.getToLoanCharge()); assertEquals("CHARGE_ADJUSTMENT", transactionRelation.getRelationType()); + assertEquals(1L, chargeAdjustmentTransaction.getPaymentDetailData().getPaymentType().getId()); PostLoansLoanIdTransactionsResponse repaymentResult = loanTransactionHelper.makeLoanRepayment((long) loanID, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("06 September 2022").locale("en") @@ -7177,7 +7179,7 @@ public class ClientLoanIntegrationTest { assertTrue(loanDetails.getStatus().getOverpaid()); this.loanTransactionHelper.makeCreditBalanceRefund((long) loanID, new PostLoansLoanIdTransactionsRequest() - .transactionAmount(200.0).transactionDate("10 October 2022").dateFormat("dd MMMM yyyy").locale("en")); + .transactionAmount(200.0).transactionDate("10 October 2022").dateFormat("dd MMMM yyyy").locale("en").paymentTypeId(1L)); loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanID); assertTrue(loanDetails.getStatus().getClosedObligationsMet()); @@ -7198,7 +7200,7 @@ public class ClientLoanIntegrationTest { assertEquals(200.0, loanDetails.getTransactions().get(3).getOverpaymentPortion()); assertEquals(LocalDate.of(2022, 10, 10), loanDetails.getTransactions().get(3).getDate()); assertEquals(0.0, loanDetails.getTransactions().get(3).getOutstandingLoanBalance()); - + assertEquals(1L, loanDetails.getTransactions().get(3).getPaymentDetailData().getPaymentType().getId()); GetJournalEntriesTransactionIdResponse journalEntriesForTransaction = journalEntryHelper .getJournalEntries("L" + loanDetails.getTransactions().get(3).getId()); List journalItems = journalEntriesForTransaction.getPageItems(); diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountCreditRefundPayoutWithChargebackTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountCreditRefundPayoutWithChargebackTest.java index d619b9d3e..1e266b071 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountCreditRefundPayoutWithChargebackTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanAccountCreditRefundPayoutWithChargebackTest.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.UUID; import org.apache.fineract.client.models.GetDelinquencyBucketsResponse; import org.apache.fineract.client.models.GetLoanProductsProductIdResponse; +import org.apache.fineract.client.models.GetLoansLoanIdTransactionsTransactionIdResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse; import org.apache.fineract.client.models.PostLoansLoanIdTransactionsTransactionIdRequest; @@ -91,9 +92,14 @@ public class LoanAccountCreditRefundPayoutWithChargebackTest { .transactionAmount(1000.0)); // Chargeback full repayment amount to add to principal balance - loanTransactionHelper.chargebackLoanTransaction(loanExternalIdStr, repaymentTransaction_1.getResourceId(), + PostLoansLoanIdTransactionsResponse chargebackResponse = loanTransactionHelper.chargebackLoanTransaction(loanExternalIdStr, + repaymentTransaction_1.getResourceId(), new PostLoansLoanIdTransactionsTransactionIdRequest().locale("en").transactionAmount(1000.0).paymentTypeId(1L)); + GetLoansLoanIdTransactionsTransactionIdResponse chargebackTransactionResponse = loanTransactionHelper + .getLoanTransactionDetails(chargebackResponse.getLoanId(), chargebackResponse.getResourceId()); + assertEquals(1L, chargebackTransactionResponse.getPaymentDetailData().getPaymentType().getId()); + // Verify Goodwill Credit can be created with full amount final PostLoansLoanIdTransactionsResponse goodwillCredit_1 = loanTransactionHelper.makeGoodwillCredit((long) loanId, new PostLoansLoanIdTransactionsRequest().dateFormat("dd MMMM yyyy").transactionDate("8 September 2022").locale("en")