cb150f7a24
- CRM domain modules removed (customers, services, software, calendar, tasks, invoices, leads, finance, etc.)
- DLS branding: package name=lab, logo wordmark, sidebar nav, header CTA
- Tenant layer extended with kind dimension (lab|clinic) + requireTenantKind helper
- Schema rewritten for DLS domain: jobs, job_files, job_status_history, prosthetics, connections, finance_entries, notifications
- Onboarding form: clinic/lab account-type selection + auto-generated memberNumber
- Placeholder routes for jobs/{inbound,outbound,new}, products, finance, connections
- PDF spec + spec.md under belgeler/
- db: lab database + 13 collections + indexes + storage bucket (job-files) provisioned via Appwrite MCP
Ref: belgeler/dls-ui-tasarim.pdf
127 lines
6.3 KiB
Markdown
127 lines
6.3 KiB
Markdown
# DLS — Dental Lab System
|
||
|
||
Diş klinikleri ↔ diş laboratuvarları arasında iş alışverişi, dosya paylaşımı ve finansal takip platformu. KovakSoft müşterileri ya **Klinik** ya da **Laboratuvar** olarak kayıt olur, "bağlantı kodu" ile karşı tarafla eşleşir, iş gönderir/alır ve ödeme akışını yönetir.
|
||
|
||
Baz: [isletmem-kovakcrm](https://git.kovaksoft.com/kovakmedya/isletmem-kovakcrm) (silicondeck/shadcn-dashboard-landing-template türevi). Auth + tenant katmanı + tema + server actions altyapısı aynen kullanılıyor; sadece domain modülleri DLS için yeniden yazıldı.
|
||
|
||
## 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**, **Recharts**
|
||
- **Appwrite** — DB, Auth, Storage, Teams (tenant izolasyonu)
|
||
- **pnpm** — package manager
|
||
- **Coolify** — Gitea webhook ile auto-deploy
|
||
|
||
## Multi-tenancy modeli
|
||
|
||
| Concept | Appwrite primitive |
|
||
|---|---|
|
||
| Tenant | Appwrite **Team** (1 team = 1 klinik veya 1 lab) |
|
||
| Tenant türü (`kind`) | `tenant_settings.kind: 'lab' \| 'clinic'` |
|
||
| Tenant üyesi | Team membership (rol: `owner` / `admin` / `member`) |
|
||
| Bağlantı kodu | `tenant_settings.memberNumber` (6 hane unique) |
|
||
| Veri izolasyonu | Her doküman `tenantId` + `Permission.read/update/delete(Role.team(tenantId))` |
|
||
| Cross-tenant erişim | `jobs`, `job_files`, `job_status_history`, `finance_entries` ek olarak karşı tarafın team permission'ına açılır |
|
||
|
||
**Kural:** Tek shared tenant değil — her klinik ve her lab kendi Appwrite Team'idir, izolasyon CRM ile aynı. `kind` boyutu sadece UI/route koruması ve iş akışı için. `requireTenantKind(ctx, ['lab'])` route guard helper'ı kullanılır.
|
||
|
||
## Modüller
|
||
|
||
| Modül | Rol | Collection(lar) |
|
||
|---|---|---|
|
||
| Anasayfa | her ikisi | (özet kartlar) |
|
||
| Gelen İşler | her ikisi | `jobs` (lab tarafında baskın) |
|
||
| Giden İşler | her ikisi | `jobs` (klinik tarafında baskın) |
|
||
| Yeni İş Yayınla | sadece klinik | `jobs` + `job_files` |
|
||
| İş detay (durum stepper) | her ikisi | `jobs` + `job_status_history` (Ölçü → Alt Yapı → Üst Yapı → Cila/Bitim) |
|
||
| Ürünler | sadece lab | `prosthetics` |
|
||
| Finans | her ikisi | `finance_entries` |
|
||
| Bağlantı Kur | her ikisi | `connections` (bağlantı kodu ile eşleşme) |
|
||
| Ayarlar | her ikisi | `tenant_settings`, üye yönetimi |
|
||
|
||
Tüm collection'larda ortak: `tenantId` (sahip), `createdBy` (userId), `$createdAt`, `$updatedAt`. Cross-tenant collection'lar (jobs, job_files, finance_entries) ek olarak `clinicTenantId` + `labTenantId` taşır.
|
||
|
||
## Bağlantı (connections) akışı
|
||
|
||
1. Klinik karşı laboratuvarın `memberNumber`'ını girer → `connections` row oluşur (`status: pending`).
|
||
2. Lab kendi tarafında pending talebi görür, **Onayla** veya **Reddet**.
|
||
3. Onaylanan bağlantı `status: approved`, sonrasında `Yeni İş Yayınla` formunda klinik bağlı lab'lerden birini seçebilir.
|
||
4. İş oluştuğunda dokümana karşı tarafın `Role.team(<otherTenantId>)` read/update permission'ı eklenir → karşı taraf otomatik görür.
|
||
|
||
## Auth
|
||
|
||
Appwrite Auth — email/password. CRM'deki akış aynen geçerli.
|
||
- Register → onboarding → **Klinik / Laboratuvar** seçimi + şirket bilgileri → `tenant_settings.kind` atanır, `memberNumber` üretilir → dashboard.
|
||
- `lib/appwrite/server.ts` — server SDK (API key ile admin ops)
|
||
- `lib/appwrite/client.ts` — browser SDK (session JWT)
|
||
- Cookie: `lab-session`, `lab-tenant`. Middleware: korumalı `(dashboard)/*`, public `(auth)/*` + marketing.
|
||
|
||
## Klasör yapısı
|
||
|
||
```
|
||
src/
|
||
├── app/
|
||
│ ├── (auth)/ login, register, reset-password
|
||
│ ├── (dashboard)/ dashboard, jobs/{inbound,outbound,new,[id]}, products, finance, connections, settings
|
||
│ ├── d/[code]/ team davet kabul
|
||
│ ├── landing/ marketing
|
||
│ └── onboarding/ ilk workspace + kind seçimi
|
||
├── components/ shadcn/ui + custom (logo, sidebar, header)
|
||
├── lib/
|
||
│ ├── appwrite/ client.ts, server.ts, schema.ts, tenant-guard.ts, ...
|
||
│ └── validation/
|
||
├── middleware.ts
|
||
└── ...
|
||
```
|
||
|
||
## Komutlar
|
||
|
||
```bash
|
||
pnpm dev # localhost:3000
|
||
pnpm build
|
||
pnpm lint
|
||
pnpm typecheck # tsc --noEmit
|
||
```
|
||
|
||
## Appwrite — MCP üzerinden işlemler
|
||
|
||
`DATABASE_ID = "lab"` — isletmem-kovakcrm projesi (ID `69f27b51000a5bee46ce`) altında ayrı database. Tüm collection / attribute / index / permission CRUD'u **Appwrite MCP** ile yapılır. Migration mantığı: yeni collection / attribute eklendiğinde MCP komutu çalıştır + `lib/appwrite/schema.ts` güncellenir (tek source of truth).
|
||
|
||
## Gitea + Coolify deploy
|
||
|
||
- **Repo:** `ssh://git@git.kovaksoft.com:2222/kovakmedya/lab.git`
|
||
- **Coolify host:** `kovaksoft-coolify` (`ssh -p 22 root@194.31.52.65`)
|
||
- **Production domain:** `https://lab.kovakcrm.com`
|
||
- **Workflow:** `main` branch'e push → Gitea webhook → Coolify auto-deploy.
|
||
- **Webhook URL (Coolify Gitea handler):** `https://admin.kovaksoft.com/webhooks/source/gitea/events/manual`
|
||
|
||
## Environment variables
|
||
|
||
```
|
||
NEXT_PUBLIC_APPWRITE_ENDPOINT=https://db.kovaksoft.com/v1
|
||
NEXT_PUBLIC_APPWRITE_PROJECT_ID=69f27b51000a5bee46ce
|
||
NEXT_PUBLIC_APPWRITE_DATABASE_ID=lab
|
||
APPWRITE_API_KEY= # server-only
|
||
APP_URL=https://lab.kovakcrm.com
|
||
```
|
||
|
||
`.env.local` git'e gitmez. Coolify'da ayrı set edilir.
|
||
|
||
## Geliştirme prensipleri
|
||
|
||
- **Mevcut temayı koru, brand değiştir.** Sidebar / header / theme customizer aynen kalır; sadece içerik DLS modüllerine bağlı.
|
||
- **Tenant filtresi şart.** Server actions / route handlers'da `tenantId` (veya cross-tenant durumda `clinicTenantId`/`labTenantId`) her query'ye eklenmeden veri çekme.
|
||
- **Server actions tercih edilir** — client'tan direkt Appwrite write yerine, server action içinden server SDK ile.
|
||
- **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
|
||
- Baz repo: https://git.kovaksoft.com/kovakmedya/isletmem-kovakcrm
|
||
- UI spec: `belgeler/dls-ui-tasarim.pdf` (orijinal Figma export)
|