FINERACT-2312: full term configuration added
This commit is contained in:
+2
@@ -195,6 +195,8 @@ public interface LoanApiConstants {
|
|||||||
|
|
||||||
String INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE = "interestRecognitionOnDisbursementDate";
|
String INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE = "interestRecognitionOnDisbursementDate";
|
||||||
|
|
||||||
|
String ALLOW_FULL_TERM_FOR_TRANCHE = "allowFullTermForTranche";
|
||||||
|
|
||||||
// Loan Summary Transaction Types
|
// Loan Summary Transaction Types
|
||||||
List<LoanTransactionType> LOAN_SUMMARY_TRANSACTION_TYPES = List.of(LoanTransactionType.CHARGE_ADJUSTMENT, //
|
List<LoanTransactionType> LOAN_SUMMARY_TRANSACTION_TYPES = List.of(LoanTransactionType.CHARGE_ADJUSTMENT, //
|
||||||
LoanTransactionType.CHARGEBACK, //
|
LoanTransactionType.CHARGEBACK, //
|
||||||
|
|||||||
+9
-7
@@ -269,6 +269,7 @@ public class LoanAccountData {
|
|||||||
private Boolean enableInstallmentLevelDelinquency;
|
private Boolean enableInstallmentLevelDelinquency;
|
||||||
private LocalDate lastClosedBusinessDate;
|
private LocalDate lastClosedBusinessDate;
|
||||||
private Boolean chargedOff;
|
private Boolean chargedOff;
|
||||||
|
private Boolean allowFullTermForTranche;
|
||||||
|
|
||||||
private Boolean enableDownPayment;
|
private Boolean enableDownPayment;
|
||||||
private BigDecimal disbursedAmountPercentageForDownPayment;
|
private BigDecimal disbursedAmountPercentageForDownPayment;
|
||||||
@@ -480,12 +481,12 @@ public class LoanAccountData {
|
|||||||
final BigDecimal disbursedAmountPercentageForDownPayment, final boolean enableAutoRepaymentForDownPayment,
|
final BigDecimal disbursedAmountPercentageForDownPayment, final boolean enableAutoRepaymentForDownPayment,
|
||||||
final boolean enableInstallmentLevelDelinquency, final EnumOptionData loanScheduleType,
|
final boolean enableInstallmentLevelDelinquency, final EnumOptionData loanScheduleType,
|
||||||
final EnumOptionData loanScheduleProcessingType, final Integer fixedLength, final StringEnumOptionData chargeOffBehaviour,
|
final EnumOptionData loanScheduleProcessingType, final Integer fixedLength, final StringEnumOptionData chargeOffBehaviour,
|
||||||
final boolean isInterestRecognitionOnDisbursementDate, final StringEnumOptionData daysInYearCustomStrategy,
|
final boolean isInterestRecognitionOnDisbursementDate, final boolean allowFullTermForTranche,
|
||||||
final boolean enableIncomeCapitalization, final StringEnumOptionData capitalizedIncomeCalculationType,
|
final StringEnumOptionData daysInYearCustomStrategy, final boolean enableIncomeCapitalization,
|
||||||
final StringEnumOptionData capitalizedIncomeStrategy, StringEnumOptionData capitalizedIncomeType,
|
final StringEnumOptionData capitalizedIncomeCalculationType, final StringEnumOptionData capitalizedIncomeStrategy,
|
||||||
final boolean enableBuyDownFee, final StringEnumOptionData buyDownFeeCalculationType,
|
StringEnumOptionData capitalizedIncomeType, final boolean enableBuyDownFee,
|
||||||
final StringEnumOptionData buyDownFeeStrategy, final StringEnumOptionData buyDownFeeIncomeType,
|
final StringEnumOptionData buyDownFeeCalculationType, final StringEnumOptionData buyDownFeeStrategy,
|
||||||
final boolean merchantBuyDownFee) {
|
final StringEnumOptionData buyDownFeeIncomeType, final boolean merchantBuyDownFee) {
|
||||||
|
|
||||||
final CollectionData delinquent = CollectionData.template();
|
final CollectionData delinquent = CollectionData.template();
|
||||||
|
|
||||||
@@ -531,7 +532,8 @@ public class LoanAccountData {
|
|||||||
.setEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency).setLoanScheduleType(loanScheduleType)
|
.setEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency).setLoanScheduleType(loanScheduleType)
|
||||||
.setLoanScheduleProcessingType(loanScheduleProcessingType).setFixedLength(fixedLength)
|
.setLoanScheduleProcessingType(loanScheduleProcessingType).setFixedLength(fixedLength)
|
||||||
.setChargeOffBehaviour(chargeOffBehaviour).setInterestRecognitionOnDisbursementDate(isInterestRecognitionOnDisbursementDate)
|
.setChargeOffBehaviour(chargeOffBehaviour).setInterestRecognitionOnDisbursementDate(isInterestRecognitionOnDisbursementDate)
|
||||||
.setDaysInYearCustomStrategy(daysInYearCustomStrategy).setEnableIncomeCapitalization(enableIncomeCapitalization)
|
.setAllowFullTermForTranche(allowFullTermForTranche).setDaysInYearCustomStrategy(daysInYearCustomStrategy)
|
||||||
|
.setEnableIncomeCapitalization(enableIncomeCapitalization)
|
||||||
.setCapitalizedIncomeCalculationType(capitalizedIncomeCalculationType)
|
.setCapitalizedIncomeCalculationType(capitalizedIncomeCalculationType)
|
||||||
.setCapitalizedIncomeStrategy(capitalizedIncomeStrategy).setCapitalizedIncomeType(capitalizedIncomeType)
|
.setCapitalizedIncomeStrategy(capitalizedIncomeStrategy).setCapitalizedIncomeType(capitalizedIncomeType)
|
||||||
.setEnableBuyDownFee(enableBuyDownFee).setBuyDownFeeCalculationType(buyDownFeeCalculationType)
|
.setEnableBuyDownFee(enableBuyDownFee).setBuyDownFeeCalculationType(buyDownFeeCalculationType)
|
||||||
|
|||||||
+19
-7
@@ -427,6 +427,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
@Column(name = "enable_installment_level_delinquency", nullable = false)
|
@Column(name = "enable_installment_level_delinquency", nullable = false)
|
||||||
private boolean enableInstallmentLevelDelinquency = false;
|
private boolean enableInstallmentLevelDelinquency = false;
|
||||||
|
|
||||||
|
@Column(name = "allow_full_term_for_tranche", nullable = false)
|
||||||
|
private boolean allowFullTermForTranche = false;
|
||||||
|
|
||||||
public static Loan newIndividualLoanApplication(final String accountNo, final Client client, final AccountType loanType,
|
public static Loan newIndividualLoanApplication(final String accountNo, final Client client, final AccountType loanType,
|
||||||
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
|
final LoanProduct loanProduct, final Fund fund, final Staff officer, final CodeValue loanPurpose,
|
||||||
final LoanRepaymentScheduleTransactionProcessor transactionProcessingStrategy,
|
final LoanRepaymentScheduleTransactionProcessor transactionProcessingStrategy,
|
||||||
@@ -436,12 +439,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate, final Boolean allowFullTermForTranche) {
|
||||||
return new Loan(accountNo, client, null, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
return new Loan(accountNo, client, null, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||||
loanRepaymentScheduleDetail, null, loanCharges, collateral, null, fixedEmiAmount, disbursementDetails,
|
loanRepaymentScheduleDetail, null, loanCharges, collateral, null, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
submittedOnDate);
|
submittedOnDate, allowFullTermForTranche);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final AccountType loanType,
|
public static Loan newGroupLoanApplication(final String accountNo, final Group group, final AccountType loanType,
|
||||||
@@ -453,12 +456,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate, final Boolean allowFullTermForTranche) {
|
||||||
return new Loan(accountNo, null, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
return new Loan(accountNo, null, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||||
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
submittedOnDate);
|
submittedOnDate, allowFullTermForTranche);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
|
||||||
@@ -470,12 +473,12 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate, final Boolean allowFullTermForTranche) {
|
||||||
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
|
||||||
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
submittedOnDate);
|
submittedOnDate, allowFullTermForTranche);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Loan() {
|
protected Loan() {
|
||||||
@@ -491,7 +494,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
|
||||||
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
|
||||||
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final Boolean enableInstallmentLevelDelinquency,
|
||||||
final LocalDate submittedOnDate) {
|
final LocalDate submittedOnDate, final Boolean allowFullTermForTranche) {
|
||||||
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
|
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;
|
||||||
|
|
||||||
this.isFloatingInterestRate = isFloatingInterestRate;
|
this.isFloatingInterestRate = isFloatingInterestRate;
|
||||||
@@ -572,6 +575,7 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
this.loanInterestRecalculationDetails.updateLoan(this);
|
this.loanInterestRecalculationDetails.updateLoan(this);
|
||||||
}
|
}
|
||||||
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
this.getLoanProductRelatedDetail()
|
this.getLoanProductRelatedDetail()
|
||||||
.setEnableAccrualActivityPosting(loanProduct.getLoanProductRelatedDetail().isEnableAccrualActivityPosting());
|
.setEnableAccrualActivityPosting(loanProduct.getLoanProductRelatedDetail().isEnableAccrualActivityPosting());
|
||||||
}
|
}
|
||||||
@@ -1783,6 +1787,14 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
|
|||||||
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAllowFullTermForTranche() {
|
||||||
|
return this.allowFullTermForTranche;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAllowFullTermForTranche(boolean allowFullTermForTranche) {
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
|
}
|
||||||
|
|
||||||
public void deductFromNetDisbursalAmount(final BigDecimal subtrahend) {
|
public void deductFromNetDisbursalAmount(final BigDecimal subtrahend) {
|
||||||
this.netDisbursalAmount = this.netDisbursalAmount.subtract(subtrahend);
|
this.netDisbursalAmount = this.netDisbursalAmount.subtract(subtrahend);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -72,6 +72,7 @@ public interface LoanProductConstants {
|
|||||||
String MULTI_DISBURSE_LOAN_PARAMETER_NAME = "multiDisburseLoan";
|
String MULTI_DISBURSE_LOAN_PARAMETER_NAME = "multiDisburseLoan";
|
||||||
String MAX_TRANCHE_COUNT_PARAMETER_NAME = "maxTrancheCount";
|
String MAX_TRANCHE_COUNT_PARAMETER_NAME = "maxTrancheCount";
|
||||||
String OUTSTANDING_LOAN_BALANCE_PARAMETER_NAME = "outstandingLoanBalance";
|
String OUTSTANDING_LOAN_BALANCE_PARAMETER_NAME = "outstandingLoanBalance";
|
||||||
|
String ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME = "allowFullTermForTranche";
|
||||||
|
|
||||||
String GRACE_ON_ARREARS_AGEING_PARAMETER_NAME = "graceOnArrearsAgeing";
|
String GRACE_ON_ARREARS_AGEING_PARAMETER_NAME = "graceOnArrearsAgeing";
|
||||||
String OVERDUE_DAYS_FOR_NPA_PARAMETER_NAME = "overdueDaysForNPA";
|
String OVERDUE_DAYS_FOR_NPA_PARAMETER_NAME = "overdueDaysForNPA";
|
||||||
|
|||||||
+6
@@ -309,6 +309,8 @@ public final class LoanProductsApiResourceSwagger {
|
|||||||
// Multi Disburse
|
// Multi Disburse
|
||||||
@Schema(example = "true")
|
@Schema(example = "true")
|
||||||
public Boolean multiDisburseLoan;
|
public Boolean multiDisburseLoan;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement. Only available for PROGRESSIVE schedule type with multi-disbursement enabled.")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(example = "50")
|
@Schema(example = "50")
|
||||||
public Integer principalThresholdForLastInstallment;
|
public Integer principalThresholdForLastInstallment;
|
||||||
@Schema(example = "true")
|
@Schema(example = "true")
|
||||||
@@ -1481,6 +1483,8 @@ public final class LoanProductsApiResourceSwagger {
|
|||||||
public Boolean isRatesEnabled;
|
public Boolean isRatesEnabled;
|
||||||
@Schema(example = "true")
|
@Schema(example = "true")
|
||||||
public Boolean multiDisburseLoan;
|
public Boolean multiDisburseLoan;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement. Only available for PROGRESSIVE schedule type with multi-disbursement enabled.")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(example = "3")
|
@Schema(example = "3")
|
||||||
public Integer maxTrancheCount;
|
public Integer maxTrancheCount;
|
||||||
@Schema(example = "36000.000000")
|
@Schema(example = "36000.000000")
|
||||||
@@ -1794,6 +1798,8 @@ public final class LoanProductsApiResourceSwagger {
|
|||||||
// Multi Disburse
|
// Multi Disburse
|
||||||
@Schema(example = "true")
|
@Schema(example = "true")
|
||||||
public Boolean multiDisburseLoan;
|
public Boolean multiDisburseLoan;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement. Only available for PROGRESSIVE schedule type with multi-disbursement enabled.")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(example = "50")
|
@Schema(example = "50")
|
||||||
public Integer principalThresholdForLastInstallment;
|
public Integer principalThresholdForLastInstallment;
|
||||||
@Schema(example = "true")
|
@Schema(example = "true")
|
||||||
|
|||||||
+70
-63
@@ -217,6 +217,7 @@ public class LoanProductData implements Serializable {
|
|||||||
private final Boolean allowApprovedDisbursedAmountsOverApplied;
|
private final Boolean allowApprovedDisbursedAmountsOverApplied;
|
||||||
private final String overAppliedCalculationType;
|
private final String overAppliedCalculationType;
|
||||||
private final Integer overAppliedNumber;
|
private final Integer overAppliedNumber;
|
||||||
|
private final Boolean allowFullTermForTranche;
|
||||||
|
|
||||||
private final BigDecimal principalThresholdForLastInstallment;
|
private final BigDecimal principalThresholdForLastInstallment;
|
||||||
|
|
||||||
@@ -332,6 +333,7 @@ public class LoanProductData implements Serializable {
|
|||||||
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
||||||
final String overAppliedCalculationType = null;
|
final String overAppliedCalculationType = null;
|
||||||
final Integer overAppliedNumber = null;
|
final Integer overAppliedNumber = null;
|
||||||
|
final Boolean allowFullTermForTranche = null;
|
||||||
|
|
||||||
final LoanProductGuaranteeData productGuaranteeData = null;
|
final LoanProductGuaranteeData productGuaranteeData = null;
|
||||||
final boolean holdGuaranteeFunds = false;
|
final boolean holdGuaranteeFunds = false;
|
||||||
@@ -392,21 +394,21 @@ public class LoanProductData implements Serializable {
|
|||||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations,
|
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations,
|
||||||
interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
||||||
disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber,
|
disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber,
|
||||||
graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
|
allowFullTermForTranche, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType,
|
||||||
interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData,
|
isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds,
|
||||||
principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
|
productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion,
|
||||||
installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId,
|
canDefineInstallmentAmount, installmentAmountInMultiplesOf, loanProductConfigurableAttributes,
|
||||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate,
|
||||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed,
|
||||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup,
|
||||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
|
isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions,
|
||||||
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
|
delinquencyBucket, dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, enableDownPayment,
|
||||||
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
|
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment, paymentAllocation, creditAllocation,
|
||||||
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
|
repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType, loanScheduleProcessingType, fixedLength,
|
||||||
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
|
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
|
||||||
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
|
daysInYearTypeCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
|
||||||
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType, merchantBuyDownFee, writeOffReasonsToExpenseMappings,
|
capitalizedIncomeType, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType,
|
||||||
writeOffReasonOptions);
|
merchantBuyDownFee, writeOffReasonsToExpenseMappings, writeOffReasonOptions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,6 +475,7 @@ public class LoanProductData implements Serializable {
|
|||||||
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
||||||
final String overAppliedCalculationType = null;
|
final String overAppliedCalculationType = null;
|
||||||
final Integer overAppliedNumber = null;
|
final Integer overAppliedNumber = null;
|
||||||
|
final Boolean allowFullTermForTranche = null;
|
||||||
|
|
||||||
final EnumOptionData daysInMonthType = null;
|
final EnumOptionData daysInMonthType = null;
|
||||||
final EnumOptionData daysInYearType = null;
|
final EnumOptionData daysInYearType = null;
|
||||||
@@ -532,21 +535,21 @@ public class LoanProductData implements Serializable {
|
|||||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations,
|
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariations,
|
||||||
interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
interestRateVariations, numberOfRepaymentVariations, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
||||||
disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber,
|
disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber,
|
||||||
graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
|
allowFullTermForTranche, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType,
|
||||||
interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData,
|
isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds,
|
||||||
principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
|
productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion,
|
||||||
installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId,
|
canDefineInstallmentAmount, installmentAmountInMultiplesOf, loanProductConfigurableAttributes,
|
||||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate,
|
||||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed,
|
||||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup,
|
||||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
|
isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions,
|
||||||
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
|
delinquencyBucket, dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, enableDownPayment,
|
||||||
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
|
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment, paymentAllocation, creditAllocation,
|
||||||
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
|
repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType, loanScheduleProcessingType, fixedLength,
|
||||||
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
|
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
|
||||||
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
|
daysInYearTypeCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
|
||||||
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType, merchantBuyDownFee, writeOffReasonsToExpenseMappings,
|
capitalizedIncomeType, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType,
|
||||||
writeOffReasonOptions);
|
merchantBuyDownFee, writeOffReasonsToExpenseMappings, writeOffReasonOptions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,6 +622,7 @@ public class LoanProductData implements Serializable {
|
|||||||
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
||||||
final String overAppliedCalculationType = null;
|
final String overAppliedCalculationType = null;
|
||||||
final Integer overAppliedNumber = null;
|
final Integer overAppliedNumber = null;
|
||||||
|
final Boolean allowFullTermForTranche = null;
|
||||||
|
|
||||||
final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL);
|
final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL);
|
||||||
final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL);
|
final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL);
|
||||||
@@ -679,21 +683,21 @@ public class LoanProductData implements Serializable {
|
|||||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle,
|
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle,
|
||||||
interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount,
|
interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount,
|
||||||
outstandingLoanBalance, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType,
|
outstandingLoanBalance, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType,
|
||||||
overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
|
overAppliedNumber, allowFullTermForTranche, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType,
|
||||||
interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData,
|
isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds,
|
||||||
principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
|
productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion,
|
||||||
installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId,
|
canDefineInstallmentAmount, installmentAmountInMultiplesOf, loanProductConfigurableAttributes,
|
||||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate,
|
||||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed,
|
||||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup,
|
||||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
|
isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions,
|
||||||
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
|
delinquencyBucket, dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, enableDownPayment,
|
||||||
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
|
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment, paymentAllocation, creditAllocation,
|
||||||
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
|
repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType, loanScheduleProcessingType, fixedLength,
|
||||||
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
|
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
|
||||||
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
|
daysInYearTypeCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
|
||||||
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType, merchantBuyDownFee, writeOffReasonsToExpenseMappings,
|
capitalizedIncomeType, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType,
|
||||||
writeOffReasonOptions);
|
merchantBuyDownFee, writeOffReasonsToExpenseMappings, writeOffReasonOptions);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,6 +764,7 @@ public class LoanProductData implements Serializable {
|
|||||||
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
final Boolean allowApprovedDisbursedAmountsOverApplied = false;
|
||||||
final String overAppliedCalculationType = null;
|
final String overAppliedCalculationType = null;
|
||||||
final Integer overAppliedNumber = null;
|
final Integer overAppliedNumber = null;
|
||||||
|
final Boolean allowFullTermForTranche = null;
|
||||||
|
|
||||||
final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL);
|
final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(DaysInMonthType.ACTUAL);
|
||||||
final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL);
|
final EnumOptionData daysInYearType = CommonEnumerations.daysInYearType(DaysInYearType.ACTUAL);
|
||||||
@@ -820,21 +825,21 @@ public class LoanProductData implements Serializable {
|
|||||||
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle,
|
includeInBorrowerCycle, useBorrowerCycle, startDate, closeDate, status, externalId, principalVariationsForBorrowerCycle,
|
||||||
interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount,
|
interestRateVariationsForBorrowerCycle, numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount,
|
||||||
outstandingLoanBalance, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType,
|
outstandingLoanBalance, disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType,
|
||||||
overAppliedNumber, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
|
overAppliedNumber, allowFullTermForTranche, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType,
|
||||||
interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, productGuaranteeData,
|
isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds,
|
||||||
principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
|
productGuaranteeData, principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion,
|
||||||
installmentAmountInMultiplesOf, loanProductConfigurableAttributes, isLinkedToFloatingInterestRates, floatingRateId,
|
canDefineInstallmentAmount, installmentAmountInMultiplesOf, loanProductConfigurableAttributes,
|
||||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential, minDifferentialLendingRate,
|
||||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableInstallmentsAllowed, minimumGap, maximumGap,
|
defaultDifferentialLendingRate, maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed,
|
||||||
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, rates, isRatesEnabled,
|
isVariableInstallmentsAllowed, minimumGap, maximumGap, syncExpectedWithDisbursementDate, canUseForTopup,
|
||||||
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
|
isEqualAmortization, rateOptions, rates, isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions,
|
||||||
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
|
delinquencyBucket, dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, enableDownPayment,
|
||||||
paymentAllocation, creditAllocationData, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
|
disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment, paymentAllocation, creditAllocationData,
|
||||||
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
|
repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType, loanScheduleProcessingType, fixedLength,
|
||||||
interestRecognitionOnDisbursementDate, daysInYearTypeCustomStrategy, enableIncomeCapitalization,
|
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
|
||||||
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
|
daysInYearTypeCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
|
||||||
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType, merchantBuyDownFee, writeOffReasonsToExpenseMappings,
|
capitalizedIncomeType, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType,
|
||||||
writeOffReasonOptions);
|
merchantBuyDownFee, writeOffReasonsToExpenseMappings, writeOffReasonOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
|
public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
|
||||||
@@ -873,9 +878,9 @@ public class LoanProductData implements Serializable {
|
|||||||
Collection<LoanProductBorrowerCycleVariationData> numberOfRepaymentVariations, Boolean multiDisburseLoan,
|
Collection<LoanProductBorrowerCycleVariationData> numberOfRepaymentVariations, Boolean multiDisburseLoan,
|
||||||
Integer maxTrancheCount, BigDecimal outstandingLoanBalance, final Boolean disallowExpectedDisbursements,
|
Integer maxTrancheCount, BigDecimal outstandingLoanBalance, final Boolean disallowExpectedDisbursements,
|
||||||
final Boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType,
|
final Boolean allowApprovedDisbursedAmountsOverApplied, final String overAppliedCalculationType,
|
||||||
final Integer overAppliedNumber, final Integer graceOnArrearsAgeing, final Integer overdueDaysForNPA,
|
final Integer overAppliedNumber, final Boolean allowFullTermForTranche, final Integer graceOnArrearsAgeing,
|
||||||
final EnumOptionData daysInMonthType, final EnumOptionData daysInYearType, final boolean isInterestRecalculationEnabled,
|
final Integer overdueDaysForNPA, final EnumOptionData daysInMonthType, final EnumOptionData daysInYearType,
|
||||||
final LoanProductInterestRecalculationData interestRecalculationData,
|
final boolean isInterestRecalculationEnabled, final LoanProductInterestRecalculationData interestRecalculationData,
|
||||||
final Integer minimumDaysBetweenDisbursalAndFirstRepayment, boolean holdGuaranteeFunds,
|
final Integer minimumDaysBetweenDisbursalAndFirstRepayment, boolean holdGuaranteeFunds,
|
||||||
final LoanProductGuaranteeData loanProductGuaranteeData, final BigDecimal principalThresholdForLastInstallment,
|
final LoanProductGuaranteeData loanProductGuaranteeData, final BigDecimal principalThresholdForLastInstallment,
|
||||||
final boolean accountMovesOutOfNPAOnlyOnArrearsCompletion, boolean canDefineInstallmentAmount,
|
final boolean accountMovesOutOfNPAOnlyOnArrearsCompletion, boolean canDefineInstallmentAmount,
|
||||||
@@ -1000,6 +1005,7 @@ public class LoanProductData implements Serializable {
|
|||||||
this.allowApprovedDisbursedAmountsOverApplied = allowApprovedDisbursedAmountsOverApplied;
|
this.allowApprovedDisbursedAmountsOverApplied = allowApprovedDisbursedAmountsOverApplied;
|
||||||
this.overAppliedCalculationType = overAppliedCalculationType;
|
this.overAppliedCalculationType = overAppliedCalculationType;
|
||||||
this.overAppliedNumber = overAppliedNumber;
|
this.overAppliedNumber = overAppliedNumber;
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
|
|
||||||
this.graceOnArrearsAgeing = graceOnArrearsAgeing;
|
this.graceOnArrearsAgeing = graceOnArrearsAgeing;
|
||||||
this.overdueDaysForNPA = overdueDaysForNPA;
|
this.overdueDaysForNPA = overdueDaysForNPA;
|
||||||
@@ -1189,6 +1195,7 @@ public class LoanProductData implements Serializable {
|
|||||||
this.allowApprovedDisbursedAmountsOverApplied = productData.allowApprovedDisbursedAmountsOverApplied;
|
this.allowApprovedDisbursedAmountsOverApplied = productData.allowApprovedDisbursedAmountsOverApplied;
|
||||||
this.overAppliedCalculationType = productData.overAppliedCalculationType;
|
this.overAppliedCalculationType = productData.overAppliedCalculationType;
|
||||||
this.overAppliedNumber = productData.overAppliedNumber;
|
this.overAppliedNumber = productData.overAppliedNumber;
|
||||||
|
this.allowFullTermForTranche = productData.allowFullTermForTranche;
|
||||||
|
|
||||||
this.minimumDaysBetweenDisbursalAndFirstRepayment = productData.minimumDaysBetweenDisbursalAndFirstRepayment;
|
this.minimumDaysBetweenDisbursalAndFirstRepayment = productData.minimumDaysBetweenDisbursalAndFirstRepayment;
|
||||||
|
|
||||||
|
|||||||
+7
-2
@@ -288,7 +288,7 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
|||||||
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
|
final LoanCapitalizedIncomeStrategy capitalizedIncomeStrategy, final LoanCapitalizedIncomeType capitalizedIncomeType,
|
||||||
final boolean enableBuyDownFee, final LoanBuyDownFeeCalculationType buyDownFeeCalculationType,
|
final boolean enableBuyDownFee, final LoanBuyDownFeeCalculationType buyDownFeeCalculationType,
|
||||||
final LoanBuyDownFeeStrategy buyDownFeeStrategy, final LoanBuyDownFeeIncomeType buyDownFeeIncomeType,
|
final LoanBuyDownFeeStrategy buyDownFeeStrategy, final LoanBuyDownFeeIncomeType buyDownFeeIncomeType,
|
||||||
final boolean merchantBuyDownFee) {
|
final boolean merchantBuyDownFee, final boolean allowFullTermForTranche) {
|
||||||
this.fund = fund;
|
this.fund = fund;
|
||||||
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
this.transactionProcessingStrategyCode = transactionProcessingStrategyCode;
|
||||||
|
|
||||||
@@ -364,7 +364,8 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
|||||||
loanConfigurableAttributes.updateLoanProduct(this);
|
loanConfigurableAttributes.updateLoanProduct(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loanProductTrancheDetails = new LoanProductTrancheDetails(multiDisburseLoan, maxTrancheCount, outstandingLoanBalance);
|
this.loanProductTrancheDetails = new LoanProductTrancheDetails(multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
||||||
|
allowFullTermForTranche);
|
||||||
this.overdueDaysForNPA = overdueDaysForNPA;
|
this.overdueDaysForNPA = overdueDaysForNPA;
|
||||||
this.productInterestRecalculationDetails = productInterestRecalculationDetails;
|
this.productInterestRecalculationDetails = productInterestRecalculationDetails;
|
||||||
this.minimumDaysBetweenDisbursalAndFirstRepayment = minimumDaysBetweenDisbursalAndFirstRepayment;
|
this.minimumDaysBetweenDisbursalAndFirstRepayment = minimumDaysBetweenDisbursalAndFirstRepayment;
|
||||||
@@ -763,4 +764,8 @@ public class LoanProduct extends AbstractPersistableCustom<Long> {
|
|||||||
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAllowFullTermForTranche() {
|
||||||
|
return this.loanProductTrancheDetails != null && this.loanProductTrancheDetails.isAllowFullTermForTranche();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -38,15 +38,19 @@ public class LoanProductTrancheDetails {
|
|||||||
@Column(name = "max_outstanding_loan_balance", scale = 6, precision = 19)
|
@Column(name = "max_outstanding_loan_balance", scale = 6, precision = 19)
|
||||||
private BigDecimal outstandingLoanBalance;
|
private BigDecimal outstandingLoanBalance;
|
||||||
|
|
||||||
|
@Column(name = "allow_full_term_for_tranche")
|
||||||
|
private boolean allowFullTermForTranche;
|
||||||
|
|
||||||
protected LoanProductTrancheDetails() {
|
protected LoanProductTrancheDetails() {
|
||||||
// TODO Auto-generated constructor stub
|
// TODO Auto-generated constructor stub
|
||||||
}
|
}
|
||||||
|
|
||||||
public LoanProductTrancheDetails(final boolean multiDisburseLoan, final Integer maxTrancheCount,
|
public LoanProductTrancheDetails(final boolean multiDisburseLoan, final Integer maxTrancheCount,
|
||||||
final BigDecimal outstandingLoanBalance) {
|
final BigDecimal outstandingLoanBalance, final boolean allowFullTermForTranche) {
|
||||||
this.multiDisburseLoan = multiDisburseLoan;
|
this.multiDisburseLoan = multiDisburseLoan;
|
||||||
this.maxTrancheCount = maxTrancheCount;
|
this.maxTrancheCount = maxTrancheCount;
|
||||||
this.outstandingLoanBalance = outstandingLoanBalance;
|
this.outstandingLoanBalance = outstandingLoanBalance;
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+8
@@ -603,6 +603,8 @@ final class LoansApiResourceSwagger {
|
|||||||
public String writeoffReason;
|
public String writeoffReason;
|
||||||
public GetLoansLoanIdLinkedAccount linkedAccount;
|
public GetLoansLoanIdLinkedAccount linkedAccount;
|
||||||
public Set<GetLoansLoanIdDisbursementDetails> disbursementDetails;
|
public Set<GetLoansLoanIdDisbursementDetails> disbursementDetails;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(example = "1100.000000")
|
@Schema(example = "1100.000000")
|
||||||
public BigDecimal fixedEmiAmount;
|
public BigDecimal fixedEmiAmount;
|
||||||
@Schema(example = "35000.000000")
|
@Schema(example = "35000.000000")
|
||||||
@@ -1198,6 +1200,8 @@ final class LoansApiResourceSwagger {
|
|||||||
public List<GetLoansLoanIdTransactions> transactions;
|
public List<GetLoansLoanIdTransactions> transactions;
|
||||||
@Schema(description = "Set of GetLoansLoanIdDisbursementDetails")
|
@Schema(description = "Set of GetLoansLoanIdDisbursementDetails")
|
||||||
public Set<GetLoansLoanIdDisbursementDetails> disbursementDetails;
|
public Set<GetLoansLoanIdDisbursementDetails> disbursementDetails;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(description = "Delinquent data")
|
@Schema(description = "Delinquent data")
|
||||||
public GetLoansLoanIdDelinquencySummary delinquent;
|
public GetLoansLoanIdDelinquencySummary delinquent;
|
||||||
@Schema(description = "Set of charges")
|
@Schema(description = "Set of charges")
|
||||||
@@ -1344,6 +1348,8 @@ final class LoansApiResourceSwagger {
|
|||||||
public String externalId;
|
public String externalId;
|
||||||
@Schema(description = "List of PostLoansDisbursementData")
|
@Schema(description = "List of PostLoansDisbursementData")
|
||||||
public List<PostLoansDisbursementData> disbursementData;
|
public List<PostLoansDisbursementData> disbursementData;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(description = "Maximum allowed outstanding balance")
|
@Schema(description = "Maximum allowed outstanding balance")
|
||||||
public BigDecimal maxOutstandingLoanBalance;
|
public BigDecimal maxOutstandingLoanBalance;
|
||||||
@Schema(example = "[2011, 10, 20]")
|
@Schema(example = "[2011, 10, 20]")
|
||||||
@@ -1550,6 +1556,8 @@ final class LoansApiResourceSwagger {
|
|||||||
public List<PutLoansLoanIdChanges> charges;
|
public List<PutLoansLoanIdChanges> charges;
|
||||||
public List<PutLoansLoanIdCollateral> collateral;
|
public List<PutLoansLoanIdCollateral> collateral;
|
||||||
public List<PutLoansLoanIdDisbursementData> disbursementData;
|
public List<PutLoansLoanIdDisbursementData> disbursementData;
|
||||||
|
@Schema(example = "false", description = "Allow full term length for each tranche disbursement")
|
||||||
|
public Boolean allowFullTermForTranche;
|
||||||
@Schema(example = "HORIZONTAL")
|
@Schema(example = "HORIZONTAL")
|
||||||
public String loanScheduleProcessingType;
|
public String loanScheduleProcessingType;
|
||||||
@Schema(example = "false")
|
@Schema(example = "false")
|
||||||
|
|||||||
+26
-1
@@ -175,7 +175,8 @@ public final class LoanApplicationValidator {
|
|||||||
LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE, LoanProductConstants.FIXED_LENGTH,
|
LoanProductConstants.LOAN_SCHEDULE_PROCESSING_TYPE, LoanProductConstants.FIXED_LENGTH,
|
||||||
LoanProductConstants.ENABLE_INSTALLMENT_LEVEL_DELINQUENCY, LoanProductConstants.ENABLE_DOWN_PAYMENT,
|
LoanProductConstants.ENABLE_INSTALLMENT_LEVEL_DELINQUENCY, LoanProductConstants.ENABLE_DOWN_PAYMENT,
|
||||||
LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT, LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
|
LoanProductConstants.ENABLE_AUTO_REPAYMENT_DOWN_PAYMENT, LoanProductConstants.DISBURSED_AMOUNT_PERCENTAGE_DOWN_PAYMENT,
|
||||||
LoanApiConstants.INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE, LoanApiConstants.daysInYearCustomStrategyParameterName));
|
LoanApiConstants.INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE, LoanApiConstants.daysInYearCustomStrategyParameterName,
|
||||||
|
LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE));
|
||||||
public static final String LOANAPPLICATION_UNDO = "loanapplication.undo";
|
public static final String LOANAPPLICATION_UNDO = "loanapplication.undo";
|
||||||
|
|
||||||
private final FromJsonHelper fromApiJsonHelper;
|
private final FromJsonHelper fromApiJsonHelper;
|
||||||
@@ -324,6 +325,18 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE, element)) {
|
||||||
|
final Boolean allowFullTermForTranche = this.fromApiJsonHelper
|
||||||
|
.extractBooleanNamed(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE, element);
|
||||||
|
baseDataValidator.reset().parameter(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE).value(allowFullTermForTranche)
|
||||||
|
.ignoreIfNull().validateForBooleanValue();
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(allowFullTermForTranche) && !loanProduct.isAllowFullTermForTranche()) {
|
||||||
|
baseDataValidator.reset().parameter(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE).failWithCode("not.allowed.by.product",
|
||||||
|
"Full term tranche cannot be enabled because the loan product does not allow it");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
||||||
@@ -946,6 +959,18 @@ public final class LoanApplicationValidator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE, element)) {
|
||||||
|
final Boolean allowFullTermForTranche = this.fromApiJsonHelper
|
||||||
|
.extractBooleanNamed(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE, element);
|
||||||
|
baseDataValidator.reset().parameter(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE).value(allowFullTermForTranche)
|
||||||
|
.ignoreIfNull().validateForBooleanValue();
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(allowFullTermForTranche) && !loanProduct.isAllowFullTermForTranche()) {
|
||||||
|
baseDataValidator.reset().parameter(LoanApiConstants.ALLOW_FULL_TERM_FOR_TRANCHE).failWithCode("not.allowed.by.product",
|
||||||
|
"Full term tranche cannot be enabled because the loan product does not allow it");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
BigDecimal fixedPrincipalPercentagePerInstallment = this.fromApiJsonHelper
|
||||||
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
.extractBigDecimalWithLocaleNamed(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName, element);
|
||||||
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
baseDataValidator.reset().parameter(LoanApiConstants.fixedPrincipalPercentagePerInstallmentParamName)
|
||||||
|
|||||||
+17
-3
@@ -248,6 +248,12 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
|||||||
isEnableInstallmentLevelDelinquency = loanProduct.isEnableInstallmentLevelDelinquency();
|
isEnableInstallmentLevelDelinquency = loanProduct.isEnableInstallmentLevelDelinquency();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Boolean allowFullTermForTranche = this.fromApiJsonHelper
|
||||||
|
.extractBooleanNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME, element);
|
||||||
|
if (allowFullTermForTranche == null) {
|
||||||
|
allowFullTermForTranche = loanProduct.isAllowFullTermForTranche();
|
||||||
|
}
|
||||||
|
|
||||||
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
|
final boolean isHolidayEnabled = this.configurationDomainService.isRescheduleRepaymentsOnHolidaysEnabled();
|
||||||
Long officeId = client != null ? client.getOffice().getId() : group.getOffice().getId();
|
Long officeId = client != null ? client.getOffice().getId() : group.getOffice().getId();
|
||||||
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
|
final List<Holiday> holidays = this.holidayRepository.findByOfficeIdAndGreaterThanDate(officeId,
|
||||||
@@ -262,19 +268,19 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
|||||||
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
|
syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails, maxOutstandingLoanBalance,
|
||||||
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
|
||||||
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, isEnableInstallmentLevelDelinquency,
|
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, isEnableInstallmentLevelDelinquency,
|
||||||
submittedOnDate);
|
submittedOnDate, allowFullTermForTranche);
|
||||||
} else if (group != null) {
|
} else if (group != null) {
|
||||||
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanAccountType, loanProduct, fund, loanOfficer, loanPurpose,
|
loanApplication = Loan.newGroupLoanApplication(accountNo, group, loanAccountType, loanProduct, fund, loanOfficer, loanPurpose,
|
||||||
transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, syncDisbursementWithMeeting, fixedEmiAmount,
|
transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, syncDisbursementWithMeeting, fixedEmiAmount,
|
||||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
||||||
isEnableInstallmentLevelDelinquency, submittedOnDate);
|
isEnableInstallmentLevelDelinquency, submittedOnDate, allowFullTermForTranche);
|
||||||
} else if (client != null) {
|
} else if (client != null) {
|
||||||
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanAccountType, loanProduct, fund, loanOfficer,
|
loanApplication = Loan.newIndividualLoanApplication(accountNo, client, loanAccountType, loanProduct, fund, loanOfficer,
|
||||||
loanPurpose, transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral, fixedEmiAmount,
|
loanPurpose, transactionProcessingStrategy, loanProductRelatedDetail, loanCharges, collateral, fixedEmiAmount,
|
||||||
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
disbursementDetails, maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate,
|
||||||
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
interestRateDifferential, rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms,
|
||||||
isEnableInstallmentLevelDelinquency, submittedOnDate);
|
isEnableInstallmentLevelDelinquency, submittedOnDate, allowFullTermForTranche);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("No loan application exists for either a client or group (or both).");
|
throw new IllegalStateException("No loan application exists for either a client or group (or both).");
|
||||||
}
|
}
|
||||||
@@ -843,6 +849,14 @@ public class LoanAssemblerImpl implements LoanAssembler {
|
|||||||
loan.updateEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency);
|
loan.updateEnableInstallmentLevelDelinquency(enableInstallmentLevelDelinquency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update allow full term for tranche
|
||||||
|
if (command.isChangeInBooleanParameterNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME,
|
||||||
|
loan.isAllowFullTermForTranche())) {
|
||||||
|
final Boolean allowFullTermForTranche = command
|
||||||
|
.booleanObjectValueOfParameterNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME);
|
||||||
|
loan.updateAllowFullTermForTranche(allowFullTermForTranche);
|
||||||
|
}
|
||||||
|
|
||||||
if (changes.containsKey("recalculateLoanSchedule")) {
|
if (changes.containsKey("recalculateLoanSchedule")) {
|
||||||
changes.remove("recalculateLoanSchedule");
|
changes.remove("recalculateLoanSchedule");
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -267,6 +267,9 @@ public class LoanProductAssembler {
|
|||||||
|
|
||||||
final Integer overAppliedNumber = command.integerValueOfParameterNamed(LoanProductConstants.OVER_APPLIED_NUMBER);
|
final Integer overAppliedNumber = command.integerValueOfParameterNamed(LoanProductConstants.OVER_APPLIED_NUMBER);
|
||||||
|
|
||||||
|
final boolean allowFullTermForTranche = command.parameterExists(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME)
|
||||||
|
&& command.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME);
|
||||||
|
|
||||||
final Integer dueDaysForRepaymentEvent = command.integerValueOfParameterNamed(LoanProductConstants.DUE_DAYS_FOR_REPAYMENT_EVENT);
|
final Integer dueDaysForRepaymentEvent = command.integerValueOfParameterNamed(LoanProductConstants.DUE_DAYS_FOR_REPAYMENT_EVENT);
|
||||||
final Integer overDueDaysForRepaymentEvent = command
|
final Integer overDueDaysForRepaymentEvent = command
|
||||||
.integerValueOfParameterNamed(LoanProductConstants.OVER_DUE_DAYS_FOR_REPAYMENT_EVENT);
|
.integerValueOfParameterNamed(LoanProductConstants.OVER_DUE_DAYS_FOR_REPAYMENT_EVENT);
|
||||||
@@ -353,7 +356,7 @@ public class LoanProductAssembler {
|
|||||||
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
|
enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour, interestRecognitionOnDisbursementDate,
|
||||||
daysInYearCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
|
daysInYearCustomStrategy, enableIncomeCapitalization, capitalizedIncomeCalculationType, capitalizedIncomeStrategy,
|
||||||
capitalizedIncomeType, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType,
|
capitalizedIncomeType, enableBuyDownFee, buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType,
|
||||||
merchantBuyDownFee);
|
merchantBuyDownFee, allowFullTermForTranche);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+9
@@ -54,9 +54,18 @@ public class LoanProductTrancheDetailsUpdateUtil {
|
|||||||
actualChanges.put(LoanProductConstants.OUTSTANDING_LOAN_BALANCE_PARAMETER_NAME, newValue);
|
actualChanges.put(LoanProductConstants.OUTSTANDING_LOAN_BALANCE_PARAMETER_NAME, newValue);
|
||||||
loanProductTrancheDetails.setOutstandingLoanBalance(newValue);
|
loanProductTrancheDetails.setOutstandingLoanBalance(newValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (command.isChangeInBooleanParameterNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME,
|
||||||
|
loanProductTrancheDetails.isAllowFullTermForTranche())) {
|
||||||
|
final boolean newValue = command
|
||||||
|
.booleanPrimitiveValueOfParameterNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME);
|
||||||
|
actualChanges.put(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME, newValue);
|
||||||
|
loanProductTrancheDetails.setAllowFullTermForTranche(newValue);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
loanProductTrancheDetails.setMaxTrancheCount(null);
|
loanProductTrancheDetails.setMaxTrancheCount(null);
|
||||||
loanProductTrancheDetails.setOutstandingLoanBalance(null);
|
loanProductTrancheDetails.setOutstandingLoanBalance(null);
|
||||||
|
loanProductTrancheDetails.setAllowFullTermForTranche(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -865,7 +865,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
+ " topup.topup_amount as topupAmount, l.last_closed_business_date as lastClosedBusinessDate,l.overpaidon_date as overpaidOnDate, "
|
+ " 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.enable_auto_repayment_for_down_payment as enableAutoRepaymentForDownPayment,"
|
+ " 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, l.loan_schedule_type as loanScheduleType, l.loan_schedule_processing_type as loanScheduleProcessingType, "
|
+ " cobu.username as chargedOffByUsername, cobu.firstname as chargedOffByFirstname, cobu.lastname as chargedOffByLastname, l.loan_schedule_type as loanScheduleType, l.loan_schedule_processing_type as loanScheduleProcessingType, "
|
||||||
+ " l.charge_off_behaviour as chargeOffBehaviour, l.interest_recognition_on_disbursement_date as interestRecognitionOnDisbursementDate " //
|
+ " l.charge_off_behaviour as chargeOffBehaviour, l.interest_recognition_on_disbursement_date as interestRecognitionOnDisbursementDate, l.allow_full_term_for_tranche as allowFullTermForTranche " //
|
||||||
+ " from m_loan l" //
|
+ " from m_loan l" //
|
||||||
+ " join m_product_loan lp on lp.id = l.product_id" //
|
+ " join m_product_loan lp on lp.id = l.product_id" //
|
||||||
+ " left join m_loan_recalculation_details lir on lir.loan_id = l.id join m_currency rc on rc."
|
+ " left join m_loan_recalculation_details lir on lir.loan_id = l.id join m_currency rc on rc."
|
||||||
@@ -1238,6 +1238,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
final Integer fixedLength = JdbcSupport.getInteger(rs, "fixedLength");
|
final Integer fixedLength = JdbcSupport.getInteger(rs, "fixedLength");
|
||||||
final LoanChargeOffBehaviour chargeOffBehaviour = LoanChargeOffBehaviour.valueOf(rs.getString("chargeOffBehaviour"));
|
final LoanChargeOffBehaviour chargeOffBehaviour = LoanChargeOffBehaviour.valueOf(rs.getString("chargeOffBehaviour"));
|
||||||
final boolean interestRecognitionOnDisbursementDate = rs.getBoolean("interestRecognitionOnDisbursementDate");
|
final boolean interestRecognitionOnDisbursementDate = rs.getBoolean("interestRecognitionOnDisbursementDate");
|
||||||
|
final boolean allowFullTermForTranche = rs.getBoolean("allowFullTermForTranche");
|
||||||
final StringEnumOptionData daysInYearCustomStrategy = ApiFacingEnum.getStringEnumOptionData(DaysInYearCustomStrategyType.class,
|
final StringEnumOptionData daysInYearCustomStrategy = ApiFacingEnum.getStringEnumOptionData(DaysInYearCustomStrategyType.class,
|
||||||
rs.getString("daysInYearCustomStrategy"));
|
rs.getString("daysInYearCustomStrategy"));
|
||||||
final boolean enableIncomeCapitalization = rs.getBoolean("enableIncomeCapitalization");
|
final boolean enableIncomeCapitalization = rs.getBoolean("enableIncomeCapitalization");
|
||||||
@@ -1274,7 +1275,7 @@ public class LoanReadPlatformServiceImpl implements LoanReadPlatformService, Loa
|
|||||||
lastClosedBusinessDate, overpaidOnDate, isChargedOff, enableDownPayment, disbursedAmountPercentageForDownPayment,
|
lastClosedBusinessDate, overpaidOnDate, isChargedOff, enableDownPayment, disbursedAmountPercentageForDownPayment,
|
||||||
enableAutoRepaymentForDownPayment, enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(),
|
enableAutoRepaymentForDownPayment, enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(),
|
||||||
loanScheduleProcessingType.asEnumOptionData(), fixedLength, chargeOffBehaviour.getValueAsStringEnumOptionData(),
|
loanScheduleProcessingType.asEnumOptionData(), fixedLength, chargeOffBehaviour.getValueAsStringEnumOptionData(),
|
||||||
interestRecognitionOnDisbursementDate, daysInYearCustomStrategy, enableIncomeCapitalization,
|
interestRecognitionOnDisbursementDate, allowFullTermForTranche, daysInYearCustomStrategy, enableIncomeCapitalization,
|
||||||
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
|
capitalizedIncomeCalculationType, capitalizedIncomeStrategy, capitalizedIncomeType, enableBuyDownFee,
|
||||||
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType, merchantBuyDownFee);
|
buyDownFeeCalculationType, buyDownFeeStrategy, buyDownFeeIncomeType, merchantBuyDownFee);
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-1
@@ -208,7 +208,8 @@ public final class LoanProductDataValidator {
|
|||||||
LoanProductAccountingParams.BUY_DOWN_EXPENSE.getValue(), LoanProductAccountingParams.INCOME_FROM_BUY_DOWN.getValue(),
|
LoanProductAccountingParams.BUY_DOWN_EXPENSE.getValue(), LoanProductAccountingParams.INCOME_FROM_BUY_DOWN.getValue(),
|
||||||
LoanProductConstants.MERCHANT_BUY_DOWN_FEE_PARAM_NAME,
|
LoanProductConstants.MERCHANT_BUY_DOWN_FEE_PARAM_NAME,
|
||||||
LoanProductAccountingParams.CAPITALIZED_INCOME_CLASSIFICATION_TO_INCOME_ACCOUNT_MAPPINGS.getValue(), //
|
LoanProductAccountingParams.CAPITALIZED_INCOME_CLASSIFICATION_TO_INCOME_ACCOUNT_MAPPINGS.getValue(), //
|
||||||
LoanProductAccountingParams.BUYDOWN_FEE_CLASSIFICATION_TO_INCOME_ACCOUNT_MAPPINGS.getValue() //
|
LoanProductAccountingParams.BUYDOWN_FEE_CLASSIFICATION_TO_INCOME_ACCOUNT_MAPPINGS.getValue(), //
|
||||||
|
LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME //
|
||||||
));
|
));
|
||||||
|
|
||||||
private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = { LoanProductConstants.amortizationTypeParamName,
|
private static final String[] SUPPORTED_LOAN_CONFIGURABLE_ATTRIBUTES = { LoanProductConstants.amortizationTypeParamName,
|
||||||
@@ -1062,6 +1063,43 @@ public final class LoanProductDataValidator {
|
|||||||
baseDataValidator.reset().parameter(INTEREST_TYPE).value(interestType).ignoreIfNull().inMinMaxRange(0, 1);
|
baseDataValidator.reset().parameter(INTEREST_TYPE).value(interestType).ignoreIfNull().inMinMaxRange(0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine effective values for allowFullTermForTranche validation
|
||||||
|
// For updates, fall back to existing product values if not in request
|
||||||
|
Boolean effectiveMultiDisburseLoan = multiDisburseLoan;
|
||||||
|
if (!this.fromApiJsonHelper.parameterExists(LoanProductConstants.MULTI_DISBURSE_LOAN_PARAMETER_NAME, element)
|
||||||
|
&& loanProduct != null) {
|
||||||
|
effectiveMultiDisburseLoan = loanProduct.isMultiDisburseLoan();
|
||||||
|
}
|
||||||
|
|
||||||
|
String effectiveLoanScheduleType = LoanScheduleType.CUMULATIVE.toString();
|
||||||
|
if (fromApiJsonHelper.parameterExists(LoanProductConstants.LOAN_SCHEDULE_TYPE, element)) {
|
||||||
|
effectiveLoanScheduleType = fromApiJsonHelper.extractStringNamed(LoanProductConstants.LOAN_SCHEDULE_TYPE, element);
|
||||||
|
} else if (loanProduct != null) {
|
||||||
|
effectiveLoanScheduleType = loanProduct.getLoanProductRelatedDetail().getLoanScheduleType().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Boolean effectiveAllowFullTermForTranche = false;
|
||||||
|
if (this.fromApiJsonHelper.parameterExists(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME, element)) {
|
||||||
|
effectiveAllowFullTermForTranche = this.fromApiJsonHelper
|
||||||
|
.extractBooleanNamed(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME, element);
|
||||||
|
baseDataValidator.reset().parameter(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME)
|
||||||
|
.value(effectiveAllowFullTermForTranche).ignoreIfNull().validateForBooleanValue();
|
||||||
|
} else if (loanProduct != null && loanProduct.getLoanProductTrancheDetails() != null) {
|
||||||
|
effectiveAllowFullTermForTranche = loanProduct.getLoanProductTrancheDetails().isAllowFullTermForTranche();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate: allowFullTermForTranche requires multi-disburse and PROGRESSIVE schedule
|
||||||
|
if (Boolean.TRUE.equals(effectiveAllowFullTermForTranche)) {
|
||||||
|
if (!Boolean.TRUE.equals(effectiveMultiDisburseLoan)) {
|
||||||
|
baseDataValidator.reset().parameter(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME).failWithCode(
|
||||||
|
"requires.multi.disburse.loan", "Full term tranche can only be enabled for multi-disbursement loan products");
|
||||||
|
}
|
||||||
|
if (!LoanScheduleType.PROGRESSIVE.toString().equals(effectiveLoanScheduleType)) {
|
||||||
|
baseDataValidator.reset().parameter(LoanProductConstants.ALLOW_FULL_TERM_FOR_TRANCHE_PARAM_NAME).failWithCode(
|
||||||
|
"requires.progressive.schedule.type", "Full term tranche can only be enabled for PROGRESSIVE loan schedule type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final String overAppliedCalculationType = this.fromApiJsonHelper.extractStringNamed(OVER_APPLIED_CALCULATION_TYPE, element);
|
final String overAppliedCalculationType = this.fromApiJsonHelper.extractStringNamed(OVER_APPLIED_CALCULATION_TYPE, element);
|
||||||
baseDataValidator.reset().parameter(OVER_APPLIED_CALCULATION_TYPE).value(overAppliedCalculationType).notExceedingLengthOf(10);
|
baseDataValidator.reset().parameter(OVER_APPLIED_CALCULATION_TYPE).value(overAppliedCalculationType).notExceedingLengthOf(10);
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-10
@@ -254,7 +254,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
|||||||
+ "lp.min_days_between_disbursal_and_first_repayment As minimumDaysBetweenDisbursalAndFirstRepayment, "
|
+ "lp.min_days_between_disbursal_and_first_repayment As minimumDaysBetweenDisbursalAndFirstRepayment, "
|
||||||
+ "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, "
|
+ "lp.amortization_method_enum as amortizationMethod, lp.arrearstolerance_amount as tolerance, "
|
||||||
+ "lp.accounting_type as accountingType, lp.include_in_borrower_cycle as includeInBorrowerCycle,lp.use_borrower_cycle as useBorrowerCycle, lp.start_date as startDate, lp.close_date as closeDate, "
|
+ "lp.accounting_type as accountingType, lp.include_in_borrower_cycle as includeInBorrowerCycle,lp.use_borrower_cycle as useBorrowerCycle, lp.start_date as startDate, lp.close_date as closeDate, "
|
||||||
+ "lp.allow_multiple_disbursals as multiDisburseLoan, lp.max_disbursals as maxTrancheCount, lp.max_outstanding_loan_balance as outstandingLoanBalance, "
|
+ "lp.allow_multiple_disbursals as multiDisburseLoan, lp.max_disbursals as maxTrancheCount, lp.max_outstanding_loan_balance as outstandingLoanBalance, lp.allow_full_term_for_tranche as allowFullTermForTranche, "
|
||||||
+ "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.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.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.installment_amount_in_multiples_of as installmentAmountInMultiplesOf, "
|
+ "lp.can_define_fixed_emi_amount as canDefineInstallmentAmount, lp.installment_amount_in_multiples_of as installmentAmountInMultiplesOf, "
|
||||||
@@ -439,6 +439,7 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
|||||||
final Boolean allowApprovedDisbursedAmountsOverApplied = rs.getBoolean("allowApprovedDisbursedAmountsOverApplied");
|
final Boolean allowApprovedDisbursedAmountsOverApplied = rs.getBoolean("allowApprovedDisbursedAmountsOverApplied");
|
||||||
final String overAppliedCalculationType = rs.getString("overAppliedCalculationType");
|
final String overAppliedCalculationType = rs.getString("overAppliedCalculationType");
|
||||||
final Integer overAppliedNumber = rs.getInt("overAppliedNumber");
|
final Integer overAppliedNumber = rs.getInt("overAppliedNumber");
|
||||||
|
final Boolean allowFullTermForTranche = rs.getBoolean("allowFullTermForTranche");
|
||||||
|
|
||||||
final int daysInMonth = JdbcSupport.getInteger(rs, "daysInMonth");
|
final int daysInMonth = JdbcSupport.getInteger(rs, "daysInMonth");
|
||||||
final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(daysInMonth);
|
final EnumOptionData daysInMonthType = CommonEnumerations.daysInMonthType(daysInMonth);
|
||||||
@@ -591,15 +592,16 @@ public class LoanProductReadPlatformServiceImpl implements LoanProductReadPlatfo
|
|||||||
principalVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle,
|
principalVariationsForBorrowerCycle, interestRateVariationsForBorrowerCycle,
|
||||||
numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
numberOfRepaymentVariationsForBorrowerCycle, multiDisburseLoan, maxTrancheCount, outstandingLoanBalance,
|
||||||
disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber,
|
disallowExpectedDisbursements, allowApprovedDisbursedAmountsOverApplied, overAppliedCalculationType, overAppliedNumber,
|
||||||
graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType, isInterestRecalculationEnabled,
|
allowFullTermForTranche, graceOnArrearsAgeing, overdueDaysForNPA, daysInMonthType, daysInYearType,
|
||||||
interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment, holdGuaranteeFunds, loanProductGuaranteeData,
|
isInterestRecalculationEnabled, interestRecalculationData, minimumDaysBetweenDisbursalAndFirstRepayment,
|
||||||
principalThresholdForLastInstallment, accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount,
|
holdGuaranteeFunds, loanProductGuaranteeData, principalThresholdForLastInstallment,
|
||||||
installmentAmountInMultiplesOf, allowAttributeOverrides, isLinkedToFloatingInterestRates, floatingRateId,
|
accountMovesOutOfNPAOnlyOnArrearsCompletion, canDefineInstallmentAmount, installmentAmountInMultiplesOf,
|
||||||
floatingRateName, interestRateDifferential, minDifferentialLendingRate, defaultDifferentialLendingRate,
|
allowAttributeOverrides, isLinkedToFloatingInterestRates, floatingRateId, floatingRateName, interestRateDifferential,
|
||||||
maxDifferentialLendingRate, isFloatingInterestRateCalculationAllowed, isVariableIntallmentsAllowed, minimumGap,
|
minDifferentialLendingRate, defaultDifferentialLendingRate, maxDifferentialLendingRate,
|
||||||
maximumGap, syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, this.rates,
|
isFloatingInterestRateCalculationAllowed, isVariableIntallmentsAllowed, minimumGap, maximumGap,
|
||||||
isRatesEnabled, fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket,
|
syncExpectedWithDisbursementDate, canUseForTopup, isEqualAmortization, rateOptions, this.rates, isRatesEnabled,
|
||||||
dueDaysForRepaymentEvent, overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageForDownPayment,
|
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
|
||||||
|
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageForDownPayment,
|
||||||
enableAutoRepaymentForDownPayment, advancedPaymentData, creditAllocationData, repaymentStartDateType,
|
enableAutoRepaymentForDownPayment, advancedPaymentData, creditAllocationData, repaymentStartDateType,
|
||||||
enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(), loanScheduleProcessingType.asEnumOptionData(),
|
enableInstallmentLevelDelinquency, loanScheduleType.asEnumOptionData(), loanScheduleProcessingType.asEnumOptionData(),
|
||||||
fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes,
|
fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes,
|
||||||
|
|||||||
@@ -225,4 +225,5 @@
|
|||||||
<include file="parts/0204_transaction_summary_with_asset_owner_and_from_asset_owner_id_for_buybacks.xml" relativeToChangelogFile="true" />
|
<include file="parts/0204_transaction_summary_with_asset_owner_and_from_asset_owner_id_for_buybacks.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0205_add_read_familymembers_permission.xml" relativeToChangelogFile="true" />
|
<include file="parts/0205_add_read_familymembers_permission.xml" relativeToChangelogFile="true" />
|
||||||
<include file="parts/0206_transaction_summary_with_asset_owner_classification_name_bug_fix.xml" relativeToChangelogFile="true" />
|
<include file="parts/0206_transaction_summary_with_asset_owner_classification_name_bug_fix.xml" relativeToChangelogFile="true" />
|
||||||
|
<include file="parts/0207_add_allow_full_term_for_tranche.xml" relativeToChangelogFile="true" />
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
|||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<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">
|
||||||
|
<changeSet author="fineract" id="1">
|
||||||
|
<addColumn tableName="m_product_loan">
|
||||||
|
<column defaultValueBoolean="false" type="boolean" name="allow_full_term_for_tranche">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
<changeSet author="fineract" id="2">
|
||||||
|
<addColumn tableName="m_loan">
|
||||||
|
<column defaultValueBoolean="false" type="boolean" name="allow_full_term_for_tranche">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
||||||
+7
-1
@@ -80,6 +80,7 @@ public class LoanBuilder {
|
|||||||
private ExternalId externalId = ExternalId.empty();
|
private ExternalId externalId = ExternalId.empty();
|
||||||
private LoanApplicationTerms loanApplicationTerms = mock(LoanApplicationTerms.class);
|
private LoanApplicationTerms loanApplicationTerms = mock(LoanApplicationTerms.class);
|
||||||
private Boolean enableInstallmentLevelDelinquency = false;
|
private Boolean enableInstallmentLevelDelinquency = false;
|
||||||
|
private Boolean allowFullTermForTranche = false;
|
||||||
private LocalDate submittedOnDate = LocalDate.now(ZoneId.systemDefault());
|
private LocalDate submittedOnDate = LocalDate.now(ZoneId.systemDefault());
|
||||||
private LocalDate approvedOnDate;
|
private LocalDate approvedOnDate;
|
||||||
private LocalDate expectedDisbursementDate;
|
private LocalDate expectedDisbursementDate;
|
||||||
@@ -115,7 +116,7 @@ public class LoanBuilder {
|
|||||||
transactionProcessor, loanRepaymentScheduleDetail, charges, collateral, fixedEmiAmount, disbursementDetails,
|
transactionProcessor, loanRepaymentScheduleDetail, charges, collateral, fixedEmiAmount, disbursementDetails,
|
||||||
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential,
|
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential,
|
||||||
rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
rates, fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, enableInstallmentLevelDelinquency,
|
||||||
submittedOnDate);
|
submittedOnDate, allowFullTermForTranche);
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
loan.setId(id);
|
loan.setId(id);
|
||||||
@@ -338,6 +339,11 @@ public class LoanBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoanBuilder withAllowFullTermForTranche(Boolean allowFullTermForTranche) {
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public LoanBuilder withSubmittedOnDate(LocalDate submittedOnDate) {
|
public LoanBuilder withSubmittedOnDate(LocalDate submittedOnDate) {
|
||||||
this.submittedOnDate = submittedOnDate;
|
this.submittedOnDate = submittedOnDate;
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ public class LoanProductValidationStepDefinitions implements En {
|
|||||||
|
|
||||||
private LoanProduct newLoanProduct(boolean allowMultipleDisbursals) {
|
private LoanProduct newLoanProduct(boolean allowMultipleDisbursals) {
|
||||||
LoanProduct lp = new LoanProduct();
|
LoanProduct lp = new LoanProduct();
|
||||||
lp.setLoanProductTrancheDetails(new LoanProductTrancheDetails(allowMultipleDisbursals, null, null));
|
lp.setLoanProductTrancheDetails(new LoanProductTrancheDetails(allowMultipleDisbursals, null, null, false));
|
||||||
return lp;
|
return lp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+187
@@ -33,15 +33,19 @@ import java.math.BigDecimal;
|
|||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.fineract.client.models.AdvancedPaymentData;
|
||||||
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
|
import org.apache.fineract.client.models.GetLoanProductsProductIdResponse;
|
||||||
import org.apache.fineract.client.models.GetLoansLoanIdDisbursementDetails;
|
import org.apache.fineract.client.models.GetLoansLoanIdDisbursementDetails;
|
||||||
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
|
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentPeriod;
|
||||||
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
|
import org.apache.fineract.client.models.GetLoansLoanIdRepaymentSchedule;
|
||||||
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
import org.apache.fineract.client.models.GetLoansLoanIdResponse;
|
||||||
|
import org.apache.fineract.client.models.PaymentAllocationOrder;
|
||||||
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
import org.apache.fineract.client.models.PostLoansLoanIdResponse;
|
||||||
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
|
import org.apache.fineract.client.models.PutLoansLoanIdResponse;
|
||||||
import org.apache.fineract.integrationtests.common.ClientHelper;
|
import org.apache.fineract.integrationtests.common.ClientHelper;
|
||||||
@@ -53,6 +57,8 @@ import org.apache.fineract.integrationtests.common.loans.LoanProductTestBuilder;
|
|||||||
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
|
import org.apache.fineract.integrationtests.common.loans.LoanStatusChecker;
|
||||||
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
|
import org.apache.fineract.integrationtests.common.loans.LoanTestLifecycleExtension;
|
||||||
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
|
import org.apache.fineract.integrationtests.common.loans.LoanTransactionHelper;
|
||||||
|
import org.apache.fineract.portfolio.loanaccount.loanschedule.domain.LoanScheduleType;
|
||||||
|
import org.apache.fineract.portfolio.loanproduct.domain.PaymentAllocationType;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -693,4 +699,185 @@ public class LoanDisbursementDetailsIntegrationTest {
|
|||||||
equalTo("error.msg.loan.disbursal.amount.can't.be.greater.than.maximum.applied.loan.amount.calculation"))
|
equalTo("error.msg.loan.disbursal.amount.can't.be.greater.than.maximum.applied.loan.amount.calculation"))
|
||||||
.expectStatusCode(403).build();
|
.expectStatusCode(403).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private AdvancedPaymentData createDefaultPaymentAllocation(String futureInstallmentAllocationRule) {
|
||||||
|
AdvancedPaymentData advancedPaymentData = new AdvancedPaymentData();
|
||||||
|
advancedPaymentData.setTransactionType("DEFAULT");
|
||||||
|
advancedPaymentData.setFutureInstallmentAllocationRule(futureInstallmentAllocationRule);
|
||||||
|
|
||||||
|
List<PaymentAllocationOrder> paymentAllocationOrders = getPaymentAllocationOrder(PaymentAllocationType.PAST_DUE_PENALTY,
|
||||||
|
PaymentAllocationType.PAST_DUE_FEE, PaymentAllocationType.PAST_DUE_PRINCIPAL, PaymentAllocationType.PAST_DUE_INTEREST,
|
||||||
|
PaymentAllocationType.DUE_PENALTY, PaymentAllocationType.DUE_FEE, PaymentAllocationType.DUE_PRINCIPAL,
|
||||||
|
PaymentAllocationType.DUE_INTEREST, PaymentAllocationType.IN_ADVANCE_PENALTY, PaymentAllocationType.IN_ADVANCE_FEE,
|
||||||
|
PaymentAllocationType.IN_ADVANCE_PRINCIPAL, PaymentAllocationType.IN_ADVANCE_INTEREST);
|
||||||
|
|
||||||
|
advancedPaymentData.setPaymentAllocationOrder(paymentAllocationOrders);
|
||||||
|
return advancedPaymentData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<PaymentAllocationOrder> getPaymentAllocationOrder(PaymentAllocationType... paymentAllocationTypes) {
|
||||||
|
AtomicInteger integer = new AtomicInteger(1);
|
||||||
|
return Arrays.stream(paymentAllocationTypes).map(pat -> {
|
||||||
|
PaymentAllocationOrder paymentAllocationOrder = new PaymentAllocationOrder();
|
||||||
|
paymentAllocationOrder.setPaymentAllocationRule(pat.name());
|
||||||
|
paymentAllocationOrder.setOrder(integer.getAndIncrement());
|
||||||
|
return paymentAllocationOrder;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLoanProductWithFullTermTrancheEnabled() {
|
||||||
|
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation("NEXT_INSTALLMENT");
|
||||||
|
|
||||||
|
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments()
|
||||||
|
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
|
||||||
|
.withInterestTypeAsDecliningBalance().withMultiDisburse().withLoanScheduleType(LoanScheduleType.PROGRESSIVE)
|
||||||
|
.addAdvancedPaymentAllocation(defaultAllocation).withAllowFullTermForTranche(true).build(null);
|
||||||
|
|
||||||
|
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||||
|
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
|
||||||
|
|
||||||
|
GetLoanProductsProductIdResponse loanProduct = this.loanTransactionHelper.getLoanProduct(loanProductId);
|
||||||
|
assertNotNull(loanProduct);
|
||||||
|
assertEquals(true, loanProduct.getMultiDisburseLoan());
|
||||||
|
assertEquals(true, loanProduct.getAllowFullTermForTranche());
|
||||||
|
log.info("-------------------LOAN PRODUCT WITH allowFullTermForTranche CREATED SUCCESSFULLY-------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLoanProductWithFullTermTrancheOnCumulativeShouldFail() {
|
||||||
|
final ResponseSpecification errorResponse = new ResponseSpecBuilder()
|
||||||
|
.expectBody("userMessageGlobalisationCode", equalTo("validation.msg.validation.errors.exist"))
|
||||||
|
.expectBody("errors[0].userMessageGlobalisationCode",
|
||||||
|
equalTo("validation.msg.loanproduct.allowFullTermForTranche.requires.progressive.schedule.type"))
|
||||||
|
.expectStatusCode(400).build();
|
||||||
|
|
||||||
|
final LoanTransactionHelper validationErrorHelper = new LoanTransactionHelper(this.requestSpec, errorResponse);
|
||||||
|
|
||||||
|
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments()
|
||||||
|
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
|
||||||
|
.withInterestTypeAsDecliningBalance().withMultiDisburse().withLoanScheduleType(LoanScheduleType.CUMULATIVE)
|
||||||
|
.withAllowFullTermForTranche(true).build(null);
|
||||||
|
|
||||||
|
validationErrorHelper.getLoanProductId(loanProductJSON);
|
||||||
|
log.info("-------------------LOAN PRODUCT WITH allowFullTermForTranche ON CUMULATIVE FAILED AS EXPECTED-------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateLoanProductWithFullTermTrancheOnSingleDisburseShouldFail() {
|
||||||
|
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation("NEXT_INSTALLMENT");
|
||||||
|
|
||||||
|
final ResponseSpecification errorResponse = new ResponseSpecBuilder()
|
||||||
|
.expectBody("userMessageGlobalisationCode", equalTo("validation.msg.validation.errors.exist"))
|
||||||
|
.expectBody("errors[0].userMessageGlobalisationCode",
|
||||||
|
equalTo("validation.msg.loanproduct.allowFullTermForTranche.requires.multi.disburse.loan"))
|
||||||
|
.expectStatusCode(400).build();
|
||||||
|
|
||||||
|
final LoanTransactionHelper validationErrorHelper = new LoanTransactionHelper(this.requestSpec, errorResponse);
|
||||||
|
|
||||||
|
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments()
|
||||||
|
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
|
||||||
|
.withInterestTypeAsDecliningBalance().withLoanScheduleType(LoanScheduleType.PROGRESSIVE)
|
||||||
|
.addAdvancedPaymentAllocation(defaultAllocation).withAllowFullTermForTranche(true).build(null);
|
||||||
|
|
||||||
|
validationErrorHelper.getLoanProductId(loanProductJSON);
|
||||||
|
log.info("-------------------LOAN PRODUCT WITH allowFullTermForTranche ON SINGLE DISBURSE FAILED AS EXPECTED-------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUpdateLoanProductPreservesAllowFullTermForTranche() {
|
||||||
|
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation("NEXT_INSTALLMENT");
|
||||||
|
|
||||||
|
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments()
|
||||||
|
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
|
||||||
|
.withInterestTypeAsDecliningBalance().withMultiDisburse().withLoanScheduleType(LoanScheduleType.PROGRESSIVE)
|
||||||
|
.addAdvancedPaymentAllocation(defaultAllocation).withAllowFullTermForTranche(true).build(null);
|
||||||
|
|
||||||
|
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||||
|
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
|
||||||
|
|
||||||
|
GetLoanProductsProductIdResponse loanProduct = this.loanTransactionHelper.getLoanProduct(loanProductId);
|
||||||
|
assertNotNull(loanProduct);
|
||||||
|
assertEquals(true, loanProduct.getAllowFullTermForTranche());
|
||||||
|
|
||||||
|
org.apache.fineract.client.models.PutLoanProductsProductIdRequest updateRequest = new org.apache.fineract.client.models.PutLoanProductsProductIdRequest();
|
||||||
|
updateRequest.setDescription("Updated description");
|
||||||
|
this.loanTransactionHelper.updateLoanProduct((long) loanProductId, updateRequest);
|
||||||
|
|
||||||
|
GetLoanProductsProductIdResponse updatedProduct = this.loanTransactionHelper.getLoanProduct(loanProductId);
|
||||||
|
assertNotNull(updatedProduct);
|
||||||
|
assertEquals(true, updatedProduct.getAllowFullTermForTranche());
|
||||||
|
assertEquals("Updated description", updatedProduct.getDescription());
|
||||||
|
log.info("-------------------LOAN PRODUCT UPDATE PRESERVED allowFullTermForTranche FLAG-------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoanInheritsAllowFullTermForTrancheFromProduct() {
|
||||||
|
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation("NEXT_INSTALLMENT");
|
||||||
|
|
||||||
|
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments()
|
||||||
|
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
|
||||||
|
.withInterestTypeAsDecliningBalance().withMultiDisburse().withLoanScheduleType(LoanScheduleType.PROGRESSIVE)
|
||||||
|
.addAdvancedPaymentAllocation(defaultAllocation).withAllowFullTermForTranche(true).build(null);
|
||||||
|
|
||||||
|
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||||
|
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
|
||||||
|
|
||||||
|
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||||
|
log.info("------------------CLIENT CREATED WITH ID----------- {}", clientId);
|
||||||
|
|
||||||
|
List<HashMap> createTranches = new ArrayList<>();
|
||||||
|
createTranches.add(this.loanTransactionHelper.createTrancheDetail(null, "01 March 2014", "5000"));
|
||||||
|
createTranches.add(this.loanTransactionHelper.createTrancheDetail(null, "01 April 2014", "5000"));
|
||||||
|
|
||||||
|
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("10000").withLoanTermFrequency("12")
|
||||||
|
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
|
||||||
|
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("1").withExpectedDisbursementDate("01 March 2014")
|
||||||
|
.withTranches(createTranches).withSubmittedOnDate("01 March 2014")
|
||||||
|
.withRepaymentStrategy(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY)
|
||||||
|
.build(clientId.toString(), loanProductId.toString(), null);
|
||||||
|
|
||||||
|
final Integer loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||||
|
log.info("------------------LOAN CREATED WITH ID----------- {}", loanId);
|
||||||
|
|
||||||
|
GetLoansLoanIdResponse loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanId);
|
||||||
|
assertNotNull(loanDetails);
|
||||||
|
assertEquals(true, loanDetails.getAllowFullTermForTranche());
|
||||||
|
log.info("-------------------LOAN INHERITED allowFullTermForTranche FROM PRODUCT SUCCESSFULLY-------");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLoanLevelOverrideOfAllowFullTermForTranche() {
|
||||||
|
AdvancedPaymentData defaultAllocation = createDefaultPaymentAllocation("NEXT_INSTALLMENT");
|
||||||
|
|
||||||
|
final String loanProductJSON = new LoanProductTestBuilder().withAmortizationTypeAsEqualInstallments()
|
||||||
|
.withInterestTypeAsDecliningBalance().withMoratorium("", "").withInterestCalculationPeriodTypeAsRepaymentPeriod(true)
|
||||||
|
.withInterestTypeAsDecliningBalance().withMultiDisburse().withLoanScheduleType(LoanScheduleType.PROGRESSIVE)
|
||||||
|
.addAdvancedPaymentAllocation(defaultAllocation).withAllowFullTermForTranche(true).build(null);
|
||||||
|
|
||||||
|
final Integer loanProductId = this.loanTransactionHelper.getLoanProductId(loanProductJSON);
|
||||||
|
log.info("------------------LOAN PRODUCT CREATED WITH ID----------- {}", loanProductId);
|
||||||
|
|
||||||
|
final Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
|
||||||
|
log.info("------------------CLIENT CREATED WITH ID----------- {}", clientId);
|
||||||
|
|
||||||
|
List<HashMap> createTranches = new ArrayList<>();
|
||||||
|
createTranches.add(this.loanTransactionHelper.createTrancheDetail(null, "01 March 2014", "5000"));
|
||||||
|
createTranches.add(this.loanTransactionHelper.createTrancheDetail(null, "01 April 2014", "5000"));
|
||||||
|
|
||||||
|
final String loanApplicationJSON = new LoanApplicationTestBuilder().withPrincipal("10000").withLoanTermFrequency("12")
|
||||||
|
.withLoanTermFrequencyAsMonths().withNumberOfRepayments("12").withRepaymentEveryAfter("1")
|
||||||
|
.withRepaymentFrequencyTypeAsMonths().withInterestRatePerPeriod("1").withExpectedDisbursementDate("01 March 2014")
|
||||||
|
.withTranches(createTranches).withSubmittedOnDate("01 March 2014")
|
||||||
|
.withRepaymentStrategy(LoanProductTestBuilder.ADVANCED_PAYMENT_ALLOCATION_STRATEGY).withAllowFullTermForTranche(false)
|
||||||
|
.build(clientId.toString(), loanProductId.toString(), null);
|
||||||
|
|
||||||
|
final Integer loanId = this.loanTransactionHelper.getLoanId(loanApplicationJSON);
|
||||||
|
log.info("------------------LOAN CREATED WITH ID----------- {}", loanId);
|
||||||
|
|
||||||
|
GetLoansLoanIdResponse loanDetails = this.loanTransactionHelper.getLoanDetails((long) loanId);
|
||||||
|
assertNotNull(loanDetails);
|
||||||
|
assertEquals(false, loanDetails.getAllowFullTermForTranche());
|
||||||
|
log.info("-------------------LOAN LEVEL OVERRIDE OF allowFullTermForTranche WORKED SUCCESSFULLY-------");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -88,6 +88,7 @@ public class LoanApplicationTestBuilder {
|
|||||||
private boolean enableDownPayment = false;
|
private boolean enableDownPayment = false;
|
||||||
private boolean enableAutoRepaymentForDownPayment = false;
|
private boolean enableAutoRepaymentForDownPayment = false;
|
||||||
private String disbursedAmountPercentageDownPayment;
|
private String disbursedAmountPercentageDownPayment;
|
||||||
|
private Boolean allowFullTermForTranche = null;
|
||||||
|
|
||||||
public String build(final String clientID, final String groupID, final String loanProductId, final String savingsID) {
|
public String build(final String clientID, final String groupID, final String loanProductId, final String savingsID) {
|
||||||
final HashMap<String, Object> map = new HashMap<>();
|
final HashMap<String, Object> map = new HashMap<>();
|
||||||
@@ -220,6 +221,9 @@ public class LoanApplicationTestBuilder {
|
|||||||
if (disbursedAmountPercentageDownPayment != null) {
|
if (disbursedAmountPercentageDownPayment != null) {
|
||||||
map.put("disbursedAmountPercentageDownPayment", disbursedAmountPercentageDownPayment);
|
map.put("disbursedAmountPercentageDownPayment", disbursedAmountPercentageDownPayment);
|
||||||
}
|
}
|
||||||
|
if (allowFullTermForTranche != null) {
|
||||||
|
map.put("allowFullTermForTranche", allowFullTermForTranche);
|
||||||
|
}
|
||||||
LOG.info("Loan Application request : {} ", map);
|
LOG.info("Loan Application request : {} ", map);
|
||||||
return new Gson().toJson(map);
|
return new Gson().toJson(map);
|
||||||
}
|
}
|
||||||
@@ -468,4 +472,9 @@ public class LoanApplicationTestBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoanApplicationTestBuilder withAllowFullTermForTranche(final Boolean allowFullTermForTranche) {
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
@@ -113,6 +113,7 @@ public class LoanProductTestBuilder {
|
|||||||
private Account feeAndPenaltyAssetAccount;
|
private Account feeAndPenaltyAssetAccount;
|
||||||
|
|
||||||
private Boolean multiDisburseLoan = false;
|
private Boolean multiDisburseLoan = false;
|
||||||
|
private Boolean allowFullTermForTranche = false;
|
||||||
private final String outstandingLoanBalance = "35000";
|
private final String outstandingLoanBalance = "35000";
|
||||||
private String maxTrancheCount = "3";
|
private String maxTrancheCount = "3";
|
||||||
private Boolean disallowExpectedDisbursements = false;
|
private Boolean disallowExpectedDisbursements = false;
|
||||||
@@ -225,6 +226,7 @@ public class LoanProductTestBuilder {
|
|||||||
}
|
}
|
||||||
if (this.multiDisburseLoan) {
|
if (this.multiDisburseLoan) {
|
||||||
map.put("multiDisburseLoan", this.multiDisburseLoan);
|
map.put("multiDisburseLoan", this.multiDisburseLoan);
|
||||||
|
map.put("allowFullTermForTranche", this.allowFullTermForTranche);
|
||||||
map.put("maxTrancheCount", this.maxTrancheCount);
|
map.put("maxTrancheCount", this.maxTrancheCount);
|
||||||
map.put("outstandingLoanBalance", this.outstandingLoanBalance);
|
map.put("outstandingLoanBalance", this.outstandingLoanBalance);
|
||||||
map.put("disallowExpectedDisbursements", this.disallowExpectedDisbursements);
|
map.put("disallowExpectedDisbursements", this.disallowExpectedDisbursements);
|
||||||
@@ -242,6 +244,10 @@ public class LoanProductTestBuilder {
|
|||||||
map.put("maxTrancheCount", this.maxTrancheCount);
|
map.put("maxTrancheCount", this.maxTrancheCount);
|
||||||
map.put("outstandingLoanBalance", this.outstandingLoanBalance);
|
map.put("outstandingLoanBalance", this.outstandingLoanBalance);
|
||||||
}
|
}
|
||||||
|
// Always send allowFullTermForTranche when it's true (for validation testing of single-disburse scenarios)
|
||||||
|
if (this.allowFullTermForTranche && !this.multiDisburseLoan) {
|
||||||
|
map.put("allowFullTermForTranche", this.allowFullTermForTranche);
|
||||||
|
}
|
||||||
|
|
||||||
if (this.fullAccountingConfig != null) {
|
if (this.fullAccountingConfig != null) {
|
||||||
map.putAll(this.fullAccountingConfig.toMap());
|
map.putAll(this.fullAccountingConfig.toMap());
|
||||||
@@ -742,6 +748,11 @@ public class LoanProductTestBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoanProductTestBuilder withAllowFullTermForTranche(boolean allowFullTermForTranche) {
|
||||||
|
this.allowFullTermForTranche = allowFullTermForTranche;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public LoanProductTestBuilder withFeeToIncomeAccountMapping(final Long chargeId, final Long accountId) {
|
public LoanProductTestBuilder withFeeToIncomeAccountMapping(final Long chargeId, final Long accountId) {
|
||||||
if (this.feeToIncomeAccountMappings == null) {
|
if (this.feeToIncomeAccountMappings == null) {
|
||||||
this.feeToIncomeAccountMappings = new ArrayList<>();
|
this.feeToIncomeAccountMappings = new ArrayList<>();
|
||||||
|
|||||||
Reference in New Issue
Block a user