Cocoa-Puffs opened a new pull request, #6707:
URL: https://github.com/apache/fineract/pull/6707

   ## Description
   
   The loan transaction adjust endpoint (`POST 
/loans/{loanId}/transactions/{transactionId}` with `transactionAmount > 0`) 
reverses a transaction and replaces it with a new one of the same type. Payout 
Refund, Goodwill Credit and Merchant Issued Refund could only be reversed, not 
adjusted. Charge Adjustment could be adjusted, but the replacement lost its 
link to the loan charge. This PR makes all four adjustable.
   
   ### Changes
   
   **Payout Refund, Merchant Issued Refund, Goodwill Credit**
   - `LoanTransaction.isEditable()` now blocks only Chargeback.
   - Payout Refund and Merchant Issued Refund adjustment is rejected when:
     - the loan calculates Interest Refunds for that type 
(`error.msg.loan.transaction.adjust.not.allowed.when.interest.refund.enabled`), 
or
     - the refund already has a non-reversed Interest Refund linked to it 
(`error.msg.loan.transaction.adjust.not.allowed.when.interest.refund.exists`). 
The replacement gets no new Interest Refund, so allowing this would silently 
drop it.
   - Reversal (amount 0) is unchanged and still reverses the linked Interest 
Refund.
   - Goodwill Credit is always adjustable.
   
   **Charge Adjustment**
   - The replacement keeps its `CHARGE_ADJUSTMENT` link to the same loan 
charge, so journal entries and later available-amount checks still resolve the 
charge.
   - The new amount is validated against the amount still available for 
adjustment on that charge. The transaction being replaced counts as available 
again.
   - The adjustment date can't be earlier than the charge's effective date, 
which is the earlier of its submitted-on and due dates. The regular 
charge-adjustment endpoint always uses the business date; the adjust endpoint 
takes a date from the request.
   - The loan-status check now matches the regular charge-adjustment endpoint.
   - A charge adjustment without a charge link (legacy data, see below) is 
rejected with `error.msg.loan.charge.adjustment.charge.not.found` instead of 
failing with an HTTP 500. It can still be reversed.
   
   **Refactoring**
   - The charge-adjustment validations were moved from 
`LoanChargeWritePlatformServiceImpl` into `LoanChargeValidator`, so the create 
and adjust paths share them.
   - `LoanAdjustmentServiceImpl` first validates the replacement 
(`validateReplacement`), then builds it in a single switch on the type 
(`buildReplacementTransaction`).
   - The linked Interest Refund lookup, both in the pre-check and in the 
reversal inside `adjustExistingTransaction`, is now one repository query: 
`LoanTransactionRelationRepository.findNonReversedInterestRefundsRelatedTo`. It 
replaces an in-memory scan of all loan transactions and their lazily loaded 
relations.
   
   **Migration**
   `1036_link_unlinked_charge_adjustments.xml` restores the missing charge link 
on legacy Charge Adjustments created by earlier adjustments. It recovers the 
charge by following ADJUST commands and REPLAYED relations back to the original 
linked transaction.
   
   ### Notes for reviewers
   
   - **Legacy data and migration:** before this change, adjusting a Charge 
Adjustment created a replacement with no link to the loan charge. With this PR 
such rows are rejected with `error.msg.loan.charge.adjustment.charge.not.found` 
(previously an HTTP 500). They would otherwise block every new charge 
adjustment on the loan. `1036_link_unlinked_charge_adjustments.xml` restores 
the missing link. For each unlinked row it walks back through the transactions 
it replaced, using two kinds of step:
     - the ADJUST command that created it 
(`m_portfolio_command_source.api_get_url` holds the original transaction);
     - `REPLAYED` relations (a replay copies the relations of the transaction 
it replaces, so a replayed unlinked row is unlinked too).
   
     It stops at the first Charge Adjustment on the same loan that is linked to 
that loan's charge, and inserts the link with audit values copied from the 
unlinked row. Rows without such a trail, or whose ancestors point to different 
charges, are left unchanged and still rejected. Running it again inserts 
nothing.
   - **Interest Refund override:** `interestRefundCalculation=true` on a refund 
creates no Interest Refund unless the loan already lists that refund type, 
because the Interest Refund calculation only counts listed types. So with the 
setting off, such refunds can be adjusted. An integration test covers this.
   - **Inactive charges:** neither the regular charge-adjustment endpoint nor 
the adjust path checks whether the loan charge is still active. For example, 
`deactivateOverdueLoanCharge` leaves existing charge adjustments in place. This 
PR keeps the adjust path consistent with the create path and adds no new 
restriction. A follow-up ticket could be created for this issue.
   
   ## Checklist
   
   Please make sure these boxes are checked before submitting your pull request 
- thanks!
   
   - [ ] Write the commit message as per [our 
guidelines](https://github.com/apache/fineract/blob/develop/CONTRIBUTING.md#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](https://fineract.apache.org/docs/current/#_testing) for verifying the 
changes made.
   - [ ] Follow our [coding 
conventions](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
   - [ ] [This PR must not be a "code 
dump"](https://cwiki.apache.org/confluence/display/FINERACT/Pull+Request+Size+Limit).
 Large changes can be made in a branch, with assistance. Ask for help on the 
[developer mailing list](https://fineract.apache.org/#contribute).
   - [ ] If merging this PR resolves a JIRA issue, I will mark that issue as 
resolved and set "Fix Version/s" appropriately.
   - [ ] I followed the [AI 
Policy](https://github.com/apache/fineract/blob/develop/CONTRIBUTING.md#ai-policy).
   
   Your assigned reviewer(s) will follow our [guidelines for code 
reviews](https://cwiki.apache.org/confluence/display/FINERACT/Code+Review+Guide).
   


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