Aman-Mittal opened a new pull request, #658:
URL: https://github.com/apache/fineract-backoffice-ui/pull/658

   Adds real-backend coverage for accounting period closures, which had none.
   
   Of the 70 e2e specs, 31 run against a real Fineract instance, and the 
accounting area was the largest gap in that set: `loan-product-accounting` and 
`share-product-accounting` cover product mappings, `teller-cash-management` 
covers financial-activity mappings, and nothing covered closures. The only 
things touching the screen were a mocked route-navigation assertion in 
`feature-coverage` and a date-picker regression in `date-picker-revisit`.
   
   That gap hid a real defect. The list bound `closure.isClosed` — a field 
carried by neither `GetGlClosureResponse` nor the live payload 
(`{"id":1,…,"deleted":false,"allowedOffices":[]}`) — through an untyped 
`appCellTemplate` context, so **every closed period rendered as "Open"**. 
`strictTemplates` cannot see into an untyped context to catch it, and the unit 
test's fixtures came from the same generated type that was missing the field. 
The adapter now derives `isClosed` from `deleted`, but nothing guarded the fix.
   
   ## What the spec asserts
   
   **A closed period reads as Closed, and the platform refuses a posting inside 
it.** The round trip, in order:
   
   1. Post a balanced manual journal entry in a freshly seeded branch — 
**succeeds**, so a later refusal cannot be blamed on the GL accounts or the 
office.
   2. Close the period for that branch through the UI form. The POST must be 
accepted: the adapter owns the date format and locale the platform parses, so a 
400 here is exactly the coupling this spec exists to catch.
   3. The new row's status chip reads `Closed`. This is the regression guard, 
asserted on `.status-chip` rather than the row because the row also holds a 
"Re-open Period" control.
   4. Post the same entry again — **refused**, with 
`error.msg.glJournalEntry.invalid.accounting.closed`. Asserted on the 
globalisation code rather than the 403 alone, so it cannot pass on an unrelated 
refusal such as a missing permission.
   5. Re-open the period through the UI, accepting the native confirm.
   6. Post the entry a third time — **succeeds**. This is what makes the 
re-open real rather than cosmetic.
   
   A row appearing in a list proves the POST was accepted; it does not prove 
the period is closed. Steps 4–6 are the half no mock can give.
   
   **The form keeps the user on the page and names the reason when Fineract 
refuses.** With a closure already in place for the office, a second one for the 
same date is refused (`error.msg.glclosure.glcode.duplicate`). The form's error 
handler only clears the saving flag, so the global interceptor's toast is the 
whole of the feedback — if that ever stops firing here, the screen silently 
re-enables the button and says nothing about why the period was not closed.
   
   ## Seed helpers
   
   `seedManualJournalEntry` did three things at once and threw on a non-ok 
response, so a spec that needs to watch a posting be *refused* could use none 
of it. Split into `seedGlAccountPair` and `attemptJournalEntry`, the latter 
returning the raw response so a caller can assert on a refusal's status and 
code. `seedManualJournalEntry` composes the two and keeps its previous 
throw-on-failure contract; the payload shape, GL account types and code 
prefixes are unchanged. Adds `seedAccountingClosure` and 
`deleteAccountingClosure`, the delete tolerating a 404 so a spec that re-opens 
through the UI can still clean up in teardown without failing for having 
succeeded.
   
   **Every closure is scoped to a freshly seeded branch office, never Head 
Office.** A closure is enforced over an office's whole subtree, so closing Head 
Office would make the platform refuse the postings the loan, savings and teller 
specs depend on — and they would fail for a reason nothing in them names. Both 
tests delete their closure in a `finally`, so a failed run does not leave one 
behind.
   
   ## Verification
   
   Each premise was probed directly against the running instance before being 
written into an assertion, because the first version of the spec guessed the 
globalisation code wrong (`error.msg.glJournalEntry.accounting.closure`, which 
does not exist):
   
   | Probe | Result |
   |---|---|
   | Posting in an open period | 200 |
   | Posting inside a closed period | 403 
`error.msg.glJournalEntry.invalid.accounting.closed` |
   | Posting after the closure is deleted | 200 |
   | Second closure, same office and date | 403 
`error.msg.glclosure.glcode.duplicate` |
   
   Test runs:
   
   ```
   npx playwright test --project=backend accounting-closure-backend.spec.ts
       3 passed (46.1s)
   
   npx playwright test --project=backend accounting-closure-backend.spec.ts 
parity-screens.spec.ts
       11 passed (1.3m)     — parity-screens is the existing caller of the 
refactored helper
   
   npm run typecheck:e2e          clean
   npm run lint                   clean
   scripts/check-license.sh       all files have license headers
   prettier --check               unchanged on all three files
   ```
   
   **The regression guard was validated by reintroducing the defect.** Binding 
the chip back to a field the adapter model does not expose makes the test fail 
with `locator resolved to <span class="status-chip open"> Open </span>`, so the 
assertion fails when the bug returns rather than merely passing today. The 
component was restored from git afterwards.
   
   Nothing under `src/` is changed — this is e2e coverage and one new entry in 
`BACKEND_SPECS`.
   


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