This is an automated email from the ASF dual-hosted git repository.

arnold pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git


The following commit(s) were added to refs/heads/develop by this push:
     new ef2c44676 FINERACT-1958-Autopayment-downpayment
ef2c44676 is described below

commit ef2c4467618bb4971013b87a0ea0c8fa17436039
Author: Ruchi Dhamankar <[email protected]>
AuthorDate: Thu Aug 10 13:15:15 2023 +0530

    FINERACT-1958-Autopayment-downpayment
---
 .../fineract/interoperation/util/MathUtil.java     |  10 +
 .../loanaccount/data/LoanTransactionEnumData.java  |   6 +-
 .../portfolio/loanaccount/domain/Loan.java         |  39 ++-
 .../loanaccount/domain/LoanTransaction.java        |  12 +-
 .../loanaccount/domain/LoanTransactionType.java    |  10 +-
 .../loanschedule/domain/LoanApplicationTerms.java  |  17 +-
 .../loanproduct/LoanProductConstants.java          |   1 +
 .../portfolio/loanproduct/domain/LoanProduct.java  |  17 +-
 .../domain/LoanProductRelatedDetail.java           |  20 +-
 .../loanproduct/service/LoanEnumerations.java      |   2 +
 .../tenant/module/loan/module-changelog-master.xml |   1 +
 ..._auto_repayment_down_payment_configuration.xml} |  21 +-
 .../loanaccount/api/LoansApiResourceSwagger.java   |   2 +
 .../loanaccount/data/LoanAccountData.java          |  10 +-
 .../service/LoanScheduleAssembler.java             |   4 +-
 .../service/LoanReadPlatformServiceImpl.java       |   6 +-
 .../LoanWritePlatformServiceJpaRepositoryImpl.java |   3 +-
 .../loanproduct/api/LoanProductsApiResource.java   |   4 +-
 .../api/LoanProductsApiResourceSwagger.java        |   6 +
 .../loanproduct/data/LoanProductData.java          |  17 +-
 .../serialization/LoanProductDataValidator.java    |  23 +-
 .../LoanProductReadPlatformServiceImpl.java        |   6 +-
 ...oanProductWithDownPaymentConfigurationTest.java | 293 +++++++++++++++++++--
 .../common/loans/LoanProductTestBuilder.java       |   7 +-
 24 files changed, 480 insertions(+), 57 deletions(-)

diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/interoperation/util/MathUtil.java
 
