Repository navigation
fix(clients): show activation and submitted dates without a time or zone - #830
Conversation
The client record's Contact & Status card ran activationDate and timeline.submittedOnDate through the dateTime pipe. Fineract sends both as local dates ([2025, 1, 2]), so the card printed "Jan 2, 2025, 12:00:00 AM GMT+5:30". The platform sends no time or zone, and the suffix changed with the viewer's machine. Both fields now use appIsoDate, the existing date-only pipe, which now reads the [year, month, day] array as well as YYYY-MM-DD. It builds the date from the numbers with the local-time constructor instead of relying on V8 parsing "2025,1,2" as a string. The output matches the loan record's dates, which already go through toLocaleDateString(). Fixes apache#748
fd7a804 to
e4d062c
Compare
E2E — mocked backend🎭 E2E Tests✅ All green — 427 passed · 0 failed · 1 skipped, across 40 spec files in 16m 16s. By spec file
All 428 tests — click to expand
Slowest 10 — what the shard counts should be tuned against
📼 Download the HTML report, videos and traces — see the Generated by run 39832167479 from |
E2E — real Fineract🎭 E2E Tests✅ All green — 171 passed · 0 failed · 0 skipped, across 50 spec files in 11m 43s. By spec file
All 171 tests — click to expand
Slowest 10 — what the shard counts should be tuned against
📼 Download the HTML report, videos and traces — see the Generated by run 39832167479 from |
🔄 What this change talks toFrom the 2 application TypeScript file(s) changed in this pull request. sequenceDiagram
autonumber
participant ClientViewComponent as ClientViewComponent (Component)
participant ClientService as ClientService (API client)
participant Fineract as Fineract (REST API)
participant Router as Router (Injected)
participant ShareAccountService as ShareAccountService (API client)
participant NotesService as NotesService (API client)
participant DialogService as DialogService (Injected)
participant I18N as I18N (Injected)
ClientViewComponent->>ClientService: getClientsClientId()
ClientService->>Fineract: getClientsClientId()
Fineract-->>ClientService: response
ClientViewComponent->>Router: navigate()
ClientViewComponent->>ClientService: getClientsClientIdAccounts()
ClientService->>Fineract: getClientsClientIdAccounts()
Fineract-->>ClientService: response
ClientViewComponent->>ShareAccountService: getAccountsType()
ShareAccountService->>Fineract: getAccountsType()
Fineract-->>ShareAccountService: response
ClientViewComponent->>ClientService: postClientsClientId()
ClientService->>Fineract: postClientsClientId()
Fineract-->>ClientService: response
ClientViewComponent->>NotesService: postResourceTypeResourceIdNotes()
NotesService->>Fineract: postResourceTypeResourceIdNotes()
Fineract-->>NotesService: response
ClientViewComponent->>DialogService: confirm()
ClientViewComponent->>I18N: translate()
ClientViewComponent->>ClientService: deleteClientsClientId()
ClientService->>Fineract: deleteClientsClientId()
Fineract-->>ClientService: response
Generated by run 39832167374 from |
What and why
The client record showed its two date-only fields, Activation Date and Submitted, as midnight timestamps with a time zone (
Jan 2, 2025, 12:00:00 AM GMT+5:30). Fineract stores both as local dates, so the time and zone came from the browser and changed with the viewer's machine.Both fields now use
appIsoDate, the existing date-only pipe, in place ofdateTime.appIsoDateread onlyYYYY-MM-DDstrings; it now also reads Fineract's[year, month, day]array and builds the date from the numbers with the local-time constructor. Passing the array tonew Date()happens to work in Chrome and Node, because V8 parses"2025,1,2"as a local date, but that parsing isn't standard and other engines need not do it. The client record's dates now print the same way as the loan record's (toLocaleDateString()). That means they follow the browser's locale rather than the language picked in the app, whichdateTimeused, and the style goes from "May 30, 2026" to the short numeric form. Making date-only values follow the in-app language belongs with the shared formatter below.The array handling goes in the pipe because there is no client adapter yet:
client-viewreadsClientServicedirectly, so there is no mapper to runtoIsoFineractDate()in. LiketoIsoFineractDate(), the pipe checks that the three parts are numbers, and once a client adapter exists it can hand the pipe ISO strings without changes here.A client with no activation or submitted date now shows
—(the pipe's empty value) where it showed nothing before.dateTimeis unchanged; its remaining users (audit log, scheduler jobs) show real timestamps.I kept this to the client record. The issue also suggests one shared formatter for every record screen that follows the tenant's date format. That touches more screens and probably needs a decision on tenant vs. browser locale, so I've left it for a follow-up. If you'd rather keep #748 open for that part, I'm happy to switch
ClosestoRefs.Closes #748
Verification
iso-date.pipe.test.ts: the array and string forms give the same calendar date, no time or zone appears in the output, and short arrays, non-numeric arrays, empty values and unparseable strings give—.client-view.component.test.tschecking the rendered Activation Date and Submitted values. Againstmainit fails withexpected 'May 30, 2026, 12:00:00 AM GMT+5:30' to be '5/30/2026', and it passes with this change.npm test -- --watch=false: 315 files, 2597 tests pass (also withTZ=America/New_York, as CI runs), and the touched specs also pass withTZset to UTC, America/Los_Angeles, America/New_York and Asia/Kolkata.npm run lint(no new warnings),npx prettier --checkon the changed files,npm run build,npm run check:icons,npm run i18n:check,./scripts/check-license.sh: all pass.Screenshots
Not included; the component test above covers the rendered value.
Checklist
src/app/api/.src/app/core/adapters/instead of direct browser globals or imperative third-party APIs. (No new component or service code.)