ayushcodes27 opened a new pull request, #204:
URL: https://github.com/apache/fineract-consumer-facing/pull/204

   ## What and why
   
   Transfers from a customer's savings account to their own loan account 
currently lack server-side validation against the loan's outstanding balance, 
allowing overpayments that require manual backoffice approval to credit back.
   
   This PR adds validation in the BFF transfers command service to enforce 
payment limits against the loan's current outstanding balance 
(`totalOutstanding`) and active status:
   - Verifies ABAC resource ownership first before querying the loan, avoiding 
unauthorized lookups or leaking loan state to non-owners.
   - Validates loan status (`active == true`) and balance (`amount <= 
totalOutstanding`) during `initiate` (preventing step-up OTP issuance for 
invalid amounts) and re-validates during `confirm` (guarding against balance 
changes during the OTP window).
   - Rejects overpayments with HTTP 422 `TransferLoanOverpaymentException` and 
inactive/zero-balance loans with HTTP 422 `TransferLoanNotActiveException`.
   - Adds i18n error translations for English and Hindi.
   
   Closes #114
   
   > [!NOTE]
   > **Design Considerations:**
   > - **Accrual considerations:** The limit is based on 
`loan.summary.totalOutstanding`. Note that this has not been benchmarked 
against products with complex mid-cycle daily interest recalculations or 
early-foreclosure fees.
   > - **Configurability:** Currently enforced as a standard domain rule 
capping repayments at `totalOutstanding`. Happy to make this configurable per 
product or via application property if maintainers prefer allowing intentional 
prepayment on specific products.
   
   ## Verification
   
   - Ran `TransfersCommandServiceImplTest` (28 unit tests passing):
     - `initiate` and `confirm` allow transfers where amount < outstanding.
     - Symmetrical boundary tests where amount == outstanding pass at both 
`initiate` and `confirm`.
     - Amount > outstanding throws `TransferLoanOverpaymentException` at 
`initiate` (verifying no OTP or step-up token is issued) and at `confirm` 
(verifying no upstream call).
     - Inactive loans and zero-balance loans throw 
`TransferLoanNotActiveException` at both phases.
     - Unowned loans fail ownership check first with 
`TransferAccessDeniedException` without calling `LoansQueryService`.
   - Ran `ModulithArchitectureTest` 
(`ApplicationModules.of(ConsumerApplication.class).verify()`): PASSED.
   - Ran `CodingConventionsArchitectureTest` (ArchUnit conventions): PASSED.
   - Validated JSON syntax for `en.json` and `hi.json`: PASSED.
   
   ## Screenshots
   
   Not applicable (backend validation & error code translations).
   
   ## AI assistance (optional)
   
   - Tool / model: Gemini
   - Harness / workflow: Assisted in workflow testing, code reviews, debugging, 
and end-to-end validation.
   
   ## Checklist
   
   - [x] I did not hand-edit generated files under 
`frontend/src/openapi-client/`.
   - [x] Backend code follows the feature and CQRS layout in 
[AGENTS.md](AGENTS.md#backend-conventions-consumer) (command and query sides, 
module boundaries); frontend code goes through the adapters in 
`frontend/src/app/core/adapters/`.
   - [x] I did not add entries to a lint or architecture baseline 
(suppressions, frozen violations) to get the build passing.
   - [x] User-facing strings use translation keys.
   - [x] I added or updated tests appropriate to this change, or explained why 
tests were not needed.
   - [x] UI workflow changes include suitable e2e coverage, including 
real-backend testing where relevant.
   - [x] Commits are signed — see [Signing your 
commits](CONTRIBUTING.md#signing-your-commits) in CONTRIBUTING.md.
   - [x] I followed the [AI-assisted contributions 
guidance](CONTRIBUTING.md#ai-assisted-contributions).
   - [x] If this adds a feature or changes what a consumer can see or do, I 
raised it on 
[[email protected]](https://lists.apache.org/[email protected])
 first, or it is a bug fix, refactor or test change, where that does not apply.
   


-- 
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