b/fineract-loan/src/main/java/org/apache/fineract/interoperation/util/MathUtil.java
index b3c822c64..f1550b26b 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/interoperation/util/MathUtil.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/interoperation/util/MathUtil.java
@@ -424,4 +424,14 @@ public final class MathUtil {
     public static Money min(Money first, Money second, Money third, boolean 
notNull) {
         return min(min(first, second, notNull), third, notNull);
     }
+
+    public static BigDecimal percentageOf(final BigDecimal value, final 
BigDecimal percentage, final int precision) {
+        BigDecimal percentageOf = BigDecimal.ZERO;
+        if (isGreaterThanZero(value)) {
+            final MathContext mc = new MathContext(precision, 
MoneyHelper.getRoundingMode());
+            final BigDecimal multiplicand = 
percentage.divide(BigDecimal.valueOf(100L), mc);
+            percentageOf = value.multiply(multiplicand, mc);
+        }
+        return percentageOf;
+    }
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java
index 47ed70bf7..8d6db7a77 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanTransactionEnumData.java
@@ -54,6 +54,7 @@ public class LoanTransactionEnumData {
     private final boolean chargeAdjustment;
     private final boolean chargeback;
     private final boolean chargeoff;
+    private final boolean downPayment;
 
     public LoanTransactionEnumData(final Long id, final String code, final 
String value) {
         this.id = id;
@@ -83,11 +84,12 @@ public class LoanTransactionEnumData {
         this.chargeback = Long.valueOf(25).equals(this.id);
         this.chargeAdjustment = Long.valueOf(26).equals(this.id);
         this.chargeoff = Long.valueOf(27).equals(this.id);
+        this.downPayment = Long.valueOf(28).equals(this.id);
     }
 
     public boolean isRepaymentType() {
-        if (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || 
isGoodwillCredit() || isChargeRefund()
-                || isChargeAdjustment()) {
+        if (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() || 
isGoodwillCredit() || isChargeRefund() || isChargeAdjustment()
+                || isDownPayment()) {
             return true;
         }
         return false;
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
index 7d78c4a1a..facf6bb29 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/Loan.java
@@ -2954,6 +2954,42 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
     }
 
+    public void handleDownPayment(final BigDecimal disbursedAmount, final 
JsonCommand command,
+            final ScheduleGeneratorDTO scheduleGeneratorDTO) {
+        if (isAutoRepaymentForDownPaymentEnabled()) {
+            LocalDate disbursedOn = 
command.localDateValueOfParameterNamed(ACTUAL_DISBURSEMENT_DATE);
+            BigDecimal disbursedAmountPercentageForDownPayment = 
this.loanRepaymentScheduleDetail
+                    .getDisbursedAmountPercentageForDownPayment();
+            ExternalId externalId = ExternalId.empty();
+            if 
(TemporaryConfigurationServiceContainer.isExternalIdAutoGenerationEnabled()) {
+                externalId = ExternalId.generate();
+            }
+            Money downPaymentMoney = Money.of(getCurrency(),
+                    MathUtil.percentageOf(disbursedAmount, 
disbursedAmountPercentageForDownPayment, 9));
+            LoanTransaction downPaymentTransaction = 
LoanTransaction.downPayment(getOffice(), downPaymentMoney, null, disbursedOn,
+                    externalId);
+            /*
+             * Currently mapping down payment transaction as repayment 
transaction to loan repayment schedule for
+             * consistency. Need to replace below logic for creating new 
installment for down payment and mapping.
+             */
+
+            LoanEvent event = LoanEvent.LOAN_REPAYMENT_OR_WAIVER;
+            validateRepaymentTypeAccountStatus(downPaymentTransaction, event);
+            HolidayDetailDTO holidayDetailDTO = 
scheduleGeneratorDTO.getHolidayDetailDTO();
+            
validateRepaymentDateIsOnHoliday(downPaymentTransaction.getTransactionDate(), 
holidayDetailDTO.isAllowTransactionsOnHoliday(),
+                    holidayDetailDTO.getHolidays());
+            
validateRepaymentDateIsOnNonWorkingDay(downPaymentTransaction.getTransactionDate(),
 holidayDetailDTO.getWorkingDays(),
+                    holidayDetailDTO.isAllowTransactionsOnNonWorkingDay());
+
+            
handleRepaymentOrRecoveryOrWaiverTransaction(downPaymentTransaction, 
loanLifecycleStateMachine, null, scheduleGeneratorDTO);
+        }
+    }
+
+    private boolean isAutoRepaymentForDownPaymentEnabled() {
+        return this.loanRepaymentScheduleDetail.isEnableDownPayment()
+                && 
this.loanRepaymentScheduleDetail.isEnableAutoRepaymentForDownPayment();
+    }
+
     public LoanTransaction handlePayDisbursementTransaction(final Long 
chargeId, final LoanTransaction chargesPayment,
             final List<Long> existingTransactionIds, final List<Long> 
existingReversedTransactionIds) {
         existingTransactionIds.addAll(findExistingTransactionIds());
@@ -3132,7 +3168,8 @@ public class Loan extends 
AbstractAuditableWithUTCDateTimeCustom {
 
     private void validateRepaymentTypeAccountStatus(LoanTransaction 
repaymentTransaction, LoanEvent event) {
         if (repaymentTransaction.isGoodwillCredit() || 
repaymentTransaction.isMerchantIssuedRefund()
-                || repaymentTransaction.isPayoutRefund() || 
repaymentTransaction.isChargeRefund() || repaymentTransaction.isRepayment()) {
+                || repaymentTransaction.isPayoutRefund() || 
repaymentTransaction.isChargeRefund() || repaymentTransaction.isRepayment()
+                || repaymentTransaction.isDownPayment()) {
 
             if (!(isOpen() || isClosedObligationsMet() || isOverPaid())) {
                 final List<ApiParameterError> dataValidationErrors = new 
ArrayList<>();
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
index 9a2116c56..c7b1afd7f 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransaction.java
@@ -180,6 +180,12 @@ public class LoanTransaction extends 
AbstractAuditableWithUTCDateTimeCustom {
                 externalId);
     }
 
+    public static LoanTransaction downPayment(final Office office, final Money 
amount, final PaymentDetail paymentDetail,
+            final LocalDate paymentDate, final ExternalId externalId) {
+        return new LoanTransaction(null, office, 
LoanTransactionType.DOWN_PAYMENT, paymentDetail, amount.getAmount(), 
paymentDate,
+                externalId);
+    }
+
     public void setLoanTransactionToRepaymentScheduleMappings(final Integer 
installmentId, final BigDecimal chargePerInstallment) {
         for (LoanTransactionToRepaymentScheduleMapping 
loanTransactionToRepaymentScheduleMapping : 
this.loanTransactionToRepaymentScheduleMappings) {
             final LoanRepaymentScheduleInstallment 
loanRepaymentScheduleInstallment = loanTransactionToRepaymentScheduleMapping
@@ -558,7 +564,7 @@ public class LoanTransaction extends 
AbstractAuditableWithUTCDateTimeCustom {
 
     public boolean isRepaymentLikeType() {
         return isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() 
|| isGoodwillCredit() || isChargeRefund()
-                || isChargeAdjustment();
+                || isChargeAdjustment() || isDownPayment();
     }
 
     public boolean isTypeAllowedForChargeback() {
@@ -573,6 +579,10 @@ public class LoanTransaction extends 
AbstractAuditableWithUTCDateTimeCustom {
         return LoanTransactionType.MERCHANT_ISSUED_REFUND.equals(getTypeOf()) 
&& isNotReversed();
     }
 
+    public boolean isDownPayment() {
+        return LoanTransactionType.DOWN_PAYMENT.equals(getTypeOf()) && 
isNotReversed();
+    }
+
     public boolean isPayoutRefund() {
         return LoanTransactionType.PAYOUT_REFUND.equals(getTypeOf()) && 
isNotReversed();
     }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java
index 5ceaf0278..ef5bd3f66 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/domain/LoanTransactionType.java
@@ -59,7 +59,8 @@ public enum LoanTransactionType {
     CHARGE_REFUND(24, "loanTransactionType.chargeRefund"), //
     CHARGEBACK(25, "loanTransactionType.chargeback"), //
     CHARGE_ADJUSTMENT(26, "loanTransactionType.chargeAdjustment"), //
-    CHARGE_OFF(27, "loanTransactionType.chargeOff");
+    CHARGE_OFF(27, "loanTransactionType.chargeOff"), //
+    DOWN_PAYMENT(28, "loanTransactionType.downPayment");
 
     private final Integer value;
     private final String code;
@@ -102,6 +103,7 @@ public enum LoanTransactionType {
             case 25 -> LoanTransactionType.CHARGEBACK;
             case 26 -> LoanTransactionType.CHARGE_ADJUSTMENT;
             case 27 -> LoanTransactionType.CHARGE_OFF;
+            case 28 -> LoanTransactionType.DOWN_PAYMENT;
             default -> LoanTransactionType.INVALID;
         };
     }
@@ -143,7 +145,7 @@ public enum LoanTransactionType {
     }
 
     public boolean isRepaymentType() {
-        return (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() 
|| isGoodwillCredit() || isChargeRefund());
+        return (isRepayment() || isMerchantIssuedRefund() || isPayoutRefund() 
|| isGoodwillCredit() || isChargeRefund() || isDownPayment());
     }
 
     public boolean isRecoveryRepayment() {
@@ -189,4 +191,8 @@ public enum LoanTransactionType {
     public boolean isChargeOff() {
         return this.equals(LoanTransactionType.CHARGE_OFF);
     }
+
+    public boolean isDownPayment() {
+        return this.equals(LoanTransactionType.DOWN_PAYMENT);
+    }
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
index 0a7243e5c..b40103736 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/domain/LoanApplicationTerms.java
@@ -209,6 +209,7 @@ public final class LoanApplicationTerms {
     private LocalDate newScheduledDueDateStart;
     private boolean isDownPaymentEnabled;
     private BigDecimal disbursedAmountPercentageForDownPayment;
+    private boolean isAutoRepaymentForDownPaymentEnabled;
 
     public static LoanApplicationTerms assembleFrom(final ApplicationCurrency 
currency, final Integer loanTermFrequency,
             final PeriodFrequencyType loanTermPeriodFrequencyType, final 
Integer numberOfRepayments, final Integer repaymentEvery,
@@ -233,7 +234,8 @@ public final class LoanApplicationTerms {
             boolean isSkipRepaymentOnFirstDayOfMonth, final HolidayDetailDTO 
holidayDetailDTO, final boolean allowCompoundingOnEod,
             final boolean isEqualAmortization, final boolean 
isInterestToBeRecoveredFirstWhenGreaterThanEMI,
             final BigDecimal fixedPrincipalPercentagePerInstallment, final 
boolean isPrincipalCompoundingDisabledForOverdueLoans,
-            final Boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment) {
+            final Boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment,
+            final Boolean isAutoRepaymentForDownPaymentEnabled) {
 
         final LoanRescheduleStrategyMethod rescheduleStrategyMethod = null;
         final CalendarHistoryDataWrapper calendarHistoryDataWrapper = null;
@@ -250,7 +252,8 @@ public final class LoanApplicationTerms {
                 calendarHistoryDataWrapper, 
isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays,
                 isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO, 
allowCompoundingOnEod, isEqualAmortization, false,
                 isInterestToBeRecoveredFirstWhenGreaterThanEMI, 
fixedPrincipalPercentagePerInstallment,
-                isPrincipalCompoundingDisabledForOverdueLoans, 
enableDownPayment, disbursedAmountPercentageForDownPayment);
+                isPrincipalCompoundingDisabledForOverdueLoans, 
enableDownPayment, disbursedAmountPercentageForDownPayment,
+                isAutoRepaymentForDownPaymentEnabled);
 
     }
 
@@ -298,8 +301,10 @@ public final class LoanApplicationTerms {
         final boolean isEqualAmortization = 
loanProductRelatedDetail.isEqualAmortization();
         final boolean isDownPaymentEnabled = 
loanProductRelatedDetail.isEnableDownPayment();
         BigDecimal disbursedAmountPercentageForDownPayment = null;
+        boolean isAutoRepaymentForDownPaymentEnabled = false;
         if (isDownPaymentEnabled) {
             disbursedAmountPercentageForDownPayment = 
loanProductRelatedDetail.getDisbursedAmountPercentageForDownPayment();
+            isAutoRepaymentForDownPaymentEnabled = 
loanProductRelatedDetail.isEnableAutoRepaymentForDownPayment();
         }
         return new LoanApplicationTerms(applicationCurrency, 
loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
                 repaymentEvery, repaymentPeriodFrequencyType, ((nthDay != 
null) ? nthDay.getValue() : null), dayOfWeek, amortizationMethod,
@@ -315,7 +320,8 @@ public final class LoanApplicationTerms {
                 isInterestChargedFromDateSameAsDisbursalDateEnabled, 
numberOfDays, isSkipRepaymentOnFirstDayOfMonth, holidayDetailDTO,
                 allowCompoundingOnEod, isEqualAmortization, 
isFirstRepaymentDateAllowedOnHoliday,
                 isInterestToBeRecoveredFirstWhenGreaterThanEMI, 
fixedPrincipalPercentagePerInstallment,
-                isPrincipalCompoundingDisabledForOverdueLoans, 
isDownPaymentEnabled, disbursedAmountPercentageForDownPayment);
+                isPrincipalCompoundingDisabledForOverdueLoans, 
isDownPaymentEnabled, disbursedAmountPercentageForDownPayment,
+                isAutoRepaymentForDownPaymentEnabled);
     }
 
     private LoanApplicationTerms(final ApplicationCurrency currency, final 
Integer loanTermFrequency,
@@ -342,7 +348,7 @@ public final class LoanApplicationTerms {
             final boolean allowCompoundingOnEod, final boolean 
isEqualAmortization, final boolean isFirstRepaymentDateAllowedOnHoliday,
             final boolean isInterestToBeRecoveredFirstWhenGreaterThanEMI, 
final BigDecimal fixedPrincipalPercentagePerInstallment,
             final boolean isPrincipalCompoundingDisabledForOverdueLoans, final 
boolean isDownPaymentEnabled,
-            final BigDecimal disbursedAmountPercentageForDownPayment) {
+            final BigDecimal disbursedAmountPercentageForDownPayment, final 
boolean isAutoRepaymentForDownPaymentEnabled) {
 
         this.currency = currency;
         this.loanTermFrequency = loanTermFrequency;
@@ -421,6 +427,7 @@ public final class LoanApplicationTerms {
         this.isPrincipalCompoundingDisabledForOverdueLoans = 
isPrincipalCompoundingDisabledForOverdueLoans;
         this.isDownPaymentEnabled = isDownPaymentEnabled;
         this.disbursedAmountPercentageForDownPayment = 
disbursedAmountPercentageForDownPayment;
+        this.isAutoRepaymentForDownPaymentEnabled = 
isAutoRepaymentForDownPaymentEnabled;
     }
 
     public Money adjustPrincipalIfLastRepaymentPeriod(final Money 
principalForPeriod, final Money totalCumulativePrincipalToDate,
@@ -1265,7 +1272,7 @@ public final class LoanApplicationTerms {
                 this.interestPaymentGrace, this.interestChargingGrace, 
this.amortizationMethod, this.inArrearsTolerance.getAmount(),
                 this.graceOnArrearsAgeing, this.daysInMonthType.getValue(), 
this.daysInYearType.getValue(),
                 this.interestRecalculationEnabled, this.isEqualAmortization, 
this.isDownPaymentEnabled,
-                this.disbursedAmountPercentageForDownPayment);
+                this.disbursedAmountPercentageForDownPayment, 
this.isAutoRepaymentForDownPaymentEnabled);
     }
 
     public Integer getLoanTermFrequency() {
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
index dd3a67710..0d6176b3d 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/LoanProductConstants.java
@@ -150,5 +150,6 @@ public interface LoanProductConstants {
     // down-payment related
     String ENABLE_DOWN_PAYMENT = "enableDownPayment";
     String DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT = 
"disbursedAmountPercentageForDownPayment";
+    String ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT = 
"enableAutoRepaymentForDownPayment";
 
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
index 178cd2abb..d0c7aabed 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProduct.java
@@ -388,6 +388,8 @@ public class LoanProduct extends AbstractPersistableCustom {
         final boolean enableDownPayment = 
command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ENABLE_DOWN_PAYMENT);
         final BigDecimal disbursedAmountPercentageDownPayment = command
                 
.bigDecimalValueOfParameterNamed(LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT);
+        final boolean enableAutoRepaymentForDownPayment = command
+                
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT);
 
         return new LoanProduct(fund, loanTransactionProcessingStrategy, name, 
shortName, description, currency, principal, minPrincipal,
                 maxPrincipal, interestRatePerPeriod, minInterestRatePerPeriod, 
maxInterestRatePerPeriod, interestFrequencyType,
@@ -405,7 +407,7 @@ public class LoanProduct extends AbstractPersistableCustom {
                 minimumGapBetweenInstallments, maximumGapBetweenInstallments, 
syncExpectedWithDisbursementDate, canUseForTopup,
                 isEqualAmortization, productRates, 
fixedPrincipalPercentagePerInstallment, disallowExpectedDisbursements,
                 allowApprovedDisbursedAmountsOverApplied, 
overAppliedCalculationType, overAppliedNumber, dueDaysForRepaymentEvent,
-                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment);
+                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment);
 
     }
 
@@ -617,7 +619,8 @@ public class LoanProduct extends AbstractPersistableCustom {
             final List<Rate> rates, final BigDecimal 
fixedPrincipalPercentagePerInstallment, final boolean 
disallowExpectedDisbursements,
             final boolean allowApprovedDisbursedAmountsOverApplied, final 
String overAppliedCalculationType,
             final Integer overAppliedNumber, final Integer 
dueDaysForRepaymentEvent, final Integer overDueDaysForRepaymentEvent,
-            final boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment) {
+            final boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment,
+            final boolean enableAutoRepaymentForDownPayment) {
         this.fund = fund;
         this.transactionProcessingStrategyCode = 
transactionProcessingStrategyCode;
         this.name = name.trim();
@@ -650,7 +653,8 @@ public class LoanProduct extends AbstractPersistableCustom {
                 considerPartialPeriodInterest, repayEvery, 
repaymentFrequencyType, defaultNumberOfInstallments, graceOnPrincipalPayment,
                 recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, 
graceOnInterestCharged, amortizationMethod,
                 inArrearsTolerance, graceOnArrearsAgeing, 
daysInMonthType.getValue(), daysInYearType.getValue(),
-                isInterestRecalculationEnabled, isEqualAmortization, 
enableDownPayment, disbursedAmountPercentageForDownPayment);
+                isInterestRecalculationEnabled, isEqualAmortization, 
enableDownPayment, disbursedAmountPercentageForDownPayment,
+                enableAutoRepaymentForDownPayment);
 
         
this.loanProductRelatedDetail.validateRepaymentPeriodWithGraceSettings();
 
@@ -1235,6 +1239,13 @@ public class LoanProduct extends 
AbstractPersistableCustom {
             
this.loanProductRelatedDetail.updateDisbursedAmountPercentageForDownPayment(newValue);
         }
 
+        if 
(command.isChangeInBooleanParameterNamed(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT,
+                
this.loanProductRelatedDetail.isEnableAutoRepaymentForDownPayment())) {
+            final boolean newValue = 
command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT);
+            
actualChanges.put(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT, 
newValue);
+            
this.loanProductRelatedDetail.updateEnableAutoRepaymentForDownPayment(newValue);
+        }
+
         return actualChanges;
     }
 
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
index d16c51b03..9b06c20d1 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/domain/LoanProductRelatedDetail.java
@@ -135,6 +135,9 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
     @Column(name = "disbursed_amount_percentage_for_down_payment", scale = 6, 
precision = 9)
     private BigDecimal disbursedAmountPercentageForDownPayment;
 
+    @Column(name = "enable_auto_repayment_for_down_payment", nullable = false)
+    private boolean enableAutoRepaymentForDownPayment;
+
     public static LoanProductRelatedDetail createFrom(final MonetaryCurrency 
currency, final BigDecimal principal,
             final BigDecimal nominalInterestRatePerPeriod, final 
PeriodFrequencyType interestRatePeriodFrequencyType,
             final BigDecimal nominalAnnualInterestRate, final InterestMethod 
interestMethod,
@@ -144,14 +147,15 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
             final Integer graceOnInterestPayment, final Integer 
graceOnInterestCharged, final AmortizationMethod amortizationMethod,
             final BigDecimal inArrearsTolerance, final Integer 
graceOnArrearsAgeing, final Integer daysInMonthType,
             final Integer daysInYearType, final boolean 
isInterestRecalculationEnabled, final boolean isEqualAmortization,
-            final boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment) {
+            final boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment,
+            final boolean enableAutoRepaymentForDownPayment) {
 
         return new LoanProductRelatedDetail(currency, principal, 
nominalInterestRatePerPeriod, interestRatePeriodFrequencyType,
                 nominalAnnualInterestRate, interestMethod, 
interestCalculationPeriodMethod, allowPartialPeriodInterestCalcualtion,
                 repaymentEvery, repaymentPeriodFrequencyType, 
numberOfRepayments, graceOnPrincipalPayment,
                 recurringMoratoriumOnPrincipalPeriods, graceOnInterestPayment, 
graceOnInterestCharged, amortizationMethod,
                 inArrearsTolerance, graceOnArrearsAgeing, daysInMonthType, 
daysInYearType, isInterestRecalculationEnabled,
-                isEqualAmortization, enableDownPayment, 
disbursedAmountPercentageForDownPayment);
+                isEqualAmortization, enableDownPayment, 
disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment);
     }
 
     protected LoanProductRelatedDetail() {
@@ -167,7 +171,8 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
             final Integer graceOnInterestPayment, final Integer 
graceOnInterestCharged, final AmortizationMethod amortizationMethod,
             final BigDecimal inArrearsTolerance, final Integer 
graceOnArrearsAgeing, final Integer daysInMonthType,
             final Integer daysInYearType, final boolean 
isInterestRecalculationEnabled, final boolean isEqualAmortization,
-            final boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment) {
+            final boolean enableDownPayment, final BigDecimal 
disbursedAmountPercentageForDownPayment,
+            final boolean enableAutoRepaymentForDownPayment) {
         this.currency = currency;
         this.principal = defaultPrincipal;
         this.nominalInterestRatePerPeriod = 
defaultNominalInterestRatePerPeriod;
@@ -196,6 +201,7 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
         this.isEqualAmortization = isEqualAmortization;
         this.enableDownPayment = enableDownPayment;
         this.disbursedAmountPercentageForDownPayment = 
disbursedAmountPercentageForDownPayment;
+        this.enableAutoRepaymentForDownPayment = 
enableAutoRepaymentForDownPayment;
     }
 
     private Integer defaultToNullIfZero(final Integer value) {
@@ -701,4 +707,12 @@ public class LoanProductRelatedDetail implements 
LoanProductMinimumRepaymentSche
     public void updateDisbursedAmountPercentageForDownPayment(BigDecimal 
disbursedAmountPercentageForDownPayment) {
         this.disbursedAmountPercentageForDownPayment = 
disbursedAmountPercentageForDownPayment;
     }
+
+    public Boolean isEnableAutoRepaymentForDownPayment() {
+        return enableAutoRepaymentForDownPayment;
+    }
+
+    public void updateEnableAutoRepaymentForDownPayment(boolean 
enableAutoRepaymentForDownPayment) {
+        this.enableAutoRepaymentForDownPayment = 
enableAutoRepaymentForDownPayment;
+    }
 }
diff --git 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
index 5b57ed8a4..735caf788 100644
--- 
a/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
+++ 
b/fineract-loan/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanEnumerations.java
@@ -293,6 +293,8 @@ public final class LoanEnumerations {
                     LoanTransactionType.CHARGE_ADJUSTMENT.getCode(), "Charge 
Adjustment");
             case CHARGE_OFF -> new 
LoanTransactionEnumData(LoanTransactionType.CHARGE_OFF.getValue().longValue(),
                     LoanTransactionType.CHARGE_OFF.getCode(), "Charge-off");
+            case DOWN_PAYMENT -> new 
LoanTransactionEnumData(LoanTransactionType.DOWN_PAYMENT.getValue().longValue(),
+                    LoanTransactionType.DOWN_PAYMENT.getCode(), "Down 
Payment");
         };
     }
 
diff --git 
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
 
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
index ca7acea64..abab920a6 100644
--- 
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
+++ 
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
@@ -25,4 +25,5 @@
   <!-- Sequence is starting from 1000 to make it easier to move existing 
liquibase changesets here -->
   <include relativeToChangelogFile="true" 
file="parts/1001_add_audit_fields_to_loan_charge.xml"/>
   <include relativeToChangelogFile="true" 
file="parts/1002_add_payment_allocation_rule.xml"/>
+  <include relativeToChangelogFile="true" 
file="parts/1003_add_loan_product_auto_repayment_down_payment_configuration.xml"/>
 </databaseChangeLog>
diff --git 
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
 
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1003_add_loan_product_auto_repayment_down_payment_configuration.xml
similarity index 53%
copy from 
fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
copy to 
fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1003_add_loan_product_auto_repayment_down_payment_configuration.xml
index ca7acea64..a1f9cad65 100644
--- 
a/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/module-changelog-master.xml
+++ 
b/fineract-loan/src/main/resources/db/changelog/tenant/module/loan/parts/1003_add_loan_product_auto_repayment_down_payment_configuration.xml
@@ -20,9 +20,20 @@
 
 -->
 <databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog";
-  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
-  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog 
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd";>
-  <!-- Sequence is starting from 1000 to make it easier to move existing 
liquibase changesets here -->
-  <include relativeToChangelogFile="true" 
file="parts/1001_add_audit_fields_to_loan_charge.xml"/>
-  <include relativeToChangelogFile="true" 
file="parts/1002_add_payment_allocation_rule.xml"/>
+                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+                   
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog 
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd";>
+    <changeSet author="fineract" id="1">
+        <addColumn tableName="m_product_loan">
+            <column defaultValueBoolean="false" type="boolean" 
name="enable_auto_repayment_for_down_payment">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+    </changeSet>
+    <changeSet author="fineract" id="2">
+        <addColumn tableName="m_loan">
+            <column defaultValueBoolean="false" type="boolean" 
name="enable_auto_repayment_for_down_payment">
+                <constraints nullable="false"/>
+            </column>
+        </addColumn>
+    </changeSet>
 </databaseChangeLog>
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
index dafac9e54..d450850c4 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/api/LoansApiResourceSwagger.java
@@ -1078,6 +1078,8 @@ final class LoansApiResourceSwagger {
         public Boolean enableDownPayment;
         @Schema(example = "0.000000")
         public BigDecimal disbursedAmountPercentageForDownPayment;
+        @Schema(example = "false")
+        public Boolean enableAutoRepaymentForDownPayment;
     }
 
     @Schema(description = "GetLoansResponse")
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
index be54f2672..575d17c65 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/data/LoanAccountData.java
@@ -258,6 +258,7 @@ public class LoanAccountData {
 
     private Boolean enableDownPayment;
     private BigDecimal disbursedAmountPercentageForDownPayment;
+    private Boolean enableAutoRepaymentForDownPayment;
 
     public static LoanAccountData importInstanceIndividual(EnumOptionData 
loanTypeEnumOption, Long clientId, Long productId,
             Long loanOfficerId, LocalDate submittedOnDate, Long fundId, 
BigDecimal principal, Integer numberOfRepayments,
@@ -660,7 +661,7 @@ public class LoanAccountData {
             final BigDecimal topupAmount, final boolean isEqualAmortization, 
final BigDecimal fixedPrincipalPercentagePerInstallment,
             final DelinquencyRangeData delinquencyRange, final boolean 
disallowExpectedDisbursements, final boolean fraud,
             LocalDate lastClosedBusinessDate, LocalDate overpaidOnDate, final 
boolean chargedOff, final boolean enableDownPayment,
-            final BigDecimal disbursedAmountPercentageForDownPayment) {
+            final BigDecimal disbursedAmountPercentageForDownPayment, final 
boolean enableAutoRepaymentForDownPayment) {
 
         final CollectionData delinquent = CollectionData.template();
 
@@ -701,8 +702,8 @@ public class LoanAccountData {
                 
.setFixedPrincipalPercentagePerInstallment(fixedPrincipalPercentagePerInstallment).setDelinquent(delinquent)
                 
.setDelinquencyRange(delinquencyRange).setDisallowExpectedDisbursements(disallowExpectedDisbursements).setFraud(fraud)
                 
.setLastClosedBusinessDate(lastClosedBusinessDate).setOverpaidOnDate(overpaidOnDate).setChargedOff(chargedOff)
-                .setEnableDownPayment(enableDownPayment)
-                
.setDisbursedAmountPercentageForDownPayment(disbursedAmountPercentageForDownPayment);
+                
.setEnableDownPayment(enableDownPayment).setDisbursedAmountPercentageForDownPayment(disbursedAmountPercentageForDownPayment)
+                
.setEnableAutoRepaymentForDownPayment(enableAutoRepaymentForDownPayment);
     }
 
     /*
@@ -788,7 +789,8 @@ public class LoanAccountData {
                 
.setDelinquencyRange(acc.delinquencyRange).setDisallowExpectedDisbursements(acc.disallowExpectedDisbursements)
                 
.setFraud(acc.fraud).setLastClosedBusinessDate(acc.getLastClosedBusinessDate()).setOverpaidOnDate(acc.overpaidOnDate)
                 
.setChargedOff(acc.chargedOff).setEnableDownPayment(acc.enableDownPayment)
-                
.setDisbursedAmountPercentageForDownPayment(acc.disbursedAmountPercentageForDownPayment);
+                
.setDisbursedAmountPercentageForDownPayment(acc.disbursedAmountPercentageForDownPayment)
+                
.setEnableAutoRepaymentForDownPayment(acc.enableAutoRepaymentForDownPayment);
     }
 
     public static LoanAccountData associationsAndTemplate(final 
LoanAccountData acc, final Collection<LoanProductData> productOptions,
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
index f533b028d..55384b5b7 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanaccount/loanschedule/service/LoanScheduleAssembler.java
@@ -452,9 +452,11 @@ public class LoanScheduleAssembler {
 
         final boolean isDownPaymentEnabled = 
loanProduct.getLoanProductRelatedDetail().isEnableDownPayment();
         BigDecimal disbursedAmountPercentageForDownPayment = null;
+        boolean isAutoRepaymentForDownPaymentEnabled = false;
         if (isDownPaymentEnabled) {
             disbursedAmountPercentageForDownPayment = 
loanProduct.getLoanProductRelatedDetail()
                     .getDisbursedAmountPercentageForDownPayment();
+            isAutoRepaymentForDownPaymentEnabled = 
loanProduct.getLoanProductRelatedDetail().isEnableAutoRepaymentForDownPayment();
         }
         return LoanApplicationTerms.assembleFrom(applicationCurrency, 
loanTermFrequency, loanTermPeriodFrequencyType, numberOfRepayments,
                 repaymentEvery, repaymentPeriodFrequencyType, nthDay, 
weekDayType, amortizationMethod, interestMethod,
@@ -469,7 +471,7 @@ public class LoanScheduleAssembler {
                 loanTermVariations, 
isInterestChargedFromDateSameAsDisbursalDateEnabled, numberOfDays, 
isSkipMeetingOnFirstDay, detailDTO,
                 allowCompoundingOnEod, isEqualAmortization, 
isInterestToBeRecoveredFirstWhenGreaterThanEMI,
                 fixedPrincipalPercentagePerInstallment, 
isPrincipalCompoundingDisabledForOverdueLoans, isDownPaymentEnabled,
-                disbursedAmountPercentageForDownPayment);
+                disbursedAmountPercentageForDownPayment, 
isAutoRepaymentForDownPaymentEnabled);
     }
 
     private CalendarInstance createCalendarForSameAsRepayment(final Integer 
repaymentEvery,
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 a5e06b898..5e187f2a4 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
@@ -694,7 +694,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                     + " lp.can_use_for_topup as canUseForTopup, l.is_topup as 
isTopup, topup.closure_loan_id as closureLoanId, "
                     + " l.total_recovered_derived as totalRecovered, 
topuploan.account_no as closureLoanAccountNo, "
                     + " topup.topup_amount as topupAmount, 
l.last_closed_business_date as lastClosedBusinessDate,l.overpaidon_date as 
overpaidOnDate, "
-                    + " l.is_charged_off as isChargedOff, 
l.charge_off_reason_cv_id as chargeOffReasonId, codec.code_value as 
chargeOffReason, l.charged_off_on_date as chargedOffOnDate, 
l.enable_down_payment as enableDownPayment, 
l.disbursed_amount_percentage_for_down_payment as 
disbursedAmountPercentageForDownPayment, "
+                    + " l.is_charged_off as isChargedOff, 
l.charge_off_reason_cv_id as chargeOffReasonId, codec.code_value as 
chargeOffReason, l.charged_off_on_date as chargedOffOnDate, 
l.enable_down_payment as enableDownPayment, 
l.disbursed_amount_percentage_for_down_payment as 
disbursedAmountPercentageForDownPayment, 
l.enable_auto_repayment_for_down_payment as enableAutoRepaymentForDownPayment,"
                     + " cobu.username as chargedOffByUsername, cobu.firstname 
as chargedOffByFirstname, cobu.lastname as chargedOffByLastname "
                     + " from m_loan l" //
                     + " join m_product_loan lp on lp.id = l.product_id" //
@@ -1040,6 +1040,7 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
 
             final boolean enableDownPayment = 
rs.getBoolean("enableDownPayment");
             final BigDecimal disbursedAmountPercentageForDownPayment = 
rs.getBigDecimal("disbursedAmountPercentageForDownPayment");
+            final boolean enableAutoRepaymentForDownPayment = 
rs.getBoolean("enableAutoRepaymentForDownPayment");
 
             return LoanAccountData.basicLoanDetails(id, accountNo, status, 
externalId, clientId, clientAccountNo, clientName,
                     clientOfficeId, clientExternalId, groupData, loanType, 
loanProductId, loanProductName, loanProductDescription,
@@ -1056,7 +1057,8 @@ public class LoanReadPlatformServiceImpl implements 
LoanReadPlatformService, Loa
                     createStandingInstructionAtDisbursement, 
isvariableInstallmentsAllowed, minimumGap, maximumGap, loanSubStatus,
                     canUseForTopup, isTopup, closureLoanId, 
closureLoanAccountNo, topupAmount, isEqualAmortization,
                     fixedPrincipalPercentagePerInstallment, delinquencyRange, 
disallowExpectedDisbursements, isFraud,
-                    lastClosedBusinessDate, overpaidOnDate, isChargedOff, 
enableDownPayment, disbursedAmountPercentageForDownPayment);
+                    lastClosedBusinessDate, overpaidOnDate, isChargedOff, 
enableDownPayment, disbursedAmountPercentageForDownPayment,
+                    enableAutoRepaymentForDownPayment);
         }
     }
 
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 02d2a833b..ada7fb2f8 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
@@ -437,7 +437,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
                 disbursementTransaction.updateLoan(loan);
                 loan.addLoanTransaction(disbursementTransaction);
             }
-
             if (loan.getRepaymentScheduleInstallments().isEmpty()) {
                 /*
                  * If no schedule, generate one (applicable to non-tranche 
multi-disbursal loans)
@@ -454,8 +453,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl 
implements LoanWritePlatf
             } else {
                 changedTransactionDetail = loan.disburse(currentUser, command, 
changes, scheduleGeneratorDTO, null);
             }
-
             loan.adjustNetDisbursalAmount(amountToDisburse.getAmount());
+            loan.handleDownPayment(amountToDisburse.getAmount(), command, 
scheduleGeneratorDTO);
         }
         if (!changes.isEmpty()) {
             if (changedTransactionDetail != null) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
index dc7a22a2f..7e427ff67 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResource.java
@@ -112,7 +112,7 @@ public class LoanProductsApiResource {
             LoanProductConstants.CAN_USE_FOR_TOPUP, 
LoanProductConstants.IS_EQUAL_AMORTIZATION_PARAM, 
LoanProductConstants.RATES_PARAM_NAME,
             LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, 
LoanProductConstants.DUE_DAYS_FOR_REPAYMENT_EVENT,
             LoanProductConstants.OVER_DUE_DAYS_FOR_REPAYMENT_EVENT, 
LoanProductConstants.ENABLE_DOWN_PAYMENT,
-            LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT));
+            LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT, 
LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT));
 
     private static final Set<String> PRODUCT_MIX_DATA_PARAMETERS = new 
HashSet<>(
             Arrays.asList("productId", "productName", "restrictedProducts", 
"allowedProducts", "productOptions"));
@@ -147,7 +147,7 @@ public class LoanProductsApiResource {
     @Operation(summary = "Create a Loan Product", description = "Depending of 
the Accounting Rule (accountingRule) selected, additional fields with details 
of the appropriate Ledger Account identifiers would need to be passed in.\n"
             + "\n" + "Refer MifosX Accounting Specs Draft for more details 
regarding the significance of the selected accounting rule\n\n"
             + "Mandatory Fields: name, shortName, currencyCode, 
digitsAfterDecimal, inMultiplesOf, principal, numberOfRepayments, 
repaymentEvery, repaymentFrequencyType, interestRatePerPeriod, 
interestRateFrequencyType, amortizationType, interestType, 
interestCalculationPeriodType, transactionProcessingStrategyCode, 
accountingRule, isInterestRecalculationEnabled, daysInYearType, 
daysInMonthType\n\n"
-            + "Optional Fields: inArrearsTolerance, graceOnPrincipalPayment, 
graceOnInterestPayment, graceOnInterestCharged, graceOnArrearsAgeing, charges, 
paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, 
penaltyToIncomeAccountMappings, includeInBorrowerCycle, 
useBorrowerCycle,principalVariationsForBorrowerCycle, 
numberOfRepaymentVariationsForBorrowerCycle, 
interestRateVariationsForBorrowerCycle, multiDisburseLoan,maxTrancheCount, 
outstandingLoanBalance,overdueDaysForNPA,h [...]
+            + "Optional Fields: inArrearsTolerance, graceOnPrincipalPayment, 
graceOnInterestPayment, graceOnInterestCharged, graceOnArrearsAgeing, charges, 
paymentChannelToFundSourceMappings, feeToIncomeAccountMappings, 
penaltyToIncomeAccountMappings, includeInBorrowerCycle, 
useBorrowerCycle,principalVariationsForBorrowerCycle, 
numberOfRepaymentVariationsForBorrowerCycle, 
interestRateVariationsForBorrowerCycle, multiDisburseLoan,maxTrancheCount, 
outstandingLoanBalance,overdueDaysForNPA,h [...]
             + "Additional Mandatory Fields for Cash(2) based accounting: 
fundSourceAccountId, loanPortfolioAccountId, interestOnLoanAccountId, 
incomeFromFeeAccountId, incomeFromPenaltyAccountId, writeOffAccountId, 
transfersInSuspenseAccountId, overpaymentLiabilityAccountId\n\n"
             + "Additional Mandatory Fields for periodic (3) and upfront 
(4)accrual accounting: fundSourceAccountId, loanPortfolioAccountId, 
interestOnLoanAccountId, incomeFromFeeAccountId, incomeFromPenaltyAccountId, 
writeOffAccountId, receivableInterestAccountId, receivableFeeAccountId, 
receivablePenaltyAccountId, transfersInSuspenseAccountId, 
overpaymentLiabilityAccountId\n\n"
             + "Additional Mandatory Fields if interest recalculation is 
enabled(true): interestRecalculationCompoundingMethod, 
rescheduleStrategyMethod, recalculationRestFrequencyType\n\n"
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
index b31fd1648..2b2e2b04d 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/api/LoanProductsApiResourceSwagger.java
@@ -159,6 +159,8 @@ final class LoanProductsApiResourceSwagger {
         public Boolean enableDownPayment;
         @Schema(example = "5.5")
         public BigDecimal disbursedAmountPercentageForDownPayment;
+        @Schema(example = "false")
+        public Boolean enableAutoRepaymentForDownPayment;
 
         // Interest Recalculation
         @Schema(example = "false")
@@ -1211,6 +1213,8 @@ final class LoanProductsApiResourceSwagger {
         public Boolean enableDownPayment;
         @Schema(example = "5.5")
         public BigDecimal disbursedAmountPercentageForDownPayment;
+        @Schema(example = "false")
+        public Boolean enableAutoRepaymentForDownPayment;
     }
 
     @Schema(description = "PutLoanProductsProductIdRequest")
@@ -1336,6 +1340,8 @@ final class LoanProductsApiResourceSwagger {
         public Boolean enableDownPayment;
         @Schema(example = "5.5")
         public BigDecimal disbursedAmountPercentageForDownPayment;
+        @Schema(example = "false")
+        public Boolean enableAutoRepaymentForDownPayment;
 
         // Interest Recalculation
         @Schema(example = "false")
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
index 3c41d3903..a82ed2d0f 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/data/LoanProductData.java
@@ -195,6 +195,7 @@ public class LoanProductData implements Serializable {
 
     private final boolean enableDownPayment;
     private final BigDecimal disbursedAmountPercentageForDownPayment;
+    private final boolean enableAutoRepaymentForDownPayment;
 
     /**
      * Used when returning lookup information about loan product for dropdowns.
@@ -286,6 +287,7 @@ public class LoanProductData implements Serializable {
         final Integer overDueDaysForRepaymentEvent = null;
         final boolean enableDownPayment = false;
         final BigDecimal disbursedAmountPercentageDownPayment = null;
+        final boolean enableAutoRepaymentForDownPayment = false;
 
         return new LoanProductData(id, name, shortName, description, currency, 
principal, minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, 
maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -304,7 +306,7 @@ public class LoanProductData implements Serializable {
                 maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, 
minimumGap, maximumGap,
                 syncExpectedWithDisbursementDate, canUseForTopup, 
isEqualAmortization, rateOptions, rates, isRatesEnabled,
                 fixedPrincipalPercentagePerInstallment, 
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
-                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment);
+                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment);
 
     }
 
@@ -396,6 +398,7 @@ public class LoanProductData implements Serializable {
         final Integer overDueDaysForRepaymentEvent = null;
         final boolean enableDownPayment = false;
         final BigDecimal disbursedAmountPercentageDownPayment = null;
+        final boolean enableAutoRepaymentForDownPayment = false;
 
         return new LoanProductData(id, name, shortName, description, currency, 
principal, minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, 
maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -414,7 +417,7 @@ public class LoanProductData implements Serializable {
                 maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, 
minimumGap, maximumGap,
                 syncExpectedWithDisbursementDate, canUseForTopup, 
isEqualAmortization, rateOptions, rates, isRatesEnabled,
                 fixedPrincipalPercentagePerInstallment, 
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
-                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment);
+                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment);
 
     }
 
@@ -513,6 +516,7 @@ public class LoanProductData implements Serializable {
         final Integer overDueDaysForRepaymentEvent = null;
         final boolean enableDownPayment = false;
         final BigDecimal disbursedAmountPercentageDownPayment = null;
+        final boolean enableAutoRepaymentForDownPayment = false;
 
         return new LoanProductData(id, name, shortName, description, currency, 
principal, minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, 
maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -531,7 +535,7 @@ public class LoanProductData implements Serializable {
                 maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, 
minimumGap, maximumGap,
                 syncExpectedWithDisbursementDate, canUseForTopup, 
isEqualAmortization, rateOptions, rates, isRatesEnabled,
                 fixedPrincipalPercentagePerInstallment, 
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
-                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment);
+                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment);
 
     }
 
@@ -624,6 +628,7 @@ public class LoanProductData implements Serializable {
         final Integer overDueDaysForRepaymentEvent = null;
         final boolean enableDownPayment = false;
         final BigDecimal disbursedAmountPercentageDownPayment = null;
+        final boolean enableAutoRepaymentForDownPayment = false;
 
         return new LoanProductData(id, name, shortName, description, currency, 
principal, minPrincipal, maxPrincipal, tolerance,
                 numberOfRepayments, minNumberOfRepayments, 
maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
@@ -642,7 +647,7 @@ public class LoanProductData implements Serializable {
                 maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, 
minimumGap, maximumGap,
                 syncExpectedWithDisbursementDate, canUseForTopup, 
isEqualAmortization, rateOptions, rates, isRatesEnabled,
                 fixedPrincipalPercentagePerInstallment, 
delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
-                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment);
+                overDueDaysForRepaymentEvent, enableDownPayment, 
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment);
 
     }
 
@@ -690,7 +695,7 @@ public class LoanProductData implements Serializable {
             final BigDecimal fixedPrincipalPercentagePerInstallment, final 
Collection<DelinquencyBucketData> delinquencyBucketOptions,
             final DelinquencyBucketData delinquencyBucket, final Integer 
dueDaysForRepaymentEvent,
             final Integer overDueDaysForRepaymentEvent, final boolean 
enableDownPayment,
-            final BigDecimal disbursedAmountPercentageForDownPayment) {
+            final BigDecimal disbursedAmountPercentageForDownPayment, final 
boolean enableAutoRepaymentForDownPayment) {
         this.id = id;
         this.name = name;
         this.shortName = shortName;
@@ -810,6 +815,7 @@ public class LoanProductData implements Serializable {
         this.overDueDaysForRepaymentEvent = overDueDaysForRepaymentEvent;
         this.enableDownPayment = enableDownPayment;
         this.disbursedAmountPercentageForDownPayment = 
disbursedAmountPercentageForDownPayment;
+        this.enableAutoRepaymentForDownPayment = 
enableAutoRepaymentForDownPayment;
     }
 
     public LoanProductData(final LoanProductData productData, final 
Collection<ChargeData> chargeOptions,
@@ -963,6 +969,7 @@ public class LoanProductData implements Serializable {
         this.overDueDaysForRepaymentEvent = 
productData.overDueDaysForRepaymentEvent;
         this.enableDownPayment = productData.enableDownPayment;
         this.disbursedAmountPercentageForDownPayment = 
productData.disbursedAmountPercentageForDownPayment;
+        this.enableAutoRepaymentForDownPayment = 
productData.enableAutoRepaymentForDownPayment;
     }
 
     private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> 
charges) {
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
index 25bbd701c..f0e2761e0 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/serialization/LoanProductDataValidator.java
@@ -160,7 +160,8 @@ public final class LoanProductDataValidator {
             
LoanProductConstants.ALLOW_APPROVED_DISBURSED_AMOUNTS_OVER_APPLIED, 
LoanProductConstants.OVER_APPLIED_CALCULATION_TYPE,
             LoanProductConstants.OVER_APPLIED_NUMBER, 
LoanProductConstants.DELINQUENCY_BUCKET_PARAM_NAME,
             LoanProductConstants.DUE_DAYS_FOR_REPAYMENT_EVENT, 
LoanProductConstants.OVER_DUE_DAYS_FOR_REPAYMENT_EVENT,
-            LoanProductConstants.ENABLE_DOWN_PAYMENT, 
LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT));
+            LoanProductConstants.ENABLE_DOWN_PAYMENT, 
LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
+            LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT));
 
     private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = { 
LoanProductConstants.amortizationTypeParamName,
             LoanProductConstants.interestTypeParamName, 
LoanProductConstants.transactionProcessingStrategyCodeParamName,
@@ -750,11 +751,30 @@ public final class LoanProductDataValidator {
             
baseDataValidator.reset().parameter(LoanProductConstants.ENABLE_DOWN_PAYMENT).value(enableDownPayment).ignoreIfNull()
                     .validateForBooleanValue();
             validateDownPaymentPercentage(enableDownPayment, 
baseDataValidator, element);
+            validateAutoRepaymentForDownPayment(enableDownPayment, 
baseDataValidator, element);
         }
 
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
 
+    private void validateAutoRepaymentForDownPayment(Boolean 
enableDownPayment, DataValidatorBuilder baseDataValidator,
+            JsonElement element) {
+        if (enableDownPayment) {
+            if 
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT,
 element)) {
+                final Boolean enableAutoRepaymentForDownPayment = 
this.fromApiJsonHelper
+                        
.extractBooleanNamed(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT, 
element);
+                
baseDataValidator.reset().parameter(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT)
+                        
.value(enableAutoRepaymentForDownPayment).ignoreIfNull().validateForBooleanValue();
+            }
+        } else {
+            if 
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT,
 element)) {
+                
baseDataValidator.reset().parameter(LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT).failWithCode(
+                        "supported.only.for.enable.down.payment.true",
+                        "Auto repayment for down-payment is supported only if 
enable down-payment is true");
+            }
+        }
+    }
+
     private void validateDownPaymentPercentage(Boolean enableDownPayment, 
DataValidatorBuilder baseDataValidator, JsonElement element) {
         if (enableDownPayment) {
             if 
(this.fromApiJsonHelper.parameterExists(LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
 element)) {
@@ -1656,6 +1676,7 @@ public final class LoanProductDataValidator {
             
baseDataValidator.reset().parameter(LoanProductConstants.ENABLE_DOWN_PAYMENT).value(enableDownPayment).ignoreIfNull()
                     .validateForBooleanValue();
             validateDownPaymentPercentage(enableDownPayment, 
baseDataValidator, element);
+            validateAutoRepaymentForDownPayment(enableDownPayment, 
baseDataValidator, element);
         }
         throwExceptionIfValidationWarningsExist(dataValidationErrors);
     }
diff --git 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
index 5d73aea85..e919cd7bf 100644
--- 
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
+++ 
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/loanproduct/service/LoanProductReadPlatformServiceImpl.java
@@ -212,7 +212,7 @@ public class LoanProductReadPlatformServiceImpl implements 
LoanProductReadPlatfo
                     + "lp.disallow_expected_disbursements as 
disallowExpectedDisbursements, lp.allow_approved_disbursed_amounts_over_applied 
as allowApprovedDisbursedAmountsOverApplied, lp.over_applied_calculation_type 
as overAppliedCalculationType, over_applied_number as overAppliedNumber, "
                     + "lp.days_in_month_enum as daysInMonth, 
lp.days_in_year_enum as daysInYear, lp.interest_recalculation_enabled as 
isInterestRecalculationEnabled, "
                     + "lp.can_define_fixed_emi_amount as 
canDefineInstallmentAmount, lp.instalment_amount_in_multiples_of as 
installmentAmountInMultiplesOf, "
-                    + "lp.due_days_for_repayment_event as 
dueDaysForRepaymentEvent, lp.overdue_days_for_repayment_event as 
overDueDaysForRepaymentEvent, lp.enable_down_payment as enableDownPayment, 
lp.disbursed_amount_percentage_for_down_payment as 
disbursedAmountPercentageForDownPayment, "
+                    + "lp.due_days_for_repayment_event as 
dueDaysForRepaymentEvent, lp.overdue_days_for_repayment_event as 
overDueDaysForRepaymentEvent, lp.enable_down_payment as enableDownPayment, 
lp.disbursed_amount_percentage_for_down_payment as 
disbursedAmountPercentageForDownPayment, 
lp.enable_auto_repayment_for_down_payment as enableAutoRepaymentForDownPayment, 
"
                     + "lpr.pre_close_interest_calculation_strategy as 
preCloseInterestCalculationStrategy, "
                     + "lpr.id as lprId, lpr.product_id as productId, 
lpr.compound_type_enum as compoundType, lpr.reschedule_strategy_enum as 
rescheduleStrategy, "
                     + "lpr.rest_frequency_type_enum as restFrequencyEnum, 
lpr.rest_frequency_interval as restFrequencyInterval, "
@@ -346,6 +346,7 @@ public class LoanProductReadPlatformServiceImpl implements 
LoanProductReadPlatfo
             final Integer overDueDaysForRepaymentEvent = 
JdbcSupport.getIntegerDefaultToNullIfZero(rs, "overDueDaysForRepaymentEvent");
             final boolean enableDownPayment = 
rs.getBoolean("enableDownPayment");
             final BigDecimal disbursedAmountPercentageForDownPayment = 
rs.getBigDecimal("disbursedAmountPercentageForDownPayment");
+            final boolean enableAutoRepaymentForDownPayment = 
rs.getBoolean("enableAutoRepaymentForDownPayment");
 
             String status = "";
             if (closeDate != null && 
closeDate.isBefore(DateUtils.getBusinessLocalDate())) {
@@ -502,7 +503,8 @@ public class LoanProductReadPlatformServiceImpl implements 
LoanProductReadPlatfo
                     maxDifferentialLendingRate, 
isFloatingInterestRateCalculationAllowed, isVariableIntallmentsAllowed, 
minimumGap,
                     maximumGap, syncExpectedWithDisbursementDate, 
canUseForTopup, isEqualAmortization, rateOptions, this.rates,
                     isRatesEnabled, fixedPrincipalPercentagePerInstallment, 
delinquencyBucketOptions, delinquencyBucket,
-                    dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, 
enableDownPayment, disbursedAmountPercentageForDownPayment);
+                    dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, 
enableDownPayment, disbursedAmountPercentageForDownPayment,
+                    enableAutoRepaymentForDownPayment);
         }
     }
 
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java
index 99c4f36da..974645b86 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/LoanProductWithDownPaymentConfigurationTest.java
@@ -19,7 +19,9 @@
 package org.apache.fineract.integrationtests;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import io.restassured.builder.RequestSpecBuilder;
 import io.restassured.builder.ResponseSpecBuilder;
@@ -27,6 +29,7 @@ import io.restassured.http.ContentType;
 import io.restassured.specification.RequestSpecification;
 import io.restassured.specification.ResponseSpecification;
 import java.math.BigDecimal;
+import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.UUID;
@@ -37,9 +40,16 @@ import 
org.apache.fineract.client.models.PostLoansLoanIdTransactionsRequest;
 import org.apache.fineract.client.models.PostLoansLoanIdTransactionsResponse;
 import org.apache.fineract.client.models.PutLoanProductsProductIdRequest;
 import org.apache.fineract.client.models.PutLoanProductsProductIdResponse;
+import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
+import org.apache.fineract.integrationtests.common.BusinessDateHelper;
 import org.apache.fineract.integrationtests.common.ClientHelper;
 import org.apache.fineract.integrationtests.common.CommonConstants;
+import org.apache.fineract.integrationtests.common.GlobalConfigurationHelper;
 import org.apache.fineract.integrationtests.common.Utils;
+import org.apache.fineract.integrationtests.common.accounting.Account;
+import org.apache.fineract.integrationtests.common.accounting.AccountHelper;
+import org.apache.fineract.integrationtests.common.accounting.JournalEntry;
+import 
org.apache.fineract.integrationtests.common.accounting.JournalEntryHelper;
 import 
org.apache.fineract.integrationtests.common.loans.LoanApplicationTestBuilder;
 import 
org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
 import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
@@ -53,6 +63,8 @@ public class LoanProductWithDownPaymentConfigurationTest {
     private RequestSpecification requestSpec;
     private LoanTransactionHelper loanTransactionHelper;
     private ClientHelper clientHelper;
+    private AccountHelper accountHelper;
+    private JournalEntryHelper journalEntryHelper;
 
     @BeforeEach
     public void setup() {
@@ -62,6 +74,8 @@ public class LoanProductWithDownPaymentConfigurationTest {
         this.responseSpec = new 
ResponseSpecBuilder().expectStatusCode(200).build();
         this.loanTransactionHelper = new 
LoanTransactionHelper(this.requestSpec, this.responseSpec);
         this.clientHelper = new ClientHelper(this.requestSpec, 
this.responseSpec);
+        this.accountHelper = new AccountHelper(this.requestSpec, 
this.responseSpec);
+        this.journalEntryHelper = new JournalEntryHelper(this.requestSpec, 
this.responseSpec);
     }
 
     @Test
@@ -74,16 +88,17 @@ public class LoanProductWithDownPaymentConfigurationTest {
         // down-payment configuration
         Boolean enableDownPayment = true;
         BigDecimal disbursedAmountPercentageForDownPayment = 
BigDecimal.valueOf(25);
-
+        Boolean enableAutoRepaymentForDownPayment = false;
         // Loan Product creation with down-payment configuration
         Integer loanProductId = 
createLoanProductWithDownPaymentConfiguration(loanTransactionHelper, 
delinquencyBucketId, enableDownPayment,
-                "25");
+                "25", enableAutoRepaymentForDownPayment);
 
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
         assertNotNull(getLoanProductsProductResponse);
         assertEquals(enableDownPayment, 
getLoanProductsProductResponse.getEnableDownPayment());
         assertEquals(0, 
getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment()
                 .compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment());
     }
 
     @Test
@@ -122,7 +137,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
         Boolean enableDownPayment = true;
 
         // Loan Product with enable down payment and with disbursed amount 
percentage as zero
-        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().withEnableDownPayment(enableDownPayment, "0")
+        final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder().withEnableDownPayment(enableDownPayment, "0", false)
                 .build(null, delinquencyBucketId);
 
         ArrayList<HashMap> loanProductErrorData = (ArrayList<HashMap>) 
validationErrorHelper
@@ -132,7 +147,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
                 
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
 
         // Loan Product with enable down payment and with disbursed amount 
percentage as greater than 100
-        final HashMap<String, Object> loanProductMap_1 = new 
LoanProductTestBuilder().withEnableDownPayment(enableDownPayment, "101")
+        final HashMap<String, Object> loanProductMap_1 = new 
LoanProductTestBuilder().withEnableDownPayment(enableDownPayment, "101", false)
                 .build(null, delinquencyBucketId);
 
         loanProductErrorData = (ArrayList<HashMap>) 
validationErrorHelper.getLoanProductError(Utils.convertToJson(loanProductMap_1),
@@ -143,7 +158,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
 
         // Loan Product with enable down payment and with disbursed amount 
percentage precision greater than 6
         final HashMap<String, Object> loanProductMap_2 = new 
LoanProductTestBuilder()
-                .withEnableDownPayment(enableDownPayment, 
"12.55555555").build(null, delinquencyBucketId);
+                .withEnableDownPayment(enableDownPayment, "12.55555555", 
false).build(null, delinquencyBucketId);
 
         loanProductErrorData = (ArrayList<HashMap>) 
validationErrorHelper.getLoanProductError(Utils.convertToJson(loanProductMap_2),
                 CommonConstants.RESPONSE_ERROR);
@@ -152,8 +167,8 @@ public class LoanProductWithDownPaymentConfigurationTest {
                 
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
 
         // Loan Product with disable down payment and with disbursed amount 
percentage
-        final HashMap<String, Object> loanProductMap_3 = new 
LoanProductTestBuilder().withEnableDownPayment(false, "12.5").build(null,
-                delinquencyBucketId);
+        final HashMap<String, Object> loanProductMap_3 = new 
LoanProductTestBuilder().withEnableDownPayment(false, "12.5", false)
+                .build(null, delinquencyBucketId);
 
         loanProductErrorData = (ArrayList<HashMap>) 
validationErrorHelper.getLoanProductError(Utils.convertToJson(loanProductMap_3),
                 CommonConstants.RESPONSE_ERROR);
@@ -162,7 +177,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
                 
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
 
         // Loan Product with enable down payment and without disbursed amount 
percentage
-        final HashMap<String, Object> loanProductMap_4 = new 
LoanProductTestBuilder().withEnableDownPayment(enableDownPayment, null)
+        final HashMap<String, Object> loanProductMap_4 = new 
LoanProductTestBuilder().withEnableDownPayment(enableDownPayment, null, false)
                 .build(null, delinquencyBucketId);
 
         loanProductErrorData = (ArrayList<HashMap>) 
validationErrorHelper.getLoanProductError(Utils.convertToJson(loanProductMap_4),
@@ -171,6 +186,15 @@ public class LoanProductWithDownPaymentConfigurationTest {
         
assertEquals("validation.msg.loanproduct.disbursedAmountPercentageForDownPayment.required.for.enable.down.payment.true",
                 
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
 
+        // Loan Product with disable down payment and enable auto repayment 
for down payment
+        final HashMap<String, Object> loanProductMap_5 = new 
LoanProductTestBuilder().withEnableDownPayment(false, null, true).build(null,
+                delinquencyBucketId);
+
+        loanProductErrorData = (ArrayList<HashMap>) 
validationErrorHelper.getLoanProductError(Utils.convertToJson(loanProductMap_5),
+                CommonConstants.RESPONSE_ERROR);
+        assertNotNull(loanProductErrorData);
+        
assertEquals("validation.msg.loanproduct.enableAutoRepaymentForDownPayment.supported.only.for.enable.down.payment.true",
+                
loanProductErrorData.get(0).get(CommonConstants.RESPONSE_ERROR_MESSAGE_CODE));
     }
 
     @Test
@@ -186,20 +210,22 @@ public class LoanProductWithDownPaymentConfigurationTest {
         // down-payment configuration
         Boolean enableDownPayment = true;
         BigDecimal disbursedAmountPercentageForDownPayment = 
BigDecimal.valueOf(25);
+        Boolean enableAutoRepaymentForDownPayment = false;
 
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
 
         // Loan Product creation with down-payment configuration
         Integer loanProductId = 
createLoanProductWithDownPaymentConfiguration(loanTransactionHelper, 
delinquencyBucketId, enableDownPayment,
-                "25");
+                "25", enableAutoRepaymentForDownPayment);
 
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
         assertNotNull(getLoanProductsProductResponse);
         assertEquals(enableDownPayment, 
getLoanProductsProductResponse.getEnableDownPayment());
         assertEquals(0, 
getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment()
                 .compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment());
 
-        final Integer loanId = createLoanAccount(clientId, 
loanProductId.longValue(), loanExternalIdStr);
+        final Integer loanId = createApproveAndDisburseLoanAccount(clientId, 
loanProductId.longValue(), loanExternalIdStr);
 
         // Retrieve Loan with loanId
 
@@ -209,6 +235,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
         assertNotNull(loanDetails);
         assertEquals(enableDownPayment, loanDetails.getEnableDownPayment());
         assertEquals(0, 
loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
loanDetails.getEnableAutoRepaymentForDownPayment());
 
     }
 
@@ -225,20 +252,22 @@ public class LoanProductWithDownPaymentConfigurationTest {
         // down-payment configuration
         Boolean enableDownPayment = true;
         BigDecimal disbursedAmountPercentageForDownPayment = 
BigDecimal.valueOf(12.5);
+        Boolean enableAutoRepaymentForDownPayment = false;
 
         final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
 
         // Loan Product creation with down-payment configuration
         Integer loanProductId = 
createLoanProductWithDownPaymentConfiguration(loanTransactionHelper, 
delinquencyBucketId, enableDownPayment,
-                "12.5");
+                "12.5", enableAutoRepaymentForDownPayment);
 
         final GetLoanProductsProductIdResponse getLoanProductsProductResponse 
= loanTransactionHelper.getLoanProduct(loanProductId);
         assertNotNull(getLoanProductsProductResponse);
         assertEquals(enableDownPayment, 
getLoanProductsProductResponse.getEnableDownPayment());
         assertEquals(0, 
getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment()
                 .compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment());
 
-        final Integer loanId = createLoanAccount(clientId, 
loanProductId.longValue(), loanExternalIdStr);
+        final Integer loanId = createApproveAndDisburseLoanAccount(clientId, 
loanProductId.longValue(), loanExternalIdStr);
 
         // Retrieve Loan with loanId
 
@@ -248,6 +277,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
         assertNotNull(loanDetails);
         assertEquals(enableDownPayment, loanDetails.getEnableDownPayment());
         assertEquals(0, 
loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
loanDetails.getEnableAutoRepaymentForDownPayment());
 
         // Modify Loan Product to update enable down payment configuration
         PutLoanProductsProductIdResponse loanProductModifyResponse = 
updateLoanProduct(loanTransactionHelper,
@@ -259,6 +289,7 @@ public class LoanProductWithDownPaymentConfigurationTest {
         assertNotNull(getLoanProductsProductResponse_1);
         assertEquals(enableDownPayment, 
getLoanProductsProductResponse_1.getEnableDownPayment());
         assertEquals(0, 
getLoanProductsProductResponse_1.getDisbursedAmountPercentageForDownPayment().compareTo(BigDecimal.valueOf(25.0)));
+        assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse_1.getEnableAutoRepaymentForDownPayment());
 
         // make repayment for loan
         final PostLoansLoanIdTransactionsResponse repaymentTransaction_1 = 
loanTransactionHelper.makeLoanRepayment(loanExternalIdStr,
@@ -271,7 +302,237 @@ public class LoanProductWithDownPaymentConfigurationTest {
         assertNotNull(loanDetails);
         assertEquals(enableDownPayment, loanDetails.getEnableDownPayment());
         assertEquals(0, 
loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment));
+        assertEquals(enableAutoRepaymentForDownPayment, 
loanDetails.getEnableAutoRepaymentForDownPayment());
+
+    }
+
+    @Test
+    public void 
loanApplicationWithLoanProductWithEnableDownPaymentAndEnableAutoRepaymentForDownPaymentTest()
 {
+        try {
+
+            // Set business date
+            LocalDate disbursementDate = LocalDate.of(2023, 03, 3);
+
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
+            BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
+
+            // Accounts oof periodic accrual
+            final Account assetAccount = 
this.accountHelper.createAssetAccount();
+            final Account incomeAccount = 
this.accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
this.accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
this.accountHelper.createLiabilityAccount();
+
+            // Loan ExternalId
+            String loanExternalIdStr = UUID.randomUUID().toString();
+
+            // Delinquency Bucket
+            final Integer delinquencyBucketId = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
+            final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                    delinquencyBucketId);
+
+            // down-payment configuration
+            Boolean enableDownPayment = true;
+            BigDecimal disbursedAmountPercentageForDownPayment = 
BigDecimal.valueOf(25);
+            Boolean enableAutoRepaymentForDownPayment = true;
+
+            final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
+
+            // Loan Product creation with down-payment configuration
+            final GetLoanProductsProductIdResponse 
getLoanProductsProductResponse = 
createLoanProductWithDownPaymentConfigurationAndAccrualAccounting(
+                    loanTransactionHelper, delinquencyBucketId, 
enableDownPayment, "25", enableAutoRepaymentForDownPayment, assetAccount,
+                    incomeAccount, expenseAccount, overpaymentAccount);
+
+            assertNotNull(getLoanProductsProductResponse);
+            assertEquals(enableDownPayment, 
getLoanProductsProductResponse.getEnableDownPayment());
+            assertEquals(0, 
getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment()
+                    .compareTo(disbursedAmountPercentageForDownPayment));
+            assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment());
+
+            final Integer loanId = 
createLoanAccountMultipleRepaymentsDisbursement(clientId, 
getLoanProductsProductResponse.getId(),
+                    loanExternalIdStr);
+
+            // Retrieve Loan with loanId
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId.longValue());
+
+            // verify down-payment details for Loan
+            assertNotNull(loanDetails);
+            assertEquals(enableDownPayment, 
loanDetails.getEnableDownPayment());
+            assertEquals(0, 
loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment));
+            assertEquals(enableAutoRepaymentForDownPayment, 
loanDetails.getEnableAutoRepaymentForDownPayment());
+
+            // first disbursement
+            loanTransactionHelper.disburseLoanWithTransactionAmount("03 March 
2023", loanId, "1000");
+
+            // verify down-payment transaction created
+            checkDownPaymentTransaction(disbursementDate, 250.0f, 0.0f, 0.0f, 
0.0f, loanId);
+
+            // verify journal entries for down-payment
+            
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "03 
March 2023",
+                    new JournalEntry(250, 
JournalEntry.TransactionType.CREDIT));
+            
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "03 
March 2023",
+                    new JournalEntry(250, JournalEntry.TransactionType.DEBIT));
+
+            // second disbursement
+
+            disbursementDate = LocalDate.of(2023, 03, 5);
+            BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
+            loanTransactionHelper.disburseLoanWithTransactionAmount("05 March 
2023", loanId, "200");
+            checkDownPaymentTransaction(disbursementDate, 50.0f, 0.0f, 0.0f, 
0.0f, loanId);
+
+            // verify journal entries for down-payment
+            
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "05 
March 2023",
+                    new JournalEntry(50, JournalEntry.TransactionType.CREDIT));
+            
this.journalEntryHelper.checkJournalEntryForAssetAccount(assetAccount, "05 
March 2023",
+                    new JournalEntry(50, JournalEntry.TransactionType.DEBIT));
+
+        } finally {
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
+        }
+
+    }
+
+    @Test
+    public void 
loanApplicationWithLoanProductWithEnableDownPaymentAndDisableAutoRepaymentForDownPaymentVerifyNoDownPaymentCreatedTest()
 {
+        try {
+
+            // Set business date
+            LocalDate disbursementDate = LocalDate.of(2023, 03, 3);
+
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.TRUE);
+            BusinessDateHelper.updateBusinessDate(requestSpec, responseSpec, 
BusinessDateType.BUSINESS_DATE, disbursementDate);
+
+            // Accounts oof periodic accrual
+            final Account assetAccount = 
this.accountHelper.createAssetAccount();
+            final Account incomeAccount = 
this.accountHelper.createIncomeAccount();
+            final Account expenseAccount = 
this.accountHelper.createExpenseAccount();
+            final Account overpaymentAccount = 
this.accountHelper.createLiabilityAccount();
+
+            // Loan ExternalId
+            String loanExternalIdStr = UUID.randomUUID().toString();
+
+            // Delinquency Bucket
+            final Integer delinquencyBucketId = 
DelinquencyBucketsHelper.createDelinquencyBucket(requestSpec, responseSpec);
+            final GetDelinquencyBucketsResponse delinquencyBucket = 
DelinquencyBucketsHelper.getDelinquencyBucket(requestSpec, responseSpec,
+                    delinquencyBucketId);
+
+            // down-payment configuration
+            Boolean enableDownPayment = true;
+            BigDecimal disbursedAmountPercentageForDownPayment = 
BigDecimal.valueOf(25);
+            Boolean enableAutoRepaymentForDownPayment = false;
+
+            final Integer clientId = 
clientHelper.createClient(ClientHelper.defaultClientCreationRequest()).getClientId().intValue();
+
+            // Loan Product creation with down-payment configuration
+            final GetLoanProductsProductIdResponse 
getLoanProductsProductResponse = 
createLoanProductWithDownPaymentConfigurationAndAccrualAccounting(
+                    loanTransactionHelper, delinquencyBucketId, 
enableDownPayment, "25", enableAutoRepaymentForDownPayment, assetAccount,
+                    incomeAccount, expenseAccount, overpaymentAccount);
+
+            assertNotNull(getLoanProductsProductResponse);
+            assertEquals(enableDownPayment, 
getLoanProductsProductResponse.getEnableDownPayment());
+            assertEquals(0, 
getLoanProductsProductResponse.getDisbursedAmountPercentageForDownPayment()
+                    .compareTo(disbursedAmountPercentageForDownPayment));
+            assertEquals(enableAutoRepaymentForDownPayment, 
getLoanProductsProductResponse.getEnableAutoRepaymentForDownPayment());
+
+            final Integer loanId = 
createLoanAccountMultipleRepaymentsDisbursement(clientId, 
getLoanProductsProductResponse.getId(),
+                    loanExternalIdStr);
+
+            // Retrieve Loan with loanId
+
+            GetLoansLoanIdResponse loanDetails = 
loanTransactionHelper.getLoanDetails(loanId.longValue());
+
+            // verify down-payment details for Loan
+            assertNotNull(loanDetails);
+            assertEquals(enableDownPayment, 
loanDetails.getEnableDownPayment());
+            assertEquals(0, 
loanDetails.getDisbursedAmountPercentageForDownPayment().compareTo(disbursedAmountPercentageForDownPayment));
+            assertEquals(enableAutoRepaymentForDownPayment, 
loanDetails.getEnableAutoRepaymentForDownPayment());
+
+            // first disbursement
+            loanTransactionHelper.disburseLoanWithTransactionAmount("03 March 
2023", loanId, "1000");
 
+            // verify no down-payment transaction created
+            checkNoDownPaymentTransaction(loanId);
+
+        } finally {
+            GlobalConfigurationHelper.updateIsBusinessDateEnabled(requestSpec, 
responseSpec, Boolean.FALSE);
+        }
+
+    }
+
+    private void checkNoDownPaymentTransaction(final Integer loanID) {
+        ArrayList<HashMap> transactions = (ArrayList<HashMap>) 
loanTransactionHelper.getLoanTransactions(this.requestSpec,
+                this.responseSpec, loanID);
+        boolean isTransactionFound = false;
+        for (int i = 0; i < transactions.size(); i++) {
+            HashMap transactionType = (HashMap) 
transactions.get(i).get("type");
+            boolean isDownPaymentTransaction = (Boolean) 
transactionType.get("downPayment");
+
+            if (isDownPaymentTransaction) {
+                isTransactionFound = true;
+                break;
+            }
+        }
+        assertFalse(isTransactionFound, "Down Payment entries are posted");
+    }
+
+    private void checkDownPaymentTransaction(final LocalDate transactionDate, 
final Float principalPortion, final Float interestPortion,
+            final Float feePortion, final Float penaltyPortion, final Integer 
loanID) {
+        ArrayList<HashMap> transactions = (ArrayList<HashMap>) 
loanTransactionHelper.getLoanTransactions(this.requestSpec,
+                this.responseSpec, loanID);
+        boolean isTransactionFound = false;
+        for (int i = 0; i < transactions.size(); i++) {
+            HashMap transactionType = (HashMap) 
transactions.get(i).get("type");
+            boolean isDownPaymentTransaction = (Boolean) 
transactionType.get("downPayment");
+
+            if (isDownPaymentTransaction) {
+                ArrayList<Integer> downPaymentDateAsArray = 
(ArrayList<Integer>) transactions.get(i).get("date");
+                LocalDate downPaymentEntryDate = 
LocalDate.of(downPaymentDateAsArray.get(0), downPaymentDateAsArray.get(1),
+                        downPaymentDateAsArray.get(2));
+
+                if (transactionDate.isEqual(downPaymentEntryDate)) {
+                    isTransactionFound = true;
+                    assertEquals(principalPortion, 
Float.valueOf(String.valueOf(transactions.get(i).get("principalPortion"))),
+                            "Mismatch in transaction amounts");
+                    assertEquals(interestPortion, 
Float.valueOf(String.valueOf(transactions.get(i).get("interestPortion"))),
+                            "Mismatch in transaction amounts");
+                    assertEquals(feePortion, 
Float.valueOf(String.valueOf(transactions.get(i).get("feeChargesPortion"))),
+                            "Mismatch in transaction amounts");
+                    assertEquals(penaltyPortion, 
Float.valueOf(String.valueOf(transactions.get(i).get("penaltyChargesPortion"))),
+                            "Mismatch in transaction amounts");
+                    break;
+                }
+            }
+        }
+        assertTrue(isTransactionFound, "No Down Payment entries are posted");
+    }
+
+    private Integer createLoanAccountMultipleRepaymentsDisbursement(final 
Integer clientID, final Long loanProductID,
+            final String externalId) {
+
+        String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("30")
+                
.withLoanTermFrequencyAsDays().withNumberOfRepayments("1").withRepaymentEveryAfter("30").withRepaymentFrequencyTypeAsDays()
+                
.withInterestRatePerPeriod("0").withInterestTypeAsFlatBalance().withAmortizationTypeAsEqualPrincipalPayments()
+                
.withInterestCalculationPeriodTypeSameAsRepaymentPeriod().withExpectedDisbursementDate("03
 March 2023")
+                .withSubmittedOnDate("03 March 
2023").withLoanType("individual").withExternalId(externalId)
+                .build(clientID.toString(), loanProductID.toString(), null);
+
+        final Integer loanId = 
loanTransactionHelper.getLoanId(loanApplicationJSON);
+        loanTransactionHelper.approveLoan("03 March 2023", "1000", loanId, 
null);
+        return loanId;
+    }
+
+    private GetLoanProductsProductIdResponse 
createLoanProductWithDownPaymentConfigurationAndAccrualAccounting(
+            LoanTransactionHelper loanTransactionHelper, Integer 
delinquencyBucketId, Boolean enableDownPayment,
+            String disbursedAmountPercentageForDownPayment, boolean 
enableAutoRepaymentForDownPayment, final Account... accounts) {
+        final String loanProductJSON = new 
LoanProductTestBuilder().withPrincipal("1000").withRepaymentTypeAsMonth()
+                
.withRepaymentAfterEvery("1").withNumberOfRepayments("1").withRepaymentTypeAsMonth().withinterestRatePerPeriod("0")
+                
.withInterestRateFrequencyTypeAsMonths().withAmortizationTypeAsEqualPrincipalPayment().withInterestTypeAsDecliningBalance()
+                
.withAccountingRulePeriodicAccrual(accounts).withInterestCalculationPeriodTypeAsRepaymentPeriod(true).withDaysInMonth("30")
+                .withDaysInYear("365").withMoratorium("0", 
"0").withMultiDisburse().withDisallowExpectedDisbursements(true)
+                .withEnableDownPayment(enableDownPayment, 
disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment)
+                .build(null);
+        final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(loanProductJSON);
+        return loanTransactionHelper.getLoanProduct(loanProductId);
     }
 
     private PutLoanProductsProductIdResponse 
updateLoanProduct(LoanTransactionHelper loanTransactionHelper, Long id) {
@@ -291,14 +552,16 @@ public class LoanProductWithDownPaymentConfigurationTest {
     }
 
     private Integer createLoanProductWithDownPaymentConfiguration(final 
LoanTransactionHelper loanTransactionHelper,
-            final Integer delinquencyBucketId, Boolean enableDownPayment, 
String disbursedAmountPercentageForDownPayment) {
+            final Integer delinquencyBucketId, Boolean enableDownPayment, 
String disbursedAmountPercentageForDownPayment,
+            Boolean enableAutoRepaymentForDownPayment) {
         final HashMap<String, Object> loanProductMap = new 
LoanProductTestBuilder()
-                .withEnableDownPayment(enableDownPayment, 
disbursedAmountPercentageForDownPayment).build(null, delinquencyBucketId);
+                .withEnableDownPayment(enableDownPayment, 
disbursedAmountPercentageForDownPayment, enableAutoRepaymentForDownPayment)
+                .build(null, delinquencyBucketId);
         final Integer loanProductId = 
loanTransactionHelper.getLoanProductId(Utils.convertToJson(loanProductMap));
         return loanProductId;
     }
 
-    private Integer createLoanAccount(final Integer clientID, final Long 
loanProductID, final String externalId) {
+    private Integer createApproveAndDisburseLoanAccount(final Integer 
clientID, final Long loanProductID, final String externalId) {
 
         String loanApplicationJSON = new 
LoanApplicationTestBuilder().withPrincipal("1000").withLoanTermFrequency("1")
                 
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("1").withRepaymentEveryAfter("1")
diff --git 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
index 2b6cbe2e4..cbcd35362 100644
--- 
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
+++ 
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/loans/LoanProductTestBuilder.java
@@ -145,6 +145,7 @@ public class LoanProductTestBuilder {
     private Integer overDueDaysForRepaymentEvent = null;
     private boolean enableDownPayment = false;
     private String disbursedAmountPercentageForDownPayment = null;
+    private boolean enableAutoRepaymentForDownPayment = false;
 
     public String build(final String chargeId) {
         final HashMap<String, Object> map = build(chargeId, null);
@@ -285,6 +286,9 @@ public class LoanProductTestBuilder {
         if (this.disbursedAmountPercentageForDownPayment != null) {
             map.put("disbursedAmountPercentageForDownPayment", 
disbursedAmountPercentageForDownPayment);
         }
+        if (enableAutoRepaymentForDownPayment) {
+            map.put("enableAutoRepaymentForDownPayment", 
enableAutoRepaymentForDownPayment);
+        }
 
         return map;
     }
@@ -697,9 +701,10 @@ public class LoanProductTestBuilder {
     }
 
     public LoanProductTestBuilder withEnableDownPayment(final Boolean 
enableDownPayment,
-            final String disbursedAmountPercentageForDownPayment) {
+            final String disbursedAmountPercentageForDownPayment, final 
Boolean enableAutoRepaymentForDownPayment) {
         this.enableDownPayment = enableDownPayment;
         this.disbursedAmountPercentageForDownPayment = 
disbursedAmountPercentageForDownPayment;
+        this.enableAutoRepaymentForDownPayment = 
enableAutoRepaymentForDownPayment;
         return this;
     }
 

Reply via email to