12 Commits

Author SHA1 Message Date
phaichayon
18cc9bbfd0 setup email 2026-07-06 23:07:55 +07:00
phaichayon
d93f25e1ce csv setupdata 2026-07-06 15:50:47 +07:00
phaichayon
944dbc031d task-d.7.12 2026-07-03 16:09:54 +07:00
phaichayon
15c56efc8b task-d.7.11 2026-07-03 14:46:42 +07:00
phaichayon
9c8d6a0d6d task-d.7.9 2026-07-03 11:39:37 +07:00
phaichayon
503f34e22f task-d.7.10 2026-07-03 11:23:24 +07:00
phaichayon
ccfd7c6cd7 task-d.7.7 2026-07-03 11:05:13 +07:00
phaichayon
9b05743b1e task-d.7.8 2026-07-03 10:19:03 +07:00
phaichayon
110c2f9e7f task-d.7.6 2026-07-03 09:51:36 +07:00
phaichayon
b7589017ab task-d.7.5 2026-07-03 09:30:57 +07:00
phaichayon
0b7aeea0a7 task-d.7.4 2026-07-03 08:18:09 +07:00
phaichayon
0c3d488d7d task-d.7.4 2026-07-02 14:27:51 +07:00
193 changed files with 21226 additions and 674 deletions

181
alla-theme.css Normal file
View File

@@ -0,0 +1,181 @@
@import "tailwindcss";
@custom-variant dark (&:is(.dark *));
:root {
--background: oklch(0.9911 0 0);
--foreground: oklch(0.2046 0 0);
--card: oklch(0.9911 0 0);
--card-foreground: oklch(0.2046 0 0);
--popover: oklch(0.9911 0 0);
--popover-foreground: oklch(0.4386 0 0);
--primary: oklch(0.4799 0.0804 155.8197);
--primary-foreground: oklch(1.0000 0 0);
--secondary: oklch(0.9940 0 0);
--secondary-foreground: oklch(0.2046 0 0);
--muted: oklch(0.9461 0 0);
--muted-foreground: oklch(0.2435 0 0);
--accent: oklch(0.9461 0 0);
--accent-foreground: oklch(0.2435 0 0);
--destructive: oklch(0.5523 0.1927 32.7272);
--destructive-foreground: oklch(0.9934 0.0032 17.2118);
--border: oklch(0.9037 0 0);
--input: oklch(0.9731 0 0);
--ring: oklch(0.5568 0.1355 155.8120);
--chart-1: oklch(0.8348 0.1302 160.9080);
--chart-2: oklch(0.6231 0.1880 259.8145);
--chart-3: oklch(0.6056 0.2189 292.7172);
--chart-4: oklch(0.7686 0.1647 70.0804);
--chart-5: oklch(0.6959 0.1491 162.4796);
--sidebar: oklch(0.9911 0 0);
--sidebar-foreground: oklch(0.5452 0 0);
--sidebar-primary: oklch(0.5568 0.1355 155.8120);
--sidebar-primary-foreground: oklch(0.2626 0.0147 166.4589);
--sidebar-accent: oklch(0.9461 0 0);
--sidebar-accent-foreground: oklch(0.2435 0 0);
--sidebar-border: oklch(0.9037 0 0);
--sidebar-ring: oklch(0.5568 0.1355 155.8120);
--font-sans: Anek Kannada, ui-sans-serif, sans-serif, system-ui;
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: monospace;
--radius: 0.5rem;
--shadow-x: 0px;
--shadow-y: 1px;
--shadow-blur: 5.5px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: #000000;
--shadow-2xs: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow-md: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 2px 4px -1px hsl(0 0% 0% / 0.10);
--shadow-lg: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 4px 6px -1px hsl(0 0% 0% / 0.10);
--shadow-xl: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 8px 10px -1px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0.025em;
--spacing: 0.25rem;
}
.dark {
--background: oklch(0.1822 0 0);
--foreground: oklch(0.9288 0.0126 255.5078);
--card: oklch(0.2046 0 0);
--card-foreground: oklch(0.9288 0.0126 255.5078);
--popover: oklch(0.2603 0 0);
--popover-foreground: oklch(0.7348 0 0);
--primary: oklch(0.5568 0.1355 155.8120);
--primary-foreground: oklch(0.9213 0.0135 167.1556);
--secondary: oklch(0.2603 0 0);
--secondary-foreground: oklch(0.9851 0 0);
--muted: oklch(0.2393 0 0);
--muted-foreground: oklch(0.7122 0 0);
--accent: oklch(0.3132 0 0);
--accent-foreground: oklch(0.9851 0 0);
--destructive: oklch(0.3123 0.0852 29.7877);
--destructive-foreground: oklch(0.9368 0.0045 34.3092);
--border: oklch(0.2809 0 0);
--input: oklch(0.2603 0 0);
--ring: oklch(0.5568 0.1355 155.8120);
--chart-1: oklch(0.8003 0.1821 151.7110);
--chart-2: oklch(0.7137 0.1434 254.6240);
--chart-3: oklch(0.7090 0.1592 293.5412);
--chart-4: oklch(0.8369 0.1644 84.4286);
--chart-5: oklch(0.7845 0.1325 181.9120);
--sidebar: oklch(0.1822 0 0);
--sidebar-foreground: oklch(0.6301 0 0);
--sidebar-primary: oklch(0.5568 0.1355 155.8120);
--sidebar-primary-foreground: oklch(0.9213 0.0135 167.1556);
--sidebar-accent: oklch(0.3132 0 0);
--sidebar-accent-foreground: oklch(0.9851 0 0);
--sidebar-border: oklch(0.2809 0 0);
--sidebar-ring: oklch(0.5568 0.1355 155.8120);
--font-sans: Anek Kannada, ui-sans-serif, sans-serif, system-ui;
--font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
--font-mono: monospace;
--radius: 0.5rem;
--shadow-x: 0px;
--shadow-y: 1px;
--shadow-blur: 5.5px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: #000000;
--shadow-2xs: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow-md: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 2px 4px -1px hsl(0 0% 0% / 0.10);
--shadow-lg: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 4px 6px -1px hsl(0 0% 0% / 0.10);
--shadow-xl: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.10), 0px 8px 10px -1px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0px 1px 5.5px 0px hsl(0 0% 0% / 0.25);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--font-serif: var(--font-serif);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--shadow-2xs: var(--shadow-2xs);
--shadow-xs: var(--shadow-xs);
--shadow-sm: var(--shadow-sm);
--shadow: var(--shadow);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
--shadow-xl: var(--shadow-xl);
--shadow-2xl: var(--shadow-2xl);
--tracking-tighter: calc(var(--tracking-normal) - 0.05em);
--tracking-tight: calc(var(--tracking-normal) - 0.025em);
--tracking-normal: var(--tracking-normal);
--tracking-wide: calc(var(--tracking-normal) + 0.025em);
--tracking-wider: calc(var(--tracking-normal) + 0.05em);
--tracking-widest: calc(var(--tracking-normal) + 0.1em);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
letter-spacing: var(--tracking-normal);
}
}

View File

@@ -0,0 +1,77 @@
# Task D.7.10 Setup Integration Test & Golden Dataset
Date: 2026-07-03
Status: implemented
## Scope Delivered
Added official setup golden dataset:
- `setup/golden-dataset/README.md`
- `setup/golden-dataset/dataset.json`
- 22 setup CSV files matching `setup/templates/templates.json`
Dataset coverage:
- Organizations: `ALLA`, `ONVALLA`
- Users: IT/admin, marketing, sales, sales manager, CEO
- Customers: 10
- Contacts: 20
- Leads: 20
- Opportunities: 15
- Quotations: 20
- Multiple branches and product types
- Quotation statuses: draft, pending approval, approved, rejected, revision
Added setup integration documentation:
- `docs/setup/integration-scenarios.md`
- `docs/setup/setup-performance-report.md`
Added automated setup contract tests:
- `src/tests/setup/helpers.ts`
- `src/tests/setup/golden-dataset.test.ts`
- `src/tests/setup/setup-install.test.ts`
- `src/tests/setup/setup-preview.test.ts`
- `src/tests/setup/setup-commit.test.ts`
- `src/tests/setup/setup-verification.test.ts`
- `src/tests/setup/setup-resume.test.ts`
- `src/tests/setup/setup-reset.test.ts`
Added script:
- `npm run test:setup`
## Test Coverage
The setup test suite validates:
- Golden dataset files exist.
- Golden dataset headers match official setup templates.
- Required row counts are present.
- Quotation statuses cover approval and revision scenarios.
- Golden dataset includes every supported setup template.
- Dataset import order follows template registry ordering.
- Preview hash semantics change when CSV content changes.
- Commit API and seed manifest integration exist.
- Commit engine preserves preview hash validation contract.
- Setup readiness and verification APIs exist.
- Setup run resume APIs exist.
- Setup wizard persists core step outputs.
- Reset and reseed APIs exist.
- Reset guard source blocks production and requires preview token semantics.
- Unsafe reset scopes are intentionally blocked.
- Integration scenarios document operational readiness checks.
## Validation
- `npm run test:setup` passed: 17 tests.
- `npm run typecheck -- --pretty false` passed.
- `npx oxlint src/tests/setup` passed.
## Residual Notes
- This task adds runnable setup contract tests using Node's built-in test runner to avoid introducing a new test framework.
- Full empty-database E2E execution is documented in `docs/setup/integration-scenarios.md` but not automated because this repository does not yet have an isolated CI test database harness.
- Performance targets are documented in `docs/setup/setup-performance-report.md`; measured preview/commit/verification timings require the future isolated database harness.

View File

@@ -0,0 +1,65 @@
# Task D.7.12 Step-by-Step First-Run Required CSV Import
Date: 2026-07-03
Status: implemented
## Review Completed
- Reviewed `AGENTS.md` task governance from the active repository instructions.
- Reviewed `docs/standards/task-contract-template.md`.
- Reviewed `docs/standards/task-catalog.md`.
- Reviewed `docs/standards/project-foundations.md`.
- Reviewed `docs/standards/architecture-rules.md`.
- Reviewed `docs/standards/ui-ux-rules.md`.
- Reviewed `docs/standards/task-review-checklist.md`.
- Reviewed setup lineage notes:
- `docs/implementation/task-d7-initial-system-setup-audit.md`
- `docs/implementation/task-d76-dashboard-setup-wizard-ui.md`
- `docs/implementation/task-d78-seed-manifest-setup-state-persistence.md`
- `docs/setup/setup-wizard-blueprint.md`
## Decision
The required CSV order is:
1. `users.csv`
2. `organizations.csv`
3. `memberships.csv`
4. `crm-role-assignments.csv`
5. `master-options.csv`
6. `branches.csv`
7. `product-types.csv`
8. `document-sequences.csv`
9. `approval-workflows.csv`
10. `approval-steps.csv`
11. `approval-matrix.csv`
This intentionally uses `users.csv` before `organizations.csv` because `organizations.csv`
resolves `created_by_email` against existing users. This follows the recommendation in
`plans/task-d.7.12.md` and avoids introducing a temporary bootstrap actor into the
organization import data path.
## Scope Delivered
- Added server-owned bootstrap required step metadata in `setup-bootstrap.service.ts`.
- Added `crm-role-assignments.csv` to the required bootstrap file list.
- Changed public bootstrap preview and commit APIs to accept one expected CSV file per step.
- Persisted each required CSV result to its own `setup_run_steps.step_key`.
- Updated bootstrap completion to require all required step keys to be `passed` or `warning`.
- Added bootstrap step dependency staleness rules in setup run persistence.
- Reworked the Administration Setup Wizard UI into a left-stepper, single-step import flow.
- Kept optional business CSV imports separate from system-required steps.
## Reuse
- Reused existing CSV preview and commit engine.
- Reused existing `/api/setup/bootstrap/preview`, `/api/setup/bootstrap/commit`, and
`/api/setup/bootstrap/complete` route groups.
- Reused existing `setup_runs` and `setup_run_steps` persistence.
- Reused setup template metadata from `setup/templates/templates.json`.
- Reused shadcn/ui dashboard primitives and existing icon registry.
## Verification
- `npm run typecheck -- --pretty false` passed.

View File

@@ -0,0 +1,67 @@
# Task D.7.3 CSV Template Generator Static Template Pack
Date: 2026-07-02
Status: implemented
## Scope Delivered
Created the official static setup CSV template pack under `setup/templates/`.
Generated supported CSV files:
- `organizations.csv`
- `users.csv`
- `memberships.csv`
- `crm-role-assignments.csv`
- `master-options.csv`
- `branches.csv`
- `product-types.csv`
- `document-sequences.csv`
- `approval-workflows.csv`
- `approval-steps.csv`
- `approval-matrix.csv`
- `customers.csv`
- `contacts.csv`
- `contact-shares.csv`
- `leads.csv`
- `opportunities.csv`
- `opportunity-parties.csv`
- `quotations.csv`
- `quotation-items.csv`
- `quotation-parties.csv`
- `quotation-topics.csv`
- `quotation-topic-items.csv`
Supporting files:
- `setup/templates/README.md`
- `setup/templates/templates.json`
Optional read-only metadata API:
- `GET /api/setup/templates`
## Safety Notes
- No CSV parser was implemented.
- No CSV validation/preview engine was implemented.
- No CSV commit/import logic was implemented.
- No seed execution was implemented.
- No reset/reseed logic was implemented.
- No unsupported CSV files were generated.
- Sample `users.csv` leaves `password` empty to avoid embedding secrets.
## Verification
- Template structure check: 22 CSV files; each has one header row and one sample row.
- Column count check: every sample row has the same column count as its header row.
- Unsupported template check: no unsupported CSV files were present.
- `templates.json` parse check: passed; 22 templates listed.
- `npm run typecheck`: passed.
- `npx oxlint src/app/api/setup setup/templates`: passed.
- `npm run lint`: failed due to pre-existing unrelated repo lint issues outside this task, including `src/features/foundation/document-template/server/management-service.ts` and skill asset scripts.
## Follow-up
- D.7.4 should use `setup/templates/templates.json` and the CSV headers as the source contract for preview validation.
- D.7.6 can call `GET /api/setup/templates` for template metadata.

View File

@@ -0,0 +1,47 @@
# Task D.7.4 CSV Preview Validation Engine
Date: 2026-07-02
Status: implemented
## Scope Delivered
- Added reusable preview-only CSV engine:
- `src/features/setup/server/csv-preview.service.ts`
- `src/features/setup/server/csv/parser.ts`
- `src/features/setup/server/csv/template-registry.ts`
- `src/features/setup/server/csv/header-validator.ts`
- `src/features/setup/server/csv/value-validator.ts`
- `src/features/setup/server/csv/dependency-resolver.ts`
- `src/features/setup/server/csv/validator.ts`
- `src/features/setup/server/csv/preview-builder.ts`
- `src/features/setup/server/csv/types.ts`
- Added protected preview route:
- `POST /api/setup/import/preview`
## Behavior
- Accepts one or more CSV files through `multipart/form-data`.
- Detects templates by filename from `setup/templates/templates.json`.
- Treats `templates.json` plus checked-in CSV headers as runtime template truth.
- Rejects unknown and unsupported templates with structured row/file errors.
- Validates exact header names, order, duplicate columns, missing columns, and extra columns.
- Parses UTF-8 comma-delimited CSV with quoted cell support.
- Reports invalid encoding, empty rows, duplicate rows, inconsistent column counts, required fields, emails, booleans, integers, decimals, dates, enums, JSON metadata, format rules, and amount/line-total warnings.
- Resolves dependencies from both uploaded batch files and existing database rows without writing.
- Detects duplicate business keys inside each uploaded file.
- Classifies rows as `create`, `update`, or `error`.
- Returns structured file/row report with `PASS`, `WARNING`, `FAIL` status and `previewHash` for D.7.5.
## Safety Notes
- No database insert/update/delete logic added.
- No seed execution added.
- No reset/reseed behavior added.
- No document number generation, approval triggering, PDF generation, or storage writes added.
- Relationship checks use read-only Drizzle selects.
- `quotation-topic-items.csv` resolves `topic_key` from the uploaded batch because `topic_key` is an import-only alias and is not persisted in `crm_quotation_topics`.
## Verification
- `npm run typecheck`: passed.
- `npx oxlint src/features/setup/server/csv src/features/setup/server/csv-preview.service.ts src/app/api/setup/import/preview`: passed.

View File

@@ -0,0 +1,66 @@
# Task D.7.5 CSV Commit Import Engine
Date: 2026-07-03
Status: implemented
## Scope Delivered
- Added protected commit API:
- `POST /api/setup/import/commit`
- Added setup CSV commit service:
- `src/features/setup/server/csv-commit.service.ts`
- `src/features/setup/server/csv/commit-builder.ts`
- `src/features/setup/server/csv/upsert-executor.ts`
- `src/features/setup/server/csv/import-report.ts`
## Behavior
- Commit requires `previewHash`.
- Commit re-runs D.7.4 preview on the submitted files.
- Commit rejects mismatched `previewHash`.
- Commit rejects preview results with blocking errors.
- Commit follows dependency order from `setup/templates/templates.json` through the D.7.4 preview ordering.
- `dryRun=true` returns planned actions and does not start transaction writes.
- Non-dry-run commits execute in a single database transaction.
- Supported rows use idempotent business-key upsert behavior.
- Password updates only run for existing users when `password` is supplied and `reset_password=true`; otherwise password input is ignored with a report warning.
- Import reports never return password hashes.
## Supported Templates
The commit executor supports the templates registered by D.7.3/D.7.4:
- `users.csv`
- `organizations.csv`
- `memberships.csv`
- `crm-role-assignments.csv`
- `master-options.csv`
- `branches.csv`
- `product-types.csv`
- `document-sequences.csv`
- `approval-workflows.csv`
- `approval-steps.csv`
- `approval-matrix.csv`
- `customers.csv`
- `contacts.csv`
- `contact-shares.csv`
- `leads.csv`
- `opportunities.csv`
- `opportunity-parties.csv`
- `quotations.csv`
- `quotation-items.csv`
- `quotation-parties.csv`
- `quotation-topics.csv`
- `quotation-topic-items.csv`
## Safety Notes
- D.7.5 reuses D.7.4 parsing, template detection, validation, dependency resolution, preview actions, and `previewHash`.
- Setup import writes directly with Drizzle for this slice because no safe setup import service contract exists for every supported template.
- The import report includes `AUDIT_GAP` warnings for direct Drizzle writes; a future service wrapper can add per-row audit semantics without changing the preview contract.
- Storage, attachments, approval execution, PDFs, setup state persistence, seed manifest persistence, and destructive reset remain out of scope.
## Verification
- `npm run typecheck` passed.
- `npx oxlint src/features/setup/server/csv src/features/setup/server/csv-commit.service.ts src/app/api/setup/import/commit/route.ts` passed.

View File

@@ -0,0 +1,71 @@
# Task D.7.6 Dashboard Setup Wizard UI
Date: 2026-07-03
Status: implemented
## Scope Delivered
Added dashboard-native setup wizard route:
- `GET /dashboard/administration/setup`
- Server-side page access restricted to `super_admin`
- Admin navigation item for `Setup Wizard`
Added setup UI orchestration:
- `src/features/setup/components/setup-wizard.tsx`
- `src/app/dashboard/administration/setup/page.tsx`
Extended setup API client surface:
- `src/features/setup/api/types.ts`
- `src/features/setup/api/service.ts`
- `src/features/setup/api/queries.ts`
- `src/features/setup/api/use-csv-commit.ts`
- `src/features/setup/api/use-setup-verification.ts`
## Behavior
- Step 1 calls setup readiness and displays overall status, PASS / WARNING / FAIL counts, grouped checks, suggested fixes, loading, error, and permission states.
- Step 2 calls template metadata and displays registered setup templates from the existing setup template API.
- Step 3 accepts one or more CSV files and does not upload them until the user clicks preview.
- Step 4 calls CSV preview, stores `previewHash` in client state only, displays per-file summaries, row/error/warning counts, and grouped safe error messages.
- Step 5 calls CSV commit with the latest `previewHash`.
- Commit is disabled when preview has `FAIL`.
- Commit requires warning acknowledgement when preview has `WARNING`.
- File changes after preview clear commit eligibility and require re-preview, using file name + size + lastModified fingerprint.
- Step 6 calls setup verification and displays grouped checks plus summary counts.
- Step 7 summarizes readiness, preview, commit, and verification results for the current browser session.
## Security And API Notes
- Setup page uses `auth()` and `PageContainer` access fallback for non-super-admin users.
- Existing setup APIs remain the enforcement boundary and still require `super_admin`.
- Upload requests use `FormData` directly so browser-managed multipart boundaries are preserved.
- UI reads safe API error messages and does not render raw stack traces.
- CSV files are uploaded only to the preview and commit endpoints.
- The wizard does not log CSV data.
## Out Of Scope Preserved
- No setup state persistence.
- No seed manifest persistence.
- No destructive reset or reseed behavior.
- No seed execution.
- No database migrations.
- No new CRM behavior.
- No file download or ZIP template generation.
Persistent setup runs and resume behavior remain deferred to D.7.8.
## Validation
- `npm run typecheck -- --pretty false` passed.
- `npx oxlint src/features/setup/api/types.ts src/features/setup/api/service.ts src/features/setup/api/queries.ts src/features/setup/api/use-csv-commit.ts src/features/setup/api/use-setup-verification.ts src/features/setup/components/setup-wizard.tsx src/app/dashboard/administration/setup/page.tsx src/config/nav-config.ts` passed.
- Existing dev server was already running at `http://localhost:3000`.
- `curl.exe -I -L --max-time 20 http://localhost:3000/dashboard/administration/setup` returned `200 OK`.
## Residual Notes
- `plans/task-d.7.6.md` was already untracked during implementation and was not modified as part of this delivery.
- The wizard is intentionally session-only until the D.7.8 setup-state persistence slice.

View File

@@ -0,0 +1,130 @@
# Task D.7.7 Scoped Reset Reseed Engine
Date: 2026-07-03
Status: implemented
## Scope Delivered
Added setup reset/reseed server foundations:
- `src/features/setup/server/reset.service.ts`
- `src/features/setup/server/reseed.service.ts`
- `src/features/setup/server/reset-guards.ts`
- `src/features/setup/server/reset-report.ts`
- `src/features/setup/server/reset-scopes.ts`
Added protected setup maintenance APIs:
- `POST /api/setup/reset/preview`
- `POST /api/setup/reset/execute`
- `POST /api/setup/reseed/preview`
- `POST /api/setup/reseed/execute`
## Reset Behavior
Reset preview is implemented for all D.7.7 scopes:
- `foundation_reset`
- `organization_reset`
- `business_reset`
- `demo_uat_reset`
- `full_reset`
- `csv_import_rollback`
- `setup_run_reset`
Reset execute is implemented only where ownership and safety are clear:
- `setup_run_reset`
- Deletes setup metadata only.
- Deletes `setup_runs`, `setup_run_steps`, `seed_manifests`, and `seed_manifest_items`.
- Does not delete business, organization, foundation, or user data.
- `business_reset`
- Deletes organization-scoped CRM business rows only.
- Retains organization, users, memberships, and foundation rows.
- Marks matching seed manifests `rolled_back`.
- Marks CSV commit and verification setup steps `stale`.
The following scopes intentionally block execution with safe reports:
- `foundation_reset`
- `organization_reset`
- `demo_uat_reset`
- `full_reset`
- `csv_import_rollback`
These are blocked until service-specific seed/reseed wrappers, deterministic UAT ownership markers, or reversible manifest ownership metadata are available.
## Reseed Behavior
Reseed preview exists for:
- `foundation`
- `demo_uat`
- `csv_manifest`
Reseed execute is blocked in D.7.7 and returns a safe report. This avoids duplicating seed scripts or pretending CSV manifests can be replayed when original CSV payloads are not persisted.
## Safety Guards
All reset/reseed APIs require:
- `super_admin`
- non-production environment
- non-production-like database host/name
- explicit scope or target
- preview before execute
- valid `previewHash`
- valid short-lived `confirmationToken`
- exact typed confirmation phrase
Organization-aware scopes require `organizationId`.
## Report Behavior
Preview reports include:
- scope or reseed target
- affected tables
- estimated row counts
- retained data
- deleted data
- storage cleanup plan
- seed manifest impact
- warnings and blocking errors
- confirmation phrase
- preview hash
- confirmation token and expiry
Execute reports include:
- execution status
- deleted row estimate
- updated manifest count
- best-effort storage cleanup result
Storage cleanup is report-only/best-effort and never silently deletes approved production artifacts.
## Out Of Scope Preserved
- Production reset workflow.
- Silent automatic reset.
- Arbitrary rollback without manifest ownership.
- Deleting approved production artifacts.
- New seed data creation.
- Installation profile plugin runtime.
- Backup/restore.
- Data anonymization.
- Cross-environment migration.
- Email/storage secret reset.
- CRM business behavior changes.
## Validation
- `npm run typecheck -- --pretty false` passed.
- `npx oxlint src/features/setup/server/reset.service.ts src/features/setup/server/reseed.service.ts src/features/setup/server/reset-guards.ts src/features/setup/server/reset-report.ts src/features/setup/server/reset-scopes.ts src/app/api/setup/reset src/app/api/setup/reseed` passed.
## Residual Notes
- Full reset remains delegated to existing guarded scripts operationally; the dashboard API returns a blocking report instead of running process-level database reset commands.
- `csv_import_rollback` remains report-only because D.7.8 seed manifest records do not persist enough row-level reversible ownership metadata for arbitrary rollback.
- `demo_uat_reset` remains blocked until UAT rows have deterministic persisted ownership markers beyond seed conventions.

View File

@@ -0,0 +1,86 @@
# Task D.7.8 Seed Manifest Setup State Persistence
Date: 2026-07-03
Status: implemented
## Scope Delivered
Added setup persistence schema and migration:
- `setup_runs`
- `setup_run_steps`
- `seed_manifests`
- `seed_manifest_items`
- `drizzle/0004_setup_state_seed_manifest.sql`
Added setup state services:
- `src/features/setup/server/setup-state.service.ts`
- `src/features/setup/server/seed-manifest.service.ts`
Added protected setup run APIs:
- `GET /api/setup/run/current`
- `POST /api/setup/run/start`
- `POST /api/setup/run/steps`
- `POST /api/setup/run/complete`
- `GET /api/setup/run/report`
Updated CSV commit integration:
- Successful non-dry-run CSV commits create seed manifest records.
- Dry-run commits do not write seed manifest records.
- Failed commits do not write seed manifest records.
Updated Setup Wizard UI:
- Loads current setup run on mount.
- Shows resumable/completed setup run banner.
- Shows persisted step statuses.
- Saves readiness, CSV preview, CSV commit, and verification step outputs.
- Marks dependent later steps stale when step input hash changes.
- Shows persisted seed manifest summaries.
- Adds complete setup action.
- Wizard remains usable if persistence APIs fail, with a warning.
## Persistence Behavior
- Step re-runs update the same `setup_run_steps` row.
- Latest step report replaces prior step report.
- CSV preview persistence strips raw row values before saving.
- CSV commit persistence strips row-level raw details before saving.
- Seed manifest item records store filenames, checksums, counts, status, and safe reports.
- No raw CSV contents, passwords, password hashes, SQL errors, storage credentials, or secrets are persisted.
## Staleness Rules Implemented
- `readiness` changes mark later setup steps stale.
- `organization` changes mark administrator, scope, sequence, approval, CSV, and verification steps stale.
- `scope` changes mark sequence, approval, CSV, and verification steps stale.
- `sequences` changes mark verification stale.
- `approval` changes mark CSV and verification stale.
- `csv_preview` changes mark `csv_commit` stale.
- `csv_commit` changes mark verification stale.
## Out Of Scope Preserved
- No destructive reset/reseed behavior.
- No `RESET_STEP` implementation.
- No installation profile plugin runtime.
- No CSV parser changes.
- No setup template changes.
- No storage or attachment import.
- No new CRM behavior.
- No production setup lock enforcement beyond completed status display.
## Validation
- `npm run typecheck -- --pretty false` passed.
- `npx oxlint src/features/setup src/app/api/setup src/app/dashboard/administration/setup src/db/schema.ts` passed.
- `npm run db:migrate` passed and applied migrations successfully.
## Residual Notes
- `plans/task-d.7.8.md` was untracked during implementation and was not modified as part of this delivery.
- The Drizzle migration was added manually to match the current repository migration style and journal.
- D.7.7 remains responsible for scoped reset/reseed behavior.

View File

@@ -0,0 +1,80 @@
# Task D.7.9 Installation Profiles & Setup Plugin Registry
Date: 2026-07-03
Status: implemented
## Scope Delivered
Added setup plugin platform layer:
- `src/features/setup/plugins/plugin-types.ts`
- `src/features/setup/plugins/plugin-registry.ts`
- `src/features/setup/plugins/installation-profile.ts`
- `src/features/setup/plugins/foundation/foundation-plugin.ts`
- `src/features/setup/plugins/crm/crm-setup-plugin.ts`
- `src/features/setup/plugins/crm/crm-installation-profile.ts`
Added installation profile API:
- `GET /api/setup/profiles`
Updated existing setup APIs:
- `GET /api/setup/templates?profile=<profileId>` now returns plugin-aware metadata while preserving legacy template fields.
- `GET /api/setup/readiness?profile=<profileId>` includes plugin registry readiness checks.
- `POST /api/setup/verify` accepts optional `profileId` and includes plugin registry verification checks.
Updated Setup Wizard:
- Loads installation profiles from the setup plugin registry.
- Allows profile selection.
- Builds wizard stepper from profile-resolved wizard steps with fallback to existing steps.
- Displays installed setup modules/plugins.
Added plugin documentation:
- `docs/setup/installation-profiles.md`
- `docs/setup/setup-plugin-development.md`
Added setup tests:
- `src/tests/setup/setup-plugin-registry.test.ts`
## Profiles
Implemented profiles:
- `crm_starter`
- `crm_demo`
- `production`
- `restore_backup`
- `custom`
## Plugins
Implemented built-in plugins:
- `foundation`
- owns setup platform foundations, setup state, seed manifests, reset framework, CSV framework, and foundation golden dataset registration
- `crm`
- owns CRM templates, CRM verification registration, CRM reset scopes, CRM reseed target registration, and CRM golden dataset registration
## Compatibility Notes
- No breaking API field removals were introduced.
- Existing template metadata fields remain: `file`, `seedType`, `importOrder`, `supported`, `requiredColumns`, `description`.
- New template metadata fields are additive: `plugin`, `profiles`, `visible`.
- Existing CSV preview/commit behavior is unchanged.
- Existing reset/reseed behavior is unchanged.
- External plugin loading, marketplace behavior, and new business modules remain out of scope.
## Validation
- `npm run typecheck -- --pretty false` passed.
- `npm run test:setup` passed: 20 tests.
- `npx oxlint src/features/setup/plugins src/app/api/setup/profiles src/app/api/setup/templates src/app/api/setup/readiness src/app/api/setup/verify src/features/setup/components/setup-wizard.tsx src/features/setup/api src/tests/setup` passed.
## Residual Notes
- Readiness and verification services now aggregate plugin registry checks additively. Existing concrete CRM checks remain in place to avoid regression.
- Future module plugins should register through `plugin-registry.ts` rather than editing the setup wizard directly.

View File

@@ -0,0 +1,167 @@
# Task P.7.2 Implementation Report
## Scope
This round implements the first working slice of the SMTP / Email Configuration Platform for ALLA OS.
Delivered scope:
- organization-scoped email configuration persistence
- encrypted SMTP password storage
- CRUD APIs for email configurations
- SMTP connection test
- send test email action
- setup readiness / verification integration
- setup wizard optional email status card
- dashboard-native email administration page
- notification runtime integration so email sending uses the stored organization configuration
## Review Summary
Reviewed before implementation:
- [AGENTS.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/AGENTS.md)
- [docs/standards/project-foundations.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/project-foundations.md)
- [docs/standards/architecture-rules.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/architecture-rules.md)
- [docs/standards/ui-ux-rules.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/ui-ux-rules.md)
- [docs/standards/task-review-checklist.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/standards/task-review-checklist.md)
- [docs/setup/verification-matrix.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/setup/verification-matrix.md)
- [docs/setup/setup-wizard-blueprint.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/setup/setup-wizard-blueprint.md)
- [docs/setup/installation-profiles.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/setup/installation-profiles.md)
- [docs/implementation/task-d72-setup-readiness-verification-apis.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/task-d72-setup-readiness-verification-apis.md)
- [docs/implementation/task-d76-dashboard-setup-wizard-ui.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/task-d76-dashboard-setup-wizard-ui.md)
- [docs/implementation/task-f4-notification-framework-foundation.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/task-f4-notification-framework-foundation.md)
- [docs/implementation/task-p.7.1-implementation.md](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/docs/implementation/task-p.7.1-implementation.md)
## Architecture Notes
The implementation intentionally extends the existing notification foundation instead of creating a second outbound-email stack.
Key decisions:
- persisted email configuration is organization-scoped in a new `email_configurations` table
- secret encryption is isolated in a reusable helper at [src/features/foundation/secrets/server/crypto.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/secrets/server/crypto.ts)
- the notification runtime keeps using the existing provider factory, but the email provider now resolves organization SMTP config from the new foundation
- setup readiness and setup verification both read from the same persisted source of truth instead of environment-only `SMTP_*` variables
- the setup wizard keeps email as an optional operator step, matching the task requirement that email must not block first-run setup by default
## Main Changes
### 1. Data Model And Secret Handling
Added:
- [src/db/schema.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/db/schema.ts)
- [drizzle/0001_yellow_wasp.sql](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/drizzle/0001_yellow_wasp.sql)
- [src/features/foundation/secrets/server/crypto.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/secrets/server/crypto.ts)
Behavior:
- SMTP passwords are stored only as encrypted ciphertext
- API responses never return decrypted or raw password values
- UI only receives `hasPassword`
- missing or weak `EMAIL_CONFIG_ENCRYPTION_KEY` blocks encryption-dependent save paths
### 2. Email Foundation Services
Added:
- [src/features/foundation/email/server/email-provider.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/server/email-provider.ts)
- [src/features/foundation/email/server/smtp-provider.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/server/smtp-provider.ts)
- [src/features/foundation/email/server/email-config.service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/server/email-config.service.ts)
- [src/features/foundation/email/server/email-test.service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/server/email-test.service.ts)
Behavior:
- create, update, list, fetch, and delete email configs
- track default / active config
- test connection and test send update `last_test_status`, `last_tested_at`, and safe `last_test_error`
- audit events are written for create, update, delete, and test outcomes
### 3. Notification Runtime Integration
Updated:
- [src/features/foundation/notifications/server/email-provider.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/notifications/server/email-provider.ts)
- [src/features/foundation/notifications/server/provider-factory.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/notifications/server/provider-factory.ts)
- [src/features/foundation/notifications/server/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/notifications/server/service.ts)
Behavior:
- email dispatches now resolve SMTP settings from the active organization configuration
- the provider factory now receives `organizationId`
- existing notification send / resend flows continue using the established foundation contract
### 4. Setup Integration
Updated:
- [src/features/setup/server/readiness.service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/setup/server/readiness.service.ts)
- [src/features/setup/server/verification.service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/setup/server/verification.service.ts)
- [src/features/setup/components/setup-wizard.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/setup/components/setup-wizard.tsx)
- [src/features/foundation/email/components/setup-email-card.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/components/setup-email-card.tsx)
Behavior:
- readiness and verification now check persisted organization email config
- no configuration returns `WARNING`, not `FAIL`, so setup remains non-blocking by default
- a lightweight email status card is shown inside the setup wizard and links to the email admin page
### 5. Admin APIs And UI
Added APIs:
- [src/app/api/notifications/email-configurations/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/notifications/email-configurations/route.ts)
- [src/app/api/notifications/email-configurations/[id]/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/notifications/email-configurations/[id]/route.ts)
- [src/app/api/notifications/email-configurations/[id]/test/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/notifications/email-configurations/[id]/test/route.ts)
- [src/app/api/notifications/email-configurations/[id]/send-test/route.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/api/notifications/email-configurations/[id]/send-test/route.ts)
Added client layer:
- [src/features/foundation/email/api/types.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/api/types.ts)
- [src/features/foundation/email/api/service.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/api/service.ts)
- [src/features/foundation/email/api/queries.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/api/queries.ts)
- [src/features/foundation/email/api/mutations.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/api/mutations.ts)
Added page:
- [src/app/dashboard/administration/email/page.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/app/dashboard/administration/email/page.tsx)
- [src/features/foundation/email/components/email-configuration-page.tsx](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/features/foundation/email/components/email-configuration-page.tsx)
- [src/config/nav-config.ts](/C:/Users/mtpphtaps/Documents/gitea/alla-allaos-fullstack/src/config/nav-config.ts)
UI notes:
- layout follows dashboard-native card rhythm rather than a separate visual system
- top summary area keeps status scannable
- quick verification panel gives one stable place for test-recipient entry
- config cards separate transport, sender identity, secret state, and test state clearly
- operator notes are intentionally calm and low-noise per task request
## Validation
Executed:
- `npm run typecheck -- --pretty false`
- `npm run db:generate`
- `npm run test:setup`
- `npx oxlint src/features/foundation/email src/features/foundation/secrets src/features/foundation/notifications/server/email-provider.ts src/features/foundation/notifications/server/provider-factory.ts src/features/setup/server/readiness.service.ts src/features/setup/server/verification.service.ts src/features/setup/components/setup-wizard.tsx src/app/api/notifications/email-configurations src/app/dashboard/administration/email/page.tsx src/config/nav-config.ts`
Results:
- TypeScript passed
- Drizzle migration generated successfully
- setup test suite passed
- targeted lint passed
## Known Gaps After This Round
- no dedicated profile-level rule yet to force email as a blocking setup requirement for selected installation profiles
- no password reset or invitation flow integration yet; this round only builds the platform and runtime foundation
- no seeded email templates or notification-template management UI specific to outbound email yet
- no per-configuration preview panel for rendered notification payloads yet
- no explicit soft-delete or archived state; delete currently removes the configuration row
## Notes
- This implementation assumes `EMAIL_CONFIG_ENCRYPTION_KEY` will be added to runtime environments before operators save SMTP passwords.
- Existing unrelated dirty files in the worktree were left untouched.

