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]