FINERACT-2455: WC - Loan Product Template Update Advanced Payment Allocation Transaction Type List - #6467
Conversation
4c12ade to
a2fc349
Compare
|
@somasorosdpc Please review the below findings / concerns: Findings
Two notes that aren't findings: the new enum's loanTransactionType field and isDefault() are currently unused (all domain/persistence code still uses the core enum), and WorkingCapitalLoanProductCRUDTest only asserts the template list is non-empty — nothing pins the restricted set, so the change has no test coverage. |
a2fc349 to
c86e17e
Compare
|
@adamsaghy I fixed all the issues.
|
adamsaghy
left a comment
There was a problem hiding this comment.
Please review the below findings / concerns:
- isValid is case-insensitive but the enum lookup is not → misleading error message
WorkingCapitalPaymentAllocationTransactionType.isValid() matches with strip().equalsIgnoreCase(), while the parser then resolves with Enums.getIfPresent(PaymentAllocationTransactionType.class, transactionType), which is an exact-name match:
if (WorkingCapitalPaymentAllocationTransactionType.isValid(transactionType)) {
rule.setTransactionType(Enums.getIfPresent(PaymentAllocationTransactionType.class, transactionType).orNull());
}
WorkingCapitalAdvancedPaymentAllocationsJsonParser.java:66
I traced this through: "default" or " REPAYMENT " passes the gate, getIfPresent returns absent, and the rule is stored with transactionType == null. Nothing is wrongly accepted — WorkingCapitalAdvancedPaymentAllocationsValidator.validate always rejects it — but the error the caller gets is the wrong one:
single rule with "default" → wc-payment-allocation-without-default, "At least one DEFAULT payment allocation must be provided"
two mis-cased rules alongside a valid DEFAULT → both collapse to null → wc-payment-allocation-with-duplicate-transaction-type, "The same transaction type must be provided only once"
Neither tells the user their casing is wrong. Simplest fix: make isValid an exact-name match (v.name().equals(transactionType)), so the gate and the lookup agree and the new wc-payment-allocation-transaction-type-not-supported error is what fires.
- Error reporting duplicates the validator and changes an existing error code
The new else branch hand-rolls the exception the validator already has a helper for (validator.raiseValidationError(code, msg) — the parser holds a validator reference), and it introduces a second code for what is conceptually the same failure as the existing wc-payment-allocation.with.not.valid.transaction.type. Two smaller points on top:
The new code uses dashes throughout (wc-payment-allocation-transaction-type-not-supported) whereas the validator's transaction-type code is dot-separated; worth matching one convention.
A missing transactionType (previously left null and reported by the validator as wc-payment-allocation.with.not.valid.transaction.type) now produces the new code and the message "Invalid transaction type" instead. That's an API error-code change for existing clients. Also, the message names neither the parameter nor the offending value — including the rejected value and the supported list would make it actionable.
3. The template's id values change meaning, silently
Old: PaymentAllocationTransactionType.getValuesAsEnumOptionDataList() uses ordinal() + 1 → DEFAULT=1, REPAYMENT=2, PAYOUT_REFUND=5, GOODWILL_CREDIT=6, CHARGE_ADJUSTMENT=8.
New: WorkingCapitalPaymentAllocationTransactionType.java:42 uses LoanTransactionType.getValue() with 0L for DEFAULT → 0, 2, 22, 23, 26.
So the same field (advancedPaymentAllocationTransactionTypes) now returns different ids for WC products than for regular loan products, and 0 is used as a sentinel for DEFAULT. If intentional, fine — but it isn't mentioned anywhere and the added test only asserts on getCode(), so nothing pins the ids. Either assert them in the test or keep the core ordinal() + 1 convention.
- Test coverage only exercises the template, not the new rejection
The added assertions in WorkingCapitalLoanProductCRUDTest.testRetrieveTemplate cover the listing. The behavioural change with actual impact — create/update of a WC product (and of a WC loan application, via the shared parser) with e.g. DOWN_PAYMENT, INTEREST_REFUND, MERCHANT_ISSUED_REFUND now being rejected where it previously succeeded — has no test. I checked: no existing WC test uses one of the dropped types, so nothing breaks, but that also means nothing guards the new rule. A negative test asserting the new error code on POST/PUT would be worth adding, and this API break deserves a line in the PR description.
- Nit — the new enum has no link to the one it gates
WorkingCapitalPaymentAllocationTransactionType mirrors PaymentAllocationTransactionType but the parser still resolves by string against the core enum. A toPaymentAllocationTransactionType() on the new enum (returning the mapped core constant) would remove the double lookup and make a future WC-only constant with no core counterpart a compile error rather than a silent null.
c86e17e to
1cd10f0
Compare
…t Allocation Transaction Type' field
1cd10f0 to
1f0120d
Compare
|
@adamsaghy I fixed the following issues:
|
bde4923 to
604597e
Compare
|
API backward compatibility should fail, because API changed. We no longer accept few values on create/edit loan product - advanced payment allocation - transaction type field, and it is documented on swagger. |
galovics
left a comment
There was a problem hiding this comment.
The design is good: the new WorkingCapitalPaymentAllocationTransactionType enum is the single source for the template, the parser/validator and the loan-level override path, so they can't drift, and the five allowed types (DEFAULT, REPAYMENT, PAYOUT_REFUND, GOODWILL_CREDIT, CHARGE_ADJUSTMENT) are exactly the ones the allocator and WorkingCapitalLoanWritePlatformServiceImpl handle (GOODWILL_CREDIT is included, so the #6349 problem doesn't come back). Keeping the core ordinals as ids is the right call. But the PR fails a required gate because it deliberately breaks the request contract.
API compatibility. run-api-backward-compatibility fails with R011 (request enum value deleted) for 9 values on POST /v1/working-capital-loan-products and both PUTs. The template change itself is additive, but this is a real break, not just a noisy check: WC shipped with the full list in allowableValues, so clients sending those values used to get 201/200 and now get 400. The break is presumably right (those types never did anything on WC), but it needs an explicit maintainer decision rather than merging around a red check, and the PR description is still the empty template with no justification.
Existing data. A product created earlier may already have, say, an INTEREST_REFUND rule saved. After this, a client that GETs, edits something, and PUTs the paymentAllocation back gets a 400 (wc-payment-allocation.with.not.valid.transaction.type), and the loan-level override goes through the same parser. Can we either add a Liquibase changeset removing unsupported rules from the product (and loan) allocation rule tables, or at least record it as a breaking change for the release notes?
Smaller:
- The Swagger
allowableValuesis a second hardcoded copy of the list (annotations can't referencevalues()), with nothing checking they match - a reflection unit test asserting equality with the enum would catch drift. The loan-levelPostPaymentAllocationRule.transactionTypenow enforces the same five values but documents none. WorkingCapitalLoanBusinessEventSerializer.PAYMENT_TRANSACTION_TYPESis another pre-existing copy of the same set (enum minus DEFAULT) - worth deriving from the enum in a follow-up.validateAllocationRule's null-type check is now unreachable because the parser throws first.- No test covers the loan application override path (
POST /working-capital-loanswithpaymentAllocation), which this also restricts. - Two commits under the same key - squash.
Recommendation: CHANGES_REQUESTED
Description
Describe the changes made and why they were made. (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!
Your assigned reviewer(s) will follow our guidelines for code reviews.