View File

@@ -0,0 +1,20 @@
# Installation Profiles
Installation profiles select setup plugins, wizard steps, required templates, verification checks, reset scopes, and reseed targets.
Current profiles:
- `crm_starter`: foundation plus CRM structure.
- `crm_demo`: foundation plus CRM golden/demo dataset.
- `production`: foundation plus CRM production setup, with destructive maintenance disabled by default.
- `restore_backup`: minimal readiness and verification for restored environments.
- `custom`: operator-selected setup modules and templates.
Profiles are resolved by `src/features/setup/plugins/plugin-registry.ts` and exposed by:
- `GET /api/setup/profiles`
- `GET /api/setup/templates?profile=<profileId>`
- `GET /api/setup/readiness?profile=<profileId>`
- `POST /api/setup/verify` with optional `profileId`
The setup wizard uses the selected profile to render profile-aware plugin metadata and wizard steps.

View File

@@ -0,0 +1,81 @@
# Setup Integration Scenarios
This document defines the D.7.10 setup integration workflow and the golden dataset validation contract.
## Golden Dataset
Source: `setup/golden-dataset/`
The dataset must remain compatible with `setup/templates/templates.json` and must not introduce business behavior beyond existing setup/import contracts.
## Scenario 1: Fresh Install Smoke
1. Start from an empty local or CI database.
2. Run migrations.
3. Run setup readiness.
4. Start a setup run.
5. Preview every CSV in `setup/golden-dataset/`.
6. Commit with the returned `previewHash`.
7. Run verification.
8. Complete setup.
9. Confirm seed manifests and setup run report exist.
Expected result: setup completes without manual SQL.
## Scenario 2: Idempotent Import
1. Preview and commit the full golden dataset.
2. Preview and commit the same files again.
3. Preview and commit the same files a third time.
Expected result: repeated imports produce update/skip behavior and do not create duplicate business-key records.
## Scenario 3: Preview Hash Rejection
1. Preview the golden dataset.
2. Modify one CSV row.
3. Attempt commit using the old `previewHash`.
Expected result: commit is rejected and requires re-preview.
## Scenario 4: Resume
1. Start setup run.
2. Save readiness and CSV preview steps.
3. Refresh browser or call `GET /api/setup/run/current`.
Expected result: persisted setup run and step statuses are returned without raw CSV contents.
## Scenario 5: Reset Safety
1. Preview `business_reset` with a target organization.
2. Execute only after matching preview hash, token, and typed phrase.
3. Preview `setup_run_reset`.
4. Confirm blocked reports for `foundation_reset`, `organization_reset`, `demo_uat_reset`, `full_reset`, and `csv_import_rollback`.
Expected result: only explicitly supported safe reset paths execute; unsupported reset paths return blocking reports.
## Scenario 6: Operational Readiness
After setup completes, verify these domains are ready:
- login
- CRM dashboard
- customer list and detail
- lead list and detail
- opportunity list and detail
- quotation list and detail
- quotation approval routing
- document sequence previews
- PDF/document template readiness
- setup report and seed manifest report
## Automated Contract Tests
Run:
```bash
npm run test:setup
```
These tests validate golden dataset headers, counts, import ordering, reset/reseed API surfaces, setup state surfaces, and non-destructive reset policy contracts.

View File

@@ -0,0 +1,27 @@
# Setup Performance Report
Date: 2026-07-03
## Targets
- Preview 1000 rows: under 5 seconds.
- Commit 1000 rows: under 10 seconds.
- Verification: under 3 seconds.
- Setup Wizard load: under 2 seconds.
## D.7.10 Status
D.7.10 adds the golden dataset and runnable setup contract tests. A dedicated isolated performance database harness is not yet present in this repository, so this report records targets and the contract coverage that protects future performance testing.
## Current Automated Coverage
- Golden dataset row counts and CSV headers.
- Template registry compatibility.
- Import order compatibility.
- Preview hash mutation semantics.
- Seed manifest and resume API surface existence.
- Reset/reseed safety API surface existence.
## Follow-Up
Add a CI-only isolated database harness that can safely run the full fresh database workflow and record elapsed times for preview, commit, verification, and wizard load.

View File

@@ -0,0 +1,37 @@
# Setup Plugin Development
Setup plugins let modules extend setup without editing the setup wizard directly.
Plugin source lives under:
```text
src/features/setup/plugins/
```
Required plugin contract:
- plugin id and version
- installation profiles
- setup templates
- wizard steps
- readiness checks
- verification checks
- CSV preview validators
- import handlers
- reset scopes
- reseed targets
- golden dataset registration
Core plugins:
- `foundation`: setup platform foundations, state, seed manifests, reset framework, CSV framework
- `crm`: CRM templates, CRM verification, CRM reset scopes, and CRM golden dataset
Future modules should add a plugin class and register it in `plugin-registry.ts`. They should not add one-off setup logic directly to the wizard.
Safety rules:
- Plugins cannot bypass Auth.js setup route protection.
- Reset scopes must declare destructive behavior and affected tables.
- CSV templates must declare ownership to avoid duplicate file contracts.
- Seed tasks must be idempotent before execution is exposed.

View File

