# İşletmem KovakCRM Multi-tenant CRM. KovakSoft müşterileri kendi şirketleri için müşteri / hizmet / yazılım / takvim / görev / finans yönetir. Her tenant kendi verilerini görür, çapraz erişim yok. ## Stack - **Next.js 16** + **React 19** (App Router, TypeScript) - **Tailwind CSS v4** + **shadcn/ui v3** (Radix primitives) - **Zustand** — client state - **TanStack Table**, **react-hook-form** + **Zod**, **dnd-kit** (Kanban), **Recharts** (template'den) - **Appwrite** — DB, Auth, Storage, Teams (tenant izolasyonu) - **pnpm** — package manager - **Coolify** — Gitea webhook ile auto-deploy Template kaynağı: `silicondeck/shadcn-dashboard-landing-template` (MIT). `nextjs-version/` klonlandı, görsel tasarım ve mevcut dashboard davranışı korunacak — sadece data layer Appwrite'e bağlanıyor. ## Multi-tenancy modeli | Concept | Appwrite primitive | |---|---| | Tenant | Appwrite **Team** (1 team = 1 şirket) | | Tenant üyesi | Team membership (rol: `owner` / `admin` / `member`) | | Veri izolasyonu | Her doküman `tenantId` attribute + `Permission.read/update/delete(Role.team(tenantId))` | | Tenant onboarding | İlk login'de team yoksa "create workspace" akışı | | Üye daveti | Appwrite `teams.createMembership` (email + role) → davet linki → kabul ile team'e dahil | **Kural:** Tüm collection'larda `tenantId` zorunlu attribute, indexed. Server-side query'lerde her zaman tenant filtresi uygulanır. Client SDK'da row-level security Appwrite Permissions ile garantilenir — kod hatasında dahi başka tenant verisi görünmez. ## Modüller | Modül | Collection | Notlar | |---|---|---| | Müşteriler | `customers` | name, email, phone, taxId, address, notes | | Hizmetler | `services` | name, description, unitPrice, currency, customerId (FK) | | Yazılımlarımız | `software` + `customer_software` | software (name, version, license); customer_software (many-to-many: customerId × softwareId, startDate, endDate, fee) | | Takvim | `calendar_events` | title, start, end, allDay, customerId?, color | | Görevler (Kanban) | `tasks` | title, description, status (`backlog`/`todo`/`in_progress`/`done`), priority, dueDate, assigneeId | | Finans | `finance_entries` | type (`income`/`expense`/`debt`/`receivable`), amount, currency, date, customerId?, invoiceId?, note | | Faturalar | `invoices` + `invoice_items` | number, customerId, issueDate, dueDate, status, totals; items (description, qty, unitPrice, vat) | | Profil ayarları | Appwrite user prefs + `tenant_settings` | tenant logo, currency default, vat default | Tüm collection'larda ortak: `tenantId`, `createdBy` (userId), `$createdAt`, `$updatedAt`. ## Auth Appwrite Auth — email/password (başlangıçta). Sonrası: magic URL + Google OAuth. - Login → team list çekilir → tek team varsa direkt dashboard, çoksa workspace switcher. - `lib/appwrite/server.ts` — server SDK (API key ile admin ops, server actions). - `lib/appwrite/client.ts` — browser SDK (session JWT, client components). - Middleware: korumalı route'lar `(dashboard)/*`, public `(auth)/*` ve marketing. ## Klasör yapısı (template'den korunan) ``` src/ ├── app/ │ ├── (auth)/ login, register, reset-password │ ├── (dashboard)/ customers, services, software, calendar, tasks, finance, invoices, settings │ └── landing/ marketing ├── assets/ SVG, images ├── components/ shadcn/ui + custom ├── config/ site config, nav ├── contexts/ React contexts ├── hooks/ ├── lib/ │ ├── appwrite/ client.ts, server.ts, schema.ts (eklenecek) │ └── tenant/ resolveTenant(), withTenant() (eklenecek) ├── middleware.ts auth/route protection ├── types/ └── utils/ ``` ## Komutlar ```bash pnpm dev # localhost:3000 pnpm build pnpm lint pnpm typecheck # tsc --noEmit ``` ## Appwrite — MCP üzerinden işlemler Database, collection, attribute, index, permission CRUD'u **Appwrite MCP** ile yapılır (manual console tıklaması yok). Migration mantığı: yeni collection / attribute eklendiğinde MCP komutu çalıştır + `lib/appwrite/schema.ts` güncellenir (tek source of truth, tipler oradan üretilir). ``` # MCP tool format tool: tables_db_create | tables_db_create_table | tables_db_create_string_attribute | ... ``` ## Gitea + Coolify deploy - **Repo:** `ssh://git@git.kovaksoft.com:2222/kovakmedya/isletmem-kovakcrm.git` - **Coolify host:** `kovaksoft-coolify` (`ssh -p 22 root@194.31.52.65`) - **Production domain:** `https://isletmem.kovakcrm.com` - **Workflow:** `main` branch'e push → Gitea webhook → Coolify auto-deploy. - Coolify'a Appwrite ENV'leri girilir (aşağı bak), build command `pnpm build`, start `pnpm start`. ## Environment variables ``` NEXT_PUBLIC_APPWRITE_ENDPOINT= NEXT_PUBLIC_APPWRITE_PROJECT_ID= APPWRITE_API_KEY= # server-only NEXT_PUBLIC_APPWRITE_DATABASE_ID= APP_URL=https://isletmem.kovakcrm.com ``` `.env.local` git'e gitmez. Coolify'da ayrı set edilir. ## Geliştirme prensipleri - **Template görselini bozma.** Sayfa layout, sidebar, theme, component'ler aynı kalır; sadece içerikteki demo data Appwrite'a bağlanır. - **Tenant filtresi şart.** Server actions / route handlers'da `tenantId`'yi her query'ye eklemeden veri çekme. - **Server actions tercih edilir** — client'tan direkt Appwrite write yerine, server action içinden server SDK ile (validation + audit kolay). - **Schema değişikliği = MCP çağrısı + `schema.ts` update + migration notu** (commit mesajına `db:` prefix). - **Türkçe UI**, kod İngilizce. ## Faydalı referanslar - Gitea CLI: `tea repos list --login git.kovaksoft.com` - Coolify VPS SSH: `ssh kovaksoft-coolify` - Appwrite docs: https://appwrite.io/docs - Template repo: https://github.com/silicondeck/shadcn-dashboard-landing-template