Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@JohnAlva
Copy link
Contributor

Description

Reverse of Accruals to adjust late deposits

-When accruals are run and there is a balance change on the account within the period, the previously posted accruals will be reversed.

Ignore if these details are present on the associated Apache Fineract JIRA ticket.

Checklist

Please make sure these boxes are checked before submitting your pull request - thanks!

  • Write the commit message as per https://github.com/apache/fineract/#pull-requests
  • Acknowledge that we will not review PRs that are not passing the build ("green") - it is your responsibility to get a proposed PR to pass the build, not primarily the project's maintainers.
  • Create/update unit or integration tests for verifying the changes made.
  • Follow coding conventions at https://cwiki.apache.org/confluence/display/FINERACT/Coding+Conventions.
  • Add required Swagger annotation and update API documentation at fineract-provider/src/main/resources/static/legacy-docs/apiLive.htm with details of any API changes
  • Submission is not a "code dump". (Large changes can be made "in repository" via a branch. Ask on the developer mailing list for guidance, if required.)

FYI our guidelines for code reviews are at https://cwiki.apache.org/confluence/display/FINERACT/Code+Review+Guide.

@adamsaghy
Copy link
Contributor

@JohnAlva Please drop this generic "Savings Accounts Improvements" and start using clear, descriptive short description for the PRs!

@JohnAlva
Copy link
Contributor Author

Hi @adamsaghy, thank you for the feedback.

Just to clarify, this PR is indeed related to the overall "Savings Accounts Improvements" initiative. The team decided to split the changes into multiple PRs to improve clarity and facilitate the review process, while keeping a consistent title to reflect that they all belong to the same scope.

@adamsaghy
Copy link
Contributor

Hi @adamsaghy, thank you for the feedback.

Just to clarify, this PR is indeed related to the overall "Savings Accounts Improvements" initiative. The team decided to split the changes into multiple PRs to improve clarity and facilitate the review process, while keeping a consistent title to reflect that they all belong to the same scope.

The Fineract story id just fine to connect them. The PR title should tell exactly what it is doing and "improvements" is too generic and useless. Kindly asking you to rename it!

@JohnAlva JohnAlva changed the title FINERACT-2312: Savings Accounts Improvements FINERACT-2312: Reverse of Accruals to adjust late deposits Jul 30, 2025
@JohnAlva
Copy link
Contributor Author

@adamsaghy sorry, but we already changed the name of each PR for each section.

@JohnAlva
Copy link
Contributor Author

Hi @adamsaghy, a quick review on this PR would be awesome. Thanks a lot in advance!

.toList();
}

public void accrualsForSavingsReverse(SavingsAccountTransactionDTO transactionDTO, final boolean backdatedTxnsAllowedTill) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do? Can you please give an example?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method reverts all accrual transactions on or after the given transaction date. It’s used when a backdated transaction is added (like a late deposit), so previously posted accruals can be recalculated correctly.

--Example:-- If a deposit is backdated to July 15 and accruals were posted on July 15, 20, and 25, those accruals will be reversed to allow correct recomputation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How the system will know the accruals were reversed, so during the next calculation it should start from that particular date?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JohnAlva well?

Copy link
Contributor

@adamsaghy adamsaghy Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JohnAlva How the system will know the accruals were reversed, so during the next calculation it should start from that particular date?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @adamsaghy

The calculation process likely still loops through the account's entire history. However:

*Accruals before the backdated transaction are untouched and skipped.

*The reversed flag on accruals on or after that date acts as a signal. It tells the system: "This is where you need to replace the old value with a new calculation."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JohnAlva @sayhaed Is this only true if there was no existing not reversed Accrual for that particular date, no?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @adamsaghy
The process is designed to handle that scenario correctly. The reversal logic will find and reverse all accrual transactions on or after the backdated transaction's date, regardless of their previous state (whether they were already reversed or not).

This ensures we always start with a clean slate before the recalculation step runs, which prevents any duplicate, active accruals for a given date.

Hope that clarifies it!

@adamsaghy
Copy link
Contributor

@JohnAlva All PR should involve proper testing attached!

} else {
accountTransactionsSorted = retrieveListOfTransactions();
}
for (final SavingsAccountTransaction transaction : accountTransactionsSorted) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also i am missing test cases to cover the functionality.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we added the test cases for this functionality

Copy link
Contributor