@@ -446,11 +446,12 @@ CREATE TABLE "crm_leads" (
"description" text, "description" text,
"project_name" text, "project_name" text,
"project_location" text, "project_location" text,
"lead_channel" text,
"product_type" text, "product_type" text,
"priority" text, "priority" text,
"estimated_value" double precision, "estimated_value" double precision,
"awareness_id" text, "awareness_id" text,
"status" text DEFAULT 'new_job' NOT NULL, "status" text NOT NULL,
"followup_status" text, "followup_status" text,
"lost_reason" text, "lost_reason" text,
"outcome" text DEFAULT 'open' NOT NULL, "outcome" text DEFAULT 'open' NOT NULL,
@@ -486,10 +487,14 @@ CREATE TABLE "crm_opportunities" (
"estimated_value" double precision, "estimated_value" double precision,
"chance_percent" integer, "chance_percent" integer,
"expected_close_date" timestamp with time zone, "expected_close_date" timestamp with time zone,
"project_close_date" timestamp with time zone,
"delivery_date" timestamp with time zone,
"competitor" text, "competitor" text,
"source" text, "source" text,
"notes" text, "notes" text,
"is_hot_project" boolean DEFAULT false NOT NULL, "is_hot_project" boolean DEFAULT false NOT NULL,
"hot_project_auto_suggested" boolean DEFAULT false NOT NULL,
"hot_project_manually_overridden" boolean DEFAULT false NOT NULL,
"is_active" boolean DEFAULT true NOT NULL, "is_active" boolean DEFAULT true NOT NULL,
"pipeline_stage" text DEFAULT 'lead' NOT NULL, "pipeline_stage" text DEFAULT 'lead' NOT NULL,
"closed_at" timestamp with time zone, "closed_at" timestamp with time zone,
@@ -687,7 +692,11 @@ CREATE TABLE "crm_quotations" (
"tax_amount" double precision DEFAULT 0 NOT NULL, "tax_amount" double precision DEFAULT 0 NOT NULL,
"total_amount" double precision DEFAULT 0 NOT NULL, "total_amount" double precision DEFAULT 0 NOT NULL,
"chance_percent" integer, "chance_percent" integer,
"project_close_date" timestamp with time zone,
"delivery_date" timestamp with time zone,
"is_hot_project" boolean DEFAULT false NOT NULL, "is_hot_project" boolean DEFAULT false NOT NULL,
"hot_project_auto_suggested" boolean DEFAULT false NOT NULL,
"hot_project_manually_overridden" boolean DEFAULT false NOT NULL,
"competitor" text, "competitor" text,
"salesman_id" text, "salesman_id" text,
"is_sent" boolean DEFAULT false NOT NULL, "is_sent" boolean DEFAULT false NOT NULL,
@@ -829,6 +838,70 @@ CREATE TABLE "products" (
"updated_at" timestamp with time zone DEFAULT now() NOT NULL "updated_at" timestamp with time zone DEFAULT now() NOT NULL
); );
--> statement-breakpoint --> statement-breakpoint
CREATE TABLE "seed_manifest_items" (
"id" text PRIMARY KEY NOT NULL,
"seed_manifest_id" text NOT NULL,
"item_key" text NOT NULL,
"source_file" text NOT NULL,
"checksum" text NOT NULL,
"status" text DEFAULT 'pending' NOT NULL,
"imported_count" integer DEFAULT 0 NOT NULL,
"updated_count" integer DEFAULT 0 NOT NULL,
"skipped_count" integer DEFAULT 0 NOT NULL,
"error_count" integer DEFAULT 0 NOT NULL,
"warning_count" integer DEFAULT 0 NOT NULL,
"report_json" jsonb,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "seed_manifests" (
"id" text PRIMARY KEY NOT NULL,
"setup_run_id" text,
"organization_id" text,
"name" text NOT NULL,
"version" text NOT NULL,
"type" text NOT NULL,
"checksum" text NOT NULL,
"status" text DEFAULT 'pending' NOT NULL,
"source" text NOT NULL,
"applied_by" text,
"applied_at" timestamp with time zone,
"report_json" jsonb,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "setup_run_steps" (
"id" text PRIMARY KEY NOT NULL,
"setup_run_id" text NOT NULL,
"step_key" text NOT NULL,
"status" text DEFAULT 'not_started' NOT NULL,
"input_hash" text,
"output_json" jsonb,
"errors_json" jsonb,
"warnings_json" jsonb,
"started_at" timestamp with time zone,
"completed_at" timestamp with time zone,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "setup_runs" (
"id" text PRIMARY KEY NOT NULL,
"status" text DEFAULT 'not_started' NOT NULL,
"mode" text DEFAULT 'production' NOT NULL,
"target_organization_id" text,
"started_by" text NOT NULL,
"completed_by" text,
"started_at" timestamp with time zone DEFAULT now() NOT NULL,
"completed_at" timestamp with time zone,
"last_error" text,
"metadata" jsonb,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "tr_audit_logs" ( CREATE TABLE "tr_audit_logs" (
"id" text PRIMARY KEY NOT NULL, "id" text PRIMARY KEY NOT NULL,
"organization_id" text NOT NULL, "organization_id" text NOT NULL,
@@ -879,4 +952,6 @@ CREATE UNIQUE INDEX "crm_user_role_assignments_org_user_role_idx" ON "crm_user_r
CREATE UNIQUE INDEX "document_sequences_org_branch_product_doc_period_idx" ON "document_sequences" USING btree ("organization_id","branch_id","product_type","document_type","period");--> statement-breakpoint CREATE UNIQUE INDEX "document_sequences_org_branch_product_doc_period_idx" ON "document_sequences" USING btree ("organization_id","branch_id","product_type","document_type","period");--> statement-breakpoint
CREATE UNIQUE INDEX "ms_options_org_category_code_idx" ON "ms_options" USING btree ("organization_id","category","code");--> statement-breakpoint CREATE UNIQUE INDEX "ms_options_org_category_code_idx" ON "ms_options" USING btree ("organization_id","category","code");--> statement-breakpoint
CREATE UNIQUE INDEX "organizations_slug_idx" ON "organizations" USING btree ("slug");--> statement-breakpoint CREATE UNIQUE INDEX "organizations_slug_idx" ON "organizations" USING btree ("slug");--> statement-breakpoint
CREATE UNIQUE INDEX "seed_manifest_items_manifest_item_idx" ON "seed_manifest_items" USING btree ("seed_manifest_id","item_key");--> statement-breakpoint
CREATE UNIQUE INDEX "setup_run_steps_run_step_idx" ON "setup_run_steps" USING btree ("setup_run_id","step_key");--> statement-breakpoint
CREATE UNIQUE INDEX "users_email_idx" ON "users" USING btree ("email"); CREATE UNIQUE INDEX "users_email_idx" ON "users" USING btree ("email");

View File

@@ -1,5 +0,0 @@
ALTER TABLE "crm_leads"
ADD COLUMN IF NOT EXISTS "lead_channel" text;
ALTER TABLE "crm_leads"
ALTER COLUMN "status" DROP DEFAULT;

View File

@@ -0,0 +1,25 @@
CREATE TABLE "email_configurations" (
"id" text PRIMARY KEY NOT NULL,
"organization_id" text NOT NULL,
"provider_type" text DEFAULT 'smtp' NOT NULL,
"name" text NOT NULL,
"host" text NOT NULL,
"port" integer DEFAULT 587 NOT NULL,
"secure" boolean DEFAULT false NOT NULL,
"username" text,
"password_encrypted" text,
"from_email" text NOT NULL,
"from_name" text,
"reply_to_email" text,
"is_default" boolean DEFAULT false NOT NULL,
"is_active" boolean DEFAULT true NOT NULL,
"last_test_status" text DEFAULT 'not_tested' NOT NULL,
"last_tested_at" timestamp with time zone,
"last_test_error" text,
"created_by" text NOT NULL,
"updated_by" text NOT NULL,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE UNIQUE INDEX "email_configurations_org_name_idx" ON "email_configurations" USING btree ("organization_id","name");

View File

@@ -1,11 +0,0 @@
ALTER TABLE "crm_opportunities"
ADD COLUMN "project_close_date" timestamp with time zone,
ADD COLUMN "delivery_date" timestamp with time zone,
ADD COLUMN "hot_project_auto_suggested" boolean DEFAULT false NOT NULL,
ADD COLUMN "hot_project_manually_overridden" boolean DEFAULT false NOT NULL;
ALTER TABLE "crm_quotations"
ADD COLUMN "project_close_date" timestamp with time zone,
ADD COLUMN "delivery_date" timestamp with time zone,
ADD COLUMN "hot_project_auto_suggested" boolean DEFAULT false NOT NULL,
ADD COLUMN "hot_project_manually_overridden" boolean DEFAULT false NOT NULL;

View File

@@ -1,10 +0,0 @@
ALTER TABLE "crm_leads" ALTER COLUMN "status" DROP DEFAULT;--> statement-breakpoint
ALTER TABLE "crm_leads" ADD COLUMN "lead_channel" text;--> statement-breakpoint
ALTER TABLE "crm_opportunities" ADD COLUMN "project_close_date" timestamp with time zone;--> statement-breakpoint
ALTER TABLE "crm_opportunities" ADD COLUMN "delivery_date" timestamp with time zone;--> statement-breakpoint
ALTER TABLE "crm_opportunities" ADD COLUMN "hot_project_auto_suggested" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "crm_opportunities" ADD COLUMN "hot_project_manually_overridden" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "crm_quotations" ADD COLUMN "project_close_date" timestamp with time zone;--> statement-breakpoint
ALTER TABLE "crm_quotations" ADD COLUMN "delivery_date" timestamp with time zone;--> statement-breakpoint
ALTER TABLE "crm_quotations" ADD COLUMN "hot_project_auto_suggested" boolean DEFAULT false NOT NULL;--> statement-breakpoint
ALTER TABLE "crm_quotations" ADD COLUMN "hot_project_manually_overridden" boolean DEFAULT false NOT NULL;

View File

@@ -1,5 +1,5 @@
{ {
"id": "6eb8d614-2b85-48c3-919e-af8fa13f0fb6", "id": "6c217ceb-57e5-410e-9132-610c819272f2",
"prevId": "00000000-0000-0000-0000-000000000000", "prevId": "00000000-0000-0000-0000-000000000000",
"version": "7", "version": "7",
"dialect": "postgresql", "dialect": "postgresql",
@@ -3045,6 +3045,12 @@
"primaryKey": false, "primaryKey": false,
"notNull": false "notNull": false
}, },
"lead_channel": {
"name": "lead_channel",
"type": "text",
"primaryKey": false,
"notNull": false
},
"product_type": { "product_type": {
"name": "product_type", "name": "product_type",
"type": "text", "type": "text",
@@ -3073,8 +3079,7 @@
"name": "status", "name": "status",
"type": "text", "type": "text",
"primaryKey": false, "primaryKey": false,
"notNull": true, "notNull": true
"default": "'new_job'"
}, },
"followup_status": { "followup_status": {
"name": "followup_status", "name": "followup_status",
@@ -3307,6 +3312,18 @@
"primaryKey": false, "primaryKey": false,
"notNull": false "notNull": false
}, },
"project_close_date": {
"name": "project_close_date",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"delivery_date": {
"name": "delivery_date",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"competitor": { "competitor": {
"name": "competitor", "name": "competitor",
"type": "text", "type": "text",
@@ -3332,6 +3349,20 @@
"notNull": true, "notNull": true,
"default": false "default": false
}, },
"hot_project_auto_suggested": {
"name": "hot_project_auto_suggested",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"hot_project_manually_overridden": {
"name": "hot_project_manually_overridden",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_active": { "is_active": {
"name": "is_active", "name": "is_active",
"type": "boolean", "type": "boolean",
@@ -4526,6 +4557,18 @@
"primaryKey": false, "primaryKey": false,
"notNull": false "notNull": false
}, },
"project_close_date": {
"name": "project_close_date",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"delivery_date": {
"name": "delivery_date",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"is_hot_project": { "is_hot_project": {
"name": "is_hot_project", "name": "is_hot_project",
"type": "boolean", "type": "boolean",
@@ -4533,6 +4576,20 @@
"notNull": true, "notNull": true,
"default": false "default": false
}, },
"hot_project_auto_suggested": {
"name": "hot_project_auto_suggested",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"hot_project_manually_overridden": {
"name": "hot_project_manually_overridden",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"competitor": { "competitor": {
"name": "competitor", "name": "competitor",
"type": "text", "type": "text",
@@ -5576,6 +5633,433 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.seed_manifest_items": {
"name": "seed_manifest_items",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"seed_manifest_id": {
"name": "seed_manifest_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"item_key": {
"name": "item_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"source_file": {
"name": "source_file",
"type": "text",
"primaryKey": false,
"notNull": true
},
"checksum": {
"name": "checksum",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"imported_count": {
"name": "imported_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"updated_count": {
"name": "updated_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"skipped_count": {
"name": "skipped_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"error_count": {
"name": "error_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"warning_count": {
"name": "warning_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"report_json": {
"name": "report_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"seed_manifest_items_manifest_item_idx": {
"name": "seed_manifest_items_manifest_item_idx",
"columns": [
{
"expression": "seed_manifest_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "item_key",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.seed_manifests": {
"name": "seed_manifests",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"setup_run_id": {
"name": "setup_run_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"organization_id": {
"name": "organization_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"checksum": {
"name": "checksum",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": true
},
"applied_by": {
"name": "applied_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"applied_at": {
"name": "applied_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"report_json": {
"name": "report_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.setup_run_steps": {
"name": "setup_run_steps",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"setup_run_id": {
"name": "setup_run_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"step_key": {
"name": "step_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'not_started'"
},
"input_hash": {
"name": "input_hash",
"type": "text",
"primaryKey": false,
"notNull": false
},
"output_json": {
"name": "output_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"errors_json": {
"name": "errors_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"warnings_json": {
"name": "warnings_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"started_at": {
"name": "started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"completed_at": {
"name": "completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"setup_run_steps_run_step_idx": {
"name": "setup_run_steps_run_step_idx",
"columns": [
{
"expression": "setup_run_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "step_key",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.setup_runs": {
"name": "setup_runs",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'not_started'"
},
"mode": {
"name": "mode",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'production'"
},
"target_organization_id": {
"name": "target_organization_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"started_by": {
"name": "started_by",
"type": "text",
"primaryKey": false,
"notNull": true
},
"completed_by": {
"name": "completed_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"started_at": {
"name": "started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"completed_at": {
"name": "completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_error": {
"name": "last_error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tr_audit_logs": { "public.tr_audit_logs": {
"name": "tr_audit_logs", "name": "tr_audit_logs",
"schema": "", "schema": "",

View File

@@ -1,6 +1,6 @@
{ {
"id": "be860157-9371-469d-84ec-aefc991ebddc", "id": "3dc70e0a-e0ce-433d-9d4b-cb2ae6455ce7",
"prevId": "6eb8d614-2b85-48c3-919e-af8fa13f0fb6", "prevId": "6c217ceb-57e5-410e-9132-610c819272f2",
"version": "7", "version": "7",
"dialect": "postgresql", "dialect": "postgresql",
"tables": { "tables": {
@@ -5270,6 +5270,175 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.email_configurations": {
"name": "email_configurations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"organization_id": {
"name": "organization_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider_type": {
"name": "provider_type",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'smtp'"
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"host": {
"name": "host",
"type": "text",
"primaryKey": false,
"notNull": true
},
"port": {
"name": "port",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 587
},
"secure": {
"name": "secure",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": false
},
"password_encrypted": {
"name": "password_encrypted",
"type": "text",
"primaryKey": false,
"notNull": false
},
"from_email": {
"name": "from_email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"from_name": {
"name": "from_name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"reply_to_email": {
"name": "reply_to_email",
"type": "text",
"primaryKey": false,
"notNull": false
},
"is_default": {
"name": "is_default",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": false
},
"is_active": {
"name": "is_active",
"type": "boolean",
"primaryKey": false,
"notNull": true,
"default": true
},
"last_test_status": {
"name": "last_test_status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'not_tested'"
},
"last_tested_at": {
"name": "last_tested_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_test_error": {
"name": "last_test_error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"created_by": {
"name": "created_by",
"type": "text",
"primaryKey": false,
"notNull": true
},
"updated_by": {
"name": "updated_by",
"type": "text",
"primaryKey": false,
"notNull": true
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"email_configurations_org_name_idx": {
"name": "email_configurations_org_name_idx",
"columns": [
{
"expression": "organization_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "name",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.memberships": { "public.memberships": {
"name": "memberships", "name": "memberships",
"schema": "", "schema": "",
@@ -5633,6 +5802,433 @@
"checkConstraints": {}, "checkConstraints": {},
"isRLSEnabled": false "isRLSEnabled": false
}, },
"public.seed_manifest_items": {
"name": "seed_manifest_items",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"seed_manifest_id": {
"name": "seed_manifest_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"item_key": {
"name": "item_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"source_file": {
"name": "source_file",
"type": "text",
"primaryKey": false,
"notNull": true
},
"checksum": {
"name": "checksum",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"imported_count": {
"name": "imported_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"updated_count": {
"name": "updated_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"skipped_count": {
"name": "skipped_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"error_count": {
"name": "error_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"warning_count": {
"name": "warning_count",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": 0
},
"report_json": {
"name": "report_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"seed_manifest_items_manifest_item_idx": {
"name": "seed_manifest_items_manifest_item_idx",
"columns": [
{
"expression": "seed_manifest_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "item_key",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.seed_manifests": {
"name": "seed_manifests",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"setup_run_id": {
"name": "setup_run_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"organization_id": {
"name": "organization_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"version": {
"name": "version",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"checksum": {
"name": "checksum",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'pending'"
},
"source": {
"name": "source",
"type": "text",
"primaryKey": false,
"notNull": true
},
"applied_by": {
"name": "applied_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"applied_at": {
"name": "applied_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"report_json": {
"name": "report_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.setup_run_steps": {
"name": "setup_run_steps",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"setup_run_id": {
"name": "setup_run_id",
"type": "text",
"primaryKey": false,
"notNull": true
},
"step_key": {
"name": "step_key",
"type": "text",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'not_started'"
},
"input_hash": {
"name": "input_hash",
"type": "text",
"primaryKey": false,
"notNull": false
},
"output_json": {
"name": "output_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"errors_json": {
"name": "errors_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"warnings_json": {
"name": "warnings_json",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"started_at": {
"name": "started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"completed_at": {
"name": "completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {
"setup_run_steps_run_step_idx": {
"name": "setup_run_steps_run_step_idx",
"columns": [
{
"expression": "setup_run_id",
"isExpression": false,
"asc": true,
"nulls": "last"
},
{
"expression": "step_key",
"isExpression": false,
"asc": true,
"nulls": "last"
}
],
"isUnique": true,
"concurrently": false,
"method": "btree",
"with": {}
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.setup_runs": {
"name": "setup_runs",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"status": {
"name": "status",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'not_started'"
},
"mode": {
"name": "mode",
"type": "text",
"primaryKey": false,
"notNull": true,
"default": "'production'"
},
"target_organization_id": {
"name": "target_organization_id",
"type": "text",
"primaryKey": false,
"notNull": false
},
"started_by": {
"name": "started_by",
"type": "text",
"primaryKey": false,
"notNull": true
},
"completed_by": {
"name": "completed_by",
"type": "text",
"primaryKey": false,
"notNull": false
},
"started_at": {
"name": "started_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"completed_at": {
"name": "completed_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false
},
"last_error": {
"name": "last_error",
"type": "text",
"primaryKey": false,
"notNull": false
},
"metadata": {
"name": "metadata",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updated_at": {
"name": "updated_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tr_audit_logs": { "public.tr_audit_logs": {
"name": "tr_audit_logs", "name": "tr_audit_logs",
"schema": "", "schema": "",

View File

@@ -5,29 +5,15 @@
{ {
"idx": 0, "idx": 0,
"version": "7", "version": "7",
"when": 1782833951256, "when": 1783326039269,
"tag": "0000_short_the_executioner", "tag": "0000_classy_unicorn",
"breakpoints": true "breakpoints": true
}, },
{ {
"idx": 1, "idx": 1,
"version": "7", "version": "7",
"when": 1782896400000, "when": 1783350585715,
"tag": "0001_lead_channel_and_status_default", "tag": "0001_yellow_wasp",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1782896500000,
"tag": "0002_opportunity_quotation_timeline_hot_project",
"breakpoints": true
},
{
"idx": 3,
"version": "7",
"when": 1782881325779,
"tag": "0003_curious_wild_child",
"breakpoints": true "breakpoints": true
} }
] ]

173
onvalla-theme.css Normal file
View File

@@ -0,0 +1,173 @@
@import "tailwindcss";
@custom-variant dark (&:is(.dark *));
:root {
--background: oklch(0.9816 0.0017 247.8390);
--foreground: oklch(0.2277 0.0534 259.0168);
--card: oklch(1.0000 0 0);
--card-foreground: oklch(0.2277 0.0534 259.0168);
--popover: oklch(1.0000 0 0);
--popover-foreground: oklch(0.2277 0.0534 259.0168);
--primary: oklch(0.3863 0.0858 321.9713);
--primary-foreground: oklch(1.0000 0 0);
--secondary: oklch(0.6340 0.2116 31.7828);
--secondary-foreground: oklch(1.0000 0 0);
--muted: oklch(0.9275 0.0017 247.8404);
--muted-foreground: oklch(0.5751 0.0259 285.5573);
--accent: oklch(0.6340 0.2116 31.7828);
--accent-foreground: oklch(1.0000 0 0);
--destructive: oklch(0.6340 0.2116 31.7828);
--destructive-foreground: oklch(1.0000 0 0);
--border: oklch(0.5751 0.0259 285.5573);
--input: oklch(0.9275 0.0017 247.8404);
--ring: oklch(0.3863 0.0858 321.9713);
--chart-1: oklch(0.3863 0.0858 321.9713);
--chart-2: oklch(0.6340 0.2116 31.7828);
--chart-3: oklch(0.2277 0.0534 259.0168);
--chart-4: oklch(0.5751 0.0259 285.5573);
--chart-5: oklch(0.2185 0.0702 317.5316);
--sidebar: oklch(1.0000 0 0);
--sidebar-foreground: oklch(0.2277 0.0534 259.0168);
--sidebar-primary: oklch(0.3863 0.0858 321.9713);
--sidebar-primary-foreground: oklch(1.0000 0 0);
--sidebar-accent: oklch(0.9275 0.0017 247.8404);
--sidebar-accent-foreground: oklch(0.2277 0.0534 259.0168);
--sidebar-border: oklch(0.9275 0.0017 247.8404);
--sidebar-ring: oklch(0.3863 0.0858 321.9713);
--font-sans: Inter, sans-serif;
--font-serif: Georgia, serif;
--font-mono: JetBrains Mono, monospace;
--radius: 0.5rem;
--shadow-x: 0px;
--shadow-y: 2px;
--shadow-blur: 10px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: #000000;
--shadow-2xs: 0px 2px 10px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0px 2px 10px 0px hsl(0 0% 0% / 0.05);
--shadow-sm: 0px 2px 10px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow: 0px 2px 10px 0px hsl(0 0% 0% / 0.10), 0px 1px 2px -1px hsl(0 0% 0% / 0.10);
--shadow-md: 0px 2px 10px 0px hsl(0 0% 0% / 0.10), 0px 2px 4px -1px hsl(0 0% 0% / 0.10);
--shadow-lg: 0px 2px 10px 0px hsl(0 0% 0% / 0.10), 0px 4px 6px -1px hsl(0 0% 0% / 0.10);
--shadow-xl: 0px 2px 10px 0px hsl(0 0% 0% / 0.10), 0px 8px 10px -1px hsl(0 0% 0% / 0.10);
--shadow-2xl: 0px 2px 10px 0px hsl(0 0% 0% / 0.25);
--tracking-normal: 0em;
--spacing: 0.25rem;
}
.dark {
--background: oklch(0.2277 0.0534 259.0168);
--foreground: oklch(0.9275 0.0017 247.8404);
--card: oklch(0.2185 0.0702 317.5316);
--card-foreground: oklch(1.0000 0 0);
--popover: oklch(0.2185 0.0702 317.5316);
--popover-foreground: oklch(1.0000 0 0);
--primary: oklch(0.3863 0.0858 321.9713);
--primary-foreground: oklch(1.0000 0 0);
--secondary: oklch(0.6340 0.2116 31.7828);
--secondary-foreground: oklch(1.0000 0 0);
--muted: oklch(0.5751 0.0259 285.5573);
--muted-foreground: oklch(0.9275 0.0017 247.8404);
--accent: oklch(0.6340 0.2116 31.7828);
--accent-foreground: oklch(1.0000 0 0);
--destructive: oklch(0.6340 0.2116 31.7828);
--destructive-foreground: oklch(1.0000 0 0);
--border: oklch(0.3863 0.0858 321.9713);
--input: oklch(0.2277 0.0534 259.0168);
--ring: oklch(0.6340 0.2116 31.7828);
--chart-1: oklch(0.3863 0.0858 321.9713);
--chart-2: oklch(0.6340 0.2116 31.7828);
--chart-3: oklch(0.5751 0.0259 285.5573);
--chart-4: oklch(0.2185 0.0702 317.5316);
--chart-5: oklch(1.0000 0 0);
--sidebar: oklch(0.2185 0.0702 317.5316);
--sidebar-foreground: oklch(0.9275 0.0017 247.8404);
--sidebar-primary: oklch(0.6340 0.2116 31.7828);
--sidebar-primary-foreground: oklch(1.0000 0 0);
--sidebar-accent: oklch(0.3863 0.0858 321.9713);
--sidebar-accent-foreground: oklch(1.0000 0 0);
--sidebar-border: oklch(0.3863 0.0858 321.9713);
--sidebar-ring: oklch(0.6340 0.2116 31.7828);
--font-sans: Inter, sans-serif;
--font-serif: Georgia, serif;
--font-mono: JetBrains Mono, monospace;
--radius: 0.5rem;
--shadow-x: 0px;
--shadow-y: 4px;
--shadow-blur: 12px;
--shadow-spread: 0px;
--shadow-opacity: 0.3;
--shadow-color: #000000;
--shadow-2xs: 0px 4px 12px 0px hsl(0 0% 0% / 0.15);
--shadow-xs: 0px 4px 12px 0px hsl(0 0% 0% / 0.15);
--shadow-sm: 0px 4px 12px 0px hsl(0 0% 0% / 0.30), 0px 1px 2px -1px hsl(0 0% 0% / 0.30);
--shadow: 0px 4px 12px 0px hsl(0 0% 0% / 0.30), 0px 1px 2px -1px hsl(0 0% 0% / 0.30);
--shadow-md: 0px 4px 12px 0px hsl(0 0% 0% / 0.30), 0px 2px 4px -1px hsl(0 0% 0% / 0.30);
--shadow-lg: 0px 4px 12px 0px hsl(0 0% 0% / 0.30), 0px 4px 6px -1px hsl(0 0% 0% / 0.30);
--shadow-xl: 0px 4px 12px 0px hsl(0 0% 0% / 0.30), 0px 8px 10px -1px hsl(0 0% 0% / 0.30);
--shadow-2xl: 0px 4px 12px 0px hsl(0 0% 0% / 0.75);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--font-serif: var(--font-serif);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
--shadow-2xs: var(--shadow-2xs);
--shadow-xs: var(--shadow-xs);
--shadow-sm: var(--shadow-sm);
--shadow: var(--shadow);
--shadow-md: var(--shadow-md);
--shadow-lg: var(--shadow-lg);
--shadow-xl: var(--shadow-xl);
--shadow-2xl: var(--shadow-2xl);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

View File

@@ -9,6 +9,7 @@
"lint": "oxlint", "lint": "oxlint",
"lint:fix": "oxlint --fix && bun format", "lint:fix": "oxlint --fix && bun format",
"lint:strict": "oxlint --deny-warnings", "lint:strict": "oxlint --deny-warnings",
"test:setup": "node --disable-warning=ExperimentalWarning --disable-warning=MODULE_TYPELESS_PACKAGE_JSON --experimental-strip-types --test src/tests/setup/*.test.ts",
"format": "oxfmt --write .", "format": "oxfmt --write .",
"format:check": "oxfmt --check .", "format:check": "oxfmt --check .",
"prepare": "husky", "prepare": "husky",

743
plans/task-d.7.10.md Normal file
View File

@@ -0,0 +1,743 @@
# Task D.7.10 Setup Integration Test & Golden Dataset
## Objective
Build a complete end-to-end integration test suite and Golden Dataset for the ALLA OS Setup Platform.
This task validates that a brand-new database can be transformed into a fully operational CRM system using only the Setup Platform.
The Golden Dataset becomes the canonical dataset for:
- Development
- CI/CD
- QA
- UAT
- Customer Demo
- Regression Testing
This task must not introduce new business behavior. It verifies the implementation completed in D.7.1D.7.8.
---
# Review Before Implementation
Review
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- plans/task-d.7.4.md
- plans/task-d.7.5.md
- plans/task-d.7.6.md
- plans/task-d.7.7.md
- plans/task-d.7.8.md
Review
docs/setup/*
Review
setup/templates/*
Review
src/features/setup/**
Review
src/db/seeds/**
Review
CRM business modules
Customer
Lead
Opportunity
Quotation
Approval
PDF
Document Sequence
Storage
---
# Objective Validation
The following workflow must succeed without manual SQL.
Empty Database
Migration
Foundation Setup
Organization Setup
CSV Import
Verification
Login
CRM Ready
Quotation Ready
Approval Ready
PDF Ready
---
# Golden Dataset
Create
setup/golden-dataset/
Contents
README.md
dataset.json
organizations.csv
users.csv
memberships.csv
crm-role-assignments.csv
master-options.csv
branches.csv
product-types.csv
document-sequences.csv
approval-workflows.csv
approval-steps.csv
approval-matrix.csv
customers.csv
contacts.csv
contact-shares.csv
leads.csv
opportunities.csv
opportunity-parties.csv
quotations.csv
quotation-items.csv
quotation-parties.csv
quotation-topics.csv
quotation-topic-items.csv
This dataset becomes the official reference dataset.
---
# Dataset Rules
Organizations
ALLA
ONVALLA
Users
IT
Marketing
Sales
Sales Manager
CEO
Customers
At least
10
Contacts
At least
20
Leads
At least
20
Opportunities
At least
15
Quotations
At least
20
Include
Draft
Pending Approval
Approved
Rejected
Revision
Include
Multiple Branches
Multiple Product Types
Multiple Approval Levels
Multiple Currencies
Discount
Tax
Project Parties
Attachments metadata only
---
# Scenario Matrix
Create
docs/setup/integration-scenarios.md
Document
Scenario
Purpose
Expected Result
Required Dataset
Verification
Example
Scenario
Fresh Installation
PASS
Scenario
Resume Setup
PASS
Scenario
CSV Re-import
Idempotent
Scenario
Duplicate Import
No Duplicate
Scenario
Business Reset
Foundation Retained
Scenario
Setup Run Reset
Business Retained
Scenario
Preview Hash Changed
Commit Blocked
Scenario
Verification After Import
PASS
Scenario
Manifest Version Check
PASS
---
# Automated Integration Tests
Create
src/tests/setup/
Recommended
setup-install.test.ts
setup-preview.test.ts
setup-commit.test.ts
setup-verification.test.ts
setup-resume.test.ts
setup-reset.test.ts
golden-dataset.test.ts
Tests must cover
Migration
Readiness
Template Registry
Preview
Commit
Verification
Manifest
Resume
Reset
---
# End-to-End Workflow Test
Automate
Fresh Database
Run Migration
Foundation Ready
Create Organization
Preview CSV
Commit CSV
Verification PASS
Login
Create Customer
Create Lead
Assign Opportunity
Create Quotation
Approval
Generate PDF
Completed
Every step must assert expected results.
---
# Idempotency Tests
Run
Import
Import Again
Import Again
Verify
No Duplicate
Only
Create
Update
Skip
Allowed.
---
# Preview Hash Tests
Verify
Preview
Commit
Modify CSV
Commit
Rejected
---
# Seed Manifest Tests
Verify
Manifest Created
Manifest Item Created
Checksum
Version
Status
Resume
---
# Reset Tests
Verify
Business Reset
Deletes CRM
Keeps Foundation
Setup Run Reset
Deletes Setup Metadata
Keeps Business
Foundation Reset
Blocked
Organization Reset
Blocked
Production Reset
Blocked
CSV Rollback
Blocked
---
# Verification Tests
Verify
PASS
Environment
Database
Storage
Template
Approval
Document Sequence
Report Definitions
Notification Templates
Organization
Branch
Product Type
CRM Assignment
---
# Performance Targets
Preview
1000 rows
<5 seconds
Commit
1000 rows
<10 seconds
Verification
<3 seconds
Setup Wizard Load
<2 seconds
---
# Deliverables
setup/golden-dataset/
README.md
dataset.json
Official CSV Pack
docs/setup/integration-scenarios.md
Automated integration tests
Setup smoke test
Golden dataset validation
Performance report
---
# Acceptance Criteria
✓ Empty database can be fully initialized.
✓ Migration succeeds.
✓ Setup Wizard completes.
✓ Golden Dataset imports successfully.
✓ Verification returns PASS.
✓ Login works.
✓ Customer creation works.
✓ Lead workflow works.
✓ Opportunity workflow works.
✓ Quotation workflow works.
✓ Approval workflow works.
✓ PDF generation works.
✓ Document sequence works.
✓ Import is idempotent.
✓ Preview hash validation works.
✓ Seed manifests created.
✓ Resume works.
✓ Business reset works.
✓ Setup metadata reset works.
✓ Blocked reset scopes remain blocked.
✓ All automated integration tests pass.
✓ Golden Dataset becomes official regression dataset.
---
# Future
After D.7.10
Freeze the Setup Platform.
All future modules
(HR, Asset, Purchase, Inventory, Service, etc.)
must integrate with the existing Setup Platform rather than creating new setup or import mechanisms.
The Setup Platform becomes the single supported installation, onboarding, import, verification, and maintenance foundation for ALLA OS.

340
plans/task-d.7.11.md Normal file
View File

@@ -0,0 +1,340 @@
# Task D.7.11 First-Run Bootstrap Setup Mode
## Objective
Implement first-run setup mode for ALLA OS.
When the database is newly migrated and the system has not been initialized, the app must automatically redirect users to a public bootstrap setup page without requiring login.
The bootstrap setup page allows uploading required CSV files, validates them, commits setup data, creates the first organization and administrator, marks setup as completed, and then redirects the user to login.
---
## Desired Flow
npm install
npm run db:generate
npm run db:migrate
npm run dev
Open browser
If setup is not completed:
redirect to
/administration/setup
No login required.
User uploads CSV files:
- users.csv
- organizations.csv
- memberships.csv
- master-options.csv
- branches.csv
- product-types.csv
- document-sequences.csv
- approval-workflows.csv
- approval-steps.csv
- approval-matrix.csv
- customers.csv
- contacts.csv
- leads.csv
- opportunities.csv
- quotations.csv
- quotation-items.csv
- quotation-parties.csv
- quotation-topics.csv
- quotation-topic-items.csv
Click Setup
System validates CSV
System commits data
System creates first admin
System marks setup completed
Redirect to login
User logs in and starts using the system
---
## Key Concept
There are now two setup modes:
1. Bootstrap Setup
Used before first login.
Route:
/administration/setup
No login required only when setup is not completed.
2. Admin Setup / Maintenance Setup
Used after login.
Route:
/dashboard/administration/setup
Requires super_admin.
---
## Required Behavior
## First Run Detection
Create setup status check:
System is not initialized when:
- no completed setup_run exists
or
- no super_admin user exists
or
- no organization exists
or
- no admin membership exists
System is initialized when:
- setup_run status = completed
- at least one super_admin exists
- at least one organization exists
- admin membership exists
---
## Middleware Redirect
Update middleware behavior:
If setup is not completed:
allow only:
/administration/setup
/api/setup/bootstrap/*
/api/setup/templates
/_next/*
static assets
redirect all other routes to:
/administration/setup
If setup is completed:
/administration/setup redirects to:
/auth/sign-in
or
/dashboard
---
## Bootstrap Setup Page
Create:
src/app/administration/setup/page.tsx
This page must not use dashboard layout.
It should be a clean public setup page.
Show:
- System status
- Required CSV upload
- Template checklist
- Preview result
- Setup button
- Completion screen
---
## Bootstrap APIs
Create public-but-guarded bootstrap APIs:
GET /api/setup/bootstrap/status
POST /api/setup/bootstrap/preview
POST /api/setup/bootstrap/commit
POST /api/setup/bootstrap/complete
These APIs do not require login only while setup is incomplete.
After setup is completed, these APIs must reject public access.
---
## Bootstrap Security
Even though no login is required, it must be protected by first-run rules.
Rules:
- Bootstrap APIs are enabled only when setup is incomplete.
- Once completed, bootstrap APIs return 403.
- Commit requires previewHash.
- Commit re-runs preview.
- Commit rejects hash mismatch.
- Setup complete requires successful commit.
- Never expose secrets.
- Passwords from users.csv must be hashed.
- No raw CSV contents are persisted.
Optional safety:
Require BOOTSTRAP_SETUP_TOKEN from .env if present.
If env exists:
User must enter token before setup.
---
## CSV Upload UX
The page should show required groups:
Foundation:
- users.csv
- organizations.csv
- memberships.csv
- master-options.csv
- branches.csv
- product-types.csv
Document / Approval:
- document-sequences.csv
- approval-workflows.csv
- approval-steps.csv
- approval-matrix.csv
Business optional:
- customers.csv
- contacts.csv
- leads.csv
- opportunities.csv
- quotations.csv
- quotation-items.csv
- quotation-parties.csv
- quotation-topics.csv
- quotation-topic-items.csv
Allow partial setup:
Required minimum:
- users.csv
- organizations.csv
- memberships.csv
- master-options.csv
- branches.csv
- product-types.csv
- document-sequences.csv
- approval-workflows.csv
- approval-steps.csv
- approval-matrix.csv
Business CSV can be optional.
---
## Setup Completion
After successful commit:
- create setup_run completed
- create seed_manifests
- mark setup status completed
- redirect to /auth/sign-in
Show message:
Setup completed. Please login with the administrator account from users.csv.
---
## Reuse Existing D.7 Work
Reuse:
- CSV templates from D.7.3
- CSV preview engine from D.7.4
- CSV commit engine from D.7.5
- setup state from D.7.8
- seed manifest from D.7.8
- plugin profiles from D.7.9
Do not rewrite import engine.
---
## Out of Scope
- Dashboard setup redesign
- New CSV format
- Reset/reseed
- Plugin marketplace
- Production public setup after completed
- Anonymous setup after system is initialized
---
## Acceptance Criteria
- Fresh database redirects to /administration/setup without login.
- /administration/setup works before first login.
- Bootstrap setup page can upload CSV files.
- Preview validates CSV files.
- Setup commit imports required setup data.
- First admin user is created.
- Organization is created.
- Setup run is marked completed.
- User is redirected to login.
- After completion, /administration/setup no longer allows public setup.
- After completion, dashboard setup requires super_admin.
- Existing /dashboard/administration/setup remains available for maintenance.
- No duplicate CSV validation/import logic is created.
- Typecheck passes.
---
## Suggested Test
1. Drop/reset database.
2. Run migration.
3. Run dev server.
4. Open `/`.
5. Confirm redirect to `/administration/setup`.
6. Upload required CSV files.
7. Preview.
8. Commit setup.
9. Confirm redirect to login.
10. Login with admin from CSV.
11. Open dashboard.
12. Confirm CRM works.
13. Try opening `/administration/setup` again.
14. Confirm public setup is blocked.

355
plans/task-d.7.12.md Normal file
View File

@@ -0,0 +1,355 @@
# Task D.7.12 Step-by-Step First-Run Required CSV Import
## Objective
Improve First-run Bootstrap Setup so required system CSV files are imported step-by-step instead of uploading all files at once.
The goal is to guide the user through each required setup dependency in the correct order:
Step 1 organizations.csv
Step 2 users.csv
Step 3 memberships.csv
Step 4 crm-role-assignments.csv
Step 5 master-options.csv
Step 6 branches.csv
Step 7 product-types.csv
Step 8 document-sequences.csv
Step 9 approval-workflows.csv
Step 10 approval-steps.csv
Step 11 approval-matrix.csv
After all required steps pass, optional business CSV import can be shown separately.
---
## Desired UX
Route:
/administration/setup
Show First-run Bootstrap Wizard.
Each step has:
- CSV file name
- purpose
- required columns
- upload area
- preview button
- run/import button
- result summary
- PASS / WARNING / FAIL status
- next button
User flow:
1. Upload organizations.csv
2. Preview
3. Run Import
4. Step marked PASS
5. Move to users.csv
6. Repeat until all system-required CSV files are complete
7. Show final verification
8. Mark setup completed
9. Redirect to login
---
## Required Import Steps
Use exact dependency order:
1. organizations.csv
2. users.csv
3. memberships.csv
4. crm-role-assignments.csv
5. master-options.csv
6. branches.csv
7. product-types.csv
8. document-sequences.csv
9. approval-workflows.csv
10. approval-steps.csv
11. approval-matrix.csv
Important:
If current import engine requires users before organizations because organizations.created_by_email resolves to users, support one of these approaches:
Option A:
Use temporary bootstrap actor for organizations.csv.
Option B:
Change order to users.csv first.
Decision must be documented before implementation.
Recommended decision:
Step 1 users.csv
Step 2 organizations.csv
Step 3 memberships.csv
because organizations.csv currently requires created_by_email.
---
## System Required Group
Define a bootstrap required group:
system_required
Files:
- users.csv
- organizations.csv
- memberships.csv
- crm-role-assignments.csv
- master-options.csv
- branches.csv
- product-types.csv
- document-sequences.csv
- approval-workflows.csv
- approval-steps.csv
- approval-matrix.csv
Business optional group:
business_optional
Files:
- customers.csv
- contacts.csv
- contact-shares.csv
- leads.csv
- opportunities.csv
- opportunity-parties.csv
- quotations.csv
- quotation-items.csv
- quotation-parties.csv
- quotation-topics.csv
- quotation-topic-items.csv
---
## Implementation Scope
Update First-run Bootstrap UI:
src/app/administration/setup/page.tsx
or bootstrap setup component under:
src/features/setup/components/bootstrap-setup-wizard.tsx
Add step configuration:
src/features/setup/bootstrap/bootstrap-required-steps.ts
Each step defines:
- stepKey
- fileName
- title
- description
- required
- dependsOn
- template metadata
- status
- previewHash
- import report
---
## API Reuse
Reuse existing APIs:
POST /api/setup/bootstrap/preview
POST /api/setup/bootstrap/commit
Each step submits one CSV file at a time.
Do not create new import logic.
Commit flow per step:
1. Upload one file
2. Preview
3. Store previewHash for that step
4. Commit same file with previewHash
5. Persist step result
6. Move to next step
---
## Persistence
Persist step status in setup_run_steps.
Step keys:
bootstrap_users
bootstrap_organizations
bootstrap_memberships
bootstrap_crm_role_assignments
bootstrap_master_options
bootstrap_branches
bootstrap_product_types
bootstrap_document_sequences
bootstrap_approval_workflows
bootstrap_approval_steps
bootstrap_approval_matrix
Each step stores safe output only.
No raw CSV contents.
---
## Dependency Rules
A step is locked until all dependsOn steps pass.
Example:
memberships.csv depends on:
- users.csv
- organizations.csv
crm-role-assignments.csv depends on:
- users.csv
- organizations.csv
- memberships.csv
- master-options.csv
- branches.csv
- product-types.csv
document-sequences.csv depends on:
- organizations.csv
- branches.csv
- product-types.csv
approval-steps.csv depends on:
- approval-workflows.csv
approval-matrix.csv depends on:
- approval-workflows.csv
- branches.csv
- product-types.csv
---
## UI Requirements
Show left stepper:
System Required
- Users
- Organizations
- Memberships
- CRM Roles
- Master Options
- Branches
- Product Types
- Document Sequences
- Approval Workflows
- Approval Steps
- Approval Matrix
Optional Business Data
- Customers
- Contacts
- Leads
- Opportunities
- Quotations
Each step panel shows:
- What this file does
- Required filename
- Required headers
- Sample template reference
- Upload control
- Preview result
- Import result
- Errors and suggested fixes
---
## Completion Rule
Setup can complete only when all system_required steps are PASS or WARNING acknowledged.
Then run:
POST /api/setup/bootstrap/complete
Completion must verify:
- super_admin exists
- organization exists
- membership exists
- CRM role assignment exists
- branch exists
- product type exists
- document sequence exists
- approval workflow/matrix exists
After success:
redirect to /auth/sign-in
---
## Optional Business Import
After system_required completion, show optional step:
Import Business Data
Allow either:
- step-by-step business import
or
- batch upload all business CSV
This can be deferred if needed.
---
## Out Of Scope
- Changing CSV template format
- Rewriting import engine
- Dashboard setup wizard redesign
- Reset/reseed
- Plugin runtime changes
- Business import advanced UI
- Production public setup after completion
---
## Acceptance Criteria
- First-run setup imports required CSV files step-by-step.
- Each step accepts only the expected CSV filename.
- Each step has Preview and Run buttons.
- Import cannot run without successful previewHash.
- Next step is locked until dependencies pass.
- Step status persists across refresh.
- System cannot complete until all required steps pass.
- Existing batch import engine remains unchanged.
- No raw CSV contents are persisted.
- Setup completion redirects to login.
- After completion, public bootstrap setup is blocked.
- Typecheck passes.

528
plans/task-d.7.3.md Normal file
View File

@@ -0,0 +1,528 @@
# Task D.7.3 CSV Template Generator Static Template Pack
## Objective
Generate a complete static CSV template pack for ALLA OS Initial Setup.
The templates will become the official data contract for future CSV Preview (D.7.4) and CSV Import (D.7.5).
This task only creates template files and supporting metadata.
Do NOT implement CSV parsing, validation, import logic, seed execution, reset logic, or setup persistence.
---
## Review Before Implementation
Read and follow:
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- docs/setup/seed-matrix.md
- docs/setup/csv-template-spec.md
- docs/setup/import-mapping.md
- docs/setup/setup-wizard-blueprint.md
Do not invent new columns.
CSV headers must exactly match csv-template-spec.md.
---
## Scope
Create folder
setup/templates/
Generate the following files
organizations.csv
users.csv
memberships.csv
crm-role-assignments.csv
master-options.csv
branches.csv
product-types.csv
document-sequences.csv
approval-workflows.csv
approval-steps.csv
approval-matrix.csv
customers.csv
contacts.csv
contact-shares.csv
leads.csv
opportunities.csv
opportunity-parties.csv
quotations.csv
quotation-items.csv
quotation-parties.csv
quotation-topics.csv
quotation-topic-items.csv
---
## CSV Rules
Every CSV must contain
1 Header row
1 Safe sample row
UTF-8 encoding
Comma delimiter
LF line ending
No BOM if current repository standard already avoids BOM
No blank columns
No undocumented columns
No formulas
No secrets
No production data
No binary references
---
## Sample Data Convention
Use one consistent sample dataset.
Organization
ALLA
Branch
head_office
Product Type
crane
Currency
THB
Administrator
admin@example.com
Marketing
mk.uat@example.com
Sales
sales.uat@example.com
Manager
manager.uat@example.com
CEO
ceo.uat@example.com
Customer
CUS-001
Lead
LD-001
Opportunity
OP-001
Quotation
QT-HO-CR-2607-001
---
## Header Rules
Headers must exactly match
docs/setup/csv-template-spec.md
Do not
rename
reorder
remove
or add columns.
---
## CSV Safety
Passwords
Use placeholder only.
Example
ChangeMe123!
Never include
real password
API key
secret
JWT
SMTP credential
storage credential
real customer
real phone
real tax id
---
## Unsupported Templates
Do NOT create
departments.csv
teams.csv
warehouses.csv
sites.csv
services.csv
price-books.csv
tax-rates.csv
attachments.csv
email-settings.csv
Keep these documented only.
---
## README
Create
setup/templates/README.md
Document
Purpose
Supported Templates
Unsupported Templates
Import Order
Relationship Rules
Sample Dataset
Placeholder Rules
Future D.7.4 Preview Flow
---
## Import Order
Document import order.
Example
01 users.csv
02 organizations.csv
03 memberships.csv
04 crm-role-assignments.csv
05 master-options.csv
06 branches.csv
07 product-types.csv
08 document-sequences.csv
09 approval-workflows.csv
10 approval-steps.csv
11 approval-matrix.csv
12 customers.csv
13 contacts.csv
14 contact-shares.csv
15 leads.csv
16 opportunities.csv
17 opportunity-parties.csv
18 quotations.csv
19 quotation-items.csv
20 quotation-parties.csv
21 quotation-topics.csv
22 quotation-topic-items.csv
Import order must match
docs/setup/seed-matrix.md
---
## Optional Metadata
Create
setup/templates/templates.json
Structure
{
"version": "1.0.0",
"generatedFrom": "docs/setup/csv-template-spec.md",
"templates": [
{
"file": "customers.csv",
"seedType": "business",
"importOrder": 12,
"supported": true
}
]
}
This metadata will be reused by D.7.6 Setup Wizard.
---
## Optional API
If simple and reusable
Create
GET /api/setup/templates
Return
Template Name
Seed Type
Import Order
Supported
Required Columns
Description
This API must be read-only.
Do NOT implement download or ZIP generation.
---
## Out Of Scope
CSV Parser
CSV Validation
CSV Preview
CSV Commit
Seed Execution
Reset
Setup Wizard
Manifest
State Machine
Migrations
Business Logic Changes
---
## Deliverables
setup/templates/
organizations.csv
users.csv
memberships.csv
crm-role-assignments.csv
master-options.csv
branches.csv
product-types.csv
document-sequences.csv
approval-workflows.csv
approval-steps.csv
approval-matrix.csv
customers.csv
contacts.csv
contact-shares.csv
leads.csv
opportunities.csv
opportunity-parties.csv
quotations.csv
quotation-items.csv
quotation-parties.csv
quotation-topics.csv
quotation-topic-items.csv
README.md
Optional
templates.json
Optional
GET /api/setup/templates
---
## Acceptance Criteria
✓ Every supported CSV exists.
✓ Every CSV contains exactly
- one header row
- one sample row
✓ Header names exactly match
docs/setup/csv-template-spec.md
✓ Sample data follows one consistent demo dataset.
✓ No unsupported CSV files are generated.
✓ No secrets or production data exist.
✓ README documents
- import order
- relationship rules
- placeholders
- supported templates
- unsupported templates
✓ templates.json (if implemented) matches generated CSV files.
✓ Optional API (if implemented) is read-only.
✓ No import logic or seed logic is implemented.
✓ Typecheck passes or unrelated failures are documented.
---
## Future Tasks
D.7.4
CSV Preview Validation Engine
D.7.5
CSV Commit Import Engine
D.7.6
Setup Wizard UI
The generated CSV files become the official template pack for all future setup and onboarding workflows.
> Implementation log 2026-07-02: Static CSV template pack completed under
> `setup/templates/`, optional metadata API added at `GET /api/setup/templates`,
> and implementation note saved to
> `docs/implementation/task-d73-csv-template-static-pack.md`.

437
plans/task-d.7.4.md Normal file
View File

@@ -0,0 +1,437 @@
# Task D.7.4 CSV Preview Validation Engine
## Objective
Implement a reusable, non-destructive CSV Preview Validation Engine for ALLA OS.
This engine must validate uploaded CSV files against the official template pack and return a complete preview report without modifying any database records.
The preview engine becomes the shared foundation for D.7.5 (CSV Commit Import Engine), Setup Wizard, and future bulk import features.
No database writes, seed execution, or reset operations are allowed in this task.
---
## Review Before Implementation
Review:
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- docs/setup/seed-matrix.md
- docs/setup/csv-template-spec.md
- docs/setup/import-mapping.md
- docs/setup/setup-wizard-blueprint.md
- docs/setup/verification-matrix.md
- setup/templates/*
- setup/templates/templates.json
Treat templates.json as the runtime source of truth.
---
## Implementation Scope
Create:
src/features/setup/server/csv-preview.service.ts
Supporting modules
src/features/setup/server/csv/
parser.ts
validator.ts
dependency-resolver.ts
header-validator.ts
value-validator.ts
preview-builder.ts
template-registry.ts
Create API
POST /api/setup/import/preview
---
## Input
Accept one or more CSV files.
Each file must match one registered template.
Files may be uploaded in any order.
Engine must automatically resolve dependency order.
---
## Validation Stages
Stage 1
Template Detection
- Match filename
- Match template registry
- Match supported template
Reject unknown templates.
---
Stage 2
Schema Validation
Validate
- header names
- header order
- duplicated columns
- missing columns
- extra columns
- template version (if available)
---
Stage 3
CSV Validation
Validate
- encoding
- delimiter
- empty rows
- duplicated rows
- inconsistent column counts
---
Stage 4
Value Validation
Validate
Required fields
Email
Boolean
Integer
Decimal
Date (YYYY-MM-DD)
Enum
Length
Regex
Custom validators
---
Stage 5
Relationship Resolution
Resolve
organization
branch
product type
users
memberships
CRM role
customer
contact
lead
opportunity
quotation
master options
Return
Resolved
Missing
Ambiguous
---
Stage 6
Dependency Validation
Read
templates.json
Validate
dependsOn
Detect
Missing parent files
Circular dependency
Invalid import order
---
Stage 7
Duplicate Detection
Classify
New
Existing
Update
Conflict
Duplicate inside CSV
---
Stage 8
Preview Report
Return
Imported
Updated
Skipped
Warnings
Errors
Grouped by file.
---
## Report Contract
```ts
type PreviewResult = {
fileName: string;
template: string;
status:
| "PASS"
| "WARNING"
| "FAIL";
summary: {
rows:number;
valid:number;
warning:number;
error:number;
};
rows:[];
}
```
Overall response
```ts
{
summary,
files:[],
generatedAt,
previewHash
}
```
previewHash will be required by D.7.5.
---
## Rules
Do not
Insert
Update
Delete
Commit
Seed
Generate IDs
Generate document numbers
Trigger approval
Generate PDFs
Only preview.
---
## Error Contract
Every error
Must contain
File
Row
Column
Code
Message
Suggested Fix
Example
```json
{
"file":"customers.csv",
"row":12,
"column":"customer_type",
"code":"UNKNOWN_OPTION",
"message":"Customer type not found.",
"suggestedFix":"Import master-options.csv first."
}
```
---
## Reuse Rules
Reuse existing
Master Option services
Organization services
CRM services
Validation helpers
Document sequence helpers
Do not duplicate logic.
---
## Deliverables
src/features/setup/server/csv-preview.service.ts
src/features/setup/server/csv/
POST /api/setup/import/preview
Shared validation utilities
Structured preview response
previewHash generator
---
## Acceptance Criteria
✓ Preview never writes database.
✓ Multiple CSVs supported.
✓ Dependency order resolved automatically.
✓ Unknown templates rejected.
✓ Header validation implemented.
✓ Data validation implemented.
✓ Relationship resolution implemented.
✓ Duplicate detection implemented.
✓ Structured report returned.
✓ previewHash generated.
✓ Uses templates.json as runtime registry.
✓ Typecheck passes.
---
## Future
D.7.5
Commit Import Engine
Uses
previewHash
Transaction
Upsert
Import Report
No validation logic should be duplicated between D.7.4 and D.7.5.

493
plans/task-d.7.5.md Normal file
View File

@@ -0,0 +1,493 @@
# Task D.7.5 CSV Commit Import Engine
## Objective
Implement the CSV Commit Import Engine for ALLA OS Initial Setup.
This task must take a previously validated CSV preview result from D.7.4, verify its `previewHash`, and commit supported CSV imports safely using transactions and idempotent upsert behavior.
D.7.5 must reuse the D.7.4 preview/validation engine and must not duplicate validation logic.
---
## Review Before Implementation
Review:
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- plans/task-d.7.4.md
- docs/setup/seed-matrix.md
- docs/setup/csv-template-spec.md
- docs/setup/import-mapping.md
- docs/setup/setup-wizard-blueprint.md
- docs/setup/verification-matrix.md
- setup/templates/*
- setup/templates/templates.json
- src/features/setup/server/csv-preview.service.ts
- src/features/setup/server/csv/**
- src/app/api/setup/import/preview/route.ts
- src/db/schema.ts
- src/db/seeds/**/*
- Existing CRM/foundation services for organizations, users, master options, document sequences, approval, customers, contacts, leads, opportunities, and quotations.
---
## Implementation Scope
Create:
src/features/setup/server/csv-commit.service.ts
Supporting modules if needed:
src/features/setup/server/csv/commit-builder.ts
src/features/setup/server/csv/upsert-executor.ts
src/features/setup/server/csv/import-report.ts
Create API:
POST /api/setup/import/commit
---
## Core Rule
D.7.5 must use the exact same parsing, template detection, validation, dependency resolution, and preview report behavior from D.7.4.
Do not create a second validation engine.
Commit flow:
1. Receive CSV files and `previewHash`.
2. Re-run preview validation using D.7.4 engine.
3. Compare new preview hash with submitted `previewHash`.
4. Reject commit if hashes do not match.
5. Reject commit if preview contains blocking errors.
6. Commit valid files in dependency/import order.
7. Return structured import report.
---
## Input
Accept `multipart/form-data`.
Required:
- CSV files
- `previewHash`
Optional:
- `mode`: `strict | permissive`
- `organizationId`
- `organizationCode`
- `dryRun`
- `allowOptionCreate`
- `skipWarnings`
- `replaceExisting`
Default behavior:
- `mode = strict`
- `dryRun = false`
- `allowOptionCreate = false`
- `skipWarnings = false`
- `replaceExisting = false`
---
## Commit Rules
### General
- Commit only rows classified as `create` or `update`.
- Do not commit rows classified as `error`.
- In strict mode, any blocking error prevents the whole commit.
- Warnings do not block commit unless `skipWarnings = false` and the warning is configured as blocking.
- Unsupported templates must never commit.
- Unknown templates must never commit.
### Transaction
- Use one database transaction for all DB-only writes in the import batch.
- If any DB write fails, rollback the whole batch.
- Storage writes are out of scope for D.7.5.
- Attachments are still unsupported/deferred.
### Upsert
Every importer must be idempotent.
Re-running the same CSV should produce either:
- `updated`
- `skipped`
- or no-op
Never create duplicate records.
---
## Supported Commit Templates
Implement commit for templates currently supported by D.7.3/D.7.4:
Foundation / Organization:
- users.csv
- organizations.csv
- memberships.csv
- crm-role-assignments.csv
- master-options.csv
- branches.csv
- product-types.csv
- document-sequences.csv
- approval-workflows.csv
- approval-steps.csv
- approval-matrix.csv
Business:
- customers.csv
- contacts.csv
- contact-shares.csv
- leads.csv
- opportunities.csv
- opportunity-parties.csv
- quotations.csv
- quotation-items.csv
- quotation-parties.csv
- quotation-topics.csv
- quotation-topic-items.csv
If a template cannot yet be safely committed because the service contract is unclear, mark it as blocked with a clear reason. Do not fake success.
---
## Required Import Order
Use import order from `setup/templates/templates.json`.
Commit order must follow resolved dependency order, not upload order.
---
## Importer Responsibilities
Each importer must define:
- template name
- target table or feature service
- business key
- create behavior
- update behavior
- skip behavior
- conflict behavior
- reference resolution
- audit behavior if existing service supports it
---
## Data Mapping
Follow:
docs/setup/import-mapping.md
Important examples:
branches.csv
maps to:
ms_options
category = crm_branch
product-types.csv
maps to:
ms_options
category = crm_product_type
document-sequences.csv
resolves:
organization_code
branch_code
product_type_code
document_type
period
prefix
quotation-topic-items.csv
uses `topic_key` from uploaded batch to resolve committed quotation topic ids.
---
## Security
- API must be protected.
- Require `super_admin` for setup-wide import.
- Organization admin may be supported later, but D.7.5 can restrict to `super_admin`.
- Do not return raw SQL, stack traces, password hashes, or secrets.
- Raw `password` from users.csv must be hashed before storage.
- Never log raw passwords.
- Empty password must not overwrite existing password.
- Existing user password can be reset only when explicit reset flag exists.
---
## Password Rules
For `users.csv`:
- New credential user requires either:
- `password`, or
- future invitation flow support.
- Existing user:
- empty password = keep existing password
- password + reset_password=true = update password hash
- password + reset_password=false = ignore password with warning
- Never return password or hash in report.
---
## Report Contract
Return:
ImportReport
Fields:
- status: PASS | WARNING | FAIL
- generatedAt
- previewHash
- committedHash
- dryRun
- summary
- files
- errors
- warnings
File report:
- fileName
- template
- status
- imported
- updated
- skipped
- errors
- warnings
Row report:
- row
- action: create | update | skip | error
- businessKey
- entityId if safe
- message
- warnings
- errors
Example:
{
"status": "PASS",
"previewHash": "...",
"committedHash": "...",
"summary": {
"imported": 10,
"updated": 4,
"skipped": 2,
"errors": 0,
"warnings": 1
},
"files": []
}
---
## Error Contract
Every error must include:
- file
- row
- column
- code
- message
- suggestedFix
Example:
{
"file": "customers.csv",
"row": 12,
"column": "customer_code",
"code": "UPSERT_FAILED",
"message": "Customer could not be imported.",
"suggestedFix": "Review the customer row and retry after fixing related references."
}
---
## Dry Run
Support `dryRun=true`.
Dry run must:
- re-run preview
- build commit plan
- return planned actions
- not write database
- not run transaction writes
---
## Audit
If existing feature services automatically write audit logs, allow them.
If importing directly with Drizzle because no safe service exists, do not invent audit semantics in D.7.5.
Instead:
- include audit gap warning in report
- document follow-up
---
## Out Of Scope
- CSV preview validation logic duplication
- CSV template creation
- Setup Wizard UI
- Seed manifest persistence
- Setup state persistence
- Rollback after successful commit
- Storage import
- Attachment import
- Email settings import
- Unsupported templates
- Destructive reset
- PDF generation
- Approval workflow execution
- Document artifact creation
---
## Deliverables
Required:
src/features/setup/server/csv-commit.service.ts
src/features/setup/server/csv/commit-builder.ts
src/features/setup/server/csv/upsert-executor.ts
src/features/setup/server/csv/import-report.ts
src/app/api/setup/import/commit/route.ts
Optional:
src/features/setup/server/csv/importers/*.ts
Recommended importer organization:
src/features/setup/server/csv/importers/
users.importer.ts
organizations.importer.ts
memberships.importer.ts
crm-role-assignments.importer.ts
master-options.importer.ts
document-sequences.importer.ts
approval.importer.ts
customers.importer.ts
contacts.importer.ts
leads.importer.ts
opportunities.importer.ts
quotations.importer.ts
---
## Acceptance Criteria
✓ POST /api/setup/import/commit exists.
✓ Commit requires `previewHash`.
✓ Commit re-runs D.7.4 preview engine.
✓ Commit rejects mismatched preview hash.
✓ Commit rejects preview with blocking errors.
✓ Commit follows dependency/import order from templates.json.
✓ Commit is transaction-safe for DB writes.
✓ Re-running the same valid CSV does not duplicate records.
✓ users.csv password handling is safe.
✓ branches.csv imports into ms_options category crm_branch.
✓ product-types.csv imports into ms_options category crm_product_type.
✓ quotation-topic-items.csv resolves topic_key from committed/imported quotation topics.
✓ Unsupported templates do not commit.
✓ dryRun returns planned actions without writing DB.
✓ Structured import report is returned.
✓ No storage/binary attachment import is implemented.
✓ Typecheck passes or unrelated failures are documented.
---
## Suggested Verification
Run:
npm run typecheck
Run scoped lint:
npx oxlint src/features/setup/server/csv src/features/setup/server/csv-commit.service.ts src/app/api/setup/import/commit
Manual test flow:
1. Call POST /api/setup/import/preview with valid CSV batch.
2. Copy previewHash.
3. Call POST /api/setup/import/commit with same files and previewHash.
4. Confirm rows are created/updated.
5. Re-run same commit.
6. Confirm no duplicates.
7. Modify CSV after preview.
8. Confirm commit rejects previewHash mismatch.
9. Submit CSV with blocking errors.
10. Confirm commit fails without partial writes.
---
## Follow-up
After this task:
D.7.6 Dashboard Setup Wizard UI
D.7.8 Seed Manifest and Setup State Persistence
D.7.7 Scoped Reset and Reseed Engine

486
plans/task-d.7.6.md Normal file
View File

@@ -0,0 +1,486 @@
# Task D.7.6 Dashboard Setup Wizard UI
## Objective
Build a dashboard-native Setup Wizard UI for ALLA OS Administration.
The wizard must connect the previously implemented setup APIs into one guided workflow:
- D.7.2 Readiness and Verification APIs
- D.7.3 CSV Template Pack and Template Metadata API
- D.7.4 CSV Preview Validation Engine
- D.7.5 CSV Commit Import Engine
This task focuses on UI and orchestration only.
Do not implement seed execution, destructive reset, setup state persistence, seed manifest persistence, or new migrations in this task.
---
## Review Before Implementation
Review:
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- plans/task-d.7.4.md
- plans/task-d.7.5.md
- docs/setup/seed-matrix.md
- docs/setup/setup-wizard-blueprint.md
- docs/setup/setup-state-machine.md
- docs/setup/verification-matrix.md
- docs/setup/csv-template-spec.md
- docs/setup/import-mapping.md
- setup/templates/README.md
- setup/templates/templates.json
- src/features/setup/api/types.ts
- src/features/setup/api/service.ts
- src/features/setup/api/queries.ts
- src/app/api/setup/readiness/route.ts
- src/app/api/setup/verify/route.ts
- src/app/api/setup/templates/route.ts
- src/app/api/setup/import/preview/route.ts
- src/app/api/setup/import/commit/route.ts
- existing dashboard pages and PageContainer usage
- src/config/nav-config.ts
---
## Implementation Scope
Create dashboard page:
src/app/dashboard/administration/setup/page.tsx
Create UI components under:
src/features/setup/components/
Recommended components:
- setup-wizard.tsx
- setup-wizard-stepper.tsx
- setup-status-badge.tsx
- setup-check-list.tsx
- setup-summary-cards.tsx
- setup-template-list.tsx
- csv-upload-dropzone.tsx
- csv-preview-table.tsx
- csv-import-report.tsx
- setup-verification-summary.tsx
- setup-finish-panel.tsx
Optional hooks:
src/features/setup/api/use-setup-readiness.ts
src/features/setup/api/use-setup-templates.ts
src/features/setup/api/use-csv-preview.ts
src/features/setup/api/use-csv-commit.ts
src/features/setup/api/use-setup-verification.ts
---
## Route and Navigation
Add menu item under Administration:
Administration
Setup Wizard
Target route:
/dashboard/administration/setup
The route must be protected by existing dashboard/auth rules.
If setup APIs require `super_admin`, the UI should show a friendly permission message when unauthorized.
---
## Wizard Steps
Implement these UI steps.
### Step 1 System Readiness
Call:
GET /api/setup/readiness
Show:
- Overall status
- PASS / WARNING / FAIL counts
- Check list grouped by area
- Suggested fixes
- Re-run button
Blocking behavior:
- FAIL should block moving forward unless step is marked dry-run / review-only.
- WARNING can continue with acknowledgement.
---
### Step 2 Template Pack
Call:
GET /api/setup/templates
Show:
- available CSV templates
- import order
- seed type
- required columns
- sample file name
- unsupported/deferred templates from README or metadata if available
Optional:
- link to local setup/templates path in documentation text only
- do not implement file download unless already available
---
### Step 3 CSV Upload
Allow upload of multiple CSV files.
Rules:
- accept only `.csv`
- show selected files
- allow remove/replace
- show detected file count
- show missing recommended templates as info only
- do not upload automatically until Preview button is clicked
---
### Step 4 CSV Preview
Call:
POST /api/setup/import/preview
Input:
multipart/form-data files
Show:
- previewHash
- overall status
- per-file status
- row count
- create/update/error/warning counts
- row-level errors
- row-level warnings
- dependency warnings
- duplicate warnings
Blocking behavior:
- FAIL blocks commit.
- WARNING requires acknowledgement before commit.
- Store previewHash in client state only for this task.
---
### Step 5 CSV Commit
Call:
POST /api/setup/import/commit
Input:
same files + previewHash
Support:
- dryRun toggle
- commit button
- show import report
Rules:
- Commit button disabled when preview has blocking errors.
- If files changed after preview, force re-preview.
- If commit returns previewHash mismatch, show clear message and require re-preview.
---
### Step 6 Verification
Call:
POST /api/setup/verify
Input:
optional organizationId / active org context
Show:
- overall status
- PASS / WARNING / FAIL counts
- grouped checks
- suggested fixes
- re-run button
---
### Step 7 Finish
Show:
- readiness summary
- template summary
- preview summary
- commit summary
- verification summary
- next recommended task
Because setup state persistence is out of scope, do not permanently lock or complete setup.
Show clear message:
This wizard session is not persisted yet. Persistent setup runs will be implemented in D.7.8.
---
## UI Requirements
Use:
- shadcn/ui
- PageContainer
- Card
- Button
- Badge
- Alert
- Table
- Tabs or Accordion where helpful
- Progress / Stepper
- ScrollArea for long reports
- responsive layout
- dark mode compatible styles
Avoid:
- hardcoded colors outside design tokens
- raw JSON dumps as main UI
- giant ungrouped error lists
- hidden errors
---
## UX Requirements
The wizard should feel like an enterprise setup console.
Must include:
- clear progress
- clear blocking vs non-blocking issues
- grouped diagnostics
- concise summary cards
- actionable suggested fixes
- retry/re-run buttons
- empty states
- loading states
- error states
- permission denied state
Recommended status language:
PASS
WARNING
FAIL
Do not translate status enum values in API handling.
---
## State Management
D.7.6 uses client-side state only.
Track:
- current step
- readiness report
- template metadata
- selected files
- preview report
- previewHash
- commit report
- verification report
- warning acknowledgement
Do not implement DB persistence.
If browser refreshes, state can reset.
Add note that persistent resume will arrive in D.7.8.
---
## API Integration Rules
- Reuse existing setup API types.
- Do not duplicate response shapes manually if types exist.
- Handle non-200 responses safely.
- Show safe error message from API contract.
- Do not display raw stack traces.
- Do not log sensitive CSV data.
- Do not upload files except to preview/commit endpoints.
---
## CSV File Change Rules
After successful preview:
- if selected files are removed, added, renamed, or content changed
- clear previewHash
- clear commit report
- require preview again
Implementation can use file name + size + lastModified fingerprint for this task.
---
## Out Of Scope
- Persistent setup state
- setup_runs / setup_run_steps migrations
- seed_manifests persistence
- seed execution
- scoped reset/reseed UI
- CSV template ZIP download
- production setup lock
- installation profile engine
- plugin runtime
- real file attachment import
- email settings persistence
- new CRM behavior
---
## Deliverables
Required:
src/app/dashboard/administration/setup/page.tsx
src/features/setup/components/setup-wizard.tsx
src/features/setup/components/setup-wizard-stepper.tsx
src/features/setup/components/setup-status-badge.tsx
src/features/setup/components/setup-check-list.tsx
src/features/setup/components/setup-summary-cards.tsx
src/features/setup/components/setup-template-list.tsx
src/features/setup/components/csv-upload-dropzone.tsx
src/features/setup/components/csv-preview-table.tsx
src/features/setup/components/csv-import-report.tsx
src/features/setup/components/setup-verification-summary.tsx
src/features/setup/components/setup-finish-panel.tsx
Navigation update:
src/config/nav-config.ts
Optional:
src/features/setup/api/use-setup-readiness.ts
src/features/setup/api/use-setup-templates.ts
src/features/setup/api/use-csv-preview.ts
src/features/setup/api/use-csv-commit.ts
src/features/setup/api/use-setup-verification.ts
---
## Acceptance Criteria
✓ Dashboard route exists at /dashboard/administration/setup.
✓ Navigation exposes Setup Wizard under Administration.
✓ Stepper wizard renders with all required steps.
✓ Readiness step calls GET /api/setup/readiness.
✓ Template step calls GET /api/setup/templates.
✓ CSV upload accepts multiple CSV files.
✓ Preview step calls POST /api/setup/import/preview.
✓ Preview report displays file and row-level validation results.
✓ Commit step calls POST /api/setup/import/commit with previewHash.
✓ Commit is disabled when preview has FAIL.
✓ File changes after preview clear previewHash and require re-preview.
✓ Verification step calls POST /api/setup/verify.
✓ Finish step summarizes all prior outputs.
✓ UI handles loading, empty, error, unauthorized, warning, and success states.
✓ Uses shadcn/ui and existing dashboard layout conventions.
✓ No setup data persistence or reset logic is introduced.
✓ Typecheck passes or unrelated failures are documented.
---
## Suggested Verification
Run:
npm run typecheck
Run scoped lint:
npx oxlint src/features/setup src/app/dashboard/administration/setup src/config/nav-config.ts
Manual test:
1. Open /dashboard/administration/setup as super_admin.
2. Run readiness.
3. View template pack.
4. Upload valid CSV batch.
5. Run preview.
6. Confirm previewHash appears.
7. Run dryRun commit.
8. Run commit.
9. Re-run verification.
10. Confirm finish summary.
11. Modify selected file after preview.
12. Confirm previewHash clears.
13. Login as non-super_admin and confirm friendly unauthorized behavior.
---
## Follow-up
After D.7.6:
D.7.8 Seed Manifest and Setup State Persistence
D.7.7 Scoped Reset and Reseed Engine
D.7.9 Installation Profile and Plugin Runtime Enhancement

611
plans/task-d.7.7.md Normal file
View File

@@ -0,0 +1,611 @@
# Task D.7.7 Scoped Reset and Reseed Engine
## Objective
Implement a safe, non-production Scoped Reset and Reseed Engine for ALLA OS Initial Setup.
This task must allow controlled reset/reseed operations for setup, foundation, organization, business, demo/UAT, and CSV-imported data while preserving production safety guards.
D.7.7 must use the Setup State and Seed Manifest foundations from D.7.8 where possible.
This task must not introduce any destructive reset path for production.
---
## Review Before Implementation
Review:
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- plans/task-d.7.4.md
- plans/task-d.7.5.md
- plans/task-d.7.6.md
- plans/task-d.7.8.md
- docs/setup/reset-reseed-matrix.md
- docs/setup/seed-version-manifest.md
- docs/setup/setup-state-machine.md
- docs/setup/seed-matrix.md
- docs/setup/import-mapping.md
- src/db/schema.ts
- src/features/setup/**
- src/app/api/setup/**
- scripts/seed-reset.ts
- scripts/db/reset-database.ts
- scripts/seed-system.ts
- scripts/seed-uat.ts
- src/db/seeds/**/*
- existing storage provider implementation
---
## Implementation Scope
Create reset/reseed services:
src/features/setup/server/reset.service.ts
src/features/setup/server/reseed.service.ts
Optional helpers:
src/features/setup/server/reset-guards.ts
src/features/setup/server/reset-report.ts
src/features/setup/server/reset-scopes.ts
Create API routes:
POST /api/setup/reset/preview
POST /api/setup/reset/execute
POST /api/setup/reseed/preview
POST /api/setup/reseed/execute
Optional UI integration:
Add a Maintenance panel in Setup Wizard or Administration Setup page.
---
## Reset Scopes
Implement scopes from docs/setup/reset-reseed-matrix.md:
foundation_reset
organization_reset
business_reset
demo_uat_reset
csv_import_rollback
setup_run_reset
full_reset
---
## Scope Rules
### foundation_reset
Deletes and optionally reseeds organization-scoped foundation rows.
May affect:
- ms_options
- document_sequences
- approval workflows
- approval steps
- approval matrices
- document template foundation rows
- document library foundation rows
- notification templates
- report definitions
Must retain:
- users
- organizations
- memberships
- business CRM data unless explicitly selected
---
### organization_reset
Deletes target organization and tenant-scoped rows.
Must require exact organization code/name confirmation.
Must retain:
- global users unless explicitly selected
Must delete:
- memberships for target organization
- CRM role assignments/profiles for target organization
- organization-scoped foundation rows
- business rows for target organization
---
### business_reset
Deletes CRM business records for target organization.
May affect:
- customers
- contacts
- contact shares
- leads
- opportunities
- quotations
- quotation items
- quotation parties
- quotation topics
- quotation topic items
- followups
- business attachment metadata
Must retain:
- organization
- users
- memberships
- foundation rows
- setup run history unless explicitly selected
---
### demo_uat_reset
Deletes deterministic Demo/UAT rows only.
Must rely on:
- UAT seed markers
- deterministic emails/codes
- seed manifest records
- known UAT seed package names
Must retain:
- production foundation
- non-UAT business data
---
### csv_import_rollback
Rolls back rows associated with a seed manifest/import package when safely reversible.
Rules:
- only rollback manifest-owned rows
- block rollback if rows were changed after import and no safe conflict policy exists
- if rollback is not fully safe, return warning and require manual review
- do not pretend arbitrary rollback is safe
---
### setup_run_reset
Deletes setup run metadata only.
May affect:
- setup_runs
- setup_run_steps
- seed_manifests
- seed_manifest_items
Must not delete:
- business data
- foundation data
- organizations
- users
---
### full_reset
Must use existing guarded reset script behavior.
Rules:
- block in production
- require explicit allow flag
- require typed confirmation
- local/test only by default
- do not expose casually in UI
---
## Safety Guards
All destructive actions require:
- super_admin
- non-production environment
- explicit scope
- target organization when scope is organization-aware
- typed confirmation
- preview before execute
- confirmation token generated from preview
- token expires after short duration
- execute must match preview hash/token
Block when:
- NODE_ENV=production
- production-like database host/name is detected
- missing target organization
- missing typed confirmation
- preview was not run
- preview token expired
- preview hash mismatch
- affected row count exceeds safe threshold unless force flag is provided
---
## Preview Behavior
Reset preview must not delete anything.
Preview returns:
- scope
- target organization
- affected tables
- estimated row counts
- retained data
- deleted data
- storage cleanup plan
- manifest impact
- warnings
- blocking errors
- confirmation phrase
- previewHash
- confirmationToken
Example:
{
"scope": "business_reset",
"targetOrganization": "ALLA",
"summary": {
"tables": 12,
"rows": 520,
"warnings": 2,
"errors": 0
},
"affectedTables": [],
"confirmationPhrase": "RESET BUSINESS ALLA",
"previewHash": "...",
"confirmationToken": "..."
}
---
## Execute Behavior
Execute requires:
- scope
- previewHash
- confirmationToken
- typed confirmation phrase
Execution must:
1. Rebuild preview.
2. Compare previewHash.
3. Validate token.
4. Validate typed confirmation.
5. Run reset inside transaction where DB-only.
6. Handle storage cleanup best-effort.
7. Persist reset report to setup run if available.
8. Return final report.
---
## Reseed Behavior
Reseed is optional but recommended for:
- foundation_reset
- demo_uat_reset
- csv_import_rollback after cleanup
Reseed must call existing seed services/scripts through safe wrappers.
Do not duplicate seed data.
Supported reseed targets:
foundation
demo_uat
csv_manifest
Rules:
- foundation reseed is idempotent
- demo/UAT reseed is deterministic
- csv_manifest reseed requires original manifest/files available or block with clear reason
---
## Storage Cleanup
Storage cleanup must be:
- best-effort
- scoped
- reported
- never silent
Rules:
- delete setup-owned temp objects only when safe
- delete demo-generated objects only under demo prefix
- do not delete approved immutable artifacts unless explicit full reset/demo reset and policy allows
- if cleanup fails, DB transaction should not necessarily rollback unless storage cleanup is required by scope
- report leftover keys
---
## Seed Manifest Integration
Use D.7.8 seed manifest tables.
Reset preview should show:
- affected seed manifests
- affected seed manifest items
- whether import rollback is safe
- checksum/package info
Reset execute should update manifest status when applicable:
- rolled_back
- warning
- failed
Do not delete manifest rows unless scope is setup_run_reset.
---
## Setup State Integration
Reset should update setup run state when applicable.
Examples:
- business_reset marks csv_commit and verification stale
- foundation_reset marks readiness, scope, sequence, approval, CSV, and verification stale
- setup_run_reset clears setup state only
- organization_reset cancels or invalidates active setup runs for that organization
Do not implement destructive RESET_STEP from UI unless explicitly scoped.
---
## API Contracts
### POST /api/setup/reset/preview
Input:
scope
organizationId?
organizationCode?
manifestId?
options?
Output:
ResetPreviewReport
---
### POST /api/setup/reset/execute
Input:
scope
previewHash
confirmationToken
confirmationPhrase
organizationId?
organizationCode?
manifestId?
options?
Output:
ResetExecuteReport
---
### POST /api/setup/reseed/preview
Input:
target
organizationId?
organizationCode?
manifestId?
options?
Output:
ReseedPreviewReport
---
### POST /api/setup/reseed/execute
Input:
target
previewHash
confirmationToken
confirmationPhrase
organizationId?
organizationCode?
manifestId?
options?
Output:
ReseedExecuteReport
---
## UI Requirements If Implemented
Add Maintenance panel:
- Reset scope selector
- Target organization selector
- Preview button
- Affected tables/counts
- Warnings/errors
- Typed confirmation input
- Execute button
- Final report
UI must hide or disable destructive actions when environment is production.
---
## Out Of Scope
- Production reset workflow
- Silent automatic reset
- Arbitrary rollback without manifest ownership
- Deleting approved production artifacts
- New seed data creation
- Installation profile engine
- Plugin runtime
- Backup/restore
- Data anonymization
- Cross-environment migration
- Email/storage secret reset
- Changing CRM business behavior
---
## Deliverables
Required:
src/features/setup/server/reset.service.ts
src/features/setup/server/reseed.service.ts
src/features/setup/server/reset-guards.ts
src/features/setup/server/reset-report.ts
API routes:
src/app/api/setup/reset/preview/route.ts
src/app/api/setup/reset/execute/route.ts
src/app/api/setup/reseed/preview/route.ts
src/app/api/setup/reseed/execute/route.ts
Optional:
src/features/setup/components/setup-maintenance-panel.tsx
---
## Acceptance Criteria
✓ Reset preview API exists.
✓ Reset execute API exists.
✓ Reseed preview API exists.
✓ Reseed execute API exists.
✓ All APIs require super_admin.
✓ Production destructive reset is blocked.
✓ Preview is required before execute.
✓ Execute requires valid previewHash.
✓ Execute requires valid confirmationToken.
✓ Execute requires typed confirmation phrase.
✓ Organization-aware scopes require target organization.
✓ Preview returns affected tables and estimated rows.
✓ Execute uses transaction for DB-only deletes.
✓ Storage cleanup is best-effort and reported.
✓ Seed manifest status updates for rollback/reset where applicable.
✓ Setup run steps are marked stale after reset.
✓ full_reset delegates to existing guarded reset behavior or blocks with clear instructions.
✓ No reset deletes approved immutable artifacts unless explicitly allowed by scope policy.
✓ No seed logic is duplicated.
✓ Typecheck passes or unrelated failures are documented.
---
## Suggested Verification
Run:
npm run typecheck
Run scoped lint:
npx oxlint src/features/setup src/app/api/setup
Manual test:
1. Run business_reset preview for ALLA.
2. Confirm affected table counts are shown.
3. Execute without preview token.
4. Confirm blocked.
5. Execute with wrong confirmation phrase.
6. Confirm blocked.
7. Execute with valid token and phrase in local environment.
8. Confirm rows deleted and foundation retained.
9. Run setup verification.
10. Confirm CSV/verification steps stale.
11. Try in NODE_ENV=production.
12. Confirm destructive reset is blocked.
13. Run setup_run_reset.
14. Confirm setup metadata deleted but business rows remain.
15. Run csv_import_rollback for manifest.
16. Confirm only manifest-owned rows are affected or rollback is blocked with manual review warning.
---
## Follow-up
After D.7.7:
D.7.9 Installation Profile and Plugin Runtime Enhancement
D.7.10 Setup Integration Test and Golden Dataset

681
plans/task-d.7.8.md Normal file
View File

@@ -0,0 +1,681 @@
# Task D.7.8 Seed Manifest and Setup State Persistence
## Objective
Add persistent setup run tracking and seed manifest lifecycle tracking for ALLA OS Initial Setup.
This task must make the Setup Wizard resumable, auditable, and able to persist setup reports across browser refreshes and future setup sessions.
D.7.8 should build on:
- D.7.2 Readiness and Verification APIs
- D.7.3 CSV Template Pack
- D.7.4 CSV Preview Validation Engine
- D.7.5 CSV Commit Import Engine
- D.7.6 Dashboard Setup Wizard UI
This task must not implement destructive reset/reseed behavior. Reset remains D.7.7.
---
## Review Before Implementation
Review:
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- plans/task-d.7.4.md
- plans/task-d.7.5.md
- plans/task-d.7.6.md
- docs/setup/setup-state-machine.md
- docs/setup/seed-version-manifest.md
- docs/setup/setup-wizard-blueprint.md
- docs/setup/verification-matrix.md
- docs/setup/reset-reseed-matrix.md
- docs/setup/setup-plugin-architecture.md
- src/db/schema.ts
- src/features/setup/**
- src/app/dashboard/administration/setup/page.tsx
- src/app/api/setup/**
- existing migration conventions under drizzle/
---
## Implementation Scope
Add setup persistence tables:
- setup_runs
- setup_run_steps
- seed_manifests
- seed_manifest_items
Add migration through existing Drizzle workflow.
Add schema definitions to:
src/db/schema.ts
or appropriate split schema location if the repo already uses modular schema files.
Add setup persistence services:
src/features/setup/server/setup-state.service.ts
src/features/setup/server/seed-manifest.service.ts
Add API routes:
GET /api/setup/run/current
POST /api/setup/run/start
POST /api/setup/run/step
POST /api/setup/run/complete
GET /api/setup/run/report
Update setup wizard UI to:
- load current setup run
- resume prior step status
- persist step outputs
- show completed/pending/stale step status
- persist finish report
- show setup completed state
Update CSV commit flow to optionally record seed manifest and manifest items.
---
## Database Tables
### setup_runs
Purpose:
One row per setup attempt/session.
Suggested fields:
id
status
mode
target_organization_id
started_by
completed_by
started_at
completed_at
last_error
metadata
created_at
updated_at
Status values:
not_started
readiness_checked
foundation_installed
organization_created
administrator_created
scope_configured
sequences_configured
approval_configured
csv_validated
csv_imported
verified
completed
failed
cancelled
Mode values:
production
demo_uat
dry_run
---
### setup_run_steps
Purpose:
Step-level state, input hash, output report, warning/error history.
Suggested fields:
id
setup_run_id
step_key
status
input_hash
output_json
errors_json
warnings_json
started_at
completed_at
created_at
updated_at
Step status values:
not_started
running
passed
warning
failed
skipped
stale
---
### seed_manifests
Purpose:
Track seed/import package lifecycle.
Suggested fields:
id
setup_run_id
organization_id
name
version
type
checksum
status
source
applied_by
applied_at
report_json
created_at
updated_at
Type values:
foundation
organization
business
demo_uat
setup_state
Status values:
pending
applied
skipped
warning
failed
rolled_back
---
### seed_manifest_items
Purpose:
Track per-file/per-seed item checksum and result.
Suggested fields:
id
seed_manifest_id
item_key
source_file
checksum
status
imported_count
updated_count
skipped_count
error_count
warning_count
report_json
created_at
updated_at
---
## State Machine Rules
Use:
docs/setup/setup-state-machine.md
Required events:
CHECK_READINESS
INSTALL_FOUNDATION
CREATE_ORGANIZATION
CREATE_ADMIN
CONFIGURE_SCOPE
CONFIGURE_SEQUENCES
CONFIGURE_APPROVAL
VALIDATE_CSV
IMPORT_CSV
RUN_VERIFICATION
COMPLETE_SETUP
FAIL_STEP
CANCEL_SETUP
RESUME_SETUP
RESET_STEP
For D.7.8, implement only non-destructive events.
Do not implement RESET_STEP destructive behavior.
RESET_STEP can return:
not implemented until D.7.7
---
## Persistence Rules
Every setup step should persist:
- step key
- status
- input hash
- output summary/report
- warnings
- errors
- completed timestamp
If the same step is re-run:
- update same step row
- keep latest report
- mark dependent later steps as stale when needed
Staleness rules:
- readiness changed → all later steps stale
- organization changed → admin, scope, sequence, approval, CSV, verification stale
- scope changed → sequence, approval, CSV, verification stale
- sequence changed → verification stale
- approval changed → CSV and verification stale
- CSV preview changed → commit stale
- CSV commit changed → verification stale
---
## Setup Run Behavior
### Current Run
GET /api/setup/run/current
Returns:
- active setup run if exists
- latest completed setup run if no active run
- setup step summaries
- manifest summaries
- completion status
### Start Run
POST /api/setup/run/start
Creates new setup run.
Rules:
- super_admin only
- if active run exists, return existing run unless `forceNew=true`
- mode defaults to production
- target organization optional until resolved
### Save Step
POST /api/setup/run/step
Persists step report.
Input:
- setupRunId
- stepKey
- status
- inputHash
- output
- warnings
- errors
Rules:
- validate step key
- update run status based on state machine
- mark downstream stale steps as needed
### Complete Run
POST /api/setup/run/complete
Rules:
- all required steps must be passed/warning acknowledged
- blocking failure prevents completion
- verification must be latest and not stale
- writes completed_at and status completed
- returns final report
### Report
GET /api/setup/run/report
Returns:
- setup run summary
- steps
- manifests
- final readiness/verification/import summaries
---
## Seed Manifest Behavior
When CSV commit succeeds, create or update a manifest.
Recommended package:
crm-business-import
Manifest item per committed CSV file.
For each file:
- source_file
- checksum
- status
- imported_count
- updated_count
- skipped_count
- error_count
- warning_count
- report_json
Version:
1.0.0
Source:
csv
Type:
business
Checksum behavior:
- same version + same checksum = skipped/already applied
- same version + changed checksum = warning unless force mode
- new checksum after successful import creates new manifest revision or new manifest row depending on chosen implementation
If D.7.5 import is dryRun:
- do not write seed manifest
- optionally persist setup step output only
---
## API Security
- all routes protected
- require super_admin for D.7.8
- never expose raw SQL errors
- never expose passwords, password hashes, secrets, storage credentials
- report only safe summaries
- setup reports can include filenames and counts, not raw CSV contents
---
## UI Updates
Update:
src/features/setup/components/setup-wizard.tsx
Add:
- load current setup run on mount
- resume banner
- persisted step status
- stale step badge
- completed setup summary
- save step result after readiness, preview, commit, verification
- complete setup button on finish step
- report panel from persisted data
Important:
The wizard should still work if persistence API fails, but must show a warning.
---
## Out Of Scope
- Destructive reset/reseed
- RESET_STEP implementation
- installation profile engine
- plugin runtime
- CSV parser changes unless needed for checksum
- setup template changes
- storage import
- attachment import
- new CRM behavior
- production setup lock enforcement beyond completed status display
---
## Deliverables
Required schema/migration:
src/db/schema.ts
drizzle migration file
Required services:
src/features/setup/server/setup-state.service.ts
src/features/setup/server/seed-manifest.service.ts
Required API routes:
src/app/api/setup/run/current/route.ts
src/app/api/setup/run/start/route.ts
src/app/api/setup/run/step/route.ts
src/app/api/setup/run/complete/route.ts
src/app/api/setup/run/report/route.ts
Required UI update:
src/features/setup/components/setup-wizard.tsx
Optional helpers:
src/features/setup/server/setup-state-machine.ts
src/features/setup/server/setup-report.service.ts
---
## Acceptance Criteria
✓ setup_runs table exists.
✓ setup_run_steps table exists.
✓ seed_manifests table exists.
✓ seed_manifest_items table exists.
✓ Drizzle migration generated.
✓ Current setup run API works.
✓ Start setup run API works.
✓ Save setup step API works.
✓ Complete setup run API works.
✓ Setup report API works.
✓ Wizard can resume current run after refresh.
✓ Wizard shows persisted step statuses.
✓ Wizard marks stale dependent steps after rerun.
✓ CSV commit creates seed manifest records when commit succeeds.
✓ dryRun commit does not create seed manifest records.
✓ Completed setup run stores final report.
✓ All APIs require super_admin.
✓ No destructive reset logic is implemented.
✓ No secrets or raw CSV contents are persisted.
✓ Typecheck passes or unrelated failures are documented.
---
## Suggested Verification
Run:
npm run db:generate
npm run db:migrate
npm run typecheck
Run scoped lint:
npx oxlint src/features/setup src/app/api/setup src/app/dashboard/administration/setup src/db/schema.ts
Manual test:
1. Open Setup Wizard.
2. Start setup run.
3. Run readiness.
4. Refresh browser.
5. Confirm readiness result persists.
6. Upload CSV and preview.
7. Refresh browser.
8. Confirm preview step status persists without raw CSV content.
9. Commit CSV.
10. Confirm seed manifest and manifest item rows exist.
11. Run verification.
12. Complete setup.
13. Refresh browser.
14. Confirm completed setup summary appears.
15. Try as non-super_admin.
16. Confirm access denied.
---
## Follow-up
After D.7.8:
D.7.7 Scoped Reset and Reseed Engine
D.7.9 Installation Profile and Plugin Runtime Enhancement

749
plans/task-d.7.9.md Normal file
View File

@@ -0,0 +1,749 @@
# Task D.7.9 Installation Profiles & Setup Plugin Registry
## Objective
Transform the ALLA OS Setup Platform into a fully extensible platform by introducing Installation Profiles and a Setup Plugin Registry.
The current Setup Platform (D.7.1D.7.10) already supports:
- Readiness
- Verification
- CSV Templates
- CSV Preview
- CSV Commit
- Setup Wizard
- Setup State
- Seed Manifest
- Reset / Reseed
- Golden Dataset
D.7.9 must remove remaining CRM-specific assumptions so future modules (CRM, HR, Asset, Inventory, Purchase, Service, etc.) can integrate into the Setup Platform without modifying the core wizard.
No existing setup behavior may regress.
---
# Review Before Implementation
Review
- AGENTS.md
- plans/task-d.7.md
- plans/task-d.7.1.md
- plans/task-d.7.2.md
- plans/task-d.7.3.md
- plans/task-d.7.4.md
- plans/task-d.7.5.md
- plans/task-d.7.6.md
- plans/task-d.7.7.md
- plans/task-d.7.8.md
- plans/task-d.7.10.md
Review
docs/setup/*
Review
setup/templates/*
Review
setup/golden-dataset/*
Review
src/features/setup/**
---
# Objective
Replace hardcoded setup behavior with configuration-driven module registration.
The Setup Platform must become reusable by every ALLA OS module.
---
# Implementation Scope
Create
src/features/setup/plugins/
Recommended structure
src/features/setup/plugins/
plugin-registry.ts
plugin-types.ts
installation-profile.ts
crm/
crm-setup-plugin.ts
crm-installation-profile.ts
foundation/
foundation-plugin.ts
---
# Installation Profiles
Introduce Installation Profiles.
Supported profiles
minimal
crm_starter
crm_demo
production
restore_backup
custom
Each profile defines
- visible wizard steps
- required templates
- verification checks
- setup sequence
- supported reset scopes
- reseed targets
- default options
Profile interface
```ts
export interface InstallationProfile {
id:string;
name:string;
description:string;
wizardSteps:string[];
requiredTemplates:string[];
verificationChecks:string[];
resetScopes:string[];
reseedTargets:string[];
defaultOptions:Record<string,unknown>;
}
```
---
# Setup Plugin Interface
Create
plugin-types.ts
```ts
export interface SetupPlugin {
id:string;
version:string;
displayName:string;
description:string;
installationProfiles():InstallationProfile[];
templates():SetupTemplateDefinition[];
wizardSteps():SetupWizardStep[];
readinessChecks():SetupReadinessCheck[];
verificationChecks():SetupVerificationCheck[];
previewValidators():CsvPreviewValidator[];
importHandlers():CsvImporter[];
resetScopes():ResetScopeDefinition[];
reseedTargets():ReseedTargetDefinition[];
}
```
---
# Plugin Registry
Create
plugin-registry.ts
Responsibilities
Register plugins
Resolve plugins
Resolve installation profiles
Resolve templates
Resolve verification checks
Resolve reset scopes
Resolve reseed targets
Resolve wizard steps
Example
registerPlugin(new FoundationPlugin());
registerPlugin(new CrmSetupPlugin());
---
# Foundation Plugin
Move common setup behavior into Foundation Plugin.
Foundation Plugin owns
Readiness
Verification
Setup State
Seed Manifest
CSV Framework
Reset Framework
Golden Dataset framework
No CRM assumptions.
---
# CRM Setup Plugin
CRM Plugin owns
CRM Templates
CRM CSV Importers
CRM Verification
CRM Wizard Steps
CRM Reset Scope
CRM Golden Dataset registration
CRM Approval registration
CRM Document Sequence registration
CRM Reports registration
---
# Dynamic Wizard
Current wizard should stop hardcoding steps.
Instead
Plugin Registry
Installation Profile
Resolve Wizard Steps
Render Wizard
Adding a module must not require editing the wizard.
---
# Dynamic Verification
Current verification service should allow plugins to register checks.
Instead of
CRM Check
Approval Check
PDF Check
Hardcoded
Use
Plugin Registry
Collect Checks
Execute
Aggregate Report
---
# Dynamic Readiness
Allow plugins to register readiness checks.
Example
Storage Plugin
Storage Check
PDF Plugin
Template Check
CRM Plugin
CRM Readiness
---
# Dynamic Template Registry
Extend
setup/templates/templates.json
Support
plugin
profile
visibility
Example
{
"file":"customers.csv",
"plugin":"crm",
"profiles":[
"crm_demo",
"production"
]
}
Wizard automatically filters templates.
---
# Dynamic Navigation
Wizard should display
Installed Modules
Foundation
CRM
Approval
Storage
Future
HR
Asset
Inventory
Purchase
Modules not installed
Hidden
---
# Profile Resolution
Selecting
crm_demo
Automatically
Enable
CRM plugin
Foundation plugin
Demo dataset
CRM templates
CRM verification
Demo reset
Disable
Restore Backup steps
Selecting
minimal
Only
Foundation
Verification
No CRM
---
# API Updates
Extend
GET /api/setup/templates
Include
plugin
profile
visible
supported
Update
GET /api/setup/readiness
Collect plugin readiness.
Update
POST /api/setup/verify
Collect plugin verification.
No API breaking changes.
---
# Setup Wizard Updates
Wizard
Load Installation Profiles
User selects profile
Resolve Plugin Graph
Build Wizard
Render Steps
Run Setup
Wizard must no longer contain CRM-specific logic.
---
# Golden Dataset Integration
Allow every plugin to register
Golden Dataset
Example
CRM
setup/golden-dataset/crm/
Future
HR
setup/golden-dataset/hr/
Asset
setup/golden-dataset/asset/
---
# Future Module Example
Adding
Asset
Should require only
registerPlugin(
AssetSetupPlugin
);
No modification
Wizard
Verification
Reset
Template Registry
CSV Engine
---
# Out Of Scope
New business module
HR implementation
Asset implementation
Inventory implementation
Purchase implementation
Plugin marketplace
External plugin loading
Remote plugins
Installation package download
Backup restore implementation
CRM business behavior changes
---
# Deliverables
Required
src/features/setup/plugins/plugin-types.ts
src/features/setup/plugins/plugin-registry.ts
src/features/setup/plugins/installation-profile.ts
src/features/setup/plugins/foundation/foundation-plugin.ts
src/features/setup/plugins/crm/crm-setup-plugin.ts
src/features/setup/plugins/crm/crm-installation-profile.ts
Update
Setup Wizard
Readiness Service
Verification Service
Template Metadata Service
Template Registry
Optional
docs/setup/setup-plugin-development.md
docs/setup/installation-profiles.md
---
# Acceptance Criteria
✓ Installation Profiles exist.
✓ Plugin Registry exists.
✓ Foundation Plugin exists.
✓ CRM Plugin exists.
✓ Wizard builds dynamically from selected profile.
✓ Wizard no longer hardcodes CRM steps.
✓ Readiness collects plugin checks.
✓ Verification collects plugin checks.
✓ Template registry supports plugin ownership.
✓ Template registry supports profile visibility.
✓ Golden Dataset supports plugin registration.
✓ Future modules can integrate by registering one plugin.
✓ Existing Setup Wizard behavior remains unchanged.
✓ Existing APIs remain backward compatible.
✓ Existing CSV Preview/Commit logic is unaffected.
✓ Typecheck passes.
✓ Existing setup integration tests continue to pass.
---
# Suggested Verification
Run
npm run typecheck
npm run test:setup
Verify
Minimal Profile
Foundation only
CRM Starter
CRM steps only
CRM Demo
CRM + Demo dataset
Production
Production profile
Confirm
Readiness still PASS
Verification still PASS
CSV Preview unchanged
CSV Commit unchanged
Setup Resume unchanged
Golden Dataset unchanged
Register a temporary mock plugin
Confirm
Wizard automatically includes plugin steps
Verification automatically executes plugin checks
Template API exposes plugin templates
Without modifying Setup Wizard source code.
---
# Completion Criteria
After D.7.9
The ALLA OS Setup Platform is officially module-driven.
All future modules (CRM, HR, Asset, Purchase, Inventory, Service, Calendar, etc.) must integrate through the Setup Plugin Registry rather than extending the Setup Wizard directly.
D.7.9 marks the architectural freeze of Setup Platform v1.0.

192
plans/task-p.7.2.md Normal file
View File

@@ -0,0 +1,192 @@
# Task P.7.2 SMTP / Email Configuration Platform
## Objective
Implement a secure SMTP / Email Configuration Platform for ALLA OS.
The goal is to let administrators configure, verify, and use outbound email safely for system notifications such as approval alerts, password reset, invitation emails, setup warnings, and future workflow notifications.
This task must integrate with the existing Setup Platform as an optional readiness/verification step.
Email configuration must not block First-run Setup unless explicitly required by the selected installation profile.
---
## Review Before Implementation
Review:
- AGENTS.md
- docs/standards/project-foundations.md
- docs/standards/architecture-rules.md
- docs/standards/ui-ux-rules.md
- docs/standards/task-review-checklist.md
- docs/setup/verification-matrix.md
- docs/setup/setup-wizard-blueprint.md
- docs/setup/installation-profiles.md
- src/features/setup/**
- src/features/foundation/notifications/**
- src/app/api/setup/readiness/route.ts
- src/app/api/setup/verify/route.ts
- src/db/schema.ts
- existing Auth.js password reset / invitation flow if present
---
## Scope
Create email configuration foundation.
Required features:
- SMTP configuration CRUD
- Secure secret handling
- SMTP connection test
- Send test email
- Email provider readiness check
- Integration with Setup Readiness / Verification
- Optional Setup Wizard step
- Audit-safe reporting
- No secret exposure in API responses
---
## Data Model
Add table:
email_configurations
Suggested fields:
id
organization_id nullable
provider_type
name
host
port
secure
username
password_encrypted
from_email
from_name
reply_to_email
is_default
is_active
last_test_status
last_tested_at
last_test_error
created_by
updated_by
created_at
updated_at
Provider type values:
smtp
future values:
sendgrid
ses
mailgun
microsoft_graph
---
## Secret Handling
SMTP password must never be stored as plain text.
Use existing encryption utility if available.
If none exists, create foundation crypto helper:
src/features/foundation/secrets/server/crypto.ts
Rules:
- encryption key from environment variable
- missing key blocks saving password
- API never returns password_encrypted
- UI shows password as "configured" or "not configured"
- password can be replaced, not read
Required environment:
EMAIL_CONFIG_ENCRYPTION_KEY
Suggested validation:
- minimum 32 bytes
- base64 or hex recommended
---
## Server Services
Create:
src/features/foundation/email/server/email-config.service.ts
src/features/foundation/email/server/email-test.service.ts
src/features/foundation/email/server/email-provider.ts
src/features/foundation/email/server/smtp-provider.ts
Responsibilities:
email-config.service.ts
- list configs
- get config
- create config
- update config
- delete/deactivate config
- set default config
- validate config
- mask secret output
email-test.service.ts
- test SMTP connection
- send test email
- update last_test_status
- update last_tested_at
- store safe last_test_error
email-provider.ts
- provider interface
smtp-provider.ts
- nodemailer implementation or existing mail library integration
---
## Provider Interface
```ts
export interface EmailProvider {
testConnection(config: EmailProviderConfig): Promise<EmailTestResult>;
sendEmail(input: SendEmailInput): Promise<SendEmailResult>;
}

View File

@@ -0,0 +1,2 @@
organization_code,entity_type,workflow_code,branch_code,product_type_code,min_amount,max_amount,currency,priority,is_default,is_active,description
1 organization_code entity_type workflow_code branch_code product_type_code min_amount max_amount currency priority is_default is_active description

View File

@@ -0,0 +1 @@
organization_code,workflow_code,step_number,role_code,role_name,approval_mode,is_required,sla_hours,calendar_mode,timeout_action
1 organization_code workflow_code step_number role_code role_name approval_mode is_required sla_hours calendar_mode timeout_action

View File

@@ -0,0 +1 @@
organization_code,workflow_code,workflow_name,entity_type,description,is_system,is_active
1 organization_code workflow_code workflow_name entity_type description is_system is_active

View File

@@ -0,0 +1,3 @@
organization_code,branch_code,branch_name,prefix,address,tax_id,phone,email,sort_order,is_active
ALLA,head_office,Head Office,AL,"933, 935, 937,939 ซอยอ่อนนุช 46 ถนนอ่อนนุช แขวงอ่อนนุช เขตสวนหลวง กรุงเทพมหานคร 10250",0107558000393,023220776,head.office@example.com,1,true
ONVALLA,head_office,Head Office,ON,เลขที่ 50 หมู่ 20 ตำบลลำลูกกา อำเภอลำลูกกา จังหวัดปทุมธานี 12150,0107558000393,021935380,eastern@example.com,2,true
1 organization_code branch_code branch_name prefix address tax_id phone email sort_order is_active
2 ALLA head_office Head Office AL 933, 935, 937,939 ซอยอ่อนนุช 46 ถนนอ่อนนุช แขวงอ่อนนุช เขตสวนหลวง กรุงเทพมหานคร 10250 0107558000393 023220776 head.office@example.com 1 true
3 ONVALLA head_office Head Office ON เลขที่ 50 หมู่ 20 ตำบลลำลูกกา อำเภอลำลูกกา จังหวัดปทุมธานี 12150 0107558000393 021935380 eastern@example.com 2 true

View File

@@ -0,0 +1,2 @@
organization_code,user_email,crm_role_code,is_primary,branch_scope_mode,branch_codes,product_type_scope_mode,product_type_codes,is_active
1 organization_code user_email crm_role_code is_primary branch_scope_mode branch_codes product_type_scope_mode product_type_codes is_active

View File

@@ -0,0 +1,6 @@
organization_code,branch_code,product_type_code,document_type,prefix,period,current_number,padding_length,format,reset_policy,is_active
ALLA,head_office,crane,customer,CUS,yearly,0,4,{prefix}-{yyyy}-{running},period,true
ALLA,head_office,crane,lead,LD,yearly,0,4,{prefix}-{yyyy}-{running},period,true
ALLA,head_office,crane,opportunity,OP,yearly,0,4,{prefix}-{yyyy}-{running},period,true
ALLA,head_office,crane,quotation,QT-AL-CR,monthly,0,4,{prefix}-{yy}{MM}-{running},period,true
ONVALLA,head_office,crane,quotation,QT-ON-CR,monthly,0,4,{prefix}-{yy}{MM}-{running},period,true
1 organization_code branch_code product_type_code document_type prefix period current_number padding_length format reset_policy is_active
2 ALLA head_office crane customer CUS yearly 0 4 {prefix}-{yyyy}-{running} period true
3 ALLA head_office crane lead LD yearly 0 4 {prefix}-{yyyy}-{running} period true
4 ALLA head_office crane opportunity OP yearly 0 4 {prefix}-{yyyy}-{running} period true
5 ALLA head_office crane quotation QT-AL-CR monthly 0 4 {prefix}-{yy}{MM}-{running} period true
6 ONVALLA head_office crane quotation QT-ON-CR monthly 0 4 {prefix}-{yy}{MM}-{running} period true

View File

@@ -0,0 +1,133 @@
organization_code,category,code,label,value,parent_category,parent_code,sort_order,is_active,metadata_json
ALLA,crm_customer_group,construction,Construction,,,,1,true,{}
ALLA,crm_customer_group,industrial,Industrial,,,,2,true,{}
ALLA,crm_customer_sub_group,factory,Factory,,crm_customer_group,industrial,1,true,{}
ALLA,crm_customer_sub_group,warehouse,Warehouse,,crm_customer_group,industrial,2,true,{}
ALLA,crm_customer_status,active,Active,,,,1,true,{}
ALLA,crm_customer_status,inactive,Inactive,,,,2,true,{}
ALLA,crm_customer_status,prospect,Prospect,,,,3,true,{}
ALLA,crm_customer_type,end_customer,End Customer,,,,1,true,{}
ALLA,crm_customer_type,contractor,Contractor,,,,2,true,{}
ALLA,crm_customer_type,consultant,Consultant,,,,3,true,{}
ALLA,crm_customer_type,developer,Developer,,,,4,true,{}
ALLA,crm_lead_channel,call_in,Call in,,,,1,true,{}
ALLA,crm_lead_channel,ecommerce,E-commerce,,,,2,true,{}
ALLA,crm_lead_channel,email,E-mail,,,,3,true,{}
ALLA,crm_lead_channel,line_oa,Line OA,,,,4,true,{}
ALLA,crm_lead_channel,visit,Visit,,,,5,true,{}
ALLA,crm_lead_channel,walk_in,Walk In,,,,6,true,{}
ALLA,crm_lead_channel,facebook,Facebook,,,,7,true,{}
ALLA,crm_lead_channel,website_contact,Website Contact,,,,8,true,{}
ALLA,crm_lead_channel,bci,BCI,,,,9,true,{}
ALLA,crm_lead_awareness,google_search,Google Search / Website,,,,1,true,{}
ALLA,crm_lead_awareness,social_media,Social media,,,,2,true,{}
ALLA,crm_lead_awareness,email_marketing,Email Marketing,,,,3,true,{}
ALLA,crm_lead_awareness,visit,Visit,,,,4,true,{}
ALLA,crm_lead_awareness,exhibition_event,Exhibition / Event,,,,5,true,{}
ALLA,crm_lead_awareness,brochure_catalog,Brochure / Catalog,,,,6,true,{}
ALLA,crm_lead_awareness,word_of_mouth,Word of mouth,,,,7,true,{}
ALLA,crm_lead_awareness,corporate_car,Corporate Car,,,,8,true,{}
ALLA,crm_lead_awareness,product_label,Product Label,,,,9,true,{}
ALLA,crm_lead_awareness,re_purchasing,Re-purchasing,,,,10,true,{}
ALLA,crm_lead_awareness,introducing,Introducing,,,,11,true,{}
ALLA,crm_lead_awareness,bci,BCI,,,,12,true,{}
ALLA,crm_lead_priority,high,High,,,,1,true,{}
ALLA,crm_lead_priority,medium,Medium,,,,2,true,{}
ALLA,crm_lead_priority,low,Low,,,,3,true,{}
ALLA,crm_followup_status,new,New,,,,1,true,{}
ALLA,crm_followup_status,contacted,Contacted,,,,2,true,{}
ALLA,crm_followup_status,follow_up,Follow Up,,,,3,true,{}
ALLA,crm_followup_status,closed,Closed,,,,4,true,{}
ALLA,crm_lost_reason,price,ราคา,,,,1,true,{}
ALLA,crm_lost_reason,delivery_time,ระยะเวลาจัดส่ง,,,,2,true,{}
ALLA,crm_lost_reason,salesperson,พนักงานขาย,,,,3,true,{}
ALLA,crm_lost_reason,service,การบริการ,,,,4,true,{}
ALLA,crm_lost_reason,customer,ลูกค้า,,,,5,true,{}
ALLA,crm_lost_reason,product_quality,คุณภาพสินค้า,,,,6,true,{}
ALLA,crm_lost_reason,other,อื่นๆ,,,,7,true,{}
ALLA,crm_lost_reason,transfer,Transfer,,,,8,true,{}
ALLA,crm_project_party_role,billing_customer,Billing Customer,,,,1,true,{}
ALLA,crm_project_party_role,end_customer,End Customer,,,,2,true,{}
ALLA,crm_project_party_role,contractor,Contractor,,,,3,true,{}
ALLA,crm_project_party_role,consultant,Consultant,,,,4,true,{}
ALLA,crm_project_party_role,developer,Developer,,,,5,true,{}
ALLA,crm_project_party_role,architect,Architect,,,,6,true,{}
ALLA,crm_quotation_type,standard,Standard,,,,1,true,{}
ALLA,crm_quotation_type,revision,Revision,,,,2,true,{}
ONVALLA,crm_customer_group,construction,Construction,,,,1,true,{}
ONVALLA,crm_customer_group,industrial,Industrial,,,,2,true,{}
ONVALLA,crm_customer_sub_group,factory,Factory,,crm_customer_group,industrial,1,true,{}
ONVALLA,crm_customer_sub_group,warehouse,Warehouse,,crm_customer_group,industrial,2,true,{}
ONVALLA,crm_customer_status,active,Active,,,,1,true,{}
ONVALLA,crm_customer_status,inactive,Inactive,,,,2,true,{}
ONVALLA,crm_customer_status,prospect,Prospect,,,,3,true,{}
ONVALLA,crm_customer_type,end_customer,End Customer,,,,1,true,{}
ONVALLA,crm_customer_type,contractor,Contractor,,,,2,true,{}
ONVALLA,crm_customer_type,consultant,Consultant,,,,3,true,{}
ONVALLA,crm_customer_type,developer,Developer,,,,4,true,{}
ONVALLA,crm_lead_channel,call_in,Call in,,,,1,true,{}
ONVALLA,crm_lead_channel,ecommerce,E-commerce,,,,2,true,{}
ONVALLA,crm_lead_channel,email,E-mail,,,,3,true,{}
ONVALLA,crm_lead_channel,line_oa,Line OA,,,,4,true,{}
ONVALLA,crm_lead_channel,visit,Visit,,,,5,true,{}
ONVALLA,crm_lead_channel,walk_in,Walk In,,,,6,true,{}
ONVALLA,crm_lead_channel,facebook,Facebook,,,,7,true,{}
ONVALLA,crm_lead_channel,website_contact,Website Contact,,,,8,true,{}
ONVALLA,crm_lead_channel,bci,BCI,,,,9,true,{}
ONVALLA,crm_lead_awareness,google_search,Google Search / Website,,,,1,true,{}
ONVALLA,crm_lead_awareness,social_media,Social media,,,,2,true,{}
ONVALLA,crm_lead_awareness,email_marketing,Email Marketing,,,,3,true,{}
ONVALLA,crm_lead_awareness,visit,Visit,,,,4,true,{}
ONVALLA,crm_lead_awareness,exhibition_event,Exhibition / Event,,,,5,true,{}
ONVALLA,crm_lead_awareness,brochure_catalog,Brochure / Catalog,,,,6,true,{}
ONVALLA,crm_lead_awareness,word_of_mouth,Word of mouth,,,,7,true,{}
ONVALLA,crm_lead_awareness,corporate_car,Corporate Car,,,,8,true,{}
ONVALLA,crm_lead_awareness,product_label,Product Label,,,,9,true,{}
ONVALLA,crm_lead_awareness,re_purchasing,Re-purchasing,,,,10,true,{}
ONVALLA,crm_lead_awareness,introducing,Introducing,,,,11,true,{}
ONVALLA,crm_lead_awareness,bci,BCI,,,,12,true,{}
ONVALLA,crm_lead_priority,high,High,,,,1,true,{}
ONVALLA,crm_lead_priority,medium,Medium,,,,2,true,{}
ONVALLA,crm_lead_priority,low,Low,,,,3,true,{}
ONVALLA,crm_followup_status,new,New,,,,1,true,{}
ONVALLA,crm_followup_status,contacted,Contacted,,,,2,true,{}
ONVALLA,crm_followup_status,follow_up,Follow Up,,,,3,true,{}
ONVALLA,crm_followup_status,closed,Closed,,,,4,true,{}
ONVALLA,crm_lost_reason,price,ราคา,,,,1,true,{}
ONVALLA,crm_lost_reason,delivery_time,ระยะเวลาจัดส่ง,,,,2,true,{}
ONVALLA,crm_lost_reason,salesperson,พนักงานขาย,,,,3,true,{}
ONVALLA,crm_lost_reason,service,การบริการ,,,,4,true,{}
ONVALLA,crm_lost_reason,customer,ลูกค้า,,,,5,true,{}
ONVALLA,crm_lost_reason,product_quality,คุณภาพสินค้า,,,,6,true,{}
ONVALLA,crm_lost_reason,other,อื่นๆ,,,,7,true,{}
ONVALLA,crm_lost_reason,transfer,Transfer,,,,8,true,{}
ONVALLA,crm_project_party_role,billing_customer,Billing Customer,,,,1,true,{}
ONVALLA,crm_project_party_role,end_customer,End Customer,,,,2,true,{}
ONVALLA,crm_project_party_role,contractor,Contractor,,,,3,true,{}
ONVALLA,crm_project_party_role,consultant,Consultant,,,,4,true,{}
ONVALLA,crm_project_party_role,developer,Developer,,,,5,true,{}
ONVALLA,crm_project_party_role,architect,Architect,,,,6,true,{}
ONVALLA,crm_quotation_type,standard,Standard,,,,1,true,{}
ONVALLA,crm_quotation_type,revision,Revision,,,,2,true,{}
1 organization_code category code label value parent_category parent_code sort_order is_active metadata_json
2 ALLA crm_customer_group construction Construction 1 true {}
3 ALLA crm_customer_group industrial Industrial 2 true {}
4 ALLA crm_customer_sub_group factory Factory crm_customer_group industrial 1 true {}
5 ALLA crm_customer_sub_group warehouse Warehouse crm_customer_group industrial 2 true {}
6 ALLA crm_customer_status active Active 1 true {}
7 ALLA crm_customer_status inactive Inactive 2 true {}
8 ALLA crm_customer_status prospect Prospect 3 true {}
9 ALLA crm_customer_type end_customer End Customer 1 true {}
10 ALLA crm_customer_type contractor Contractor 2 true {}
11 ALLA crm_customer_type consultant Consultant 3 true {}
12 ALLA crm_customer_type developer Developer 4 true {}
13 ALLA crm_lead_channel call_in Call in 1 true {}
14 ALLA crm_lead_channel ecommerce E-commerce 2 true {}
15 ALLA crm_lead_channel email E-mail 3 true {}
16 ALLA crm_lead_channel line_oa Line OA 4 true {}
17 ALLA crm_lead_channel visit Visit 5 true {}
18 ALLA crm_lead_channel walk_in Walk In 6 true {}
19 ALLA crm_lead_channel facebook Facebook 7 true {}
20 ALLA crm_lead_channel website_contact Website Contact 8 true {}
21 ALLA crm_lead_channel bci BCI 9 true {}
22 ALLA crm_lead_awareness google_search Google Search / Website 1 true {}
23 ALLA crm_lead_awareness social_media Social media 2 true {}
24 ALLA crm_lead_awareness email_marketing Email Marketing 3 true {}
25 ALLA crm_lead_awareness visit Visit 4 true {}
26 ALLA crm_lead_awareness exhibition_event Exhibition / Event 5 true {}
27 ALLA crm_lead_awareness brochure_catalog Brochure / Catalog 6 true {}
28 ALLA crm_lead_awareness word_of_mouth Word of mouth 7 true {}
29 ALLA crm_lead_awareness corporate_car Corporate Car 8 true {}
30 ALLA crm_lead_awareness product_label Product Label 9 true {}
31 ALLA crm_lead_awareness re_purchasing Re-purchasing 10 true {}
32 ALLA crm_lead_awareness introducing Introducing 11 true {}
33 ALLA crm_lead_awareness bci BCI 12 true {}
34 ALLA crm_lead_priority high High 1 true {}
35 ALLA crm_lead_priority medium Medium 2 true {}
36 ALLA crm_lead_priority low Low 3 true {}
37 ALLA crm_followup_status new New 1 true {}
38 ALLA crm_followup_status contacted Contacted 2 true {}
39 ALLA crm_followup_status follow_up Follow Up 3 true {}
40 ALLA crm_followup_status closed Closed 4 true {}
41 ALLA crm_lost_reason price ราคา 1 true {}
42 ALLA crm_lost_reason delivery_time ระยะเวลาจัดส่ง 2 true {}
43 ALLA crm_lost_reason salesperson พนักงานขาย 3 true {}
44 ALLA crm_lost_reason service การบริการ 4 true {}
45 ALLA crm_lost_reason customer ลูกค้า 5 true {}
46 ALLA crm_lost_reason product_quality คุณภาพสินค้า 6 true {}
47 ALLA crm_lost_reason other อื่นๆ 7 true {}
48 ALLA crm_lost_reason transfer Transfer 8 true {}
49 ALLA crm_project_party_role billing_customer Billing Customer 1 true {}
50 ALLA crm_project_party_role end_customer End Customer 2 true {}
51 ALLA crm_project_party_role contractor Contractor 3 true {}
52 ALLA crm_project_party_role consultant Consultant 4 true {}
53 ALLA crm_project_party_role developer Developer 5 true {}
54 ALLA crm_project_party_role architect Architect 6 true {}
55 ALLA crm_quotation_type standard Standard 1 true {}
56 ALLA crm_quotation_type revision Revision 2 true {}
57 ONVALLA crm_customer_group construction Construction 1 true {}
58 ONVALLA crm_customer_group industrial Industrial 2 true {}
59 ONVALLA crm_customer_sub_group factory Factory crm_customer_group industrial 1 true {}
60 ONVALLA crm_customer_sub_group warehouse Warehouse crm_customer_group industrial 2 true {}
61 ONVALLA crm_customer_status active Active 1 true {}
62 ONVALLA crm_customer_status inactive Inactive 2 true {}
63 ONVALLA crm_customer_status prospect Prospect 3 true {}
64 ONVALLA crm_customer_type end_customer End Customer 1 true {}
65 ONVALLA crm_customer_type contractor Contractor 2 true {}
66 ONVALLA crm_customer_type consultant Consultant 3 true {}
67 ONVALLA crm_customer_type developer Developer 4 true {}
68 ONVALLA crm_lead_channel call_in Call in 1 true {}
69 ONVALLA crm_lead_channel ecommerce E-commerce 2 true {}
70 ONVALLA crm_lead_channel email E-mail 3 true {}
71 ONVALLA crm_lead_channel line_oa Line OA 4 true {}
72 ONVALLA crm_lead_channel visit Visit 5 true {}
73 ONVALLA crm_lead_channel walk_in Walk In 6 true {}
74 ONVALLA crm_lead_channel facebook Facebook 7 true {}
75 ONVALLA crm_lead_channel website_contact Website Contact 8 true {}
76 ONVALLA crm_lead_channel bci BCI 9 true {}
77 ONVALLA crm_lead_awareness google_search Google Search / Website 1 true {}
78 ONVALLA crm_lead_awareness social_media Social media 2 true {}
79 ONVALLA crm_lead_awareness email_marketing Email Marketing 3 true {}
80 ONVALLA crm_lead_awareness visit Visit 4 true {}
81 ONVALLA crm_lead_awareness exhibition_event Exhibition / Event 5 true {}
82 ONVALLA crm_lead_awareness brochure_catalog Brochure / Catalog 6 true {}
83 ONVALLA crm_lead_awareness word_of_mouth Word of mouth 7 true {}
84 ONVALLA crm_lead_awareness corporate_car Corporate Car 8 true {}
85 ONVALLA crm_lead_awareness product_label Product Label 9 true {}
86 ONVALLA crm_lead_awareness re_purchasing Re-purchasing 10 true {}
87 ONVALLA crm_lead_awareness introducing Introducing 11 true {}
88 ONVALLA crm_lead_awareness bci BCI 12 true {}
89 ONVALLA crm_lead_priority high High 1 true {}
90 ONVALLA crm_lead_priority medium Medium 2 true {}
91 ONVALLA crm_lead_priority low Low 3 true {}
92 ONVALLA crm_followup_status new New 1 true {}
93 ONVALLA crm_followup_status contacted Contacted 2 true {}
94 ONVALLA crm_followup_status follow_up Follow Up 3 true {}
95 ONVALLA crm_followup_status closed Closed 4 true {}
96 ONVALLA crm_lost_reason price ราคา 1 true {}
97 ONVALLA crm_lost_reason delivery_time ระยะเวลาจัดส่ง 2 true {}
98 ONVALLA crm_lost_reason salesperson พนักงานขาย 3 true {}
99 ONVALLA crm_lost_reason service การบริการ 4 true {}
100 ONVALLA crm_lost_reason customer ลูกค้า 5 true {}
101 ONVALLA crm_lost_reason product_quality คุณภาพสินค้า 6 true {}
102 ONVALLA crm_lost_reason other อื่นๆ 7 true {}
103 ONVALLA crm_lost_reason transfer Transfer 8 true {}
104 ONVALLA crm_project_party_role billing_customer Billing Customer 1 true {}
105 ONVALLA crm_project_party_role end_customer End Customer 2 true {}
106 ONVALLA crm_project_party_role contractor Contractor 3 true {}
107 ONVALLA crm_project_party_role consultant Consultant 4 true {}
108 ONVALLA crm_project_party_role developer Developer 5 true {}
109 ONVALLA crm_project_party_role architect Architect 6 true {}
110 ONVALLA crm_quotation_type standard Standard 1 true {}
111 ONVALLA crm_quotation_type revision Revision 2 true {}

View File

@@ -0,0 +1,27 @@
organization_code,user_email,membership_role,business_role,permissions,branch_scope_codes,product_type_scope_codes
ALLA,super_admin@allaos.local,admin,system_admin,*,*,*
ALLA,gm.uat@allaos.local,user,general_manager,crm.dashboard.read|crm.customer.read|crm.lead.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office|eastern|northern,crane|dockdoor|solar|service
ALLA,ceo.uat@allaos.local,user,executive,crm.dashboard.read|crm.approval.read,head_office|eastern|northern,crane|dockdoor|solar|service
ALLA,head_mk.uat@allaos.local,user,marketing_manager,crm.dashboard.read|crm.lead.read|crm.lead.create|crm.lead.update|crm.lead.assign,head_office,crane|dockdoor|solar
ALLA,mk.uat@allaos.local,user,marketing,crm.lead.read|crm.lead.create,head_office,crane|dockdoor|solar
ALLA,manager.uat@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office|eastern|northern,crane|dockdoor|solar|service
ALLA,mgr_crane.uat@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,eastern,crane
ALLA,sales_crane.uat@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,eastern,crane
ALLA,mgr_dock.uat@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office,dockdoor
ALLA,sales_dock.uat@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,head_office,dockdoor
ALLA,mgr_solar.uat@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,northern,solar
ALLA,sales_solar.uat@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,northern,solar
ALLA,sales.uat@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,head_office|eastern,crane|dockdoor
ONVALLA,gm.onvalla@allaos.local,user,general_manager,crm.dashboard.read|crm.customer.read|crm.lead.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office|eastern|northern,crane|dockdoor|solar|service
ONVALLA,ceo.onvalla@allaos.local,user,executive,crm.dashboard.read|crm.approval.read,head_office|eastern|northern,crane|dockdoor|solar|service
ONVALLA,head_mk.onvalla@allaos.local,user,marketing_manager,crm.dashboard.read|crm.lead.read|crm.lead.create|crm.lead.update|crm.lead.assign,head_office,crane|dockdoor|solar
ONVALLA,mk.onvalla@allaos.local,user,marketing,crm.lead.read|crm.lead.create,head_office,crane|dockdoor|solar
ONVALLA,manager.onvalla@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office|eastern|northern,crane|dockdoor|solar|service
ONVALLA,mgr_crane.onvalla@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,eastern,crane
ONVALLA,sales_crane.onvalla@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,eastern,crane
ONVALLA,mgr_dock.onvalla@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office,dockdoor
ONVALLA,sales_dock.onvalla@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,head_office,dockdoor
ONVALLA,mgr_solar.onvalla@allaos.local,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,northern,solar
ONVALLA,sales_solar.onvalla@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,northern,solar
ONVALLA,sales.onvalla@allaos.local,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,head_office|eastern,crane|dockdoor
1 organization_code user_email membership_role business_role permissions branch_scope_codes product_type_scope_codes
2 ALLA super_admin@allaos.local admin system_admin * * *
3 ALLA gm.uat@allaos.local user general_manager crm.dashboard.read|crm.customer.read|crm.lead.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office|eastern|northern crane|dockdoor|solar|service
4 ALLA ceo.uat@allaos.local user executive crm.dashboard.read|crm.approval.read head_office|eastern|northern crane|dockdoor|solar|service
5 ALLA head_mk.uat@allaos.local user marketing_manager crm.dashboard.read|crm.lead.read|crm.lead.create|crm.lead.update|crm.lead.assign head_office crane|dockdoor|solar
6 ALLA mk.uat@allaos.local user marketing crm.lead.read|crm.lead.create head_office crane|dockdoor|solar
7 ALLA manager.uat@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office|eastern|northern crane|dockdoor|solar|service
8 ALLA mgr_crane.uat@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read eastern crane
9 ALLA sales_crane.uat@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read eastern crane
10 ALLA mgr_dock.uat@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office dockdoor
11 ALLA sales_dock.uat@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read head_office dockdoor
12 ALLA mgr_solar.uat@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read northern solar
13 ALLA sales_solar.uat@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read northern solar
14 ALLA sales.uat@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read head_office|eastern crane|dockdoor
15 ONVALLA gm.onvalla@allaos.local user general_manager crm.dashboard.read|crm.customer.read|crm.lead.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office|eastern|northern crane|dockdoor|solar|service
16 ONVALLA ceo.onvalla@allaos.local user executive crm.dashboard.read|crm.approval.read head_office|eastern|northern crane|dockdoor|solar|service
17 ONVALLA head_mk.onvalla@allaos.local user marketing_manager crm.dashboard.read|crm.lead.read|crm.lead.create|crm.lead.update|crm.lead.assign head_office crane|dockdoor|solar
18 ONVALLA mk.onvalla@allaos.local user marketing crm.lead.read|crm.lead.create head_office crane|dockdoor|solar
19 ONVALLA manager.onvalla@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office|eastern|northern crane|dockdoor|solar|service
20 ONVALLA mgr_crane.onvalla@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read eastern crane
21 ONVALLA sales_crane.onvalla@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read eastern crane
22 ONVALLA mgr_dock.onvalla@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office dockdoor
23 ONVALLA sales_dock.onvalla@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read head_office dockdoor
24 ONVALLA mgr_solar.onvalla@allaos.local user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read northern solar
25 ONVALLA sales_solar.onvalla@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read northern solar
26 ONVALLA sales.onvalla@allaos.local user sales crm.customer.read|crm.opportunity.read|crm.quotation.read head_office|eastern crane|dockdoor

View File

@@ -0,0 +1,3 @@
organization_code,organization_name,slug,created_by_email,tax_id,default_currency,phone,email,address,logo_url,plan,status
ALLA,ALLA Company Limited,alla,super_admin@allaos.local,1200101745173,THB,02-000-0000,admin@alla.example,99/9 Rama IX Road Bangkok,,enterprise,active
ONVALLA,ONVALLA Demo Company,onvalla,super_admin@allaos.local,1200101745178,THB,02-000-0099,admin@onvalla.example,88/8 Demo Road Bangkok,,enterprise,active
1 organization_code organization_name slug created_by_email tax_id default_currency phone email address logo_url plan status
2 ALLA ALLA Company Limited alla super_admin@allaos.local 1200101745173 THB 02-000-0000 admin@alla.example 99/9 Rama IX Road Bangkok enterprise active
3 ONVALLA ONVALLA Demo Company onvalla super_admin@allaos.local 1200101745178 THB 02-000-0099 admin@onvalla.example 88/8 Demo Road Bangkok enterprise active

View File

@@ -0,0 +1,5 @@
organization_code,product_type_code,product_type_name,document_prefix,sort_order,is_active,metadata_json
ALLA,crane,Crane,CR,1,true,{}
ALLA,dockdoor,DocK Door,DK,2,true,{}
ONVALLA,crane,Crane,CR,3,true,{}
ONVALLA,solarcell,Solar cell,SC,4,true,{}
1 organization_code product_type_code product_type_name document_prefix sort_order is_active metadata_json
2 ALLA crane Crane CR 1 true {}
3 ALLA dockdoor DocK Door DK 2 true {}
4 ONVALLA crane Crane CR 3 true {}
5 ONVALLA solarcell Solar cell SC 4 true {}

View File

@@ -0,0 +1,26 @@
email,name,system_role,password,active_organization_code,image_url,reset_password
super_admin@allaos.local,System Administrator,super_admin,ChangeMe123!,ALLA,,FALSE
gm.uat@allaos.local,General Manager,user,ChangeMe123!,ALLA,,FALSE
ceo.uat@allaos.local,Chief Executive Officer,user,ChangeMe123!,ALLA,,FALSE
head_mk.uat@allaos.local,Head of Marketing,user,ChangeMe123!,ALLA,,FALSE
mk.uat@allaos.local,Marketing User,user,ChangeMe123!,ALLA,,FALSE
manager.uat@allaos.local,Sales Director,user,ChangeMe123!,ALLA,,FALSE
mgr_crane.uat@allaos.local,Crane Sales Manager,user,ChangeMe123!,ALLA,,FALSE
sales_crane.uat@allaos.local,Crane Sales,user,ChangeMe123!,ALLA,,FALSE
mgr_dock.uat@allaos.local,Dock Door Sales Manager,user,ChangeMe123!,ALLA,,FALSE
sales_dock.uat@allaos.local,Dock Door Sales,user,ChangeMe123!,ALLA,,FALSE
mgr_solar.uat@allaos.local,Solar Sales Manager,user,ChangeMe123!,ALLA,,FALSE
sales_solar.uat@allaos.local,Solar Sales,user,ChangeMe123!,ALLA,,FALSE
sales.uat@allaos.local,General Sales,user,ChangeMe123!,ALLA,,FALSE
gm.onvalla@allaos.local,General Manager,user,ChangeMe123!,ONVALLA,,FALSE
ceo.onvalla@allaos.local,Chief Executive Officer,user,ChangeMe123!,ONVALLA,,FALSE
head_mk.onvalla@allaos.local,Head of Marketing,user,ChangeMe123!,ONVALLA,,FALSE
mk.onvalla@allaos.local,Marketing User,user,ChangeMe123!,ONVALLA,,FALSE
manager.onvalla@allaos.local,Sales Director,user,ChangeMe123!,ONVALLA,,FALSE
mgr_crane.onvalla@allaos.local,Crane Sales Manager,user,ChangeMe123!,ONVALLA,,FALSE
sales_crane.onvalla@allaos.local,Crane Sales,user,ChangeMe123!,ONVALLA,,FALSE
mgr_dock.onvalla@allaos.local,Dock Door Sales Manager,user,ChangeMe123!,ONVALLA,,FALSE
sales_dock.onvalla@allaos.local,Dock Door Sales,user,ChangeMe123!,ONVALLA,,FALSE
mgr_solar.onvalla@allaos.local,Solar Sales Manager,user,ChangeMe123!,ONVALLA,,FALSE
sales_solar.onvalla@allaos.local,Solar Sales,user,ChangeMe123!,ONVALLA,,FALSE
sales.onvalla@allaos.local,General Sales,user,ChangeMe123!,ONVALLA,,FALSE
1 email name system_role password active_organization_code image_url reset_password
2 super_admin@allaos.local System Administrator super_admin ChangeMe123! ALLA FALSE
3 gm.uat@allaos.local General Manager user ChangeMe123! ALLA FALSE
4 ceo.uat@allaos.local Chief Executive Officer user ChangeMe123! ALLA FALSE
5 head_mk.uat@allaos.local Head of Marketing user ChangeMe123! ALLA FALSE
6 mk.uat@allaos.local Marketing User user ChangeMe123! ALLA FALSE
7 manager.uat@allaos.local Sales Director user ChangeMe123! ALLA FALSE
8 mgr_crane.uat@allaos.local Crane Sales Manager user ChangeMe123! ALLA FALSE
9 sales_crane.uat@allaos.local Crane Sales user ChangeMe123! ALLA FALSE
10 mgr_dock.uat@allaos.local Dock Door Sales Manager user ChangeMe123! ALLA FALSE
11 sales_dock.uat@allaos.local Dock Door Sales user ChangeMe123! ALLA FALSE
12 mgr_solar.uat@allaos.local Solar Sales Manager user ChangeMe123! ALLA FALSE
13 sales_solar.uat@allaos.local Solar Sales user ChangeMe123! ALLA FALSE
14 sales.uat@allaos.local General Sales user ChangeMe123! ALLA FALSE
15 gm.onvalla@allaos.local General Manager user ChangeMe123! ONVALLA FALSE
16 ceo.onvalla@allaos.local Chief Executive Officer user ChangeMe123! ONVALLA FALSE
17 head_mk.onvalla@allaos.local Head of Marketing user ChangeMe123! ONVALLA FALSE
18 mk.onvalla@allaos.local Marketing User user ChangeMe123! ONVALLA FALSE
19 manager.onvalla@allaos.local Sales Director user ChangeMe123! ONVALLA FALSE
20 mgr_crane.onvalla@allaos.local Crane Sales Manager user ChangeMe123! ONVALLA FALSE
21 sales_crane.onvalla@allaos.local Crane Sales user ChangeMe123! ONVALLA FALSE
22 mgr_dock.onvalla@allaos.local Dock Door Sales Manager user ChangeMe123! ONVALLA FALSE
23 sales_dock.onvalla@allaos.local Dock Door Sales user ChangeMe123! ONVALLA FALSE
24 mgr_solar.onvalla@allaos.local Solar Sales Manager user ChangeMe123! ONVALLA FALSE
25 sales_solar.onvalla@allaos.local Solar Sales user ChangeMe123! ONVALLA FALSE
26 sales.onvalla@allaos.local General Sales user ChangeMe123! ONVALLA FALSE

View File

@@ -0,0 +1,31 @@
# ALLA OS Setup Golden Dataset
This dataset is the canonical setup fixture for development, CI contract checks, QA, UAT, customer demo, and regression testing.
It mirrors the official setup template registry and is intentionally safe sample data.
## Dataset Summary
- Organizations: `ALLA`, `ONVALLA`
- Users: IT, Marketing, Sales, Sales Manager, CEO
- Customers: 10
- Contacts: 20
- Leads: 20
- Opportunities: 15
- Quotations: 20
- Branches: 3
- Product types: 3
- Quotation statuses include draft, pending approval, approved, rejected, and revision.
## Workflow
1. Apply migrations.
2. Run setup readiness.
3. Start setup run.
4. Preview all CSV files in this directory.
5. Commit with the returned `previewHash`.
6. Run verification.
7. Complete setup.
8. Use reset preview APIs for maintenance tests.
Do not edit headers manually. Headers must remain identical to `setup/templates/*.csv`.

View File

@@ -0,0 +1,3 @@
organization_code,entity_type,workflow_code,branch_code,product_type_code,min_amount,max_amount,currency,priority,is_default,is_active,description
ALLA,quotation,quotation_standard,head_office,crane,0,5000000,THB,100,true,true,Default crane approval
ALLA,quotation,quotation_standard,eastern,hoist,0,3000000,THB,90,false,true,Eastern hoist approval
1 organization_code entity_type workflow_code branch_code product_type_code min_amount max_amount currency priority is_default is_active description
2 ALLA quotation quotation_standard head_office crane 0 5000000 THB 100 true true Default crane approval
3 ALLA quotation quotation_standard eastern hoist 0 3000000 THB 90 false true Eastern hoist approval

View File

@@ -0,0 +1,3 @@
organization_code,workflow_code,step_number,role_code,role_name,approval_mode,is_required,sla_hours,calendar_mode,timeout_action
ALLA,quotation_standard,1,sales_manager,Sales Manager,sequential,true,24,calendar_days,none
ALLA,quotation_standard,2,ceo,Chief Executive Officer,sequential,true,48,calendar_days,none
1 organization_code workflow_code step_number role_code role_name approval_mode is_required sla_hours calendar_mode timeout_action
2 ALLA quotation_standard 1 sales_manager Sales Manager sequential true 24 calendar_days none
3 ALLA quotation_standard 2 ceo Chief Executive Officer sequential true 48 calendar_days none

View File

@@ -0,0 +1,2 @@
organization_code,workflow_code,workflow_name,entity_type,description,is_system,is_active
ALLA,quotation_standard,Quotation Standard Approval,quotation,Default quotation approval,false,true
1 organization_code workflow_code workflow_name entity_type description is_system is_active
2 ALLA quotation_standard Quotation Standard Approval quotation Default quotation approval false true

View File

@@ -0,0 +1,4 @@
organization_code,branch_code,branch_name,prefix,address,tax_id,phone,email,sort_order,is_active
ALLA,head_office,Head Office,HO,99/9 Rama IX Road Bangkok,0107558000393,02-000-0000,head.office@example.com,1,true
ALLA,eastern,Eastern Branch,ES,55/5 Chonburi Industrial Estate,0107558000393,038-000-000,eastern@example.com,2,true
ALLA,northern,Northern Branch,NO,44/4 Chiang Mai Road,0107558000393,053-000-000,northern@example.com,3,true
1 organization_code branch_code branch_name prefix address tax_id phone email sort_order is_active
2 ALLA head_office Head Office HO 99/9 Rama IX Road Bangkok 0107558000393 02-000-0000 head.office@example.com 1 true
3 ALLA eastern Eastern Branch ES 55/5 Chonburi Industrial Estate 0107558000393 038-000-000 eastern@example.com 2 true
4 ALLA northern Northern Branch NO 44/4 Chiang Mai Road 0107558000393 053-000-000 northern@example.com 3 true

View File

@@ -0,0 +1,6 @@
organization_code,customer_code,contact_email,shared_to_user_email,shared_by_user_email,remark,is_active
ALLA,CUS-001,anan@siam.example,sales.uat@example.com,admin@example.com,Golden share,true
ALLA,CUS-002,chai@metro.example,sales.uat@example.com,admin@example.com,Golden share,true
ALLA,CUS-003,ekk@north.example,manager.uat@example.com,admin@example.com,Golden share,true
ALLA,CUS-004,golf@easternsteel.example,sales.uat@example.com,admin@example.com,Golden share,true
ALLA,CUS-005,itt@central-log.example,sales.uat@example.com,admin@example.com,Golden share,true
1 organization_code customer_code contact_email shared_to_user_email shared_by_user_email remark is_active
2 ALLA CUS-001 anan@siam.example sales.uat@example.com admin@example.com Golden share true
3 ALLA CUS-002 chai@metro.example sales.uat@example.com admin@example.com Golden share true
4 ALLA CUS-003 ekk@north.example manager.uat@example.com admin@example.com Golden share true
5 ALLA CUS-004 golf@easternsteel.example sales.uat@example.com admin@example.com Golden share true
6 ALLA CUS-005 itt@central-log.example sales.uat@example.com admin@example.com Golden share true

View File

@@ -0,0 +1,21 @@
organization_code,customer_code,contact_name,created_by_email,position,department,phone,mobile,email,is_primary,notes,is_active
ALLA,CUS-001,Anan Sales,admin@example.com,Procurement Manager,Procurement,02-000-1001,081-000-0001,anan@siam.example,true,Primary contact,true
ALLA,CUS-001,Ben Engineer,admin@example.com,Plant Engineer,Engineering,02-000-1002,081-000-0002,ben@siam.example,false,Technical contact,true
ALLA,CUS-002,Chai Manager,admin@example.com,Project Manager,Project,02-000-1003,081-000-0003,chai@metro.example,true,Primary contact,true
ALLA,CUS-002,Dara QS,admin@example.com,QS,Commercial,02-000-1004,081-000-0004,dara@metro.example,false,Commercial contact,true
ALLA,CUS-003,Ekk Designer,admin@example.com,Designer,Design,02-000-1005,081-000-0005,ekk@north.example,true,Primary contact,true
ALLA,CUS-003,Fon Architect,admin@example.com,Architect,Design,02-000-1006,081-000-0006,fon@north.example,false,Design contact,true
ALLA,CUS-004,Golf Ops,admin@example.com,Operations Manager,Operations,02-000-1007,081-000-0007,golf@easternsteel.example,true,Primary contact,true
ALLA,CUS-004,Hana Buyer,admin@example.com,Buyer,Procurement,02-000-1008,081-000-0008,hana@easternsteel.example,false,Buyer contact,true
ALLA,CUS-005,Itt Logistics,admin@example.com,Logistics Manager,Logistics,02-000-1009,081-000-0009,itt@central-log.example,true,Primary contact,true
ALLA,CUS-005,Jin Warehouse,admin@example.com,Warehouse Lead,Warehouse,02-000-1010,081-000-0010,jin@central-log.example,false,Warehouse contact,true
ALLA,CUS-006,Kai Site,admin@example.com,Site Manager,Project,02-000-1011,081-000-0011,kai@harbor.example,true,Primary contact,true
ALLA,CUS-006,Lek Admin,admin@example.com,Admin,Administration,02-000-1012,081-000-0012,lek@harbor.example,false,Admin contact,true
ALLA,CUS-007,Mai Plant,admin@example.com,Plant Manager,Production,02-000-1013,081-000-0013,mai@peakfoods.example,true,Primary contact,true
ALLA,CUS-007,Nok Maintenance,admin@example.com,Maintenance,Engineering,02-000-1014,081-000-0014,nok@peakfoods.example,false,Maintenance contact,true
ALLA,CUS-008,Oat Packaging,admin@example.com,Factory Manager,Factory,02-000-1015,081-000-0015,oat@riverpack.example,true,Primary contact,true
ALLA,CUS-008,Pim Buyer,admin@example.com,Buyer,Procurement,02-000-1016,081-000-0016,pim@riverpack.example,false,Buyer contact,true
ALLA,CUS-009,Q Auto,admin@example.com,Production Manager,Production,02-000-1017,081-000-0017,q@summitauto.example,true,Primary contact,true
ALLA,CUS-009,Rin Engineer,admin@example.com,Engineer,Engineering,02-000-1018,081-000-0018,rin@summitauto.example,false,Engineer contact,true
ALLA,CUS-010,Som Developer,admin@example.com,Development Manager,Development,02-000-1019,081-000-0019,som@urban.example,true,Primary contact,true
ALLA,CUS-010,Tan Project,admin@example.com,Project Coordinator,Project,02-000-1020,081-000-0020,tan@urban.example,false,Project contact,true
1 organization_code customer_code contact_name created_by_email position department phone mobile email is_primary notes is_active
2 ALLA CUS-001 Anan Sales admin@example.com Procurement Manager Procurement 02-000-1001 081-000-0001 anan@siam.example true Primary contact true
3 ALLA CUS-001 Ben Engineer admin@example.com Plant Engineer Engineering 02-000-1002 081-000-0002 ben@siam.example false Technical contact true
4 ALLA CUS-002 Chai Manager admin@example.com Project Manager Project 02-000-1003 081-000-0003 chai@metro.example true Primary contact true
5 ALLA CUS-002 Dara QS admin@example.com QS Commercial 02-000-1004 081-000-0004 dara@metro.example false Commercial contact true
6 ALLA CUS-003 Ekk Designer admin@example.com Designer Design 02-000-1005 081-000-0005 ekk@north.example true Primary contact true
7 ALLA CUS-003 Fon Architect admin@example.com Architect Design 02-000-1006 081-000-0006 fon@north.example false Design contact true
8 ALLA CUS-004 Golf Ops admin@example.com Operations Manager Operations 02-000-1007 081-000-0007 golf@easternsteel.example true Primary contact true
9 ALLA CUS-004 Hana Buyer admin@example.com Buyer Procurement 02-000-1008 081-000-0008 hana@easternsteel.example false Buyer contact true
10 ALLA CUS-005 Itt Logistics admin@example.com Logistics Manager Logistics 02-000-1009 081-000-0009 itt@central-log.example true Primary contact true
11 ALLA CUS-005 Jin Warehouse admin@example.com Warehouse Lead Warehouse 02-000-1010 081-000-0010 jin@central-log.example false Warehouse contact true
12 ALLA CUS-006 Kai Site admin@example.com Site Manager Project 02-000-1011 081-000-0011 kai@harbor.example true Primary contact true
13 ALLA CUS-006 Lek Admin admin@example.com Admin Administration 02-000-1012 081-000-0012 lek@harbor.example false Admin contact true
14 ALLA CUS-007 Mai Plant admin@example.com Plant Manager Production 02-000-1013 081-000-0013 mai@peakfoods.example true Primary contact true
15 ALLA CUS-007 Nok Maintenance admin@example.com Maintenance Engineering 02-000-1014 081-000-0014 nok@peakfoods.example false Maintenance contact true
16 ALLA CUS-008 Oat Packaging admin@example.com Factory Manager Factory 02-000-1015 081-000-0015 oat@riverpack.example true Primary contact true
17 ALLA CUS-008 Pim Buyer admin@example.com Buyer Procurement 02-000-1016 081-000-0016 pim@riverpack.example false Buyer contact true
18 ALLA CUS-009 Q Auto admin@example.com Production Manager Production 02-000-1017 081-000-0017 q@summitauto.example true Primary contact true
19 ALLA CUS-009 Rin Engineer admin@example.com Engineer Engineering 02-000-1018 081-000-0018 rin@summitauto.example false Engineer contact true
20 ALLA CUS-010 Som Developer admin@example.com Development Manager Development 02-000-1019 081-000-0019 som@urban.example true Primary contact true
21 ALLA CUS-010 Tan Project admin@example.com Project Coordinator Project 02-000-1020 081-000-0020 tan@urban.example false Project contact true

View File

@@ -0,0 +1,6 @@
organization_code,user_email,crm_role_code,is_primary,branch_scope_mode,branch_codes,product_type_scope_mode,product_type_codes,is_active
ALLA,admin@example.com,crm_admin,true,all,,all,,true
ALLA,mk.uat@example.com,marketing,true,selected,head_office,selected,crane|hoist,true
ALLA,sales.uat@example.com,sales,true,selected,head_office|eastern,selected,crane|hoist,true
ALLA,manager.uat@example.com,sales_manager,true,all,,all,,true
ALLA,ceo.uat@example.com,ceo,true,all,,all,,true
1 organization_code user_email crm_role_code is_primary branch_scope_mode branch_codes product_type_scope_mode product_type_codes is_active
2 ALLA admin@example.com crm_admin true all all true
3 ALLA mk.uat@example.com marketing true selected head_office selected crane|hoist true
4 ALLA sales.uat@example.com sales true selected head_office|eastern selected crane|hoist true
5 ALLA manager.uat@example.com sales_manager true all all true
6 ALLA ceo.uat@example.com ceo true all all true

View File

@@ -0,0 +1,11 @@
organization_code,customer_code,customer_name,customer_type,customer_status,created_by_email,branch_code,abbr,tax_id,address,province,district,sub_district,postal_code,country,phone,fax,email,website,lead_channel,customer_group,customer_sub_group,owner_user_email,notes,is_active
ALLA,CUS-001,Siam Factory,end_customer,active,admin@example.com,head_office,SF,0105559000001,1 Factory Road,Bangkok,Bang Kapi,Hua Mak,10240,TH,02-100-0001,,contact@siam.example,https://siam.example,website,industrial,factory,sales.uat@example.com,Golden customer 1,true
ALLA,CUS-002,Metro Contractor,contractor,active,admin@example.com,eastern,MC,0105559000002,2 Contractor Road,Chonburi,Mueang,Saen Suk,20000,TH,02-100-0002,,contact@metro.example,https://metro.example,referral,industrial,factory,sales.uat@example.com,Golden customer 2,true
ALLA,CUS-003,North Design,consultant,prospect,admin@example.com,northern,ND,0105559000003,3 Design Road,Chiang Mai,Mueang,Suthep,50200,TH,02-100-0003,,contact@north.example,https://north.example,event,industrial,factory,manager.uat@example.com,Golden customer 3,true
ALLA,CUS-004,Eastern Steel,end_customer,active,admin@example.com,eastern,ES,0105559000004,4 Steel Road,Rayong,Mueang,Noen Phra,21000,TH,02-100-0004,,contact@easternsteel.example,https://easternsteel.example,website,industrial,factory,sales.uat@example.com,Golden customer 4,true
ALLA,CUS-005,Central Logistics,end_customer,active,admin@example.com,head_office,CL,0105559000005,5 Logistics Road,Bangkok,Lat Krabang,Lat Krabang,10520,TH,02-100-0005,,contact@central-log.example,https://central-log.example,referral,industrial,factory,sales.uat@example.com,Golden customer 5,true
ALLA,CUS-006,Harbor Engineering,contractor,prospect,admin@example.com,eastern,HE,0105559000006,6 Harbor Road,Chonburi,Sriracha,Sriracha,20110,TH,02-100-0006,,contact@harbor.example,https://harbor.example,event,industrial,factory,manager.uat@example.com,Golden customer 6,true
ALLA,CUS-007,Peak Foods,end_customer,active,admin@example.com,northern,PF,0105559000007,7 Food Road,Lamphun,Mueang,Nai Mueang,51000,TH,02-100-0007,,contact@peakfoods.example,https://peakfoods.example,website,industrial,factory,sales.uat@example.com,Golden customer 7,true
ALLA,CUS-008,River Packaging,end_customer,active,admin@example.com,head_office,RP,0105559000008,8 Packaging Road,Pathum Thani,Khlong Luang,Khlong Nueng,12120,TH,02-100-0008,,contact@riverpack.example,https://riverpack.example,referral,industrial,factory,sales.uat@example.com,Golden customer 8,true
ALLA,CUS-009,Summit Auto,end_customer,active,admin@example.com,eastern,SA,0105559000009,9 Auto Road,Chachoengsao,Bang Pakong,Bang Pakong,24130,TH,02-100-0009,,contact@summitauto.example,https://summitauto.example,event,industrial,factory,manager.uat@example.com,Golden customer 9,true
ALLA,CUS-010,Urban Developer,contractor,prospect,admin@example.com,head_office,UD,0105559000010,10 Tower Road,Bangkok,Pathum Wan,Lumphini,10330,TH,02-100-0010,,contact@urban.example,https://urban.example,website,industrial,factory,sales.uat@example.com,Golden customer 10,true
1 organization_code customer_code customer_name customer_type customer_status created_by_email branch_code abbr tax_id address province district sub_district postal_code country phone fax email website lead_channel customer_group customer_sub_group owner_user_email notes is_active
2 ALLA CUS-001 Siam Factory end_customer active admin@example.com head_office SF 0105559000001 1 Factory Road Bangkok Bang Kapi Hua Mak 10240 TH 02-100-0001 contact@siam.example https://siam.example website industrial factory sales.uat@example.com Golden customer 1 true
3 ALLA CUS-002 Metro Contractor contractor active admin@example.com eastern MC 0105559000002 2 Contractor Road Chonburi Mueang Saen Suk 20000 TH 02-100-0002 contact@metro.example https://metro.example referral industrial factory sales.uat@example.com Golden customer 2 true
4 ALLA CUS-003 North Design consultant prospect admin@example.com northern ND 0105559000003 3 Design Road Chiang Mai Mueang Suthep 50200 TH 02-100-0003 contact@north.example https://north.example event industrial factory manager.uat@example.com Golden customer 3 true
5 ALLA CUS-004 Eastern Steel end_customer active admin@example.com eastern ES 0105559000004 4 Steel Road Rayong Mueang Noen Phra 21000 TH 02-100-0004 contact@easternsteel.example https://easternsteel.example website industrial factory sales.uat@example.com Golden customer 4 true
6 ALLA CUS-005 Central Logistics end_customer active admin@example.com head_office CL 0105559000005 5 Logistics Road Bangkok Lat Krabang Lat Krabang 10520 TH 02-100-0005 contact@central-log.example https://central-log.example referral industrial factory sales.uat@example.com Golden customer 5 true
7 ALLA CUS-006 Harbor Engineering contractor prospect admin@example.com eastern HE 0105559000006 6 Harbor Road Chonburi Sriracha Sriracha 20110 TH 02-100-0006 contact@harbor.example https://harbor.example event industrial factory manager.uat@example.com Golden customer 6 true
8 ALLA CUS-007 Peak Foods end_customer active admin@example.com northern PF 0105559000007 7 Food Road Lamphun Mueang Nai Mueang 51000 TH 02-100-0007 contact@peakfoods.example https://peakfoods.example website industrial factory sales.uat@example.com Golden customer 7 true
9 ALLA CUS-008 River Packaging end_customer active admin@example.com head_office RP 0105559000008 8 Packaging Road Pathum Thani Khlong Luang Khlong Nueng 12120 TH 02-100-0008 contact@riverpack.example https://riverpack.example referral industrial factory sales.uat@example.com Golden customer 8 true
10 ALLA CUS-009 Summit Auto end_customer active admin@example.com eastern SA 0105559000009 9 Auto Road Chachoengsao Bang Pakong Bang Pakong 24130 TH 02-100-0009 contact@summitauto.example https://summitauto.example event industrial factory manager.uat@example.com Golden customer 9 true
11 ALLA CUS-010 Urban Developer contractor prospect admin@example.com head_office UD 0105559000010 10 Tower Road Bangkok Pathum Wan Lumphini 10330 TH 02-100-0010 contact@urban.example https://urban.example website industrial factory sales.uat@example.com Golden customer 10 true

View File

@@ -0,0 +1,55 @@
{
"name": "alla-os-setup-golden-dataset",
"version": "1.0.0",
"generatedFrom": "plans/task-d.7.10.md",
"templateRegistry": "setup/templates/templates.json",
"description": "Canonical ALLA OS setup dataset for development, CI contract checks, QA, UAT, demos, and regression testing.",
"organizations": ["ALLA", "ONVALLA"],
"counts": {
"organizations": 2,
"users": 5,
"customers": 10,
"contacts": 20,
"leads": 20,
"opportunities": 15,
"quotations": 20,
"branches": 3,
"productTypes": 3
},
"workflow": [
"migration",
"readiness",
"template_registry",
"preview",
"commit",
"verification",
"manifest",
"resume",
"reset"
],
"expectedQuotationStatuses": ["draft", "pending_approval", "approved", "rejected", "revision"],
"files": [
"users.csv",
"organizations.csv",
"memberships.csv",
"crm-role-assignments.csv",
"master-options.csv",
"branches.csv",
"product-types.csv",
"document-sequences.csv",
"approval-workflows.csv",
"approval-steps.csv",
"approval-matrix.csv",
"customers.csv",
"contacts.csv",
"contact-shares.csv",
"leads.csv",
"opportunities.csv",
"opportunity-parties.csv",
"quotations.csv",
"quotation-items.csv",
"quotation-parties.csv",
"quotation-topics.csv",
"quotation-topic-items.csv"
]
}

View File

@@ -0,0 +1,5 @@
organization_code,branch_code,product_type_code,document_type,prefix,period,current_number,padding_length,format,reset_policy,is_active
ALLA,head_office,crane,customer,CUS,yearly,0,4,{prefix}-{yyyy}-{running},yearly,true
ALLA,head_office,crane,lead,LD,yearly,0,4,{prefix}-{yyyy}-{running},yearly,true
ALLA,head_office,crane,opportunity,OP,yearly,0,4,{prefix}-{yyyy}-{running},yearly,true
ALLA,head_office,crane,quotation,QT-HO-CR,monthly,0,4,{prefix}-{yy}{MM}-{running},monthly,true
1 organization_code branch_code product_type_code document_type prefix period current_number padding_length format reset_policy is_active
2 ALLA head_office crane customer CUS yearly 0 4 {prefix}-{yyyy}-{running} yearly true
3 ALLA head_office crane lead LD yearly 0 4 {prefix}-{yyyy}-{running} yearly true
4 ALLA head_office crane opportunity OP yearly 0 4 {prefix}-{yyyy}-{running} yearly true
5 ALLA head_office crane quotation QT-HO-CR monthly 0 4 {prefix}-{yy}{MM}-{running} monthly true

View File

@@ -0,0 +1,21 @@
organization_code,lead_code,status,created_by_email,branch_code,customer_code,contact_email,description,project_name,project_location,lead_channel,product_type_code,priority,estimated_value,awareness_code,followup_status,lost_reason,outcome,owner_marketing_user_email,assigned_sales_owner_email,assignment_remark
ALLA,LD-001,new,mk.uat@example.com,head_office,CUS-001,anan@siam.example,Crane inquiry,Plant crane upgrade,Bangkok,website,crane,high,1200000,website,new,,,mk.uat@example.com,sales.uat@example.com,Assigned from golden dataset
ALLA,LD-002,contacted,mk.uat@example.com,eastern,CUS-002,chai@metro.example,Hoist inquiry,Warehouse hoist,Chonburi,referral,hoist,medium,450000,referral,contacted,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-003,new,mk.uat@example.com,northern,CUS-003,ekk@north.example,Service inquiry,Maintenance plan,Chiang Mai,event,service,medium,150000,event,new,,,mk.uat@example.com,manager.uat@example.com,Assigned
ALLA,LD-004,new,mk.uat@example.com,eastern,CUS-004,golf@easternsteel.example,Crane expansion,Steel bay crane,Rayong,website,crane,high,2200000,website,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-005,contacted,mk.uat@example.com,head_office,CUS-005,itt@central-log.example,Hoist replacement,Logistics hoist,Bangkok,referral,hoist,medium,600000,referral,contacted,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-006,new,mk.uat@example.com,eastern,CUS-006,kai@harbor.example,Project crane,Harbor yard,Chonburi,event,crane,high,3000000,event,new,,,mk.uat@example.com,manager.uat@example.com,Assigned
ALLA,LD-007,new,mk.uat@example.com,northern,CUS-007,mai@peakfoods.example,Food plant service,Service contract,Lamphun,website,service,low,120000,website,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-008,contacted,mk.uat@example.com,head_office,CUS-008,oat@riverpack.example,Packaging crane,Packaging line,Pathum Thani,referral,crane,medium,950000,referral,contacted,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-009,new,mk.uat@example.com,eastern,CUS-009,q@summitauto.example,Auto hoist,Assembly hoist,Chachoengsao,event,hoist,high,780000,event,new,,,mk.uat@example.com,manager.uat@example.com,Assigned
ALLA,LD-010,new,mk.uat@example.com,head_office,CUS-010,som@urban.example,Tower crane,Developer project,Bangkok,website,crane,high,4200000,website,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-011,new,mk.uat@example.com,head_office,CUS-001,ben@siam.example,Spare service,Siam service,Bangkok,referral,service,low,90000,referral,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-012,contacted,mk.uat@example.com,eastern,CUS-002,dara@metro.example,Contractor crane,Metro project,Chonburi,event,crane,medium,1300000,event,contacted,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-013,new,mk.uat@example.com,northern,CUS-003,fon@north.example,Design assist,North plant,Chiang Mai,website,hoist,medium,500000,website,new,,,mk.uat@example.com,manager.uat@example.com,Assigned
ALLA,LD-014,new,mk.uat@example.com,eastern,CUS-004,hana@easternsteel.example,Steel service,Rayong steel,Rayong,referral,service,low,110000,referral,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-015,contacted,mk.uat@example.com,head_office,CUS-005,jin@central-log.example,Warehouse crane,Central warehouse,Bangkok,event,crane,high,1800000,event,contacted,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-016,new,mk.uat@example.com,eastern,CUS-006,lek@harbor.example,Harbor hoist,Harbor support,Chonburi,website,hoist,medium,650000,website,new,,,mk.uat@example.com,manager.uat@example.com,Assigned
ALLA,LD-017,new,mk.uat@example.com,northern,CUS-007,nok@peakfoods.example,Maintenance hoist,Food maintenance,Lamphun,referral,hoist,low,250000,referral,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-018,contacted,mk.uat@example.com,head_office,CUS-008,pim@riverpack.example,Line upgrade,Packaging expansion,Pathum Thani,event,crane,medium,1400000,event,contacted,,,mk.uat@example.com,sales.uat@example.com,Assigned
ALLA,LD-019,new,mk.uat@example.com,eastern,CUS-009,rin@summitauto.example,Auto service,Summit service,Chachoengsao,website,service,low,160000,website,new,,,mk.uat@example.com,manager.uat@example.com,Assigned
ALLA,LD-020,new,mk.uat@example.com,head_office,CUS-010,tan@urban.example,Developer hoist,Tower support,Bangkok,referral,hoist,medium,820000,referral,new,,,mk.uat@example.com,sales.uat@example.com,Assigned
1 organization_code lead_code status created_by_email branch_code customer_code contact_email description project_name project_location lead_channel product_type_code priority estimated_value awareness_code followup_status lost_reason outcome owner_marketing_user_email assigned_sales_owner_email assignment_remark
2 ALLA LD-001 new mk.uat@example.com head_office CUS-001 anan@siam.example Crane inquiry Plant crane upgrade Bangkok website crane high 1200000 website new mk.uat@example.com sales.uat@example.com Assigned from golden dataset
3 ALLA LD-002 contacted mk.uat@example.com eastern CUS-002 chai@metro.example Hoist inquiry Warehouse hoist Chonburi referral hoist medium 450000 referral contacted mk.uat@example.com sales.uat@example.com Assigned
4 ALLA LD-003 new mk.uat@example.com northern CUS-003 ekk@north.example Service inquiry Maintenance plan Chiang Mai event service medium 150000 event new mk.uat@example.com manager.uat@example.com Assigned
5 ALLA LD-004 new mk.uat@example.com eastern CUS-004 golf@easternsteel.example Crane expansion Steel bay crane Rayong website crane high 2200000 website new mk.uat@example.com sales.uat@example.com Assigned
6 ALLA LD-005 contacted mk.uat@example.com head_office CUS-005 itt@central-log.example Hoist replacement Logistics hoist Bangkok referral hoist medium 600000 referral contacted mk.uat@example.com sales.uat@example.com Assigned
7 ALLA LD-006 new mk.uat@example.com eastern CUS-006 kai@harbor.example Project crane Harbor yard Chonburi event crane high 3000000 event new mk.uat@example.com manager.uat@example.com Assigned
8 ALLA LD-007 new mk.uat@example.com northern CUS-007 mai@peakfoods.example Food plant service Service contract Lamphun website service low 120000 website new mk.uat@example.com sales.uat@example.com Assigned
9 ALLA LD-008 contacted mk.uat@example.com head_office CUS-008 oat@riverpack.example Packaging crane Packaging line Pathum Thani referral crane medium 950000 referral contacted mk.uat@example.com sales.uat@example.com Assigned
10 ALLA LD-009 new mk.uat@example.com eastern CUS-009 q@summitauto.example Auto hoist Assembly hoist Chachoengsao event hoist high 780000 event new mk.uat@example.com manager.uat@example.com Assigned
11 ALLA LD-010 new mk.uat@example.com head_office CUS-010 som@urban.example Tower crane Developer project Bangkok website crane high 4200000 website new mk.uat@example.com sales.uat@example.com Assigned
12 ALLA LD-011 new mk.uat@example.com head_office CUS-001 ben@siam.example Spare service Siam service Bangkok referral service low 90000 referral new mk.uat@example.com sales.uat@example.com Assigned
13 ALLA LD-012 contacted mk.uat@example.com eastern CUS-002 dara@metro.example Contractor crane Metro project Chonburi event crane medium 1300000 event contacted mk.uat@example.com sales.uat@example.com Assigned
14 ALLA LD-013 new mk.uat@example.com northern CUS-003 fon@north.example Design assist North plant Chiang Mai website hoist medium 500000 website new mk.uat@example.com manager.uat@example.com Assigned
15 ALLA LD-014 new mk.uat@example.com eastern CUS-004 hana@easternsteel.example Steel service Rayong steel Rayong referral service low 110000 referral new mk.uat@example.com sales.uat@example.com Assigned
16 ALLA LD-015 contacted mk.uat@example.com head_office CUS-005 jin@central-log.example Warehouse crane Central warehouse Bangkok event crane high 1800000 event contacted mk.uat@example.com sales.uat@example.com Assigned
17 ALLA LD-016 new mk.uat@example.com eastern CUS-006 lek@harbor.example Harbor hoist Harbor support Chonburi website hoist medium 650000 website new mk.uat@example.com manager.uat@example.com Assigned
18 ALLA LD-017 new mk.uat@example.com northern CUS-007 nok@peakfoods.example Maintenance hoist Food maintenance Lamphun referral hoist low 250000 referral new mk.uat@example.com sales.uat@example.com Assigned
19 ALLA LD-018 contacted mk.uat@example.com head_office CUS-008 pim@riverpack.example Line upgrade Packaging expansion Pathum Thani event crane medium 1400000 event contacted mk.uat@example.com sales.uat@example.com Assigned
20 ALLA LD-019 new mk.uat@example.com eastern CUS-009 rin@summitauto.example Auto service Summit service Chachoengsao website service low 160000 website new mk.uat@example.com manager.uat@example.com Assigned
21 ALLA LD-020 new mk.uat@example.com head_office CUS-010 tan@urban.example Developer hoist Tower support Bangkok referral hoist medium 820000 referral new mk.uat@example.com sales.uat@example.com Assigned

View File

@@ -0,0 +1,21 @@
organization_code,category,code,label,value,parent_category,parent_code,sort_order,is_active,metadata_json
ALLA,crm_customer_type,end_customer,End Customer,,,,1,true,{}
ALLA,crm_customer_type,contractor,Contractor,,,,2,true,{}
ALLA,crm_customer_type,consultant,Consultant,,,,3,true,{}
ALLA,crm_customer_status,active,Active,,,,1,true,{}
ALLA,crm_customer_status,prospect,Prospect,,,,2,true,{}
ALLA,crm_lead_channel,website,Website,,,,1,true,{}
ALLA,crm_lead_channel,referral,Referral,,,,2,true,{}
ALLA,crm_lead_channel,event,Event,,,,3,true,{}
ALLA,crm_lead_priority,high,High,,,,1,true,{}
ALLA,crm_lead_priority,medium,Medium,,,,2,true,{}
ALLA,crm_lead_priority,low,Low,,,,3,true,{}
ALLA,crm_followup_status,new,New,,,,1,true,{}
ALLA,crm_followup_status,contacted,Contacted,,,,2,true,{}
ALLA,crm_lost_reason,budget,Budget mismatch,,,,1,true,{}
ALLA,crm_project_party_role,end_customer,End Customer,,,,1,true,{}
ALLA,crm_project_party_role,contractor,Contractor,,,,2,true,{}
ALLA,crm_project_party_role,consultant,Consultant,,,,3,true,{}
ALLA,crm_quotation_type,standard,Standard,,,,1,true,{}
ALLA,crm_customer_group,industrial,Industrial,,,,1,true,{}
ALLA,crm_customer_sub_group,factory,Factory,crm_customer_group,industrial,1,true,{}
1 organization_code category code label value parent_category parent_code sort_order is_active metadata_json
2 ALLA crm_customer_type end_customer End Customer 1 true {}
3 ALLA crm_customer_type contractor Contractor 2 true {}
4 ALLA crm_customer_type consultant Consultant 3 true {}
5 ALLA crm_customer_status active Active 1 true {}
6 ALLA crm_customer_status prospect Prospect 2 true {}
7 ALLA crm_lead_channel website Website 1 true {}
8 ALLA crm_lead_channel referral Referral 2 true {}
9 ALLA crm_lead_channel event Event 3 true {}
10 ALLA crm_lead_priority high High 1 true {}
11 ALLA crm_lead_priority medium Medium 2 true {}
12 ALLA crm_lead_priority low Low 3 true {}
13 ALLA crm_followup_status new New 1 true {}
14 ALLA crm_followup_status contacted Contacted 2 true {}
15 ALLA crm_lost_reason budget Budget mismatch 1 true {}
16 ALLA crm_project_party_role end_customer End Customer 1 true {}
17 ALLA crm_project_party_role contractor Contractor 2 true {}
18 ALLA crm_project_party_role consultant Consultant 3 true {}
19 ALLA crm_quotation_type standard Standard 1 true {}
20 ALLA crm_customer_group industrial Industrial 1 true {}
21 ALLA crm_customer_sub_group factory Factory crm_customer_group industrial 1 true {}

View File

@@ -0,0 +1,6 @@
organization_code,user_email,membership_role,business_role,permissions,branch_scope_codes,product_type_scope_codes
ALLA,admin@example.com,admin,sales_manager,crm.dashboard.read|crm.customer.read|crm.customer.create|crm.lead.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office|eastern|northern,crane|hoist|service
ALLA,mk.uat@example.com,user,marketing,crm.lead.read|crm.lead.create,head_office,crane|hoist
ALLA,sales.uat@example.com,user,sales,crm.customer.read|crm.opportunity.read|crm.quotation.read,head_office|eastern,crane|hoist
ALLA,manager.uat@example.com,user,sales_manager,crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read,head_office|eastern|northern,crane|hoist|service
ALLA,ceo.uat@example.com,user,executive,crm.dashboard.read|crm.approval.read,head_office|eastern|northern,crane|hoist|service
1 organization_code user_email membership_role business_role permissions branch_scope_codes product_type_scope_codes
2 ALLA admin@example.com admin sales_manager crm.dashboard.read|crm.customer.read|crm.customer.create|crm.lead.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office|eastern|northern crane|hoist|service
3 ALLA mk.uat@example.com user marketing crm.lead.read|crm.lead.create head_office crane|hoist
4 ALLA sales.uat@example.com user sales crm.customer.read|crm.opportunity.read|crm.quotation.read head_office|eastern crane|hoist
5 ALLA manager.uat@example.com user sales_manager crm.dashboard.read|crm.customer.read|crm.opportunity.read|crm.quotation.read|crm.approval.read head_office|eastern|northern crane|hoist|service
6 ALLA ceo.uat@example.com user executive crm.dashboard.read|crm.approval.read head_office|eastern|northern crane|hoist|service

View File

@@ -0,0 +1,16 @@
organization_code,opportunity_code,customer_code,title,product_type_code,status,priority,created_by_email,updated_by_email,lead_code,contact_email,branch_code,description,requirement,project_name,project_location,outcome_status,lead_channel,estimated_value,chance_percent,expected_close_date,competitor,source,notes,is_hot_project,pipeline_stage,assigned_to_user_email
ALLA,OP-001,CUS-001,Siam crane upgrade,crane,open,high,sales.uat@example.com,sales.uat@example.com,LD-001,anan@siam.example,head_office,Crane upgrade,10 ton crane,Plant crane upgrade,Bangkok,open,website,1200000,70,2026-08-15,Competitor A,website,Golden opportunity,true,proposal,sales.uat@example.com
ALLA,OP-002,CUS-002,Metro warehouse hoist,hoist,open,medium,sales.uat@example.com,sales.uat@example.com,LD-002,chai@metro.example,eastern,Warehouse hoist,5 ton hoist,Warehouse hoist,Chonburi,open,referral,450000,60,2026-08-20,Competitor B,referral,Golden opportunity,false,qualification,sales.uat@example.com
ALLA,OP-003,CUS-003,North service plan,service,open,medium,manager.uat@example.com,manager.uat@example.com,LD-003,ekk@north.example,northern,Service plan,Annual maintenance,Maintenance plan,Chiang Mai,open,event,150000,50,2026-09-01,,event,Golden opportunity,false,qualification,manager.uat@example.com
ALLA,OP-004,CUS-004,Eastern steel bay crane,crane,open,high,sales.uat@example.com,sales.uat@example.com,LD-004,golf@easternsteel.example,eastern,Steel bay crane,20 ton crane,Steel bay crane,Rayong,open,website,2200000,75,2026-09-10,Competitor C,website,Golden opportunity,true,proposal,sales.uat@example.com
ALLA,OP-005,CUS-005,Central logistics hoist,hoist,open,medium,sales.uat@example.com,sales.uat@example.com,LD-005,itt@central-log.example,head_office,Hoist replacement,Replacement hoist,Logistics hoist,Bangkok,open,referral,600000,65,2026-09-15,,referral,Golden opportunity,false,proposal,sales.uat@example.com
ALLA,OP-006,CUS-006,Harbor yard crane,crane,open,high,manager.uat@example.com,manager.uat@example.com,LD-006,kai@harbor.example,eastern,Harbor crane,Outdoor crane,Harbor yard,Chonburi,open,event,3000000,80,2026-10-01,Competitor D,event,Golden opportunity,true,proposal,manager.uat@example.com
ALLA,OP-007,CUS-007,Peak service contract,service,open,low,sales.uat@example.com,sales.uat@example.com,LD-007,mai@peakfoods.example,northern,Service contract,Annual contract,Food service,Lamphun,open,website,120000,40,2026-08-30,,website,Golden opportunity,false,qualification,sales.uat@example.com
ALLA,OP-008,CUS-008,River packaging crane,crane,open,medium,sales.uat@example.com,sales.uat@example.com,LD-008,oat@riverpack.example,head_office,Packaging crane,Line crane,Packaging line,Pathum Thani,open,referral,950000,55,2026-09-20,Competitor E,referral,Golden opportunity,false,proposal,sales.uat@example.com
ALLA,OP-009,CUS-009,Summit auto hoist,hoist,open,high,manager.uat@example.com,manager.uat@example.com,LD-009,q@summitauto.example,eastern,Auto hoist,Assembly hoist,Assembly hoist,Chachoengsao,open,event,780000,60,2026-09-25,,event,Golden opportunity,false,proposal,manager.uat@example.com
ALLA,OP-010,CUS-010,Urban tower crane,crane,open,high,sales.uat@example.com,sales.uat@example.com,LD-010,som@urban.example,head_office,Tower crane,Tower project,Developer project,Bangkok,open,website,4200000,70,2026-10-10,Competitor F,website,Golden opportunity,true,proposal,sales.uat@example.com
ALLA,OP-011,CUS-001,Siam spare service,service,open,low,sales.uat@example.com,sales.uat@example.com,LD-011,ben@siam.example,head_office,Spare service,Service package,Siam service,Bangkok,open,referral,90000,45,2026-08-28,,referral,Golden opportunity,false,qualification,sales.uat@example.com
ALLA,OP-012,CUS-002,Metro contractor crane,crane,open,medium,sales.uat@example.com,sales.uat@example.com,LD-012,dara@metro.example,eastern,Contractor crane,Site crane,Metro project,Chonburi,open,event,1300000,55,2026-09-18,Competitor G,event,Golden opportunity,false,proposal,sales.uat@example.com
ALLA,OP-013,CUS-003,North design hoist,hoist,open,medium,manager.uat@example.com,manager.uat@example.com,LD-013,fon@north.example,northern,Design hoist,Hoist plan,North plant,Chiang Mai,open,website,500000,50,2026-09-12,,website,Golden opportunity,false,qualification,manager.uat@example.com
ALLA,OP-014,CUS-004,Eastern steel service,service,open,low,sales.uat@example.com,sales.uat@example.com,LD-014,hana@easternsteel.example,eastern,Steel service,Service visit,Rayong steel,Rayong,open,referral,110000,45,2026-08-26,,referral,Golden opportunity,false,qualification,sales.uat@example.com
ALLA,OP-015,CUS-005,Central warehouse crane,crane,open,high,sales.uat@example.com,sales.uat@example.com,LD-015,jin@central-log.example,head_office,Warehouse crane,Warehouse crane,Central warehouse,Bangkok,open,event,1800000,65,2026-09-30,Competitor H,event,Golden opportunity,true,proposal,sales.uat@example.com
1 organization_code opportunity_code customer_code title product_type_code status priority created_by_email updated_by_email lead_code contact_email branch_code description requirement project_name project_location outcome_status lead_channel estimated_value chance_percent expected_close_date competitor source notes is_hot_project pipeline_stage assigned_to_user_email
2 ALLA OP-001 CUS-001 Siam crane upgrade crane open high sales.uat@example.com sales.uat@example.com LD-001 anan@siam.example head_office Crane upgrade 10 ton crane Plant crane upgrade Bangkok open website 1200000 70 2026-08-15 Competitor A website Golden opportunity true proposal sales.uat@example.com
3 ALLA OP-002 CUS-002 Metro warehouse hoist hoist open medium sales.uat@example.com sales.uat@example.com LD-002 chai@metro.example eastern Warehouse hoist 5 ton hoist Warehouse hoist Chonburi open referral 450000 60 2026-08-20 Competitor B referral Golden opportunity false qualification sales.uat@example.com
4 ALLA OP-003 CUS-003 North service plan service open medium manager.uat@example.com manager.uat@example.com LD-003 ekk@north.example northern Service plan Annual maintenance Maintenance plan Chiang Mai open event 150000 50 2026-09-01 event Golden opportunity false qualification manager.uat@example.com
5 ALLA OP-004 CUS-004 Eastern steel bay crane crane open high sales.uat@example.com sales.uat@example.com LD-004 golf@easternsteel.example eastern Steel bay crane 20 ton crane Steel bay crane Rayong open website 2200000 75 2026-09-10 Competitor C website Golden opportunity true proposal sales.uat@example.com
6 ALLA OP-005 CUS-005 Central logistics hoist hoist open medium sales.uat@example.com sales.uat@example.com LD-005 itt@central-log.example head_office Hoist replacement Replacement hoist Logistics hoist Bangkok open referral 600000 65 2026-09-15 referral Golden opportunity false proposal sales.uat@example.com
7 ALLA OP-006 CUS-006 Harbor yard crane crane open high manager.uat@example.com manager.uat@example.com LD-006 kai@harbor.example eastern Harbor crane Outdoor crane Harbor yard Chonburi open event 3000000 80 2026-10-01 Competitor D event Golden opportunity true proposal manager.uat@example.com
8 ALLA OP-007 CUS-007 Peak service contract service open low sales.uat@example.com sales.uat@example.com LD-007 mai@peakfoods.example northern Service contract Annual contract Food service Lamphun open website 120000 40 2026-08-30 website Golden opportunity false qualification sales.uat@example.com
9 ALLA OP-008 CUS-008 River packaging crane crane open medium sales.uat@example.com sales.uat@example.com LD-008 oat@riverpack.example head_office Packaging crane Line crane Packaging line Pathum Thani open referral 950000 55 2026-09-20 Competitor E referral Golden opportunity false proposal sales.uat@example.com
10 ALLA OP-009 CUS-009 Summit auto hoist hoist open high manager.uat@example.com manager.uat@example.com LD-009 q@summitauto.example eastern Auto hoist Assembly hoist Assembly hoist Chachoengsao open event 780000 60 2026-09-25 event Golden opportunity false proposal manager.uat@example.com
11 ALLA OP-010 CUS-010 Urban tower crane crane open high sales.uat@example.com sales.uat@example.com LD-010 som@urban.example head_office Tower crane Tower project Developer project Bangkok open website 4200000 70 2026-10-10 Competitor F website Golden opportunity true proposal sales.uat@example.com
12 ALLA OP-011 CUS-001 Siam spare service service open low sales.uat@example.com sales.uat@example.com LD-011 ben@siam.example head_office Spare service Service package Siam service Bangkok open referral 90000 45 2026-08-28 referral Golden opportunity false qualification sales.uat@example.com
13 ALLA OP-012 CUS-002 Metro contractor crane crane open medium sales.uat@example.com sales.uat@example.com LD-012 dara@metro.example eastern Contractor crane Site crane Metro project Chonburi open event 1300000 55 2026-09-18 Competitor G event Golden opportunity false proposal sales.uat@example.com
14 ALLA OP-013 CUS-003 North design hoist hoist open medium manager.uat@example.com manager.uat@example.com LD-013 fon@north.example northern Design hoist Hoist plan North plant Chiang Mai open website 500000 50 2026-09-12 website Golden opportunity false qualification manager.uat@example.com
15 ALLA OP-014 CUS-004 Eastern steel service service open low sales.uat@example.com sales.uat@example.com LD-014 hana@easternsteel.example eastern Steel service Service visit Rayong steel Rayong open referral 110000 45 2026-08-26 referral Golden opportunity false qualification sales.uat@example.com
16 ALLA OP-015 CUS-005 Central warehouse crane crane open high sales.uat@example.com sales.uat@example.com LD-015 jin@central-log.example head_office Warehouse crane Warehouse crane Central warehouse Bangkok open event 1800000 65 2026-09-30 Competitor H event Golden opportunity true proposal sales.uat@example.com

View File

@@ -0,0 +1,16 @@
organization_code,opportunity_code,customer_code,role_code,remark
ALLA,OP-001,CUS-001,end_customer,End customer
ALLA,OP-002,CUS-002,contractor,Contractor
ALLA,OP-003,CUS-003,consultant,Consultant
ALLA,OP-004,CUS-004,end_customer,End customer
ALLA,OP-005,CUS-005,end_customer,End customer
ALLA,OP-006,CUS-006,contractor,Contractor
ALLA,OP-007,CUS-007,end_customer,End customer
ALLA,OP-008,CUS-008,end_customer,End customer
ALLA,OP-009,CUS-009,end_customer,End customer
ALLA,OP-010,CUS-010,contractor,Contractor
ALLA,OP-011,CUS-001,end_customer,End customer
ALLA,OP-012,CUS-002,contractor,Contractor
ALLA,OP-013,CUS-003,consultant,Consultant
ALLA,OP-014,CUS-004,end_customer,End customer
ALLA,OP-015,CUS-005,end_customer,End customer
1 organization_code opportunity_code customer_code role_code remark
2 ALLA OP-001 CUS-001 end_customer End customer
3 ALLA OP-002 CUS-002 contractor Contractor
4 ALLA OP-003 CUS-003 consultant Consultant
5 ALLA OP-004 CUS-004 end_customer End customer
6 ALLA OP-005 CUS-005 end_customer End customer
7 ALLA OP-006 CUS-006 contractor Contractor
8 ALLA OP-007 CUS-007 end_customer End customer
9 ALLA OP-008 CUS-008 end_customer End customer
10 ALLA OP-009 CUS-009 end_customer End customer
11 ALLA OP-010 CUS-010 contractor Contractor
12 ALLA OP-011 CUS-001 end_customer End customer
13 ALLA OP-012 CUS-002 contractor Contractor
14 ALLA OP-013 CUS-003 consultant Consultant
15 ALLA OP-014 CUS-004 end_customer End customer
16 ALLA OP-015 CUS-005 end_customer End customer

View File

@@ -0,0 +1,3 @@
organization_code,organization_name,slug,created_by_email,tax_id,default_currency,phone,email,address,logo_url,plan,status
ALLA,ALLA Company Limited,alla,admin@example.com,0107558000393,THB,02-000-0000,admin@alla.example,99/9 Rama IX Road Bangkok,,enterprise,active
ONVALLA,ONVALLA Demo Company,onvalla,admin@example.com,0107558000401,THB,02-000-0099,admin@onvalla.example,88/8 Demo Road Bangkok,,demo,active
1 organization_code organization_name slug created_by_email tax_id default_currency phone email address logo_url plan status
2 ALLA ALLA Company Limited alla admin@example.com 0107558000393 THB 02-000-0000 admin@alla.example 99/9 Rama IX Road Bangkok enterprise active
3 ONVALLA ONVALLA Demo Company onvalla admin@example.com 0107558000401 THB 02-000-0099 admin@onvalla.example 88/8 Demo Road Bangkok demo active

View File

@@ -0,0 +1,4 @@
organization_code,product_type_code,product_type_name,document_prefix,sort_order,is_active,metadata_json
ALLA,crane,Crane,CR,1,true,{}
ALLA,hoist,Hoist,HO,2,true,{}
ALLA,service,Service,SV,3,true,{}
1 organization_code product_type_code product_type_name document_prefix sort_order is_active metadata_json
2 ALLA crane Crane CR 1 true {}
3 ALLA hoist Hoist HO 2 true {}
4 ALLA service Service SV 3 true {}

View File

@@ -0,0 +1,21 @@
organization_code,quotation_code,item_number,product_type_code,description,quantity,unit_price,total_price,unit,discount,discount_type,tax_rate,notes,sort_order
ALLA,QT-HO-CR-2607-001,1,crane,Crane system package,1,1000000,1000000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-002,1,hoist,Hoist system package,1,450000,450000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-003,1,service,Service package,1,150000,150000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-004,1,crane,Steel bay crane package,1,2200000,2200000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-005,1,hoist,Logistics hoist package,1,600000,600000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-006,1,crane,Harbor crane package,1,3000000,3000000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-007,1,service,Annual service package,1,120000,120000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-008,1,crane,Packaging crane package,1,950000,950000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-009,1,hoist,Auto hoist package,1,780000,780000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-010,1,crane,Tower crane package,1,4200000,4200000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-011,1,service,Spare service package,1,90000,90000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-012,1,crane,Contractor crane package,1,1300000,1300000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-013,1,hoist,Design hoist package,1,500000,500000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-014,1,service,Steel service package,1,110000,110000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-015,1,crane,Warehouse crane package,1,1800000,1800000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-016,1,hoist,Harbor hoist support,1,650000,650000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-017,1,hoist,Maintenance hoist package,1,250000,250000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-018,1,crane,Line upgrade package,1,1400000,1400000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-019,1,service,Auto service package,1,160000,160000,set,0,amount,7,Golden item,1
ALLA,QT-HO-CR-2607-020,1,hoist,Developer hoist package,1,820000,820000,set,0,amount,7,Golden item,1
1 organization_code quotation_code item_number product_type_code description quantity unit_price total_price unit discount discount_type tax_rate notes sort_order
2 ALLA QT-HO-CR-2607-001 1 crane Crane system package 1 1000000 1000000 set 0 amount 7 Golden item 1
3 ALLA QT-HO-CR-2607-002 1 hoist Hoist system package 1 450000 450000 set 0 amount 7 Golden item 1
4 ALLA QT-HO-CR-2607-003 1 service Service package 1 150000 150000 set 0 amount 7 Golden item 1
5 ALLA QT-HO-CR-2607-004 1 crane Steel bay crane package 1 2200000 2200000 set 0 amount 7 Golden item 1
6 ALLA QT-HO-CR-2607-005 1 hoist Logistics hoist package 1 600000 600000 set 0 amount 7 Golden item 1
7 ALLA QT-HO-CR-2607-006 1 crane Harbor crane package 1 3000000 3000000 set 0 amount 7 Golden item 1
8 ALLA QT-HO-CR-2607-007 1 service Annual service package 1 120000 120000 set 0 amount 7 Golden item 1
9 ALLA QT-HO-CR-2607-008 1 crane Packaging crane package 1 950000 950000 set 0 amount 7 Golden item 1
10 ALLA QT-HO-CR-2607-009 1 hoist Auto hoist package 1 780000 780000 set 0 amount 7 Golden item 1
11 ALLA QT-HO-CR-2607-010 1 crane Tower crane package 1 4200000 4200000 set 0 amount 7 Golden item 1
12 ALLA QT-HO-CR-2607-011 1 service Spare service package 1 90000 90000 set 0 amount 7 Golden item 1
13 ALLA QT-HO-CR-2607-012 1 crane Contractor crane package 1 1300000 1300000 set 0 amount 7 Golden item 1
14 ALLA QT-HO-CR-2607-013 1 hoist Design hoist package 1 500000 500000 set 0 amount 7 Golden item 1
15 ALLA QT-HO-CR-2607-014 1 service Steel service package 1 110000 110000 set 0 amount 7 Golden item 1
16 ALLA QT-HO-CR-2607-015 1 crane Warehouse crane package 1 1800000 1800000 set 0 amount 7 Golden item 1
17 ALLA QT-HO-CR-2607-016 1 hoist Harbor hoist support 1 650000 650000 set 0 amount 7 Golden item 1
18 ALLA QT-HO-CR-2607-017 1 hoist Maintenance hoist package 1 250000 250000 set 0 amount 7 Golden item 1
19 ALLA QT-HO-CR-2607-018 1 crane Line upgrade package 1 1400000 1400000 set 0 amount 7 Golden item 1
20 ALLA QT-HO-CR-2607-019 1 service Auto service package 1 160000 160000 set 0 amount 7 Golden item 1
21 ALLA QT-HO-CR-2607-020 1 hoist Developer hoist package 1 820000 820000 set 0 amount 7 Golden item 1

View File

@@ -0,0 +1,21 @@
organization_code,quotation_code,customer_code,role_code,is_primary,remark
ALLA,QT-HO-CR-2607-001,CUS-001,end_customer,true,End customer
ALLA,QT-HO-CR-2607-002,CUS-002,contractor,true,Contractor
ALLA,QT-HO-CR-2607-003,CUS-003,consultant,true,Consultant
ALLA,QT-HO-CR-2607-004,CUS-004,end_customer,true,End customer
ALLA,QT-HO-CR-2607-005,CUS-005,end_customer,true,End customer
ALLA,QT-HO-CR-2607-006,CUS-006,contractor,true,Contractor
ALLA,QT-HO-CR-2607-007,CUS-007,end_customer,true,End customer
ALLA,QT-HO-CR-2607-008,CUS-008,end_customer,true,End customer
ALLA,QT-HO-CR-2607-009,CUS-009,end_customer,true,End customer
ALLA,QT-HO-CR-2607-010,CUS-010,contractor,true,Contractor
ALLA,QT-HO-CR-2607-011,CUS-001,end_customer,true,End customer
ALLA,QT-HO-CR-2607-012,CUS-002,contractor,true,Contractor
ALLA,QT-HO-CR-2607-013,CUS-003,consultant,true,Consultant
ALLA,QT-HO-CR-2607-014,CUS-004,end_customer,true,End customer
ALLA,QT-HO-CR-2607-015,CUS-005,end_customer,true,End customer
ALLA,QT-HO-CR-2607-016,CUS-006,contractor,true,Contractor
ALLA,QT-HO-CR-2607-017,CUS-007,end_customer,true,End customer
ALLA,QT-HO-CR-2607-018,CUS-008,end_customer,true,End customer
ALLA,QT-HO-CR-2607-019,CUS-009,end_customer,true,End customer
ALLA,QT-HO-CR-2607-020,CUS-010,contractor,true,Contractor
1 organization_code quotation_code customer_code role_code is_primary remark
2 ALLA QT-HO-CR-2607-001 CUS-001 end_customer true End customer
3 ALLA QT-HO-CR-2607-002 CUS-002 contractor true Contractor
4 ALLA QT-HO-CR-2607-003 CUS-003 consultant true Consultant
5 ALLA QT-HO-CR-2607-004 CUS-004 end_customer true End customer
6 ALLA QT-HO-CR-2607-005 CUS-005 end_customer true End customer
7 ALLA QT-HO-CR-2607-006 CUS-006 contractor true Contractor
8 ALLA QT-HO-CR-2607-007 CUS-007 end_customer true End customer
9 ALLA QT-HO-CR-2607-008 CUS-008 end_customer true End customer
10 ALLA QT-HO-CR-2607-009 CUS-009 end_customer true End customer
11 ALLA QT-HO-CR-2607-010 CUS-010 contractor true Contractor
12 ALLA QT-HO-CR-2607-011 CUS-001 end_customer true End customer
13 ALLA QT-HO-CR-2607-012 CUS-002 contractor true Contractor
14 ALLA QT-HO-CR-2607-013 CUS-003 consultant true Consultant
15 ALLA QT-HO-CR-2607-014 CUS-004 end_customer true End customer
16 ALLA QT-HO-CR-2607-015 CUS-005 end_customer true End customer
17 ALLA QT-HO-CR-2607-016 CUS-006 contractor true Contractor
18 ALLA QT-HO-CR-2607-017 CUS-007 end_customer true End customer
19 ALLA QT-HO-CR-2607-018 CUS-008 end_customer true End customer
20 ALLA QT-HO-CR-2607-019 CUS-009 end_customer true End customer
21 ALLA QT-HO-CR-2607-020 CUS-010 contractor true Contractor

View File

@@ -0,0 +1,21 @@
organization_code,quotation_code,topic_key,content,sort_order
ALLA,QT-HO-CR-2607-001,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-002,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-003,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-004,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-005,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-006,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-007,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-008,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-009,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-010,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-011,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-012,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-013,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-014,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-015,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-016,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-017,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-018,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-019,scope,Supply and installation according to golden dataset scope.,1
ALLA,QT-HO-CR-2607-020,scope,Supply and installation according to golden dataset scope.,1
1 organization_code quotation_code topic_key content sort_order
2 ALLA QT-HO-CR-2607-001 scope Supply and installation according to golden dataset scope. 1
3 ALLA QT-HO-CR-2607-002 scope Supply and installation according to golden dataset scope. 1
4 ALLA QT-HO-CR-2607-003 scope Supply and installation according to golden dataset scope. 1
5 ALLA QT-HO-CR-2607-004 scope Supply and installation according to golden dataset scope. 1
6 ALLA QT-HO-CR-2607-005 scope Supply and installation according to golden dataset scope. 1
7 ALLA QT-HO-CR-2607-006 scope Supply and installation according to golden dataset scope. 1
8 ALLA QT-HO-CR-2607-007 scope Supply and installation according to golden dataset scope. 1
9 ALLA QT-HO-CR-2607-008 scope Supply and installation according to golden dataset scope. 1
10 ALLA QT-HO-CR-2607-009 scope Supply and installation according to golden dataset scope. 1
11 ALLA QT-HO-CR-2607-010 scope Supply and installation according to golden dataset scope. 1
12 ALLA QT-HO-CR-2607-011 scope Supply and installation according to golden dataset scope. 1
13 ALLA QT-HO-CR-2607-012 scope Supply and installation according to golden dataset scope. 1
14 ALLA QT-HO-CR-2607-013 scope Supply and installation according to golden dataset scope. 1
15 ALLA QT-HO-CR-2607-014 scope Supply and installation according to golden dataset scope. 1
16 ALLA QT-HO-CR-2607-015 scope Supply and installation according to golden dataset scope. 1
17 ALLA QT-HO-CR-2607-016 scope Supply and installation according to golden dataset scope. 1
18 ALLA QT-HO-CR-2607-017 scope Supply and installation according to golden dataset scope. 1
19 ALLA QT-HO-CR-2607-018 scope Supply and installation according to golden dataset scope. 1
20 ALLA QT-HO-CR-2607-019 scope Supply and installation according to golden dataset scope. 1
21 ALLA QT-HO-CR-2607-020 scope Supply and installation according to golden dataset scope. 1

View File

@@ -0,0 +1,21 @@
organization_code,quotation_code,topic_key,topic_type,title,sort_order
ALLA,QT-HO-CR-2607-001,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-002,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-003,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-004,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-005,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-006,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-007,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-008,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-009,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-010,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-011,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-012,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-013,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-014,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-015,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-016,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-017,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-018,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-019,scope,terms,Scope of Supply,1
ALLA,QT-HO-CR-2607-020,scope,terms,Scope of Supply,1
1 organization_code quotation_code topic_key topic_type title sort_order
2 ALLA QT-HO-CR-2607-001 scope terms Scope of Supply 1
3 ALLA QT-HO-CR-2607-002 scope terms Scope of Supply 1
4 ALLA QT-HO-CR-2607-003 scope terms Scope of Supply 1
5 ALLA QT-HO-CR-2607-004 scope terms Scope of Supply 1
6 ALLA QT-HO-CR-2607-005 scope terms Scope of Supply 1
7 ALLA QT-HO-CR-2607-006 scope terms Scope of Supply 1
8 ALLA QT-HO-CR-2607-007 scope terms Scope of Supply 1
9 ALLA QT-HO-CR-2607-008 scope terms Scope of Supply 1
10 ALLA QT-HO-CR-2607-009 scope terms Scope of Supply 1
11 ALLA QT-HO-CR-2607-010 scope terms Scope of Supply 1
12 ALLA QT-HO-CR-2607-011 scope terms Scope of Supply 1
13 ALLA QT-HO-CR-2607-012 scope terms Scope of Supply 1
14 ALLA QT-HO-CR-2607-013 scope terms Scope of Supply 1
15 ALLA QT-HO-CR-2607-014 scope terms Scope of Supply 1
16 ALLA QT-HO-CR-2607-015 scope terms Scope of Supply 1
17 ALLA QT-HO-CR-2607-016 scope terms Scope of Supply 1
18 ALLA QT-HO-CR-2607-017 scope terms Scope of Supply 1
19 ALLA QT-HO-CR-2607-018 scope terms Scope of Supply 1
20 ALLA QT-HO-CR-2607-019 scope terms Scope of Supply 1
21 ALLA QT-HO-CR-2607-020 scope terms Scope of Supply 1

View File

@@ -0,0 +1,21 @@
organization_code,quotation_code,customer_code,quotation_date,quotation_type,status,currency,subtotal,total_amount,created_by_email,updated_by_email,opportunity_code,contact_email,branch_code,valid_until,project_name,project_location,attention,reference,notes,revision,parent_quotation_code,revision_remark,exchange_rate,discount,discount_type,tax_rate,tax_amount,chance_percent,is_hot_project,competitor,salesman_email,is_sent,sent_at,sent_via
ALLA,QT-HO-CR-2607-001,CUS-001,2026-07-01,standard,draft,THB,1000000,1070000,sales.uat@example.com,sales.uat@example.com,OP-001,anan@siam.example,head_office,2026-08-01,Plant crane upgrade,Bangkok,Anan Sales,REF-001,Golden quotation,0,,,1,0,amount,7,70000,70,true,Competitor A,sales.uat@example.com,false,,
ALLA,QT-HO-CR-2607-002,CUS-002,2026-07-02,standard,pending_approval,THB,450000,481500,sales.uat@example.com,sales.uat@example.com,OP-002,chai@metro.example,eastern,2026-08-02,Warehouse hoist,Chonburi,Chai Manager,REF-002,Golden quotation,0,,,1,0,amount,7,31500,60,false,Competitor B,sales.uat@example.com,true,2026-07-03,email
ALLA,QT-HO-CR-2607-003,CUS-003,2026-07-03,standard,approved,THB,150000,160500,manager.uat@example.com,manager.uat@example.com,OP-003,ekk@north.example,northern,2026-08-03,Maintenance plan,Chiang Mai,Ekk Designer,REF-003,Golden quotation,0,,,1,0,amount,7,10500,50,false,,manager.uat@example.com,true,2026-07-04,email
ALLA,QT-HO-CR-2607-004,CUS-004,2026-07-04,standard,rejected,THB,2200000,2354000,sales.uat@example.com,sales.uat@example.com,OP-004,golf@easternsteel.example,eastern,2026-08-04,Steel bay crane,Rayong,Golf Ops,REF-004,Golden quotation,0,,,1,0,amount,7,154000,75,true,Competitor C,sales.uat@example.com,true,2026-07-05,email
ALLA,QT-HO-CR-2607-005,CUS-005,2026-07-05,standard,revision,THB,600000,642000,sales.uat@example.com,sales.uat@example.com,OP-005,itt@central-log.example,head_office,2026-08-05,Logistics hoist,Bangkok,Itt Logistics,REF-005,Golden quotation,1,QT-HO-CR-2607-002,Revised scope,1,0,amount,7,42000,65,false,,sales.uat@example.com,true,2026-07-06,email
ALLA,QT-HO-CR-2607-006,CUS-006,2026-07-06,standard,draft,THB,3000000,3210000,manager.uat@example.com,manager.uat@example.com,OP-006,kai@harbor.example,eastern,2026-08-06,Harbor yard,Chonburi,Kai Site,REF-006,Golden quotation,0,,,1,0,amount,7,210000,80,true,Competitor D,manager.uat@example.com,false,,
ALLA,QT-HO-CR-2607-007,CUS-007,2026-07-07,standard,pending_approval,THB,120000,128400,sales.uat@example.com,sales.uat@example.com,OP-007,mai@peakfoods.example,northern,2026-08-07,Food service,Lamphun,Mai Plant,REF-007,Golden quotation,0,,,1,0,amount,7,8400,40,false,,sales.uat@example.com,true,2026-07-08,email
ALLA,QT-HO-CR-2607-008,CUS-008,2026-07-08,standard,approved,THB,950000,1016500,sales.uat@example.com,sales.uat@example.com,OP-008,oat@riverpack.example,head_office,2026-08-08,Packaging line,Pathum Thani,Oat Packaging,REF-008,Golden quotation,0,,,1,0,amount,7,66500,55,false,Competitor E,sales.uat@example.com,true,2026-07-09,email
ALLA,QT-HO-CR-2607-009,CUS-009,2026-07-09,standard,rejected,THB,780000,834600,manager.uat@example.com,manager.uat@example.com,OP-009,q@summitauto.example,eastern,2026-08-09,Assembly hoist,Chachoengsao,Q Auto,REF-009,Golden quotation,0,,,1,0,amount,7,54600,60,false,,manager.uat@example.com,true,2026-07-10,email
ALLA,QT-HO-CR-2607-010,CUS-010,2026-07-10,standard,revision,THB,4200000,4494000,sales.uat@example.com,sales.uat@example.com,OP-010,som@urban.example,head_office,2026-08-10,Developer project,Bangkok,Som Developer,REF-010,Golden quotation,1,QT-HO-CR-2607-001,Revision 1,1,0,amount,7,294000,70,true,Competitor F,sales.uat@example.com,true,2026-07-11,email
ALLA,QT-HO-CR-2607-011,CUS-001,2026-07-11,standard,draft,THB,90000,96300,sales.uat@example.com,sales.uat@example.com,OP-011,ben@siam.example,head_office,2026-08-11,Siam service,Bangkok,Ben Engineer,REF-011,Golden quotation,0,,,1,0,amount,7,6300,45,false,,sales.uat@example.com,false,,
ALLA,QT-HO-CR-2607-012,CUS-002,2026-07-12,standard,pending_approval,THB,1300000,1391000,sales.uat@example.com,sales.uat@example.com,OP-012,dara@metro.example,eastern,2026-08-12,Metro project,Chonburi,Dara QS,REF-012,Golden quotation,0,,,1,0,amount,7,91000,55,false,Competitor G,sales.uat@example.com,true,2026-07-13,email
ALLA,QT-HO-CR-2607-013,CUS-003,2026-07-13,standard,approved,THB,500000,535000,manager.uat@example.com,manager.uat@example.com,OP-013,fon@north.example,northern,2026-08-13,North plant,Chiang Mai,Fon Architect,REF-013,Golden quotation,0,,,1,0,amount,7,35000,50,false,,manager.uat@example.com,true,2026-07-14,email
ALLA,QT-HO-CR-2607-014,CUS-004,2026-07-14,standard,rejected,THB,110000,117700,sales.uat@example.com,sales.uat@example.com,OP-014,hana@easternsteel.example,eastern,2026-08-14,Rayong steel,Rayong,Hana Buyer,REF-014,Golden quotation,0,,,1,0,amount,7,7700,45,false,,sales.uat@example.com,true,2026-07-15,email
ALLA,QT-HO-CR-2607-015,CUS-005,2026-07-15,standard,revision,THB,1800000,1926000,sales.uat@example.com,sales.uat@example.com,OP-015,jin@central-log.example,head_office,2026-08-15,Central warehouse,Bangkok,Jin Warehouse,REF-015,Golden quotation,1,QT-HO-CR-2607-012,Revision 1,1,0,amount,7,126000,65,true,Competitor H,sales.uat@example.com,true,2026-07-16,email
ALLA,QT-HO-CR-2607-016,CUS-006,2026-07-16,standard,draft,THB,650000,695500,manager.uat@example.com,manager.uat@example.com,OP-006,lek@harbor.example,eastern,2026-08-16,Harbor support,Chonburi,Lek Admin,REF-016,Golden quotation,0,,,1,0,amount,7,45500,50,false,,manager.uat@example.com,false,,
ALLA,QT-HO-CR-2607-017,CUS-007,2026-07-17,standard,pending_approval,THB,250000,267500,sales.uat@example.com,sales.uat@example.com,OP-007,nok@peakfoods.example,northern,2026-08-17,Food maintenance,Lamphun,Nok Maintenance,REF-017,Golden quotation,0,,,1,0,amount,7,17500,40,false,,sales.uat@example.com,true,2026-07-18,email
ALLA,QT-HO-CR-2607-018,CUS-008,2026-07-18,standard,approved,THB,1400000,1498000,sales.uat@example.com,sales.uat@example.com,OP-008,pim@riverpack.example,head_office,2026-08-18,Packaging expansion,Pathum Thani,Pim Buyer,REF-018,Golden quotation,0,,,1,0,amount,7,98000,55,false,,sales.uat@example.com,true,2026-07-19,email
ALLA,QT-HO-CR-2607-019,CUS-009,2026-07-19,standard,rejected,THB,160000,171200,manager.uat@example.com,manager.uat@example.com,OP-009,rin@summitauto.example,eastern,2026-08-19,Summit service,Chachoengsao,Rin Engineer,REF-019,Golden quotation,0,,,1,0,amount,7,11200,35,false,,manager.uat@example.com,true,2026-07-20,email
ALLA,QT-HO-CR-2607-020,CUS-010,2026-07-20,standard,revision,THB,820000,877400,sales.uat@example.com,sales.uat@example.com,OP-010,tan@urban.example,head_office,2026-08-20,Tower support,Bangkok,Tan Project,REF-020,Golden quotation,1,QT-HO-CR-2607-017,Revision 1,1,0,amount,7,57400,50,false,,sales.uat@example.com,true,2026-07-21,email
1 organization_code quotation_code customer_code quotation_date quotation_type status currency subtotal total_amount created_by_email updated_by_email opportunity_code contact_email branch_code valid_until project_name project_location attention reference notes revision parent_quotation_code revision_remark exchange_rate discount discount_type tax_rate tax_amount chance_percent is_hot_project competitor salesman_email is_sent sent_at sent_via
2 ALLA QT-HO-CR-2607-001 CUS-001 2026-07-01 standard draft THB 1000000 1070000 sales.uat@example.com sales.uat@example.com OP-001 anan@siam.example head_office 2026-08-01 Plant crane upgrade Bangkok Anan Sales REF-001 Golden quotation 0 1 0 amount 7 70000 70 true Competitor A sales.uat@example.com false
3 ALLA QT-HO-CR-2607-002 CUS-002 2026-07-02 standard pending_approval THB 450000 481500 sales.uat@example.com sales.uat@example.com OP-002 chai@metro.example eastern 2026-08-02 Warehouse hoist Chonburi Chai Manager REF-002 Golden quotation 0 1 0 amount 7 31500 60 false Competitor B sales.uat@example.com true 2026-07-03 email
4 ALLA QT-HO-CR-2607-003 CUS-003 2026-07-03 standard approved THB 150000 160500 manager.uat@example.com manager.uat@example.com OP-003 ekk@north.example northern 2026-08-03 Maintenance plan Chiang Mai Ekk Designer REF-003 Golden quotation 0 1 0 amount 7 10500 50 false manager.uat@example.com true 2026-07-04 email
5 ALLA QT-HO-CR-2607-004 CUS-004 2026-07-04 standard rejected THB 2200000 2354000 sales.uat@example.com sales.uat@example.com OP-004 golf@easternsteel.example eastern 2026-08-04 Steel bay crane Rayong Golf Ops REF-004 Golden quotation 0 1 0 amount 7 154000 75 true Competitor C sales.uat@example.com true 2026-07-05 email
6 ALLA QT-HO-CR-2607-005 CUS-005 2026-07-05 standard revision THB 600000 642000 sales.uat@example.com sales.uat@example.com OP-005 itt@central-log.example head_office 2026-08-05 Logistics hoist Bangkok Itt Logistics REF-005 Golden quotation 1 QT-HO-CR-2607-002 Revised scope 1 0 amount 7 42000 65 false sales.uat@example.com true 2026-07-06 email
7 ALLA QT-HO-CR-2607-006 CUS-006 2026-07-06 standard draft THB 3000000 3210000 manager.uat@example.com manager.uat@example.com OP-006 kai@harbor.example eastern 2026-08-06 Harbor yard Chonburi Kai Site REF-006 Golden quotation 0 1 0 amount 7 210000 80 true Competitor D manager.uat@example.com false
8 ALLA QT-HO-CR-2607-007 CUS-007 2026-07-07 standard pending_approval THB 120000 128400 sales.uat@example.com sales.uat@example.com OP-007 mai@peakfoods.example northern 2026-08-07 Food service Lamphun Mai Plant REF-007 Golden quotation 0 1 0 amount 7 8400 40 false sales.uat@example.com true 2026-07-08 email
9 ALLA QT-HO-CR-2607-008 CUS-008 2026-07-08 standard approved THB 950000 1016500 sales.uat@example.com sales.uat@example.com OP-008 oat@riverpack.example head_office 2026-08-08 Packaging line Pathum Thani Oat Packaging REF-008 Golden quotation 0 1 0 amount 7 66500 55 false Competitor E sales.uat@example.com true 2026-07-09 email
10 ALLA QT-HO-CR-2607-009 CUS-009 2026-07-09 standard rejected THB 780000 834600 manager.uat@example.com manager.uat@example.com OP-009 q@summitauto.example eastern 2026-08-09 Assembly hoist Chachoengsao Q Auto REF-009 Golden quotation 0 1 0 amount 7 54600 60 false manager.uat@example.com true 2026-07-10 email
11 ALLA QT-HO-CR-2607-010 CUS-010 2026-07-10 standard revision THB 4200000 4494000 sales.uat@example.com sales.uat@example.com OP-010 som@urban.example head_office 2026-08-10 Developer project Bangkok Som Developer REF-010 Golden quotation 1 QT-HO-CR-2607-001 Revision 1 1 0 amount 7 294000 70 true Competitor F sales.uat@example.com true 2026-07-11 email
12 ALLA QT-HO-CR-2607-011 CUS-001 2026-07-11 standard draft THB 90000 96300 sales.uat@example.com sales.uat@example.com OP-011 ben@siam.example head_office 2026-08-11 Siam service Bangkok Ben Engineer REF-011 Golden quotation 0 1 0 amount 7 6300 45 false sales.uat@example.com false
13 ALLA QT-HO-CR-2607-012 CUS-002 2026-07-12 standard pending_approval THB 1300000 1391000 sales.uat@example.com sales.uat@example.com OP-012 dara@metro.example eastern 2026-08-12 Metro project Chonburi Dara QS REF-012 Golden quotation 0 1 0 amount 7 91000 55 false Competitor G sales.uat@example.com true 2026-07-13 email
14 ALLA QT-HO-CR-2607-013 CUS-003 2026-07-13 standard approved THB 500000 535000 manager.uat@example.com manager.uat@example.com OP-013 fon@north.example northern 2026-08-13 North plant Chiang Mai Fon Architect REF-013 Golden quotation 0 1 0 amount 7 35000 50 false manager.uat@example.com true 2026-07-14 email
15 ALLA QT-HO-CR-2607-014 CUS-004 2026-07-14 standard rejected THB 110000 117700 sales.uat@example.com sales.uat@example.com OP-014 hana@easternsteel.example eastern 2026-08-14 Rayong steel Rayong Hana Buyer REF-014 Golden quotation 0 1 0 amount 7 7700 45 false sales.uat@example.com true 2026-07-15 email
16 ALLA QT-HO-CR-2607-015 CUS-005 2026-07-15 standard revision THB 1800000 1926000 sales.uat@example.com sales.uat@example.com OP-015 jin@central-log.example head_office 2026-08-15 Central warehouse Bangkok Jin Warehouse REF-015 Golden quotation 1 QT-HO-CR-2607-012 Revision 1 1 0 amount 7 126000 65 true Competitor H sales.uat@example.com true 2026-07-16 email
17 ALLA QT-HO-CR-2607-016 CUS-006 2026-07-16 standard draft THB 650000 695500 manager.uat@example.com manager.uat@example.com OP-006 lek@harbor.example eastern 2026-08-16 Harbor support Chonburi Lek Admin REF-016 Golden quotation 0 1 0 amount 7 45500 50 false manager.uat@example.com false
18 ALLA QT-HO-CR-2607-017 CUS-007 2026-07-17 standard pending_approval THB 250000 267500 sales.uat@example.com sales.uat@example.com OP-007 nok@peakfoods.example northern 2026-08-17 Food maintenance Lamphun Nok Maintenance REF-017 Golden quotation 0 1 0 amount 7 17500 40 false sales.uat@example.com true 2026-07-18 email
19 ALLA QT-HO-CR-2607-018 CUS-008 2026-07-18 standard approved THB 1400000 1498000 sales.uat@example.com sales.uat@example.com OP-008 pim@riverpack.example head_office 2026-08-18 Packaging expansion Pathum Thani Pim Buyer REF-018 Golden quotation 0 1 0 amount 7 98000 55 false sales.uat@example.com true 2026-07-19 email
20 ALLA QT-HO-CR-2607-019 CUS-009 2026-07-19 standard rejected THB 160000 171200 manager.uat@example.com manager.uat@example.com OP-009 rin@summitauto.example eastern 2026-08-19 Summit service Chachoengsao Rin Engineer REF-019 Golden quotation 0 1 0 amount 7 11200 35 false manager.uat@example.com true 2026-07-20 email
21 ALLA QT-HO-CR-2607-020 CUS-010 2026-07-20 standard revision THB 820000 877400 sales.uat@example.com sales.uat@example.com OP-010 tan@urban.example head_office 2026-08-20 Tower support Bangkok Tan Project REF-020 Golden quotation 1 QT-HO-CR-2607-017 Revision 1 1 0 amount 7 57400 50 false sales.uat@example.com true 2026-07-21 email

View File

@@ -0,0 +1,6 @@
email,name,system_role,password,active_organization_code,image_url,reset_password
admin@example.com,System Administrator,super_admin,ChangeMe123!,ALLA,,false
mk.uat@example.com,Marketing User,user,ChangeMe123!,ALLA,,false
sales.uat@example.com,Sales User,user,ChangeMe123!,ALLA,,false
manager.uat@example.com,Sales Manager,user,ChangeMe123!,ALLA,,false
ceo.uat@example.com,Chief Executive Officer,user,ChangeMe123!,ALLA,,false
1 email name system_role password active_organization_code image_url reset_password
2 admin@example.com System Administrator super_admin ChangeMe123! ALLA false
3 mk.uat@example.com Marketing User user ChangeMe123! ALLA false
4 sales.uat@example.com Sales User user ChangeMe123! ALLA false
5 manager.uat@example.com Sales Manager user ChangeMe123! ALLA false
6 ceo.uat@example.com Chief Executive Officer user ChangeMe123! ALLA false

91
setup/templates/README.md Normal file
View File

@@ -0,0 +1,91 @@
# ALLA OS Setup CSV Templates
This folder contains the supported static CSV template pack for Task D.7.3.
Rules:
- UTF-8 text.
- Comma delimiter.
- LF line endings.
- One header row and one safe sample row per CSV.
- No unsupported template files are generated.
- No production data, formulas, secrets, or binary references are included.
## Sample Dataset
All templates use one consistent sample dataset:
- Organization: `ALLA`
- Branch: `head_office`
- Product type: `crane`
- Currency: `THB`
- Administrator: `admin@example.com`
- Marketing: `mk.uat@example.com`
- Sales: `sales.uat@example.com`
- Manager: `manager.uat@example.com`
- CEO: `ceo.uat@example.com`
- Customer: `CUS-001`
- Lead: `LD-001`
- Opportunity: `OP-001`
- Quotation: `QT-HO-CR-2607-001`
## Import Order
| Order | File | Purpose |
| --- | --- | --- |
| 01 | `users.csv` | Setup-managed users |
| 02 | `organizations.csv` | Tenant organizations |
| 03 | `memberships.csv` | Organization memberships |
| 05 | `crm-role-assignments.csv` | CRM role assignments |
| 06 | `master-options.csv` | Generic master options |
| 07 | `branches.csv` | Branch options |
| 08 | `product-types.csv` | Product type options |
| 14 | `document-sequences.csv` | Document numbering |
| 15 | `approval-workflows.csv` | Approval workflows |
| 16 | `approval-steps.csv` | Approval workflow steps |
| 17 | `approval-matrix.csv` | Approval routing matrix |
| 30 | `customers.csv` | CRM customers |
| 32 | `contacts.csv` | Customer contacts |
| 33 | `contact-shares.csv` | Contact sharing grants |
| 34 | `leads.csv` | Marketing leads |
| 36 | `opportunities.csv` | Sales opportunities |
| 37 | `opportunity-parties.csv` | Opportunity project parties |
| 40 | `quotations.csv` | Quotation headers |
| 41 | `quotation-items.csv` | Quotation line items |
| 42 | `quotation-parties.csv` | Quotation project parties |
| 43 | `quotation-topics.csv` | Quotation topic headers |
| 44 | `quotation-topic-items.csv` | Quotation topic rows |
## Relationship Rules
- `organization_code` links rows to the organization import context.
- `user_email`, `created_by_email`, `updated_by_email`, and role-related email fields resolve to `users.email`.
- `branch_code` resolves to `ms_options` category `crm_branch`.
- `product_type_code` resolves to `ms_options` category `crm_product_type`.
- `customer_code`, `lead_code`, `opportunity_code`, and `quotation_code` are business keys within the organization.
- `topic_key` is an import-only alias linking `quotation-topics.csv` to `quotation-topic-items.csv`.
- Pipe-delimited fields, such as permission or scope lists, use `|`.
## Placeholders
These templates intentionally leave sensitive or runtime values empty:
- `users.csv` has an empty `password` sample value.
- Runtime approval and PDF artifact fields are not present.
- Binary attachment paths are not present.
## Unsupported Templates
The following files are documented but not generated because the current schema does not support them as safe first-class setup imports:
- `departments.csv`
- `teams.csv`
- `warehouses.csv`
- `sites.csv`
- `services.csv`
- `price-books.csv`
- `tax-rates.csv`
- `attachments.csv`
- `email-settings.csv`
See `docs/setup/csv-template-spec.md` and `docs/setup/import-mapping.md` for the full contract.

View File

@@ -0,0 +1,2 @@
organization_code,entity_type,workflow_code,branch_code,product_type_code,min_amount,max_amount,currency,priority,is_default,is_active,description
ALLA,quotation,quotation_standard,head_office,crane,0,5000000,THB,100,true,true,Default crane approval
1 organization_code entity_type workflow_code branch_code product_type_code min_amount max_amount currency priority is_default is_active description
2 ALLA quotation quotation_standard head_office crane 0 5000000 THB 100 true true Default crane approval

View File

@@ -0,0 +1,2 @@
organization_code,workflow_code,step_number,role_code,role_name,approval_mode,is_required,sla_hours,calendar_mode,timeout_action
ALLA,quotation_standard,1,sales_manager,Sales Manager,sequential,true,24,calendar_days,none
1 organization_code workflow_code step_number role_code role_name approval_mode is_required sla_hours calendar_mode timeout_action
2 ALLA quotation_standard 1 sales_manager Sales Manager sequential true 24 calendar_days none

View File

@@ -0,0 +1,2 @@
organization_code,workflow_code,workflow_name,entity_type,description,is_system,is_active
ALLA,quotation_standard,Quotation Standard Approval,quotation,Default quotation approval,false,true
1 organization_code workflow_code workflow_name entity_type description is_system is_active
2 ALLA quotation_standard Quotation Standard Approval quotation Default quotation approval false true

View File

@@ -0,0 +1,2 @@
organization_code,branch_code,branch_name,prefix,address,tax_id,phone,email,sort_order,is_active
ALLA,head_office,Head Office,HO,99/9 Rama IX Road Bangkok,0107558000393,02-000-0000,head.office@example.com,1,true
1 organization_code branch_code branch_name prefix address tax_id phone email sort_order is_active
2 ALLA head_office Head Office HO 99/9 Rama IX Road Bangkok 0107558000393 02-000-0000 head.office@example.com 1 true

View File

@@ -0,0 +1,2 @@
organization_code,customer_code,contact_email,shared_to_user_email,shared_by_user_email,remark,is_active
ALLA,CUS-001,anan@siam.example,sales.uat@example.com,admin@example.com,Shared for setup sample,true
1 organization_code customer_code contact_email shared_to_user_email shared_by_user_email remark is_active
2 ALLA CUS-001 anan@siam.example sales.uat@example.com admin@example.com Shared for setup sample true

View File

@@ -0,0 +1,2 @@
organization_code,customer_code,contact_name,created_by_email,position,department,phone,mobile,email,is_primary,notes,is_active
ALLA,CUS-001,Anan Sales,admin@example.com,Procurement Manager,Procurement,02-000-1001,081-000-0001,anan@siam.example,true,Primary procurement contact,true
1 organization_code customer_code contact_name created_by_email position department phone mobile email is_primary notes is_active
2 ALLA CUS-001 Anan Sales admin@example.com Procurement Manager Procurement 02-000-1001 081-000-0001 anan@siam.example true Primary procurement contact true

View File

@@ -0,0 +1,2 @@
organization_code,user_email,crm_role_code,is_primary,branch_scope_mode,branch_codes,product_type_scope_mode,product_type_codes,is_active
ALLA,admin@example.com,crm_admin,true,all,,all,,true
1 organization_code user_email crm_role_code is_primary branch_scope_mode branch_codes product_type_scope_mode product_type_codes is_active
2 ALLA admin@example.com crm_admin true all all true

View File

@@ -0,0 +1,2 @@
organization_code,customer_code,customer_name,customer_type,customer_status,created_by_email,branch_code,abbr,tax_id,address,province,district,sub_district,postal_code,country,phone,fax,email,website,lead_channel,customer_group,customer_sub_group,owner_user_email,notes,is_active
ALLA,CUS-001,Siam Manufacturing,company,active,admin@example.com,head_office,SIAM,0105555000001,100 Industrial Road,Bangkok,Bang Na,Bang Na,10260,Thailand,02-000-1000,,contact@siam.example,https://siam.example,website,industrial,factory,sales.uat@example.com,Initial setup sample customer,true
1 organization_code customer_code customer_name customer_type customer_status created_by_email branch_code abbr tax_id address province district sub_district postal_code country phone fax email website lead_channel customer_group customer_sub_group owner_user_email notes is_active
2 ALLA CUS-001 Siam Manufacturing company active admin@example.com head_office SIAM 0105555000001 100 Industrial Road Bangkok Bang Na Bang Na 10260 Thailand 02-000-1000 contact@siam.example https://siam.example website industrial factory sales.uat@example.com Initial setup sample customer true

View File

@@ -0,0 +1,2 @@
organization_code,branch_code,product_type_code,document_type,prefix,period,current_number,padding_length,format,reset_policy,is_active
ALLA,head_office,crane,quotation,QT-HO-CR-,2607,0,3,{prefix}{period}-{running},period,true
1 organization_code branch_code product_type_code document_type prefix period current_number padding_length format reset_policy is_active
2 ALLA head_office crane quotation QT-HO-CR- 2607 0 3 {prefix}{period}-{running} period true

View File

@@ -0,0 +1,2 @@
organization_code,lead_code,status,created_by_email,branch_code,customer_code,contact_email,description,project_name,project_location,lead_channel,product_type_code,priority,estimated_value,awareness_code,followup_status,lost_reason,outcome,owner_marketing_user_email,assigned_sales_owner_email,assignment_remark
ALLA,LD-001,assigned,mk.uat@example.com,head_office,CUS-001,anan@siam.example,Customer requested crane consultation,Warehouse Crane,Bangkok Warehouse,website,crane,high,1000000,google_search_website,quotation_preparation,,open,mk.uat@example.com,sales.uat@example.com,Assigned from setup sample
1 organization_code lead_code status created_by_email branch_code customer_code contact_email description project_name project_location lead_channel product_type_code priority estimated_value awareness_code followup_status lost_reason outcome owner_marketing_user_email assigned_sales_owner_email assignment_remark
2 ALLA LD-001 assigned mk.uat@example.com head_office CUS-001 anan@siam.example Customer requested crane consultation Warehouse Crane Bangkok Warehouse website crane high 1000000 google_search_website quotation_preparation open mk.uat@example.com sales.uat@example.com Assigned from setup sample

View File

@@ -0,0 +1,2 @@
organization_code,category,code,label,value,parent_category,parent_code,sort_order,is_active,metadata_json
ALLA,crm_customer_group,industrial,Industrial,industrial,,,1,true,{}
1 organization_code category code label value parent_category parent_code sort_order is_active metadata_json
2 ALLA crm_customer_group industrial Industrial industrial 1 true {}

View File

@@ -0,0 +1,2 @@
organization_code,user_email,membership_role,business_role,permissions,branch_scope_codes,product_type_scope_codes
ALLA,admin@example.com,admin,crm_admin,crm.dashboard.read|crm.role.read|crm.user_role_assignment.read,head_office,crane
1 organization_code user_email membership_role business_role permissions branch_scope_codes product_type_scope_codes
2 ALLA admin@example.com admin crm_admin crm.dashboard.read|crm.role.read|crm.user_role_assignment.read head_office crane

View File

@@ -0,0 +1,2 @@
organization_code,opportunity_code,customer_code,title,product_type_code,status,priority,created_by_email,updated_by_email,lead_code,contact_email,branch_code,description,requirement,project_name,project_location,outcome_status,lead_channel,estimated_value,chance_percent,expected_close_date,competitor,source,notes,is_hot_project,pipeline_stage,assigned_to_user_email
ALLA,OP-001,CUS-001,Warehouse Crane Expansion,crane,negotiation,high,sales.uat@example.com,sales.uat@example.com,LD-001,anan@siam.example,head_office,Crane expansion opportunity,Overhead crane with installation,Warehouse Crane,Bangkok Warehouse,open,website,1000000,70,2026-08-31,,setup,Initial setup sample opportunity,false,opportunity,sales.uat@example.com
1 organization_code opportunity_code customer_code title product_type_code status priority created_by_email updated_by_email lead_code contact_email branch_code description requirement project_name project_location outcome_status lead_channel estimated_value chance_percent expected_close_date competitor source notes is_hot_project pipeline_stage assigned_to_user_email
2 ALLA OP-001 CUS-001 Warehouse Crane Expansion crane negotiation high sales.uat@example.com sales.uat@example.com LD-001 anan@siam.example head_office Crane expansion opportunity Overhead crane with installation Warehouse Crane Bangkok Warehouse open website 1000000 70 2026-08-31 setup Initial setup sample opportunity false opportunity sales.uat@example.com

View File

@@ -0,0 +1,2 @@
organization_code,opportunity_code,customer_code,role_code,remark
ALLA,OP-001,CUS-001,end_customer,Primary project owner
1 organization_code opportunity_code customer_code role_code remark
2 ALLA OP-001 CUS-001 end_customer Primary project owner

View File

@@ -0,0 +1,2 @@
organization_code,organization_name,slug,created_by_email,tax_id,default_currency,phone,email,address,logo_url,plan,status
ALLA,ALLA Public Company Limited,alla,admin@example.com,0107558000393,THB,02-000-0000,info@example.com,99/9 Rama IX Road Bangkok,,enterprise,active
1 organization_code organization_name slug created_by_email tax_id default_currency phone email address logo_url plan status
2 ALLA ALLA Public Company Limited alla admin@example.com 0107558000393 THB 02-000-0000 info@example.com 99/9 Rama IX Road Bangkok enterprise active

View File

@@ -0,0 +1,2 @@
organization_code,product_type_code,product_type_name,document_prefix,sort_order,is_active,metadata_json
ALLA,crane,Crane,CR,1,true,{}
1 organization_code product_type_code product_type_name document_prefix sort_order is_active metadata_json
2 ALLA crane Crane CR 1 true {}

View File

@@ -0,0 +1,2 @@
organization_code,quotation_code,item_number,product_type_code,description,quantity,unit_price,total_price,unit,discount,discount_type,tax_rate,notes,sort_order
ALLA,QT-HO-CR-2607-001,1,crane,Crane installation package,1,1000000,1000000,set,0,,7,Setup sample quotation item,1
1 organization_code quotation_code item_number product_type_code description quantity unit_price total_price unit discount discount_type tax_rate notes sort_order
2 ALLA QT-HO-CR-2607-001 1 crane Crane installation package 1 1000000 1000000 set 0 7 Setup sample quotation item 1

View File

@@ -0,0 +1,2 @@
organization_code,quotation_code,customer_code,role_code,is_primary,remark
ALLA,QT-HO-CR-2607-001,CUS-001,end_customer,true,Primary quotation customer
1 organization_code quotation_code customer_code role_code is_primary remark
2 ALLA QT-HO-CR-2607-001 CUS-001 end_customer true Primary quotation customer

View File

@@ -0,0 +1,2 @@
organization_code,quotation_code,topic_key,content,sort_order
ALLA,QT-HO-CR-2607-001,scope-main,Supply and install one overhead crane system,1
1 organization_code quotation_code topic_key content sort_order
2 ALLA QT-HO-CR-2607-001 scope-main Supply and install one overhead crane system 1

View File

@@ -0,0 +1,2 @@
organization_code,quotation_code,topic_key,topic_type,title,sort_order
ALLA,QT-HO-CR-2607-001,scope-main,scope,Scope of Work,1
1 organization_code quotation_code topic_key topic_type title sort_order
2 ALLA QT-HO-CR-2607-001 scope-main scope Scope of Work 1

View File

@@ -0,0 +1,2 @@
organization_code,quotation_code,customer_code,quotation_date,quotation_type,status,currency,subtotal,total_amount,created_by_email,updated_by_email,opportunity_code,contact_email,branch_code,valid_until,project_name,project_location,attention,reference,notes,revision,parent_quotation_code,revision_remark,exchange_rate,discount,discount_type,tax_rate,tax_amount,chance_percent,is_hot_project,competitor,salesman_email,is_sent,sent_at,sent_via
ALLA,QT-HO-CR-2607-001,CUS-001,2026-07-02,crane,draft,THB,1000000,1070000,sales.uat@example.com,sales.uat@example.com,OP-001,anan@siam.example,head_office,2026-08-01,Warehouse Crane,Bangkok Warehouse,Anan Sales,SETUP-SAMPLE,Initial setup sample quotation,0,,,1,0,,7,70000,70,false,,sales.uat@example.com,false,,
1 organization_code quotation_code customer_code quotation_date quotation_type status currency subtotal total_amount created_by_email updated_by_email opportunity_code contact_email branch_code valid_until project_name project_location attention reference notes revision parent_quotation_code revision_remark exchange_rate discount discount_type tax_rate tax_amount chance_percent is_hot_project competitor salesman_email is_sent sent_at sent_via
2 ALLA QT-HO-CR-2607-001 CUS-001 2026-07-02 crane draft THB 1000000 1070000 sales.uat@example.com sales.uat@example.com OP-001 anan@siam.example head_office 2026-08-01 Warehouse Crane Bangkok Warehouse Anan Sales SETUP-SAMPLE Initial setup sample quotation 0 1 0 7 70000 70 false sales.uat@example.com false

View File

@@ -0,0 +1,255 @@
{
"version": "1.0.0",
"generatedFrom": "docs/setup/csv-template-spec.md",
"dataset": {
"organizationCode": "ALLA",
"branchCode": "head_office",
"productTypeCode": "crane",
"currency": "THB",
"administratorEmail": "admin@example.com",
"marketingEmail": "mk.uat@example.com",
"salesEmail": "sales.uat@example.com",
"managerEmail": "manager.uat@example.com",
"ceoEmail": "ceo.uat@example.com"
},
"templates": [
{
"file": "users.csv",
"seedType": "organization",
"importOrder": 1,
"supported": true,
"requiredColumns": ["email", "name", "system_role"],
"description": "Setup-managed users."
},
{
"file": "organizations.csv",
"seedType": "organization",
"importOrder": 2,
"supported": true,
"requiredColumns": ["organization_code", "organization_name", "slug", "created_by_email"],
"description": "Tenant organizations."
},
{
"file": "memberships.csv",
"seedType": "organization",
"importOrder": 3,
"supported": true,
"requiredColumns": ["organization_code", "user_email", "membership_role", "business_role"],
"description": "App-level organization memberships."
},
{
"file": "crm-role-assignments.csv",
"seedType": "organization",
"importOrder": 5,
"supported": true,
"requiredColumns": [
"organization_code",
"user_email",
"crm_role_code",
"is_primary",
"branch_scope_mode",
"product_type_scope_mode"
],
"description": "CRM role assignments and scopes."
},
{
"file": "master-options.csv",
"seedType": "foundation",
"importOrder": 6,
"supported": true,
"requiredColumns": ["organization_code", "category", "code", "label"],
"description": "Generic governed master options."
},
{
"file": "branches.csv",
"seedType": "organization",
"importOrder": 7,
"supported": true,
"requiredColumns": ["organization_code", "branch_code", "branch_name"],
"description": "Branch options mapped to ms_options category crm_branch."
},
{
"file": "product-types.csv",
"seedType": "organization",
"importOrder": 8,
"supported": true,
"requiredColumns": ["organization_code", "product_type_code", "product_type_name"],
"description": "Product type options mapped to ms_options category crm_product_type."
},
{
"file": "document-sequences.csv",
"seedType": "foundation",
"importOrder": 14,
"supported": true,
"requiredColumns": ["organization_code", "document_type", "prefix", "period"],
"description": "Document numbering configuration."
},
{
"file": "approval-workflows.csv",
"seedType": "foundation",
"importOrder": 15,
"supported": true,
"requiredColumns": ["organization_code", "workflow_code", "workflow_name", "entity_type"],
"description": "Approval workflow headers."
},
{
"file": "approval-steps.csv",
"seedType": "foundation",
"importOrder": 16,
"supported": true,
"requiredColumns": ["organization_code", "workflow_code", "step_number", "role_code", "role_name"],
"description": "Approval workflow steps."
},
{
"file": "approval-matrix.csv",
"seedType": "foundation",
"importOrder": 17,
"supported": true,
"requiredColumns": ["organization_code", "entity_type", "workflow_code", "priority", "is_default"],
"description": "Approval workflow routing matrix."
},
{
"file": "customers.csv",
"seedType": "business",
"importOrder": 30,
"supported": true,
"requiredColumns": [
"organization_code",
"customer_code",
"customer_name",
"customer_type",
"customer_status",
"created_by_email"
],
"description": "CRM customers."
},
{
"file": "contacts.csv",
"seedType": "business",
"importOrder": 32,
"supported": true,
"requiredColumns": ["organization_code", "customer_code", "contact_name", "created_by_email"],
"description": "Customer contacts."
},
{
"file": "contact-shares.csv",
"seedType": "business",
"importOrder": 33,
"supported": true,
"requiredColumns": [
"organization_code",
"customer_code",
"contact_email",
"shared_to_user_email",
"shared_by_user_email"
],
"description": "Contact sharing grants."
},
{
"file": "leads.csv",
"seedType": "business",
"importOrder": 34,
"supported": true,
"requiredColumns": ["organization_code", "lead_code", "status", "created_by_email"],
"description": "Marketing-owned leads."
},
{
"file": "opportunities.csv",
"seedType": "business",
"importOrder": 36,
"supported": true,
"requiredColumns": [
"organization_code",
"opportunity_code",
"customer_code",
"title",
"product_type_code",
"status",
"priority",
"created_by_email",
"updated_by_email"
],
"description": "Sales opportunities."
},
{
"file": "opportunity-parties.csv",
"seedType": "business",
"importOrder": 37,
"supported": true,
"requiredColumns": ["organization_code", "opportunity_code", "customer_code", "role_code"],
"description": "Opportunity project parties."
},
{
"file": "quotations.csv",
"seedType": "business",
"importOrder": 40,
"supported": true,
"requiredColumns": [
"organization_code",
"quotation_code",
"customer_code",
"quotation_date",
"quotation_type",
"status",
"currency",
"subtotal",
"total_amount",
"created_by_email",
"updated_by_email"
],
"description": "Quotation headers."
},
{
"file": "quotation-items.csv",
"seedType": "business",
"importOrder": 41,
"supported": true,
"requiredColumns": [
"organization_code",
"quotation_code",
"item_number",
"product_type_code",
"description",
"quantity",
"unit_price",
"total_price"
],
"description": "Quotation line items."
},
{
"file": "quotation-parties.csv",
"seedType": "business",
"importOrder": 42,
"supported": true,
"requiredColumns": ["organization_code", "quotation_code", "customer_code", "role_code"],
"description": "Quotation project parties."
},
{
"file": "quotation-topics.csv",
"seedType": "business",
"importOrder": 43,
"supported": true,
"requiredColumns": ["organization_code", "quotation_code", "topic_key", "topic_type", "title"],
"description": "Quotation topic headers."
},
{
"file": "quotation-topic-items.csv",
"seedType": "business",
"importOrder": 44,
"supported": true,
"requiredColumns": ["organization_code", "quotation_code", "topic_key", "content"],
"description": "Quotation topic rows."
}
],
"unsupportedTemplates": [
"departments.csv",
"teams.csv",
"warehouses.csv",
"sites.csv",
"services.csv",
"price-books.csv",
"tax-rates.csv",
"attachments.csv",
"email-settings.csv"
]
}

View File

@@ -0,0 +1,2 @@
email,name,system_role,password,active_organization_code,image_url,reset_password
admin@allaos.local,System Administrator,super_admin,gikiyd[ibKym,ALLA,,FALSE
1 email name system_role password active_organization_code image_url reset_password
2 admin@allaos.local System Administrator super_admin gikiyd[ibKym ALLA FALSE

View File

@@ -0,0 +1,33 @@
import { redirect } from "next/navigation";
import { SetupWizard } from "@/features/setup/components/setup-wizard";
import { getBootstrapSetupStatus } from "@/features/setup/server/setup-bootstrap.service";
export const metadata = {
title: "ALLA OS Setup",
};
export default async function BootstrapSetupPage() {
const status = await getBootstrapSetupStatus();
if (status.initialized) {
redirect("/auth/sign-in");
}
return (
<main className="min-h-screen bg-background py-8 px-4">
<div className="flex w-full flex-col gap-6">
<div className="space-y-2">
<h1 className="text-3xl font-semibold tracking-normal">
ALLA OS Setup
</h1>
<p className="max-w-3xl text-sm text-muted-foreground">
Preview setup CSV files from SETUP_IMPORT_DIR, run the import, then
complete setup.
</p>
</div>
<SetupWizard mode="public" tokenRequired={status.tokenRequired} />
</div>
</main>
);
}

View File

@@ -0,0 +1,116 @@
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import {
deleteEmailConfiguration,
getEmailConfiguration,
updateEmailConfiguration,
} from '@/features/foundation/email/server/email-config.service';
import { PERMISSIONS } from '@/lib/auth/rbac';
import { AuthError, requireOrganizationAccess } from '@/lib/auth/session';
const emailConfigurationSchema = z.object({
providerType: z.literal('smtp').default('smtp'),
name: z.string().trim().min(1).max(120),
host: z.string().trim().min(1).max(255),
port: z.number().int().min(1).max(65535),
secure: z.boolean(),
username: z.string().trim().max(255).nullable().optional(),
password: z.string().trim().max(1000).nullable().optional(),
clearPassword: z.boolean().optional(),
fromEmail: z.string().trim().email(),
fromName: z.string().trim().max(255).nullable().optional(),
replyToEmail: z.string().trim().email().nullable().optional(),
isDefault: z.boolean().optional(),
isActive: z.boolean().optional(),
});
export async function GET(
_request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
try {
const { organization } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
const { id } = await context.params;
const configuration = await getEmailConfiguration(organization.id, id);
if (!configuration) {
return NextResponse.json({ message: 'Email configuration was not found.' }, { status: 404 });
}
return NextResponse.json(configuration);
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
return NextResponse.json({ message: 'Unable to load email configuration' }, { status: 500 });
}
}
export async function PATCH(
request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
try {
const { organization, session } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
const { id } = await context.params;
const payload = emailConfigurationSchema.parse(await request.json());
return NextResponse.json(
await updateEmailConfiguration({
organizationId: organization.id,
userId: session.user.id,
id,
values: payload,
})
);
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
if (error instanceof z.ZodError) {
return NextResponse.json(
{ message: 'Invalid email configuration payload', errors: error.flatten() },
{ status: 400 }
);
}
if (error instanceof Error) {
return NextResponse.json({ message: error.message }, { status: 400 });
}
return NextResponse.json({ message: 'Unable to update email configuration' }, { status: 500 });
}
}
export async function DELETE(
_request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
try {
const { organization, session } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
const { id } = await context.params;
await deleteEmailConfiguration({
organizationId: organization.id,
userId: session.user.id,
id,
});
return NextResponse.json({ success: true });
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
if (error instanceof Error) {
return NextResponse.json({ message: error.message }, { status: 400 });
}
return NextResponse.json({ message: 'Unable to delete email configuration' }, { status: 500 });
}
}

View File

@@ -0,0 +1,46 @@
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import { sendTestEmail } from '@/features/foundation/email/server/email-test.service';
import { PERMISSIONS } from '@/lib/auth/rbac';
import { AuthError, requireOrganizationAccess } from '@/lib/auth/session';
const sendTestEmailSchema = z.object({
recipientEmail: z.string().trim().email(),
});
export async function POST(
request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
try {
const { organization, session } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
const { id } = await context.params;
const payload = sendTestEmailSchema.parse(await request.json());
return NextResponse.json(
await sendTestEmail({
organizationId: organization.id,
userId: session.user.id,
configurationId: id,
recipientEmail: payload.recipientEmail,
})
);
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
if (error instanceof z.ZodError) {
return NextResponse.json(
{ message: 'Invalid test email payload', errors: error.flatten() },
{ status: 400 }
);
}
if (error instanceof Error) {
return NextResponse.json({ message: error.message }, { status: 400 });
}
return NextResponse.json({ message: 'Unable to send test email' }, { status: 500 });
}
}

View File

@@ -0,0 +1,33 @@
import { NextRequest, NextResponse } from 'next/server';
import { testEmailConfigurationConnection } from '@/features/foundation/email/server/email-test.service';
import { PERMISSIONS } from '@/lib/auth/rbac';
import { AuthError, requireOrganizationAccess } from '@/lib/auth/session';
export async function POST(
_request: NextRequest,
context: { params: Promise<{ id: string }> }
) {
try {
const { organization, session } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
const { id } = await context.params;
return NextResponse.json(
await testEmailConfigurationConnection({
organizationId: organization.id,
userId: session.user.id,
configurationId: id,
})
);
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
if (error instanceof Error) {
return NextResponse.json({ message: error.message }, { status: 400 });
}
return NextResponse.json({ message: 'Unable to test email configuration' }, { status: 500 });
}
}

View File

@@ -0,0 +1,73 @@
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import {
createEmailConfiguration,
listEmailConfigurations,
} from '@/features/foundation/email/server/email-config.service';
import { PERMISSIONS } from '@/lib/auth/rbac';
import { AuthError, requireOrganizationAccess } from '@/lib/auth/session';
const emailConfigurationSchema = z.object({
providerType: z.literal('smtp').default('smtp'),
name: z.string().trim().min(1).max(120),
host: z.string().trim().min(1).max(255),
port: z.number().int().min(1).max(65535),
secure: z.boolean(),
username: z.string().trim().max(255).nullable().optional(),
password: z.string().trim().max(1000).nullable().optional(),
clearPassword: z.boolean().optional(),
fromEmail: z.string().trim().email(),
fromName: z.string().trim().max(255).nullable().optional(),
replyToEmail: z.string().trim().email().nullable().optional(),
isDefault: z.boolean().optional(),
isActive: z.boolean().optional(),
});
export async function GET() {
try {
const { organization } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
return NextResponse.json(await listEmailConfigurations(organization.id));
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
return NextResponse.json({ message: 'Unable to load email configurations' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const { organization, session } = await requireOrganizationAccess({
permission: PERMISSIONS.notificationsAdmin,
});
const payload = emailConfigurationSchema.parse(await request.json());
return NextResponse.json(
await createEmailConfiguration({
organizationId: organization.id,
userId: session.user.id,
values: payload,
}),
{ status: 201 }
);
} catch (error) {
if (error instanceof AuthError) {
return NextResponse.json({ message: error.message }, { status: error.status });
}
if (error instanceof z.ZodError) {
return NextResponse.json(
{ message: 'Invalid email configuration payload', errors: error.flatten() },
{ status: 400 }
);
}
if (error instanceof Error) {
return NextResponse.json({ message: error.message }, { status: 400 });
}
return NextResponse.json({ message: 'Unable to create email configuration' }, { status: 500 });
}
}

Some files were not shown because too many files have changed in this diff Show More