Skip to content

Commit

Permalink
FINERACT-1981: Allow for calculation of Interest on first day
Browse files Browse the repository at this point in the history
  • Loading branch information
Jose Alberto Hernandez committed Feb 3, 2025
1 parent 0b9687d commit ed5da06
Show file tree
Hide file tree
Showing 11 changed files with 124 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,9 @@ public class Loan extends AbstractAuditableWithUTCDateTimeCustom<Long> {
@Column(name = "enable_installment_level_delinquency", nullable = false)
private boolean enableInstallmentLevelDelinquency = false;

@Column(name = "interest_recognition_on_disbursement_date", nullable = false)
private boolean isInterestRecognitionOnDisbursementDate = false;

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 LoanRepaymentScheduleTransactionProcessor transactionProcessingStrategy,
Expand All @@ -482,12 +485,13 @@ public static Loan newIndividualLoanApplication(final String accountNo, final Cl
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate,
final Boolean isInterestRecognitionOnDisbursementDate) {
return new Loan(accountNo, client, null, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
loanRepaymentScheduleDetail, null, loanCharges, collateral, null, fixedEmiAmount, disbursementDetails,
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
enableInstallmentLevelDelinquency, submittedOnDate);
enableInstallmentLevelDelinquency, submittedOnDate, isInterestRecognitionOnDisbursementDate);
}

public static Loan newGroupLoanApplication(final String accountNo, final Group group, final AccountType loanType,
Expand All @@ -499,12 +503,13 @@ public static Loan newGroupLoanApplication(final String accountNo, final Group g
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate,
final Boolean isInterestRecognitionOnDisbursementDate) {
return new Loan(accountNo, null, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
enableInstallmentLevelDelinquency, submittedOnDate);
enableInstallmentLevelDelinquency, submittedOnDate, isInterestRecognitionOnDisbursementDate);
}

public static Loan newIndividualLoanApplicationFromGroup(final String accountNo, final Client client, final Group group,
Expand All @@ -516,12 +521,13 @@ public static Loan newIndividualLoanApplicationFromGroup(final String accountNo,
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate,
final Boolean isInterestRecognitionOnDisbursementDate) {
return new Loan(accountNo, client, group, loanType, fund, officer, loanPurpose, transactionProcessingStrategy, loanProduct,
loanRepaymentScheduleDetail, null, loanCharges, null, syncDisbursementWithMeeting, fixedEmiAmount, disbursementDetails,
maxOutstandingLoanBalance, createStandingInstructionAtDisbursement, isFloatingInterestRate, interestRateDifferential, rates,
fixedPrincipalPercentagePerInstallment, externalId, loanApplicationTerms, loanScheduleModel,
enableInstallmentLevelDelinquency, submittedOnDate);
enableInstallmentLevelDelinquency, submittedOnDate, isInterestRecognitionOnDisbursementDate);
}

