# DLS — Ürün Tasarım Spec'i

Bu dosya `dls-ui-tasarim.pdf` (orijinal Figma export) baz alınarak hazırlanmış geliştirilmiş ürün spec'idir. PDF UI mock'ları içerir; bu doküman akış, veri modeli, rol ayrımı ve karar gerektiren noktaları somutlaştırır.

## Sistem özeti

DLS, **diş klinikleri** ile **diş laboratuvarları** arasındaki iş alışverişini dijitalleştirir:

- Klinik bir hasta için protez işi açar (tür, üye sayısı, renk, ölçü taraması, görseller).
- İşi bağlı bir laboratuvara yollar.
- Laboratuvar gelen kutusundan görür, durum adımlarını işler (Ölçü → Alt Yapı → Üst Yapı → Cila/Bitim).
- Tamamlandığında klinik gönderim aşamasına geçer.
- Her iki taraf finansal akışı (ödenmiş/bekleyen) kendi tarafında izler.

## Roller

Tek bir hesap modeli, iki tenant türü (`kind`):

| `kind` | İlgili eylemler |
|---|---|
| `clinic` | İş yayınla, kendi gönderdiklerini takip et, lab bağlantısı talep et, ödeme yap |
| `lab` | Ürün katalog yönet, gelen işleri al/onayla, durum güncelle, fatura kes |

`requireTenantKind(ctx, ['lab' \| 'clinic'])` server-side route guard — sayfa render edilmeden önce yetki sorgular.

## Sayfa haritası (PDF'e göre)

| URL | PDF sayfa | İçerik |
|---|---|---|
| `/dashboard` | 1 | Anasayfa — özet kartlar (açık işler, işlem bekleyen, bildirimler, istatistik chart) |
| `/jobs/inbound` | 2 | Gelen İşler tablosu (Klinik / Hasta Kodu / Üye / Renk / Tür / Açıklama / İşlem) |
| `/jobs/[id]` | 3 | İş detay — bilgiler + durum stepper (Ölçü / Alt Yapı Prova / Üst Yapı Prova / Cila/Bitim) + Görselleri Görüntüle / Taranan Dosyalar / Kaydet |
| `/jobs/outbound` | 4 | Giden İşler tablosu (aynı sütunlar) |
| `/jobs/new` | (header CTA) | "Yeni İş Yayınla" formu — klinik tarafı |
| `/products` | 5 | Eklenen Ürünler (sadece lab) — Protez Türü / Fiyat tablo + ekleme formu |
| `/finance` | 6 | Finans (Bekliyor) — tahsilat/ödeme listesi |
| `/connections` | 7 | Bağlantı Kur — kendi bağlantı kodun + bekleyen talepler + onaylı bağlantılar |
| `/settings/*` | 8 | Ayarlar (workspace, üye, hesap, görünüm) |
| `/sign-in`, `/sign-up` | 9 | Giriş/kayıt — PDF "Labaratuvar Giriş" + "Klinik Giriş" iki ayrı form gösteriyor; biz tek form + onboarding'de `kind` seçimi yapıyoruz |

