3 Commits (main)

Author SHA1 Message Date
Thomas Joise aa541270d6 fix(onboarding): APEX-imported projects were invisible on the stalled tile
client_module.created_at was added and stamped in assignModule, and
stalledProjects now correctly excludes no-tick projects whose created_at
is NULL — but the APEX importer (the path that created the real ~300
clients' projects) inserted client_module WITHOUT created_at. Every
imported project with zero ticks was therefore permanently invisible on
the "Onboarding stalled" tile, exactly the population it exists for.

Three parts:
- Stamp created_at in the APEX importer's client_module insert.
- Backfill existing NULL rows from installed_on where known (both
  db.ts migrate() for SQLite and migrations-pg.ts for Postgres); never
  fabricate a date when installed_on is also unknown.
- stalledProjects now returns { rows, unknownAgeExcluded } instead of a
  bare array, so projects excluded for unprovable age are counted, not
  silently dropped. GET /projects/stalled responds with
  { ok, projects, unknownAgeExcluded }; UI wiring left to the parallel
  agent.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 day ago
Thomas Joise 9457b0f145 fix(milestones): fresh projects false-flagged as stalled, fallback modules stuck at quoted, bulk ops skipped status/link logic (FIX D, E, F)
FIX D: stalledProjects treated a no-tick project's missing done_on as the
sentinel '0000-00-00', always older than any cutoff, so every
freshly-assigned project immediately showed up on the "Onboarding stalled"
tile. It's now measured against client_module.created_at (stamped by
assignModule); when that's also unknown (predates the column, or an import
path that doesn't stamp it) the project is excluded rather than assumed
ancient.

FIX E: STEP_STATUS only mapped the new template's keys, but TAIL_FALLBACK
(any module with no seeded/owner-configured tail -- WHATSAPP, ATM, AMC, ...)
still uses the legacy 'installed' key, so ticking "Installation done" on
those modules left status at 'quoted' forever. Added installed->installed
to STEP_STATUS (checked: no legacy payment key needs a mapping, since
payment never drove status even in the new vocabulary).

FIX F: bulkSetMilestone did a bare UPDATE, so a bulk go_live never advanced
client_module.status and a bulk untick never cleared a stale
payment_id/document_id link. Each id now routes through setMilestone itself
(same status-advance + link-clearing path a single tick uses), inside the
existing transaction -- nested transaction() calls become savepoints on
both engines, so a project without the milestone key is caught and skipped
without losing "bulk ops only touch projects that have the milestone".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 day ago
Thomas Joise 75fb41c366 feat(onboarding): stalled-project query for the dashboard/MIS tile
Adds stalledProjects(db, olderThanDays, today) to repos-milestones.ts:
active projects with a pending step whose last progress (MAX done_on,
or module creation if nothing ticked) is older than N days. GET
/projects/stalled reads ?days= with a project.stall_days setting
fallback (default 30).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2 days ago