Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
/**
|
|
|
|
|
* Seed script for Port Nimara CRM.
|
|
|
|
|
*
|
2026-04-24 13:26:37 +02:00
|
|
|
* Top-level orchestrator:
|
2026-05-03 15:59:36 +02:00
|
|
|
* 1. Create the operational ports (idempotent):
|
|
|
|
|
* - Port Nimara (primary install — the real marina)
|
|
|
|
|
* - Port Amador (secondary, kept for multi-tenant isolation tests
|
|
|
|
|
* and as scaffolding for a future Panama install)
|
2026-04-24 13:26:37 +02:00
|
|
|
* 2. Create 5 system roles with full permission maps
|
|
|
|
|
* 3. Create the super admin user profile placeholder (matt@portnimara.com)
|
|
|
|
|
* 4. For each port, call `seedPortData(portId, portSlug)` from seed-data.ts
|
|
|
|
|
* to produce the realistic multi-cardinality fixture
|
2026-05-03 15:59:36 +02:00
|
|
|
* (117 berths from the NocoDB snapshot, plus clients, companies, yachts,
|
|
|
|
|
* memberships, interests, reservations, ownership-transfer history).
|
2026-04-24 13:26:37 +02:00
|
|
|
* 5. Print a summary.
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
*
|
2026-04-24 13:26:37 +02:00
|
|
|
* Run with: pnpm db:seed
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import 'dotenv/config';
|
2026-04-24 13:26:37 +02:00
|
|
|
import { eq } from 'drizzle-orm';
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
import { db } from './index';
|
|
|
|
|
import { ports } from './schema/ports';
|
|
|
|
|
import { roles, userProfiles } from './schema/users';
|
|
|
|
|
import type { RolePermissions } from './schema/users';
|
2026-04-24 13:26:37 +02:00
|
|
|
import { seedPortData, type SeedSummary } from './seed-data';
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
|
|
|
|
|
// ─── Permission Maps ─────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
const ALL_PERMISSIONS: RolePermissions = {
|
|
|
|
|
clients: { view: true, create: true, edit: true, delete: true, merge: true, export: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
change_stage: true,
|
|
|
|
|
generate_eoi: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
berths: { view: true, edit: true, import: true, manage_waiting_list: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
documents: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
send_for_signing: true,
|
|
|
|
|
upload_signed: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
},
|
|
|
|
|
expenses: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
export: true,
|
|
|
|
|
scan_receipt: true,
|
|
|
|
|
},
|
|
|
|
|
invoices: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
send: true,
|
|
|
|
|
record_payment: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
files: { view: true, upload: true, delete: true, manage_folders: true },
|
|
|
|
|
email: { view: true, send: true, configure_account: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
reminders: {
|
|
|
|
|
view_own: true,
|
|
|
|
|
view_all: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit_own: true,
|
|
|
|
|
edit_all: true,
|
|
|
|
|
assign_others: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
calendar: { connect: true, view_events: true },
|
|
|
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
|
|
|
|
document_templates: { view: true, generate: true, manage: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
yachts: { view: true, create: true, edit: true, delete: true, transfer: true },
|
|
|
|
|
companies: { view: true, create: true, edit: true, delete: true },
|
|
|
|
|
memberships: { view: true, manage: true },
|
|
|
|
|
reservations: { view: true, create: true, activate: true, cancel: true },
|
|
|
|
|
admin: {
|
|
|
|
|
manage_users: true,
|
|
|
|
|
view_audit_log: true,
|
|
|
|
|
manage_settings: true,
|
|
|
|
|
manage_webhooks: true,
|
|
|
|
|
manage_reports: true,
|
|
|
|
|
manage_custom_fields: true,
|
|
|
|
|
manage_forms: true,
|
|
|
|
|
manage_tags: true,
|
|
|
|
|
system_backup: true,
|
|
|
|
|
},
|
feat(platform): residential module + admin UI + reliability fixes
Residential platform
- New schema: residentialClients, residentialInterests (separate from
marina/yacht clients) with migration 0010
- Service layer with CRUD + audit + sockets + per-port portal toggle
- v1 + public API routes (/api/v1/residential/*, /api/public/residential-inquiries)
- List + detail pages with inline editing for clients and interests
- Per-user residentialAccess toggle on userPortRoles (migration 0011)
- Permission keys: residential_clients, residential_interests
- Sidebar nav + role form integration
- Smoke spec covering page loads, UI create flow, public endpoint
Admin & shared UI
- Admin → Forms (form templates CRUD) with validators + service
- Notification preferences page (in-app + email per type)
- Email composition + accounts list + threads view
- Branded auth shell shared across CRM + portal auth surfaces
- Inline editing extended to yacht/company/interest detail pages
- InlineTagEditor + per-entity tags endpoints (yachts, companies)
- Notes service polymorphic across clients/interests/yachts/companies
- Client list columns: yachtCount + companyCount badges
- Reservation file-download via presigned URL (replaces stale <a href>)
Route handler refactor
- Extracted yachts/companies/berths reservation handlers to sibling
handlers.ts files (Next.js 15 route.ts only allows specific exports)
Reliability fixes
- apiFetch double-stringify bug fixed across 13 components
(apiFetch already JSON.stringifies its body; passing a stringified
body produced double-encoded JSON which failed zod validation)
- SocketProvider gated behind useSyncExternalStore-based mount check
to avoid useSession() SSR crashes under React 19 + Next 15
- apiFetch falls back to URL-pathname → port-id resolution when the
Zustand store hasn't hydrated yet (fresh contexts, e2e tests)
- CRM invite flow (schema, service, route, email, dev script)
- Dashboard route → [portSlug]/dashboard/page.tsx + redirect
- Document the dev-server restart-after-migration gotcha in CLAUDE.md
Tests
- 5-case residential smoke spec
- Integration test updates for new service signatures
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:54:32 +02:00
|
|
|
residential_clients: { view: true, create: true, edit: true, delete: true },
|
|
|
|
|
residential_interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
change_stage: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const DIRECTOR_PERMISSIONS: RolePermissions = {
|
|
|
|
|
clients: { view: true, create: true, edit: true, delete: true, merge: true, export: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
change_stage: true,
|
|
|
|
|
generate_eoi: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
berths: { view: true, edit: true, import: true, manage_waiting_list: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
documents: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
send_for_signing: true,
|
|
|
|
|
upload_signed: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
},
|
|
|
|
|
expenses: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
export: true,
|
|
|
|
|
scan_receipt: true,
|
|
|
|
|
},
|
|
|
|
|
invoices: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
send: true,
|
|
|
|
|
record_payment: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
files: { view: true, upload: true, delete: true, manage_folders: true },
|
|
|
|
|
email: { view: true, send: true, configure_account: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
reminders: {
|
|
|
|
|
view_own: true,
|
|
|
|
|
view_all: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit_own: true,
|
|
|
|
|
edit_all: true,
|
|
|
|
|
assign_others: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
calendar: { connect: true, view_events: true },
|
|
|
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
|
|
|
|
document_templates: { view: true, generate: true, manage: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
yachts: { view: true, create: true, edit: true, delete: true, transfer: true },
|
|
|
|
|
companies: { view: true, create: true, edit: true, delete: true },
|
|
|
|
|
memberships: { view: true, manage: true },
|
|
|
|
|
reservations: { view: true, create: true, activate: true, cancel: true },
|
|
|
|
|
admin: {
|
|
|
|
|
manage_users: true,
|
|
|
|
|
view_audit_log: true,
|
|
|
|
|
manage_settings: true,
|
|
|
|
|
manage_webhooks: true,
|
|
|
|
|
manage_reports: true,
|
|
|
|
|
manage_custom_fields: true,
|
|
|
|
|
manage_forms: true,
|
|
|
|
|
manage_tags: true,
|
|
|
|
|
system_backup: false,
|
|
|
|
|
},
|
feat(platform): residential module + admin UI + reliability fixes
Residential platform
- New schema: residentialClients, residentialInterests (separate from
marina/yacht clients) with migration 0010
- Service layer with CRUD + audit + sockets + per-port portal toggle
- v1 + public API routes (/api/v1/residential/*, /api/public/residential-inquiries)
- List + detail pages with inline editing for clients and interests
- Per-user residentialAccess toggle on userPortRoles (migration 0011)
- Permission keys: residential_clients, residential_interests
- Sidebar nav + role form integration
- Smoke spec covering page loads, UI create flow, public endpoint
Admin & shared UI
- Admin → Forms (form templates CRUD) with validators + service
- Notification preferences page (in-app + email per type)
- Email composition + accounts list + threads view
- Branded auth shell shared across CRM + portal auth surfaces
- Inline editing extended to yacht/company/interest detail pages
- InlineTagEditor + per-entity tags endpoints (yachts, companies)
- Notes service polymorphic across clients/interests/yachts/companies
- Client list columns: yachtCount + companyCount badges
- Reservation file-download via presigned URL (replaces stale <a href>)
Route handler refactor
- Extracted yachts/companies/berths reservation handlers to sibling
handlers.ts files (Next.js 15 route.ts only allows specific exports)
Reliability fixes
- apiFetch double-stringify bug fixed across 13 components
(apiFetch already JSON.stringifies its body; passing a stringified
body produced double-encoded JSON which failed zod validation)
- SocketProvider gated behind useSyncExternalStore-based mount check
to avoid useSession() SSR crashes under React 19 + Next 15
- apiFetch falls back to URL-pathname → port-id resolution when the
Zustand store hasn't hydrated yet (fresh contexts, e2e tests)
- CRM invite flow (schema, service, route, email, dev script)
- Dashboard route → [portSlug]/dashboard/page.tsx + redirect
- Document the dev-server restart-after-migration gotcha in CLAUDE.md
Tests
- 5-case residential smoke spec
- Integration test updates for new service signatures
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:54:32 +02:00
|
|
|
residential_clients: { view: true, create: true, edit: true, delete: true },
|
|
|
|
|
residential_interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: true,
|
|
|
|
|
change_stage: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SALES_MANAGER_PERMISSIONS: RolePermissions = {
|
|
|
|
|
clients: { view: true, create: true, edit: true, delete: false, merge: true, export: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
change_stage: true,
|
|
|
|
|
generate_eoi: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
feat(berths): full NocoDB field parity, numeric types, sales edit access
Aligns the berths schema with the 117 production rows in NocoDB and exposes
every field for editing via the BerthForm sheet.
Schema (migration 0020):
- power_capacity / voltage / nominal_boat_size / nominal_boat_size_m: text -> numeric
(NocoDB stores plain numbers; text was wrong shape and broke filter/sort)
- ADD status_override_mode text (1/117 legacy rows have a value; carried
forward for parity but not yet wired into the UI)
- USING NULLIF(TRIM(...), '')::numeric so legacy whitespace and empty
strings convert cleanly
Validator + service:
- updateBerthSchema / createBerthSchema use z.coerce.number() for the
four numeric fields
- berths.service stringifies numeric values for Drizzle's numeric type
Form (src/components/berths/berth-form.tsx):
- adds: nominal boat size (ft/m), water depth (ft/m) + "is minimum" flag,
side pontoon, cleat type/capacity, bollard type/capacity, bow facing
- converts to typed selects (with NocoDB option lists in src/lib/constants):
area, side pontoon, mooring type, cleat type/capacity, bollard type/capacity,
access
- power capacity / voltage become numeric inputs (with kW / V hints)
Permissions (seed.ts + dev DB):
- sales_manager and sales_agent: berths.edit false -> true
("sales will sometimes have to update these and I cannot be the only one")
- super_admin / director already had it; viewer stays read-only
- dev DB updated in-place via UPDATE roles ... jsonb_set
Verification:
- pnpm exec vitest run: 858/858 passing
- pnpm exec tsc --noEmit: same 36 errors as baseline (all pre-existing
on feat/mobile-foundation, none introduced)
- lint clean
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 15:30:32 +02:00
|
|
|
berths: { view: true, edit: true, import: false, manage_waiting_list: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
documents: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
send_for_signing: true,
|
|
|
|
|
upload_signed: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
},
|
|
|
|
|
expenses: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
export: true,
|
|
|
|
|
scan_receipt: true,
|
|
|
|
|
},
|
|
|
|
|
invoices: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
send: true,
|
|
|
|
|
record_payment: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
files: { view: true, upload: true, delete: false, manage_folders: true },
|
|
|
|
|
email: { view: true, send: true, configure_account: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
reminders: {
|
|
|
|
|
view_own: true,
|
|
|
|
|
view_all: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit_own: true,
|
|
|
|
|
edit_all: true,
|
|
|
|
|
assign_others: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
calendar: { connect: true, view_events: true },
|
|
|
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
|
|
|
|
document_templates: { view: true, generate: true, manage: false },
|
2026-04-24 12:30:06 +02:00
|
|
|
yachts: { view: true, create: true, edit: true, delete: false, transfer: true },
|
|
|
|
|
companies: { view: true, create: true, edit: true, delete: false },
|
|
|
|
|
memberships: { view: true, manage: true },
|
|
|
|
|
reservations: { view: true, create: true, activate: true, cancel: true },
|
|
|
|
|
admin: {
|
|
|
|
|
manage_users: false,
|
|
|
|
|
view_audit_log: false,
|
|
|
|
|
manage_settings: false,
|
|
|
|
|
manage_webhooks: false,
|
|
|
|
|
manage_reports: false,
|
|
|
|
|
manage_custom_fields: false,
|
|
|
|
|
manage_forms: false,
|
|
|
|
|
manage_tags: true,
|
|
|
|
|
system_backup: false,
|
|
|
|
|
},
|
feat(platform): residential module + admin UI + reliability fixes
Residential platform
- New schema: residentialClients, residentialInterests (separate from
marina/yacht clients) with migration 0010
- Service layer with CRUD + audit + sockets + per-port portal toggle
- v1 + public API routes (/api/v1/residential/*, /api/public/residential-inquiries)
- List + detail pages with inline editing for clients and interests
- Per-user residentialAccess toggle on userPortRoles (migration 0011)
- Permission keys: residential_clients, residential_interests
- Sidebar nav + role form integration
- Smoke spec covering page loads, UI create flow, public endpoint
Admin & shared UI
- Admin → Forms (form templates CRUD) with validators + service
- Notification preferences page (in-app + email per type)
- Email composition + accounts list + threads view
- Branded auth shell shared across CRM + portal auth surfaces
- Inline editing extended to yacht/company/interest detail pages
- InlineTagEditor + per-entity tags endpoints (yachts, companies)
- Notes service polymorphic across clients/interests/yachts/companies
- Client list columns: yachtCount + companyCount badges
- Reservation file-download via presigned URL (replaces stale <a href>)
Route handler refactor
- Extracted yachts/companies/berths reservation handlers to sibling
handlers.ts files (Next.js 15 route.ts only allows specific exports)
Reliability fixes
- apiFetch double-stringify bug fixed across 13 components
(apiFetch already JSON.stringifies its body; passing a stringified
body produced double-encoded JSON which failed zod validation)
- SocketProvider gated behind useSyncExternalStore-based mount check
to avoid useSession() SSR crashes under React 19 + Next 15
- apiFetch falls back to URL-pathname → port-id resolution when the
Zustand store hasn't hydrated yet (fresh contexts, e2e tests)
- CRM invite flow (schema, service, route, email, dev script)
- Dashboard route → [portSlug]/dashboard/page.tsx + redirect
- Document the dev-server restart-after-migration gotcha in CLAUDE.md
Tests
- 5-case residential smoke spec
- Integration test updates for new service signatures
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:54:32 +02:00
|
|
|
residential_clients: { view: false, create: false, edit: false, delete: false },
|
|
|
|
|
residential_interests: {
|
|
|
|
|
view: false,
|
|
|
|
|
create: false,
|
|
|
|
|
edit: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
change_stage: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SALES_AGENT_PERMISSIONS: RolePermissions = {
|
|
|
|
|
clients: { view: true, create: true, edit: true, delete: false, merge: false, export: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
change_stage: true,
|
|
|
|
|
generate_eoi: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
feat(berths): full NocoDB field parity, numeric types, sales edit access
Aligns the berths schema with the 117 production rows in NocoDB and exposes
every field for editing via the BerthForm sheet.
Schema (migration 0020):
- power_capacity / voltage / nominal_boat_size / nominal_boat_size_m: text -> numeric
(NocoDB stores plain numbers; text was wrong shape and broke filter/sort)
- ADD status_override_mode text (1/117 legacy rows have a value; carried
forward for parity but not yet wired into the UI)
- USING NULLIF(TRIM(...), '')::numeric so legacy whitespace and empty
strings convert cleanly
Validator + service:
- updateBerthSchema / createBerthSchema use z.coerce.number() for the
four numeric fields
- berths.service stringifies numeric values for Drizzle's numeric type
Form (src/components/berths/berth-form.tsx):
- adds: nominal boat size (ft/m), water depth (ft/m) + "is minimum" flag,
side pontoon, cleat type/capacity, bollard type/capacity, bow facing
- converts to typed selects (with NocoDB option lists in src/lib/constants):
area, side pontoon, mooring type, cleat type/capacity, bollard type/capacity,
access
- power capacity / voltage become numeric inputs (with kW / V hints)
Permissions (seed.ts + dev DB):
- sales_manager and sales_agent: berths.edit false -> true
("sales will sometimes have to update these and I cannot be the only one")
- super_admin / director already had it; viewer stays read-only
- dev DB updated in-place via UPDATE roles ... jsonb_set
Verification:
- pnpm exec vitest run: 858/858 passing
- pnpm exec tsc --noEmit: same 36 errors as baseline (all pre-existing
on feat/mobile-foundation, none introduced)
- lint clean
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 15:30:32 +02:00
|
|
|
berths: { view: true, edit: true, import: false, manage_waiting_list: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
documents: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
send_for_signing: true,
|
|
|
|
|
upload_signed: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
},
|
|
|
|
|
expenses: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
export: true,
|
|
|
|
|
scan_receipt: true,
|
|
|
|
|
},
|
|
|
|
|
invoices: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: true,
|
|
|
|
|
edit: true,
|
|
|
|
|
delete: false,
|
|
|
|
|
send: true,
|
|
|
|
|
record_payment: true,
|
|
|
|
|
export: true,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
files: { view: true, upload: true, delete: false, manage_folders: false },
|
|
|
|
|
email: { view: true, send: true, configure_account: true },
|
2026-04-24 12:30:06 +02:00
|
|
|
reminders: {
|
|
|
|
|
view_own: true,
|
|
|
|
|
view_all: false,
|
|
|
|
|
create: true,
|
|
|
|
|
edit_own: true,
|
|
|
|
|
edit_all: false,
|
|
|
|
|
assign_others: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
calendar: { connect: true, view_events: true },
|
|
|
|
|
reports: { view_dashboard: true, view_analytics: true, export: true },
|
|
|
|
|
document_templates: { view: true, generate: true, manage: false },
|
2026-04-24 12:30:06 +02:00
|
|
|
yachts: { view: true, create: true, edit: true, delete: false, transfer: false },
|
|
|
|
|
companies: { view: true, create: true, edit: false, delete: false },
|
|
|
|
|
memberships: { view: true, manage: false },
|
|
|
|
|
reservations: { view: true, create: true, activate: true, cancel: false },
|
|
|
|
|
admin: {
|
|
|
|
|
manage_users: false,
|
|
|
|
|
view_audit_log: false,
|
|
|
|
|
manage_settings: false,
|
|
|
|
|
manage_webhooks: false,
|
|
|
|
|
manage_reports: false,
|
|
|
|
|
manage_custom_fields: false,
|
|
|
|
|
manage_forms: false,
|
|
|
|
|
manage_tags: true,
|
|
|
|
|
system_backup: false,
|
|
|
|
|
},
|
feat(platform): residential module + admin UI + reliability fixes
Residential platform
- New schema: residentialClients, residentialInterests (separate from
marina/yacht clients) with migration 0010
- Service layer with CRUD + audit + sockets + per-port portal toggle
- v1 + public API routes (/api/v1/residential/*, /api/public/residential-inquiries)
- List + detail pages with inline editing for clients and interests
- Per-user residentialAccess toggle on userPortRoles (migration 0011)
- Permission keys: residential_clients, residential_interests
- Sidebar nav + role form integration
- Smoke spec covering page loads, UI create flow, public endpoint
Admin & shared UI
- Admin → Forms (form templates CRUD) with validators + service
- Notification preferences page (in-app + email per type)
- Email composition + accounts list + threads view
- Branded auth shell shared across CRM + portal auth surfaces
- Inline editing extended to yacht/company/interest detail pages
- InlineTagEditor + per-entity tags endpoints (yachts, companies)
- Notes service polymorphic across clients/interests/yachts/companies
- Client list columns: yachtCount + companyCount badges
- Reservation file-download via presigned URL (replaces stale <a href>)
Route handler refactor
- Extracted yachts/companies/berths reservation handlers to sibling
handlers.ts files (Next.js 15 route.ts only allows specific exports)
Reliability fixes
- apiFetch double-stringify bug fixed across 13 components
(apiFetch already JSON.stringifies its body; passing a stringified
body produced double-encoded JSON which failed zod validation)
- SocketProvider gated behind useSyncExternalStore-based mount check
to avoid useSession() SSR crashes under React 19 + Next 15
- apiFetch falls back to URL-pathname → port-id resolution when the
Zustand store hasn't hydrated yet (fresh contexts, e2e tests)
- CRM invite flow (schema, service, route, email, dev script)
- Dashboard route → [portSlug]/dashboard/page.tsx + redirect
- Document the dev-server restart-after-migration gotcha in CLAUDE.md
Tests
- 5-case residential smoke spec
- Integration test updates for new service signatures
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:54:32 +02:00
|
|
|
residential_clients: { view: false, create: false, edit: false, delete: false },
|
|
|
|
|
residential_interests: {
|
|
|
|
|
view: false,
|
|
|
|
|
create: false,
|
|
|
|
|
edit: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
change_stage: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const VIEWER_PERMISSIONS: RolePermissions = {
|
|
|
|
|
clients: { view: true, create: false, edit: false, delete: false, merge: false, export: false },
|
2026-04-24 12:30:06 +02:00
|
|
|
interests: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: false,
|
|
|
|
|
edit: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
change_stage: false,
|
|
|
|
|
generate_eoi: false,
|
|
|
|
|
export: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
berths: { view: true, edit: false, import: false, manage_waiting_list: false },
|
2026-04-24 12:30:06 +02:00
|
|
|
documents: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: false,
|
|
|
|
|
send_for_signing: false,
|
|
|
|
|
upload_signed: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
},
|
|
|
|
|
expenses: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: false,
|
|
|
|
|
edit: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
export: false,
|
|
|
|
|
scan_receipt: false,
|
|
|
|
|
},
|
|
|
|
|
invoices: {
|
|
|
|
|
view: true,
|
|
|
|
|
create: false,
|
|
|
|
|
edit: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
send: false,
|
|
|
|
|
record_payment: false,
|
|
|
|
|
export: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
files: { view: true, upload: false, delete: false, manage_folders: false },
|
|
|
|
|
email: { view: true, send: false, configure_account: false },
|
2026-04-24 12:30:06 +02:00
|
|
|
reminders: {
|
|
|
|
|
view_own: true,
|
|
|
|
|
view_all: false,
|
|
|
|
|
create: false,
|
|
|
|
|
edit_own: false,
|
|
|
|
|
edit_all: false,
|
|
|
|
|
assign_others: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
calendar: { connect: false, view_events: true },
|
|
|
|
|
reports: { view_dashboard: true, view_analytics: false, export: false },
|
|
|
|
|
document_templates: { view: true, generate: false, manage: false },
|
2026-04-24 12:30:06 +02:00
|
|
|
yachts: { view: true, create: false, edit: false, delete: false, transfer: false },
|
|
|
|
|
companies: { view: true, create: false, edit: false, delete: false },
|
|
|
|
|
memberships: { view: true, manage: false },
|
|
|
|
|
reservations: { view: true, create: false, activate: false, cancel: false },
|
|
|
|
|
admin: {
|
|
|
|
|
manage_users: false,
|
|
|
|
|
view_audit_log: false,
|
|
|
|
|
manage_settings: false,
|
|
|
|
|
manage_webhooks: false,
|
|
|
|
|
manage_reports: false,
|
|
|
|
|
manage_custom_fields: false,
|
|
|
|
|
manage_forms: false,
|
|
|
|
|
manage_tags: false,
|
|
|
|
|
system_backup: false,
|
|
|
|
|
},
|
feat(platform): residential module + admin UI + reliability fixes
Residential platform
- New schema: residentialClients, residentialInterests (separate from
marina/yacht clients) with migration 0010
- Service layer with CRUD + audit + sockets + per-port portal toggle
- v1 + public API routes (/api/v1/residential/*, /api/public/residential-inquiries)
- List + detail pages with inline editing for clients and interests
- Per-user residentialAccess toggle on userPortRoles (migration 0011)
- Permission keys: residential_clients, residential_interests
- Sidebar nav + role form integration
- Smoke spec covering page loads, UI create flow, public endpoint
Admin & shared UI
- Admin → Forms (form templates CRUD) with validators + service
- Notification preferences page (in-app + email per type)
- Email composition + accounts list + threads view
- Branded auth shell shared across CRM + portal auth surfaces
- Inline editing extended to yacht/company/interest detail pages
- InlineTagEditor + per-entity tags endpoints (yachts, companies)
- Notes service polymorphic across clients/interests/yachts/companies
- Client list columns: yachtCount + companyCount badges
- Reservation file-download via presigned URL (replaces stale <a href>)
Route handler refactor
- Extracted yachts/companies/berths reservation handlers to sibling
handlers.ts files (Next.js 15 route.ts only allows specific exports)
Reliability fixes
- apiFetch double-stringify bug fixed across 13 components
(apiFetch already JSON.stringifies its body; passing a stringified
body produced double-encoded JSON which failed zod validation)
- SocketProvider gated behind useSyncExternalStore-based mount check
to avoid useSession() SSR crashes under React 19 + Next 15
- apiFetch falls back to URL-pathname → port-id resolution when the
Zustand store hasn't hydrated yet (fresh contexts, e2e tests)
- CRM invite flow (schema, service, route, email, dev script)
- Dashboard route → [portSlug]/dashboard/page.tsx + redirect
- Document the dev-server restart-after-migration gotcha in CLAUDE.md
Tests
- 5-case residential smoke spec
- Integration test updates for new service signatures
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 21:54:32 +02:00
|
|
|
residential_clients: { view: false, create: false, edit: false, delete: false },
|
|
|
|
|
residential_interests: {
|
|
|
|
|
view: false,
|
|
|
|
|
create: false,
|
|
|
|
|
edit: false,
|
|
|
|
|
delete: false,
|
|
|
|
|
change_stage: false,
|
|
|
|
|
},
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
};
|
|
|
|
|
|
2026-04-24 13:26:37 +02:00
|
|
|
// ─── Port Definitions ────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
const PORT_DEFINITIONS: Array<{
|
|
|
|
|
name: string;
|
|
|
|
|
slug: string;
|
|
|
|
|
primaryColor: string;
|
|
|
|
|
defaultCurrency: string;
|
|
|
|
|
timezone: string;
|
|
|
|
|
}> = [
|
|
|
|
|
{
|
|
|
|
|
name: 'Port Nimara',
|
|
|
|
|
slug: 'port-nimara',
|
|
|
|
|
primaryColor: '#0F4C81',
|
|
|
|
|
defaultCurrency: 'USD',
|
|
|
|
|
timezone: 'America/Anguilla',
|
|
|
|
|
},
|
2026-05-03 15:59:36 +02:00
|
|
|
// Second port kept for multi-tenant isolation tests (cross-port scoping,
|
|
|
|
|
// permission boundaries). Drop or rename if the production install is
|
|
|
|
|
// single-port.
|
2026-04-24 13:26:37 +02:00
|
|
|
{
|
2026-05-03 15:59:36 +02:00
|
|
|
name: 'Port Amador',
|
|
|
|
|
slug: 'port-amador',
|
|
|
|
|
primaryColor: '#D97706',
|
|
|
|
|
defaultCurrency: 'USD',
|
|
|
|
|
timezone: 'America/Panama',
|
2026-04-24 13:26:37 +02:00
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
// ─── Seed Function ────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
async function seed() {
|
|
|
|
|
console.log('Seeding Port Nimara CRM...');
|
|
|
|
|
|
2026-04-24 13:26:37 +02:00
|
|
|
// ── 1. Ports ────────────────────────────────────────────────────────────────
|
|
|
|
|
console.log('Creating ports...');
|
|
|
|
|
const portIds: Array<{ id: string; name: string; slug: string }> = [];
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
|
2026-04-24 13:26:37 +02:00
|
|
|
for (const def of PORT_DEFINITIONS) {
|
|
|
|
|
const [inserted] = await db
|
|
|
|
|
.insert(ports)
|
|
|
|
|
.values({
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
name: def.name,
|
|
|
|
|
slug: def.slug,
|
|
|
|
|
logoUrl: null,
|
|
|
|
|
primaryColor: def.primaryColor,
|
|
|
|
|
defaultCurrency: def.defaultCurrency,
|
|
|
|
|
timezone: def.timezone,
|
|
|
|
|
settings: {},
|
|
|
|
|
isActive: true,
|
|
|
|
|
})
|
|
|
|
|
.onConflictDoNothing()
|
|
|
|
|
.returning();
|
|
|
|
|
|
|
|
|
|
if (inserted) {
|
|
|
|
|
console.log(` Port created: ${def.name} (${inserted.id})`);
|
|
|
|
|
portIds.push({ id: inserted.id, name: def.name, slug: def.slug });
|
|
|
|
|
} else {
|
|
|
|
|
// Port already existed — look it up so we can still seed fixtures for it.
|
|
|
|
|
const [existing] = await db.select().from(ports).where(eq(ports.slug, def.slug)).limit(1);
|
|
|
|
|
if (existing) {
|
|
|
|
|
console.log(` Port exists: ${def.name} (${existing.id})`);
|
|
|
|
|
portIds.push({ id: existing.id, name: def.name, slug: def.slug });
|
|
|
|
|
} else {
|
|
|
|
|
console.warn(` Port insert conflict but lookup returned no row: ${def.slug}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── 2. System Roles ─────────────────────────────────────────────────────────
|
|
|
|
|
console.log('Creating system roles...');
|
|
|
|
|
|
|
|
|
|
const systemRoles = [
|
|
|
|
|
{
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
name: 'super_admin',
|
|
|
|
|
description: 'Full system access. Bypasses all permission checks.',
|
|
|
|
|
permissions: ALL_PERMISSIONS,
|
|
|
|
|
isGlobal: true,
|
|
|
|
|
isSystem: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
name: 'director',
|
|
|
|
|
description: 'Operational admin within assigned port(s). Can manage users and settings.',
|
|
|
|
|
permissions: DIRECTOR_PERMISSIONS,
|
|
|
|
|
isGlobal: true,
|
|
|
|
|
isSystem: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
name: 'sales_manager',
|
|
|
|
|
description: 'Full sales access. Can view all reminders, assign tasks, and export reports.',
|
|
|
|
|
permissions: SALES_MANAGER_PERMISSIONS,
|
|
|
|
|
isGlobal: true,
|
|
|
|
|
isSystem: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
name: 'sales_agent',
|
2026-04-24 12:30:06 +02:00
|
|
|
description:
|
|
|
|
|
'Standard sales role. View/create/edit clients and interests, manage own reminders.',
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
permissions: SALES_AGENT_PERMISSIONS,
|
|
|
|
|
isGlobal: true,
|
|
|
|
|
isSystem: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
name: 'viewer',
|
|
|
|
|
description: 'Read-only access to all records.',
|
|
|
|
|
permissions: VIEWER_PERMISSIONS,
|
|
|
|
|
isGlobal: true,
|
|
|
|
|
isSystem: true,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
for (const role of systemRoles) {
|
|
|
|
|
await db.insert(roles).values(role).onConflictDoNothing();
|
2026-04-24 13:26:37 +02:00
|
|
|
console.log(` Role: ${role.name}`);
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── 3. Super Admin User Profile ─────────────────────────────────────────────
|
|
|
|
|
// Note: Better Auth creates the actual `user` record on first login.
|
|
|
|
|
// We create the profile extension now, linked to a known user_id.
|
|
|
|
|
// The Better Auth user_id for matt@portnimara.com must match this value
|
|
|
|
|
// once Better Auth is configured. Use a stable placeholder ID here.
|
|
|
|
|
console.log('Creating super admin user profile...');
|
|
|
|
|
|
|
|
|
|
const superAdminUserId = 'super-admin-matt-portnimara';
|
|
|
|
|
|
|
|
|
|
await db
|
|
|
|
|
.insert(userProfiles)
|
|
|
|
|
.values({
|
|
|
|
|
id: crypto.randomUUID(),
|
|
|
|
|
userId: superAdminUserId,
|
|
|
|
|
displayName: 'Matt',
|
|
|
|
|
avatarUrl: null,
|
|
|
|
|
phone: null,
|
|
|
|
|
isSuperAdmin: true,
|
|
|
|
|
isActive: true,
|
|
|
|
|
lastLoginAt: null,
|
|
|
|
|
preferences: {},
|
|
|
|
|
})
|
|
|
|
|
.onConflictDoNothing();
|
|
|
|
|
|
2026-04-24 13:26:37 +02:00
|
|
|
console.log(` Super admin profile for user_id: ${superAdminUserId}`);
|
|
|
|
|
|
|
|
|
|
// ── 4. Per-port fixtures ────────────────────────────────────────────────────
|
|
|
|
|
console.log('');
|
|
|
|
|
console.log('Seeding per-port fixtures...');
|
|
|
|
|
|
|
|
|
|
const summaries: Array<{ name: string; summary: SeedSummary | null }> = [];
|
|
|
|
|
for (const p of portIds) {
|
|
|
|
|
console.log(` [${p.slug}] seeding fixture data...`);
|
|
|
|
|
const summary = await seedPortData(p.id, p.slug);
|
|
|
|
|
summaries.push({ name: p.name, summary });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ── 5. Summary ─────────────────────────────────────────────────────────────
|
|
|
|
|
console.log('');
|
|
|
|
|
console.log('─── Summary ───────────────────────────────────────────────');
|
|
|
|
|
for (const s of summaries) {
|
|
|
|
|
if (s.summary === null) {
|
|
|
|
|
console.log(` ✓ Port "${s.name}" — already seeded (skipped)`);
|
|
|
|
|
} else {
|
|
|
|
|
const x = s.summary;
|
|
|
|
|
console.log(
|
|
|
|
|
` ✓ Port "${s.name}" — ${x.berths} berths, ${x.clients} clients, ${x.companies} companies, ${x.yachts} yachts, ${x.interests} interests, ${x.reservations} reservations`,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00
|
|
|
console.log('');
|
|
|
|
|
console.log('Seed complete!');
|
|
|
|
|
console.log('');
|
|
|
|
|
console.log('NOTE: The Better Auth user for matt@portnimara.com must be created');
|
|
|
|
|
console.log(`separately. Once created, update user_profiles.user_id to match`);
|
|
|
|
|
console.log(`the actual Better Auth user ID (currently placeholder: ${superAdminUserId})`);
|
|
|
|
|
|
|
|
|
|
process.exit(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
seed().catch((err) => {
|
|
|
|
|
console.error('Seed failed:', err);
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|