feat(data): add admin Load demo data endpoint (PMS-679) #457

Merged
nrupard merged 1 commit from feat/PMS-679-load-demo-data-button into main 2026-07-22 15:58:52 +02:00
Owner

What

Adds an admin-only POST /api/v1/data/seed-demo endpoint that loads Mokosh's built-in demo dataset (one sample company, two contacts, three tickets) into the caller's tenant. Additive and non-destructive: it loads only into an empty tenant and never wipes.

Why

Seeding the demo dataset was reachable only from the CLI (mokosh-bootstrap qa-seed / showcase-seed) or the best-effort first-visit auto-seed. Nate asked for a UI button that works with seed data, not just a just/CLI command, for standing up and re-populating the demo. Bunyip's admin Seed page has "Load template" buttons that populate the DB from embedded seed data; this is the Mokosh equivalent for its single demo set.

How

SeedService::load_demo_data -> LoadDemoOutcome is the explicit-request counterpart to ensure_demo_seeded: it reuses the same tenant_has_companies emptiness gate and seed_rows, but surfaces its outcome (Seeded vs. AlreadyHasData) instead of swallowing it. The data_transfer module exposes it as admin-only POST /data/seed-demo, sharing the seed middleware's SeedService Arc so an explicit load and the auto-seed agree on the per-process seen set and can never double-seed. The endpoint always returns 200 with { seeded, message }; seeded=false is the legitimate "already has data" outcome, not an error. The shared multi-user landing tenant (PMS-239) is refused. MOKOSH_DEMO_SEED does not gate this explicit path (it governs the automatic first-visit seed).

Behaviour (chosen with Nate)

Additive, only-if-empty: refuse (no wipe, no tenant-name confirm) when the tenant already has data. A single demo dataset, not multiple named templates (deferred as YAGNI).

Tests

tests/seed_demo.rs adds three cases: an empty tenant loads the demo rows and returns Seeded; a tenant with a pre-existing company writes nothing and returns AlreadyHasData; the shared landing tenant is refused. cargo check --all-targets and clippy are clean; the seed suite passes against Postgres.

Frontend

The mokosh-apps Settings -> Data "Load demo data" button calls this endpoint (companion PR on branch feat/PMS-679-load-demo-data-button in mokosh-apps).

PMS-679

## What Adds an admin-only `POST /api/v1/data/seed-demo` endpoint that loads Mokosh's built-in demo dataset (one sample company, two contacts, three tickets) into the caller's tenant. Additive and non-destructive: it loads only into an empty tenant and never wipes. ## Why Seeding the demo dataset was reachable only from the CLI (`mokosh-bootstrap qa-seed` / `showcase-seed`) or the best-effort first-visit auto-seed. Nate asked for a UI button that works with seed data, not just a `just`/CLI command, for standing up and re-populating the demo. Bunyip's admin Seed page has "Load template" buttons that populate the DB from embedded seed data; this is the Mokosh equivalent for its single demo set. ## How `SeedService::load_demo_data -> LoadDemoOutcome` is the explicit-request counterpart to `ensure_demo_seeded`: it reuses the same `tenant_has_companies` emptiness gate and `seed_rows`, but surfaces its outcome (`Seeded` vs. `AlreadyHasData`) instead of swallowing it. The `data_transfer` module exposes it as admin-only `POST /data/seed-demo`, sharing the seed middleware's `SeedService` `Arc` so an explicit load and the auto-seed agree on the per-process seen set and can never double-seed. The endpoint always returns 200 with `{ seeded, message }`; `seeded=false` is the legitimate "already has data" outcome, not an error. The shared multi-user landing tenant (PMS-239) is refused. `MOKOSH_DEMO_SEED` does not gate this explicit path (it governs the automatic first-visit seed). ## Behaviour (chosen with Nate) Additive, only-if-empty: refuse (no wipe, no tenant-name confirm) when the tenant already has data. A single demo dataset, not multiple named templates (deferred as YAGNI). ## Tests `tests/seed_demo.rs` adds three cases: an empty tenant loads the demo rows and returns `Seeded`; a tenant with a pre-existing company writes nothing and returns `AlreadyHasData`; the shared landing tenant is refused. `cargo check --all-targets` and clippy are clean; the seed suite passes against Postgres. ## Frontend The mokosh-apps Settings -> Data "Load demo data" button calls this endpoint (companion PR on branch `feat/PMS-679-load-demo-data-button` in mokosh-apps). PMS-679
feat(data): add admin "Load demo data" endpoint (PMS-679)
All checks were successful
E2E / Playwright against staging (pull_request) Successful in 53s
Check / fmt + clippy + build + tests (pull_request) Successful in 1m53s
Create release / Gate (release-branch merges only) (pull_request) Successful in 1s
Create release / Create release from merged PR (pull_request) Has been skipped
Integration / integration tests (pull_request) Successful in 8m28s
67c16d4baf
Seeding the built-in demo dataset was reachable only from the CLI (mokosh-bootstrap qa-seed / showcase-seed) or the best-effort first-visit auto-seed, so an admin had no way to explicitly populate a fresh tenant with demo data from the app. The Settings -> Data page could export and import tenant data but not load the sample set the demo relies on.

Add SeedService::load_demo_data -> LoadDemoOutcome, the explicit-request counterpart to ensure_demo_seeded: it reuses the same emptiness gate and seed_rows but returns its outcome instead of swallowing it, and only ever loads into an empty tenant (additive, never wipes; the shared multi-user landing tenant from PMS-239 is refused too). Expose it as admin-only POST /api/v1/data/seed-demo in the data_transfer module, sharing the seed middleware's SeedService Arc so an explicit load and the auto-seed agree on the per-process seen set and never double-seed. The endpoint always returns 200: seeded=false is the legitimate "already has data" outcome, not an error. MOKOSH_DEMO_SEED does not gate this path (it governs the automatic first-visit seed, not an explicit operator action).

tests/seed_demo.rs covers the empty (Seeded), non-empty (AlreadyHasData, nothing written), and shared-landing-tenant (refused) cases. codebase-state.md documents the new method and route. The mokosh-apps Settings -> Data "Load demo data" button (companion PR) calls this endpoint.

#PMS-679

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nrupard deleted branch feat/PMS-679-load-demo-data-button 2026-07-22 15:58:53 +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-server!457
No description provided.