- 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
7.7 KiB
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.memberNumberolarak 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ı koducompanyName,companyTaxId,companyAddress,companyEmail,companyPhone,logodefaultCurrency(varsayılanTRY)
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,labTenantIdstatus: 'pending' | 'approved' | 'rejected'requestedBy,requestedAt,approvedAt?,rejectedAt?- Permission:
Role.team(clinicTenantId)+Role.team(labTenantId)(her ikisi de görür)
jobs
clinicTenantId,labTenantId,createdBypatientCode,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,uploadedBykind: '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),createdByname,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ü)
- Klinik →
/connections→ "Bağlantı talep et" → karşı tarafınmemberNumber'ını gir. - Server action
connectionsrow yaratır (status: pending), her iki team'e permission açar. - Lab →
/connections→ bekleyen talepler listesinde görür → Onayla veya Reddet. - Onaylanırsa
status: approved. Klinik artık/jobs/newformunda bu lab'i seçebilir. - Reddedilirse
status: rejected, tekrar talep edilebilir.
İş akışı (jobs yaşam döngüsü)
- Klinik
/jobs/newformuyla iş açar (lab seçimi onaylı bağlantılardan), durumpending. - Lab gelen kutusunda görür, İşleme Al →
status: in_progress,currentStep: olcu. - Lab her aşamayı tamamlayınca
job_status_historyrow eklenir +currentStepilerler. - Cila/Bitim sonrası
status: sent. Klinik teslim alıncadelivered. - 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ı:
- Kayıt sonrası ilk girişte. Mevcut workspace'i yoksa zorunlu.
- Hesap türü seç (Klinik / Lab) → state.
- Şirket adı + opsiyonel vergi/telefon.
- Submit →
createWorkspaceAction:- Appwrite Team yarat
tenant_settingsrow yarat (kind,memberNumberüretilmiş)- Active tenant cookie + user prefs
- 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.
memberNumberregister/login için kullanılmaz, sadece bağlantı kurmak için. - Cila/Bitim sonrası kargo/teslim alanı PDF'te yok; spec'te
status: sent → deliveredile temsil edildi. Kargo takip eklenirsejobs.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 istenirseconnection_codescollection eklenir.
Yapılacaklar (oturum kapanışı sonrası)
- Appwrite MCP ile
labdatabase + collection'lar (bu commit'te schema TS hazır, fiziksel oluşturma bir sonraki adım) jobsmodülü (liste + form + detay)connectionsmodülü (request/approve akışı)productsmodülü (lab katalog CRUD)financemodülü (cross-tenant idempotent sync helper)- Coolify app + DNS
lab.kovakcrm.com - Landing page DLS'e uyarla