@adamsaghy adamsaghy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review my comments!

@JohnAlva JohnAlva marked this pull request as draft August 15, 2025 17:08
@JohnAlva
Copy link
Contributor Author

It is put in draft by dependency to pr #4885

@JohnAlva JohnAlva marked this pull request as ready for review August 20, 2025 21:49
@sayhaed sayhaed force-pushed the reverse_accruals branch 7 times, most recently from e137ccf to 2f675b0 Compare August 22, 2025 15:16
@sayhaed
Copy link
Contributor

sayhaed commented Aug 22, 2025

Sure we made the changes, can you help us with the review

@JohnAlva JohnAlva requested a review from adamsaghy August 22, 2025 17:10
@sayhaed
Copy link
Contributor

sayhaed commented Aug 25, 2025

Hi @adamsaghy, can you help us with the review please?

@IOhacker
Copy link
Contributor

LGTM


final List<LocalDate> accrualTransactionDates = savingsAccount.retrieveOrderedAccrualTransactions().stream()
.map(transaction -> transaction.getTransactionDate()).toList();
final List<LocalDate> accrualTransactionDatesReverse = savingsAccount.retrieveOrderedAccrualTransactions().stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please rename this field? At first glance it seems to be a list of accrual transactions in reverse date order, but in fact it’s a list of reversed accrual transactions. The name should make that explicit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure we will change that part


for (PostingPeriod period : allPostingPeriods) {
LocalDate valueDate = period.getPeriodInterval().endDate();
List<LocalDate> matchingAccrualDates = accrualTransactionDatesReverse.stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you help me understand this logic? I have no clue why we need reversed accrual transactions with transaction date that matches with the period end date.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @adamsaghy

Basically, that code handles the cleanup after a user reverses an old accrual. It makes sure we create a new transaction to replace the reversed one, even if the new interest amount is zero.

This is to avoid leaving a "hole" in the transaction history and to keep the accounting records correct.

Copy link
Contributor

@adamsaghy adamsaghy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please kindly see my concerns!

Copy link
Contributor

@sayhaed sayhaed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @adamsaghy can you help us wit the review :)


for (PostingPeriod period : allPostingPeriods) {
LocalDate valueDate = period.getPeriodInterval().endDate();
List<LocalDate> matchingAccrualDates = accrualTransactionDatesReverse.stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @adamsaghy

Basically, that code handles the cleanup after a user reverses an old accrual. It makes sure we create a new transaction to replace the reversed one, even if the new interest amount is zero.

This is to avoid leaving a "hole" in the transaction history and to keep the accounting records correct.


final List<LocalDate> accrualTransactionDates = savingsAccount.retrieveOrderedAccrualTransactions().stream()
.map(transaction -> transaction.getTransactionDate()).toList();
final List<LocalDate> accrualTransactionDatesReverse = savingsAccount.retrieveOrderedAccrualTransactions().stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure we will change that part

@adamsaghy
Copy link
Contributor

#4904 (comment)
We cannot have Accrual transactions with amount of 0!

@sayhaed
Copy link
Contributor

sayhaed commented Aug 27, 2025

You are absolutely right, and my apologies for the confusing explanation. We cannot have accrual transactions with a zero amount.

The intent of this code is to correctly adjust accruals after back-dated transactions are made. If a deposit or withdrawal affects a past period, the original accrual is reversed. This logic then triggers a recalculation to post the new, correct accrual based on the updated transaction history.

Its purpose is strictly for this adjustment process, not to create zero-amount transactions.

@JohnAlva JohnAlva requested a review from adamsaghy August 27, 2025 17:18
@adamsaghy
Copy link
Contributor

adamsaghy commented Aug 28, 2025

@JohnAlva @sayhaed I see no changes and some of my questions are waiting to be answered!

@sayhaed
Copy link
Contributor

sayhaed commented Aug 28, 2025

Hi @adamsaghy,

Thanks for the follow-up. I have now replied to your previous technical question.

As that explanation shows, the current logic already handles the scenario you described correctly, which is why no code changes were necessary.

Thank you again for your insightful comments. I hope my answers have addressed all your questions.

@IOhacker
Copy link
Contributor

IOhacker commented Sep 3, 2025

LGTM

@adamsaghy adamsaghy merged commit fb8f2f7 into apache:develop Sep 4, 2025
39 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants