fix(companies): refresh Statistics counts after adding a site #227

Merged
nrupard merged 1 commit from fix/PMS-363-company-sites-counter-reactive into main 2026-06-16 17:28:10 +02:00
Owner

What

Fixes the reactivity gap on the Company detail page (PMS-363, external review #2 finding #6): after adding a site, the Sites table updated but the Sites Statistics counter stayed at the mount-time value until a manual reload.

Root cause

All three Statistics counters derive from one source - company_resource, the denormalized company fetch done once on mount:

contacts.rs:1048  let open_tickets  = company.open_ticket_count...
contacts.rs:1049  let contact_count = company.contact_count...
contacts.rs:1050  let site_count    = company.site_count...

The add-site modal only restarted sites_resource (the Sites table's own data). company_resource was never restarted anywhere, so the denormalized site_count stayed stale until a full page remount.

Change

Restart company_resource alongside sites_resource in the site-form onsaved. Resource is Copy, so it is passed into CompanySitesCard by value. The counters keep their authoritative server-side source and refresh in the same render cycle.

Rejected the derive-from-child-len() alternative: PaginatedSites drops total/meta (struct PaginatedSites { data: Vec<SiteSummary> }), so data.len() would break if the endpoint paginates.

Counter audit (AC #3)

Counter Source On-page mutation Reactive before After
Sites company_resource add-site modal (stays on page) STALE (the bug) reactive
Contacts company_resource "Add Contact" is <a href> full nav -> remount refetches already correct reactive
Open Tickets company_resource none latent-stale reactive

Correction to the issue text: it stated the Contacts counter "uses a different data binding that refetches after a mutation." That is inaccurate - Contacts reads the same company_resource (line 1049). It only appeared reactive because its add flow is a full navigation that remounts the page. All three counters shared one latent staleness; only Sites had an on-page mutation to expose it, and restarting company_resource now covers all three.

No projects/assets/contracts counters exist on this page; the Statistics card has exactly these three.

Verification

  • cargo fmt --all
  • cargo clippy --target wasm32-unknown-unknown -- -D warnings clean
  • Compiles to wasm32-unknown-unknown

🤖 Generated with Claude Code

## What Fixes the reactivity gap on the Company detail page (PMS-363, external review #2 finding #6): after adding a site, the Sites table updated but the Sites Statistics counter stayed at the mount-time value until a manual reload. ## Root cause All three Statistics counters derive from one source - `company_resource`, the denormalized company fetch done once on mount: ``` contacts.rs:1048 let open_tickets = company.open_ticket_count... contacts.rs:1049 let contact_count = company.contact_count... contacts.rs:1050 let site_count = company.site_count... ``` The add-site modal only restarted `sites_resource` (the Sites table's own data). `company_resource` was never restarted anywhere, so the denormalized `site_count` stayed stale until a full page remount. ## Change Restart `company_resource` alongside `sites_resource` in the site-form `onsaved`. `Resource` is `Copy`, so it is passed into `CompanySitesCard` by value. The counters keep their authoritative server-side source and refresh in the same render cycle. Rejected the derive-from-child-`len()` alternative: `PaginatedSites` drops total/meta (`struct PaginatedSites { data: Vec<SiteSummary> }`), so `data.len()` would break if the endpoint paginates. ## Counter audit (AC #3) | Counter | Source | On-page mutation | Reactive before | After | |---|---|---|---|---| | Sites | `company_resource` | add-site modal (stays on page) | STALE (the bug) | reactive | | Contacts | `company_resource` | "Add Contact" is `<a href>` full nav -> remount refetches | already correct | reactive | | Open Tickets | `company_resource` | none | latent-stale | reactive | Correction to the issue text: it stated the Contacts counter "uses a different data binding that refetches after a mutation." That is inaccurate - Contacts reads the same `company_resource` (line 1049). It only appeared reactive because its add flow is a full navigation that remounts the page. All three counters shared one latent staleness; only Sites had an on-page mutation to expose it, and restarting `company_resource` now covers all three. No projects/assets/contracts counters exist on this page; the Statistics card has exactly these three. ## Verification - `cargo fmt --all` - `cargo clippy --target wasm32-unknown-unknown -- -D warnings` clean - Compiles to wasm32-unknown-unknown 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(companies): refresh Statistics counts after adding a site
All checks were successful
Check / clippy + fmt + tests (pull_request) Successful in 57s
Create release / Create release from merged PR (pull_request) Has been skipped
8e5ed7a8e2
The Company detail Statistics card (Open Tickets, Contacts, Sites) reads denormalized counts off `company_resource`, the single company fetch done on mount. Adding a site only restarted `sites_resource` (the Sites table's own data), so the Sites table refreshed but the Sites counter kept showing the mount-time value until a manual page reload.

Restart `company_resource` alongside `sites_resource` in the site-form `onsaved` so the denormalized counts re-derive in the same render cycle. `Resource` is `Copy`, so it is passed into `CompanySitesCard` by value.

Counter audit (all three share `company_resource`, lines 1048-1050):
- Sites: had an inline add-site modal that stays on the page, exposing the stale counter. Fixed here.
- Contacts: "Add Contact" is a full navigation (`<a href>`) to the new-contact page; returning remounts the page and refetches `company_resource`, so its counter was already correct. The issue's claim that Contacts used a different reactive binding was inaccurate - it shares the same source; it simply had no on-page mutation to expose the staleness.
- Open Tickets: no inline mutation on this page; latent-stale like Contacts, and now also covered whenever `company_resource` restarts.

#PMS-363

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch fix/PMS-363-company-sites-counter-reactive 2026-06-16 17:28:10 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-apps!227
No description provided.