Product Roadmap
Complete

#92 — Client CSV import

The only feature in the ~475-feature comparison that ALL six competitors have natively and Firmary lacks — a firm cannot switch to Firmary without a way to bring its client list. First slice of the onboarding track (full migration tooling from TaxDome/Canopy/Karbon is Phase 5); pair with lead-capture forms if cheap. Size: S. Source: product-roadmap.md §4 (2026-07-09 comparison fold-in).

4 Comments

Posting anonymously

claude-agent·12 days ago

Closed during the 2026-08-23 GitHub migration: shipped (PR #28, merged 5ccd6b3) — full client CSV import wizard. Known limits recorded on the PR: contacts not imported, CSV only, name-only dedupe.

Posting anonymously

claude-agent·about 2 months ago

Merged into dev (new shared integration branch per 2026-07-09 operating model) at 5ccd6b3; combined tree re-verified on dev (typecheck/lint/boundaries clean, new unit tests pass, build green incl. both new routes, bundle gate green across 288 routes). Ships to master with the next release cut. Marking complete.

Posting anonymously

claude-agent·about 2 months ago

Agent A — code complete & verified; awaiting merge (PR #28).

What changed: Full client CSV import wizard at /staff/clients/import ("Import CSV" button on /staff/clients). Upload -> map columns (auto-suggested from headers + custom-field defs, with sample values) -> dry-run preview (per-row created/duplicate/problem results) -> import. Server is the only parser (in-repo RFC4180: quoted cells, BOM, CRLF, comma/semicolon/tab detection); cells validated per target (kind/status enums, tag catalog resolve-or-create with auto-color, custom-field type coercion incl. $1,200-style numbers and MM/DD/YYYY dates). Firm-wide duplicate names skipped, never merged; error rows reported and left out; valid rows commit in one transaction with client.created/updated outbox events + audit rows (per client + one import summary, via:csv_import). Limits 1 MB / 2000 rows.

User-visible: a firm can finally bring its client list from TaxDome/Canopy/Karbon/spreadsheet — names, business/individual, lifecycle status, tags, and custom-field values in one pass, with a safe preview before anything is written.

Files: apps/web/app/staff/clients/import/{page,actions,import-wizard}.tsx; apps/web/modules/auth-and-tenancy/api/importClients.ts (+integration test); modules/auth-and-tenancy/server/csv.ts (+unit tests); apps/web/e2e/clients-csv-import.spec.ts; packages/validators auth-and-tenancy.ts (ImportClientsInput); packages/database repository.ts (listActiveClientNames); clients/page.tsx button; dependency-cruiser allowlist; contract "As built" section; launch-truth-table + product-roadmap rows.

Verification (all on branch agent-a/client-csv-import, commit 7eacbb4): csv.test.ts 13/13; importClients.integration.test.ts 7/7 vs migrated ephemeral DB; full auth-and-tenancy suite 210 pass/4 skip; validators 151; database 54; lint/typecheck/lint:boundaries clean (0 errors); pnpm --filter web build green; Playwright e2e clients-csv-import.spec.ts 1/1 against live dev stack.

Remaining risks/limits: contacts are NOT imported (contacts require Logto users — invite flow stays the path; noted as follow-up); no XLSX (CSV only); dedupe is by normalized name only (no merge/update of existing clients — re-import skips them). Status stays In Progress until Daniel merges https://github.com/Firmary/firmary-os/pull/28 — flipping to complete then.

Posting anonymously

claude-agent·about 2 months ago

Agent A claiming this until completion or block. Scope: end-to-end client CSV import — staff-side upload UI, column mapping, validation/preview, tenant-isolated import into clients (+contacts/custom fields where cheap), error reporting, tests, docs. Started: 2026-07-09 ~11:55pm America/Chicago.

Posting anonymously