> PDF'teki "Üye Numarası" alanı login'de **kullanılmıyor**. Üye numarası `tenant_settings.memberNumber` olarak sistem tarafından üretiliyor ve **bağlantı kodu** olarak işlev görüyor (PDF'teki "Bağlantı Kodu" panelinin de aynısı).

## Veri modeli (`lib/appwrite/schema.ts`)

Tüm collection'lar `tenant_settings.tenantId = Appwrite Team.$id`.

### `tenant_settings`
- `tenantId` (unique, indexed)
- `kind: 'lab' | 'clinic'`
- `memberNumber: string` (6 hane, unique, indexed) — bağlantı kodu
- `companyName`, `companyTaxId`, `companyAddress`, `companyEmail`, `companyPhone`, `logo`
- `defaultCurrency` (varsayılan `TRY`)

### `profiles`
Kullanıcı başına ek bilgi (display name, telefon, ünvan). Auth identity Appwrite Auth'tadır; ek alanlar burada.

### `connections`
İki tenant arası bağlantı.
- `clinicTenantId`, `labTenantId`
- `status: 'pending' | 'approved' | 'rejected'`
- `requestedBy`, `requestedAt`, `approvedAt?`, `rejectedAt?`
- Permission: `Role.team(clinicTenantId)` + `Role.team(labTenantId)` (her ikisi de görür)

### `jobs`
- `clinicTenantId`, `labTenantId`, `createdBy`
- `patientCode`, `prostheticType` (`metal_porselen`, `zirkonyum`, `implant_ustu_zirkonyum`, `gecici`, `e_max`, `diger`)
- `memberCount` (üye sayısı), `color` (Vita renk kodu örn. A2), `description?`, `price?`, `currency?`, `dueDate?`
- `status: 'pending' | 'in_progress' | 'sent' | 'delivered' | 'cancelled'`
- `currentStep: 'olcu' | 'alt_yapi_prova' | 'ust_yapi_prova' | 'cila_bitim'`
- Permission: `Role.team(clinicTenantId)` + `Role.team(labTenantId)`

### `job_files`
- `jobId`, `clinicTenantId`, `labTenantId`, `uploadedBy`
- `kind: 'scan' | 'image' | 'document'`
- `fileId` (Appwrite Storage bucket: `job-files`), `name`, `size`, `mimeType?`
- Permission: aynı job permission'ı

### `job_status_history`
Stepper geçişleri — denetim izi.
- `jobId`, `clinicTenantId`, `labTenantId`, `step`, `completedBy`, `completedAt`, `note?`

### `prosthetics` (lab katalog)
- `tenantId` (lab'in tenant id'si), `createdBy`
- `name`, `type`, `unitPrice`, `currency?`, `archived?`
- Permission: `Role.team(tenantId)` (sadece kendi tarafı)

### `finance_entries`
- `tenantId`, `createdBy`, `jobId?`, `counterpartTenantId?`
- `type: 'income' | 'expense' | 'receivable' | 'payable'`
- `amount`, `currency?`, `status: 'pending' | 'paid' | 'cancelled'`, `date`, `description?`
- Permission: `Role.team(tenantId)` (klinik ve lab kendi defterlerini görür; karşı taraf görmez)

### `notifications`
- `tenantId`, `userId?`, `jobId?`, `connectionId?`, `message`, `read`

### `audit_logs`, `invite_links`, `password_resets`, `user_preferences`
CRM'den birebir kullanılıyor.

## Bağlantı akışı (`connections` yaşam döngüsü)

1. **Klinik** → `/connections` → "Bağlantı talep et" → karşı tarafın `memberNumber`'ını gir.
2. Server action `connections` row yaratır (`status: pending`), her iki team'e permission açar.
3. **Lab** → `/connections` → bekleyen talepler listesinde görür → **Onayla** veya **Reddet**.
4. Onaylanırsa `status: approved`. Klinik artık `/jobs/new` formunda bu lab'i seçebilir.
5. Reddedilirse `status: rejected`, tekrar talep edilebilir.

## İş akışı (`jobs` yaşam döngüsü)

1. Klinik `/jobs/new` formuyla iş açar (lab seçimi onaylı bağlantılardan), durum `pending`.
2. Lab gelen kutusunda görür, **İşleme Al** → `status: in_progress`, `currentStep: olcu`.
3. Lab her aşamayı tamamlayınca `job_status_history` row eklenir + `currentStep` ilerler.
4. Cila/Bitim sonrası `status: sent`. Klinik teslim alınca `delivered`.
5. Tamamlandığında lab `finance_entries` (income, pending) açar; klinik tarafında (expense, pending) açılır (idempotent sync helper ile).

## Onboarding akışı

`/onboarding` sayfası:
1. Kayıt sonrası ilk girişte. Mevcut workspace'i yoksa zorunlu.
2. **Hesap türü seç** (Klinik / Lab) → state.
3. Şirket adı + opsiyonel vergi/telefon.
4. Submit → `createWorkspaceAction`:
   - Appwrite Team yarat
   - `tenant_settings` row yarat (`kind`, `memberNumber` üretilmiş)
   - Active tenant cookie + user prefs
5. Redirect `/dashboard`.

İmport akışı (cross-app team import) için de `kind` seçimi zorunlu.

## Açık tasarım kararları

- **Login formunda "Üye Numarası"** PDF'te var; biz e-posta+şifre kullanıyoruz. `memberNumber` register/login için **kullanılmaz**, sadece bağlantı kurmak için.
- **Cila/Bitim** sonrası kargo/teslim alanı PDF'te yok; spec'te `status: sent → delivered` ile temsil edildi. Kargo takip eklenirse `jobs.shipmentTracking?` opsiyonel field eklenir.
- **Finans entegrasyonu** PDF'te "Finans (Bekliyor)" başlığı dışında detay vermiyor. Spec'te `finance_entries` (income/expense/receivable/payable) ile başlattık; faturalama, ödeme provider entegrasyonu sonraki faz.
- **PDF'in "Bağlantı Kodu" tek bir kalıcı kod** olarak modellendi (`memberNumber`). Her connection için ayrı OTP/kod istenirse `connection_codes` collection eklenir.

## Yapılacaklar (oturum kapanışı sonrası)

- [ ] Appwrite MCP ile `lab` database + collection'lar (bu commit'te schema TS hazır, fiziksel oluşturma bir sonraki adım)
- [ ] `jobs` modülü (liste + form + detay)
- [ ] `connections` modülü (request/approve akışı)
- [ ] `products` modülü (lab katalog CRUD)
- [ ] `finance` modülü (cross-tenant idempotent sync helper)
- [ ] Coolify app + DNS `lab.kovakcrm.com`
- [ ] Landing page DLS'e uyarla