protected Loan() {
Expand All @@ -537,7 +543,8 @@ private Loan(final String accountNo, final Client client, final Group group, fin
final Boolean createStandingInstructionAtDisbursement, final Boolean isFloatingInterestRate,
final BigDecimal interestRateDifferential, final List<Rate> rates, final BigDecimal fixedPrincipalPercentagePerInstallment,
final ExternalId externalId, final LoanApplicationTerms loanApplicationTerms, final LoanScheduleModel loanScheduleModel,
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate) {
final Boolean enableInstallmentLevelDelinquency, final LocalDate submittedOnDate,
final Boolean isInterestRecognitionOnDisbursementDate) {
this.loanRepaymentScheduleDetail = loanRepaymentScheduleDetail;

this.isFloatingInterestRate = isFloatingInterestRate;
Expand Down Expand Up @@ -627,6 +634,7 @@ private Loan(final String accountNo, final Client client, final Group group, fin
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
this.getLoanProductRelatedDetail()
.setEnableAccrualActivityPosting(loanProduct.getLoanProductRelatedDetail().isEnableAccrualActivityPosting());
this.isInterestRecognitionOnDisbursementDate = isInterestRecognitionOnDisbursementDate;
}

public Integer getNumberOfRepayments() {
Expand Down Expand Up @@ -3560,6 +3568,10 @@ public void updateEnableInstallmentLevelDelinquency(boolean enableInstallmentLev
this.enableInstallmentLevelDelinquency = enableInstallmentLevelDelinquency;
}

public void updateInterestRecognitionOnDisbursementDate(boolean isInterestRecognitionOnDisbursementDate) {
this.isInterestRecognitionOnDisbursementDate = isInterestRecognitionOnDisbursementDate;
}

public void deductFromNetDisbursalAmount(final BigDecimal subtrahend) {
this.netDisbursalAmount = this.netDisbursalAmount.subtract(subtrahend);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,5 @@ public interface LoanProductConstants {
String SUPPORTED_INTEREST_REFUND_TYPES = "supportedInterestRefundTypes";
String CHARGE_OFF_BEHAVIOUR = "chargeOffBehaviour";

String INTEREST_RECOGNITION_ON_DISBURSEMENT_DATE = "interestRecognitionOnDisbursementDate";
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ private PostLoanProductsRequest() {}
public Integer repaymentStartDateType;
@Schema(example = "false")
public Boolean enableAccrualActivityPosting;
@Schema(example = "false")
public Boolean interestRecognitionOnDisbursementDate;

// Interest Recalculation
@Schema(example = "false")
Expand Down Expand Up @@ -1421,6 +1423,8 @@ private GetLoanCharge() {}
public List<StringEnumOptionData> supportedInterestRefundTypes;
public List<GetLoanProductsTemplateResponse.GetLoanProductsChargeOffReasonOptions> chargeOffReasonOptions;
public StringEnumOptionData chargeOffBehaviour;
@Schema(example = "false")
public Boolean interestRecognitionOnDisbursementDate;
}

@Schema(description = "PutLoanProductsProductIdRequest")
Expand Down Expand Up @@ -1558,6 +1562,8 @@ private PutLoanProductsProductIdRequest() {}
public Boolean enableAutoRepaymentForDownPayment;
@Schema(example = "1")
public Integer repaymentStartDateType;
@Schema(example = "false")
public Boolean interestRecognitionOnDisbursementDate;

// Interest Recalculation
@Schema(example = "false")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ public class LoanProductData implements Serializable {

private final EnumOptionData loanScheduleType;
private final EnumOptionData loanScheduleProcessingType;
private final boolean interestRecognitionOnDisbursementDate;

/**
* Used when returning lookup information about loan product for dropdowns.
Expand Down Expand Up @@ -338,6 +339,7 @@ public static LoanProductData lookup(final Long id, final String name, final Boo
final boolean enableAccrualActivityPosting = false;
final List<StringEnumOptionData> supportedInterestRefundTypes = null;
final StringEnumOptionData chargeOffBehaviour = null;
final boolean interestRecognitionOnDisbursementDate = false;

return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
Expand All @@ -358,7 +360,8 @@ public static LoanProductData lookup(final Long id, final String name, final Boo
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour);
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate);

}

Expand Down Expand Up @@ -461,6 +464,7 @@ public static LoanProductData lookupWithCurrency(final Long id, final String nam
final boolean enableAccrualActivityPosting = false;
final List<StringEnumOptionData> supportedInterestRefundTypes = null;
final StringEnumOptionData chargeOffBehaviour = null;
final boolean interestRecognitionOnDisbursementDate = false;

return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
Expand All @@ -481,7 +485,8 @@ public static LoanProductData lookupWithCurrency(final Long id, final String nam
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour);
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate);

}

Expand Down Expand Up @@ -591,6 +596,7 @@ public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
final boolean enableAccrualActivityPosting = false;
final List<StringEnumOptionData> supportedInterestRefundTypes = null;
final StringEnumOptionData chargeOffBehaviour = LoanChargeOffBehaviour.REGULAR.getValueAsStringEnumOptionData();
final boolean interestRecognitionOnDisbursementDate = false;

return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
Expand All @@ -611,7 +617,8 @@ public static LoanProductData sensibleDefaultsForNewLoanProductCreation() {
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocation, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour);
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate);

}

Expand Down Expand Up @@ -715,6 +722,7 @@ public static LoanProductData loanProductWithFloatingRates(final Long id, final
final boolean enableAccrualActivityPosting = false;
final List<StringEnumOptionData> supportedInterestRefundTypes = null;
final StringEnumOptionData chargeOffBehaviour = null;
final boolean interestRecognitionOnDisbursementDate = false;

return new LoanProductData(id, name, shortName, description, currency, principal, minPrincipal, maxPrincipal, tolerance,
numberOfRepayments, minNumberOfRepayments, maxNumberOfRepayments, repaymentEvery, interestRatePerPeriod,
Expand All @@ -735,7 +743,8 @@ public static LoanProductData loanProductWithFloatingRates(final Long id, final
fixedPrincipalPercentagePerInstallment, delinquencyBucketOptions, delinquencyBucket, dueDaysForRepaymentEvent,
overDueDaysForRepaymentEvent, enableDownPayment, disbursedAmountPercentageDownPayment, enableAutoRepaymentForDownPayment,
paymentAllocation, creditAllocationData, repaymentStartDateType, enableInstallmentLevelDelinquency, loanScheduleType,
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour);
loanScheduleProcessingType, fixedLength, enableAccrualActivityPosting, supportedInterestRefundTypes, chargeOffBehaviour,
interestRecognitionOnDisbursementDate);
}

public static LoanProductData withAccountingDetails(final LoanProductData productData, final Map<String, Object> accountingMappings,
Expand Down Expand Up @@ -789,7 +798,7 @@ public LoanProductData(final Long id, final String name, final String shortName,
final EnumOptionData repaymentStartDateType, final boolean enableInstallmentLevelDelinquency,
final EnumOptionData loanScheduleType, final EnumOptionData loanScheduleProcessingType, final Integer fixedLength,
final boolean enableAccrualActivityPosting, final List<StringEnumOptionData> supportedInterestRefundTypes,
StringEnumOptionData chargeOffBehaviour) {
StringEnumOptionData chargeOffBehaviour, final boolean interestRecognitionOnDisbursementDate) {
this.id = id;
this.name = name;
this.shortName = shortName;
Expand Down Expand Up @@ -932,6 +941,7 @@ public LoanProductData(final Long id, final String name, final String shortName,
this.chargeOffBehaviour = chargeOffBehaviour;
this.chargeOffBehaviourOptions = null;
this.chargeOffReasonOptions = null;
this.interestRecognitionOnDisbursementDate = interestRecognitionOnDisbursementDate;
}

public LoanProductData(final LoanProductData productData, final Collection<ChargeData> chargeOptions,
Expand Down Expand Up @@ -1116,6 +1126,7 @@ public LoanProductData(final LoanProductData productData, final Collection<Charg
this.chargeOffBehaviour = productData.chargeOffBehaviour;
this.chargeOffBehaviourOptions = chargeOffBehaviourOptions;
this.chargeOffReasonOptions = chargeOffReasonOptions;
this.interestRecognitionOnDisbursementDate = productData.interestRecognitionOnDisbursementDate;
}

private Collection<ChargeData> nullIfEmpty(final Collection<ChargeData> charges) {
Expand Down
Loading

0 comments on commit ed5da06

Please sign in to comment.