Aman-Mittal opened a new pull request, #686:
URL: https://github.com/apache/fineract-backoffice-ui/pull/686
## What and why
Adds `STAFF_API` and `HOLIDAY_API`, gives `OFFICE_API` the
`get`/`create`/`update` its own doc comment said to add once a caller existed,
and migrates **14 files**. Offices, staff and holidays are one domain in
Fineract's model — all three scoped by office — so they move together. The
`local/no-generated-api-import` baseline falls **458 → 444**.
Closes #680. Closes #682.
Every disagreement below was verified against a running `apache/fineract`.
### Staff: a display defect, and not the lesson you'd expect
`staff-form.component.ts` read `GET /staff/{id}`'s `joiningDate` through
`formatArrayDate()`, which answers the literal string `'-'` for anything that
is not a `[y, m, d]` array. This endpoint sends a **string**:
```
GET /staff/1 → "joiningDate":"2020-01-01" ← string
GET /offices → "openingDate":[2009,1,1] ← array
```
So the staff edit form displayed a dash where the joining date should be.
**Scope of the damage, checked rather than assumed:** the control is
`[disabled]="isEditMode"` and `onSubmit()` sends only `externalId` and
`isLoanOfficer` on that path, so nothing was persisted wrongly — display only.
Its spec passed throughout, on a fixture that invented `joiningDate: [2026, 1,
5]`.
The lesson is **not** "trust the generated type". `StaffData` declares
`joiningDate?: string` and is correct. It is that two endpoints in the same
Organization area encode dates two different ways, and nothing in the type says
which — so a screen cannot tell what it is getting and should not have to.
`toIsoFineractDate()` accepts both.
### Holidays: the familiar direction, three times over
`GetHolidaysResponse` declares `fromDate`, `toDate` and
`repaymentsRescheduledTo` as `string`; all three arrive as arrays.
`description` and `reschedulingType` are sent and never declared, so the form
recovered the rescheduling rule by checking whether a reschedule date happened
to be set.
And `PutHolidaysHolidayIdRequest` declares only `name` and `description`
while the endpoint accepts everything the form sends:
```json
{"resourceId":1,"changes":{"description":"probe","fromDate":"07 January
2027",
"toDate":"07 January 2027","repaymentsRescheduledTo":"08 January 2027",
...}}
```
The form was already sending all of it, through a `Record<string, unknown>`
cast to a type that declared none of it.
### Five copies of one conversion
Before this, `toIsoFineractDate`'s logic existed in **five** places: the
shared helper, `formatArrayDate` in `core/utils/date-formatter.ts`, a local
`formatArrayDate` method on `holidays-list.component.ts`, `pickerDate` in
`holiday-form.component.ts` (the same function rewritten line for line), and
inline in `transaction-detail-dialog.component.ts`. Every one takes `unknown`
or widens, because the declared type cannot be used. Two are gone here.
### Two transport concerns moved off their screens
- **Blank optional fields.** `mobileNo: ''` is not an omission — Fineract
rejects the whole submission with "mobileNo must contain only digits", naming a
field the user deliberately left empty. `staff-form` had a `withoutBlanks()`
helper; the adapter promises it now, and its spec asserts the key is *absent*
rather than merely falsy.
- **`OfficeApi.create` answers the new office's id**, because
`create-office-dialog` dismisses with it so the form that opened it can select
the office just created.
## Verification
- **1922 unit tests pass** (285 files, 54 new). `npm run lint` and `prettier
--check .` clean, baseline re-pruned.
- **Six mutations applied and killed:** dropping the string branch of the
staff joining date; sending blanks instead of omitting them; deriving a
holiday's `isPending` from the wrong field; sending a reschedule date under the
rule that forbids one; dropping the `dateFormat` Fineract parses the opening
date against; and discarding the id a create answers.
**That last one survived the first mutation run**, and is the finding worth
passing on: the dialog's own spec mocks the contract, so a `create()` that
answered nothing was invisible to it. It took an adapter-level test to catch,
and that test is in this PR. A contract's return value needs testing at the
contract, not at its callers.
## One self-inflicted bug, recorded because it will recur
`holiday.api.ts` imports its adapter for the injection-token factory. The
adapter then imported `RESCHEDULING_TYPE` — a *value* — back from the contract,
closing a runtime cycle: **all 285 spec files failed to load**, with an error
pointing at an unrelated `config.service`. The other contracts here only ever
get *types* back, which erase at compile time, which is why none of them hit
this. The constant now lives in `holiday-rescheduling-type.ts`, which imports
nothing, and says why in its header.
## Not included, deliberately
Tellers were in scope for this batch and dropped:
`GetTellersResponse.startDate` is declared `string` and really is one,
`CashierData` agrees field for field, and `GetTellersTellerIdCashiersResponse`
correctly models the `{tellerId, …, cashiers: []}` envelope that
`cashiers-list` already documents. A teller contract would earn its place on
reach alone (9 files), which is a legitimate but different argument — the
entity-notes one — and not worth padding this PR with. Worth a follow-up issue
rather than a silent inclusion.
## Screenshots
Not applicable — the only visible change is the staff edit form now showing
the real joining date instead of `-`.
## Checklist
- [x] I did not hand-edit generated files under `src/app/api/`.
- [x] New component or service code uses the adapter boundary in
`src/app/core/adapters/`.
- [x] User-facing strings use translation keys.
- [x] I added or updated tests appropriate to this change.
- [ ] UI workflow changes include suitable e2e coverage — not added here.
The staff joining-date fix is covered by a component spec and a mapper spec;
the existing `backend` project specs for these screens are unaffected.
- [x] Commits are signed.
--
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]