naman2627 opened a new pull request, #6547:
URL: https://github.com/apache/fineract/pull/6547

   ## Problem
   `SavingsAccountInterestPostingServiceImpl` selects the transactions for a 
posting period by comparing only the calendar month:
   `periodInterval.startDate().getMonth() == tx.getDate().getMonth()`
   in `listForOverdraft`, `listForInterestPosting` and `isOverdraftAccount` 
(introduced in FINERACT-2312, a6fa1adc99).
   
   This ignores the year and the posting period's real start/end dates, so 
transactions outside the period's first month are dropped and the days their 
balances cover earn no interest.
   
   Reproduced (overdraft + interest-receivable, accrual periodic, 10% nominal, 
daily compounding, daily balance, 365 days, QUARTERLY posting; deposits of 
10,000 on 2025-01-01 and 10,000 on 2025-02-15, up-to date 2025-04-02):
   - Expected Q1 interest: **373.64**
   - Actual on develop: **124.03** (shortfall 249.61, ~two-thirds)
   - Same inputs without overdraft/interest-receivable (non-split branch): 
373.64, correct
   
   **Scope is wider than the JIRA title suggests.** Monthly posting is also 
affected whenever a period's first transaction isn't on the 1st — the balance 
carried over from the previous month is dropped. The existing integration tests 
always place transactions on the first day of a period, which is why this 
wasn't caught.
   
   ## Fix
   Replace the four month-equality checks with an interval-overlap check 
against the posting period:
   
   ```java
   private static boolean hasBalanceWithin(final SavingsAccountTransactionData 
tx, final LocalDateInterval periodInterval) {
       return tx.fallsWithin(periodInterval) || 
tx.spansAnyPortionOf(periodInterval);
   }
   ```
   
   `fallsWithin` and `spansAnyPortionOf` are existing methods (since 2022) and 
are the same pair `PostingPeriod#createFromDTO` already uses to decide which 
transactions contribute to a period — so the list-building filter now matches 
the criteria the interest calculation itself applies. Both compare the 
transaction's balance span (`transactionDate` → `balanceEndDate`), inclusive at 
both ends, and a balance straddling a period boundary is capped by the existing 
`toEndOfDayBalanceBoundedBy`.
   
   The overdraft/regular classification (`MathUtil.isLessThanZero(...)` on the 
running balance) is **unchanged** — only the date filter is corrected. This 
also resolves the idle-overdraft-month case as a consequence of the same 
filter; it does not change the behaviour covered by FINERACT-2869 (#6532).
   
   +9/−4 in one file, plus tests. No refactors.
   
   ## Verification
   - New `SavingsAccountOverdraftInterestSplitTest`, both cases fail on develop 
and pass with the fix:
     - quarterly: split path posts 373.64 (was 124.03), matching the non-split 
control
     - monthly: confirms the carried-over overdraft balance is counted once, 
not twice — with the fix the split result matches the non-split control of 
−86.16 to within one rounding step (0.01); on develop the split path gives 
+24.56 instead
   - `:fineract-savings:test` passes: **57/57**, including the existing savings 
tests.
   - `spotlessApply` clean.
   - **Not run:** the full `gradlew build` did not complete locally — it hit an 
out-of-memory crash on my machine in unrelated modules (`oauth2-tests`, 
`twofactor-tests`, `custom/acme`), not in savings. `SavingsInterestPostingTest` 
(integration-tests module) also wasn't run as it needs a running server. 
Relying on CI for both.
   
   Resolves FINERACT-2881.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to