Atalay Tours.Yönetim
Atalay Tours.Yönetim
Tur Operasyon Yönetim Paneli

Atalay Tours Yönetim / Front End Projesi

Birden fazla web sitenizin tur, transfer ve paket operasyonlarını tek bir ekrandan yönetin — rezervasyonlar, tedarikçi ödemeleri, çok dilli içerik ve harici platform entegrasyonları hepsi bir arada.

Payload 3.79 Next.js 16.1 React 19 PostgreSQL 18 · Drizzle S3 / RustFS 7 dil · TR/EN/DE/RU/PL/NL/DA
Keşfet ↓
01 — Genel Bakış

Tüm operasyon, tek bir domain-odaklı panelde

Kod tabanı işlevsel katmanlara değil, iş alanlarına (domain) göre organize edilmiştir. Her koleksiyon kümesi bir iş sürecine karşılık gelir — birbirine hook'larla bağlanır, iş mantığı src/lib/ altında paylaşılan çözücülerde toplanır.

🎫

Biletler & Rezervasyon

Günlük iş akışının kalbi: turlar, transfer biletleri, tedarikçi biletleri.

reservations/
🚐

Transferler

Dinamik fiyat motoru: sabit, zone ve km bazlı; mesafe matrisi.

transfers/
🗺️

Turlar & Paketler

Çok dilli katalog; özellik & program seçenekleriyle.

tours/
🤝

Tedarikçiler

Cari hesaplar, işlemler (debit/credit), faturalar & mutabakat.

suppliers/
📍

Lokasyonlar

Ülkeler, ilçeler, bölgeler, oteller, havalimanları.

locations/
🔌

Entegrasyonlar

GetYourGuide & Tripadvisor siparişleri otomatik sisteme akar. Google Maps API ile enlem/boylam bazlı mesafe hesabı ve km fiyatlandırması.

integrations/
💱

Para Birimi

TCMB (Merkez Bankası) kur senkronu ve temizliği.

core/CurrencyRates
⚙️

Çekirdek

Kullanıcılar, Medya, Siteler, Booking kaynakları, Seed kayıtları.

core/
02 — Çoklu Site Yönetimi

Tek panel, birden çok web sitesi

Aynı CMS, birden fazla web sitesinin turlarını profesyonelce yönetir. Her içerik bir siteye izoledir; her site kendi desteklediği dilleri tanımlar.

  • Sites koleksiyonu: name, benzersiz domain, isActive, supportedLocales (7 dile kadar), description.
  • Her Tour'da zorunlu site ilişkisi → tur sadece ilgili sitede görünür.
  • TourPackage, site bilgisini bağlı tur'dan otomatik türetir.
  • BlogPost'ta zorunlu, Media'da opsiyonel site alanı.
  • Admin liste kolonlarında site görünür → hızlı filtreleme.

Aktif siteler — tek panel

  • greencanyonboattours.comtekne turları
  • bestboattrips.comtekne turları
  • Her sitenin içeriği ve desteklediği diller birbirinden bağımsız — yönetim tek ekrandan.

    src/collections/core/Sites.ts
    03 — Turlar & Tur Paketleri

    Tur kataloğu ve satılabilir paketler

    Her tur için önce içerik tanımlanır (açıklama, program, özellikler); ardından bu tura ait satılabilir paketler oluşturulur: dönem, fiyat ve araç/tedarikçi maliyeti. Aynı tura farklı dönemler veya fiyat seçenekleri için birden fazla paket açılabilir.

    🗺️

    Tour — "Ne"

    • name, shortDescription, longDescription (çok dilli)
    • district / region, slug, media[]
    • Özellik havuzları: includedFeatures, excludedFeatures, highlightFeatures, safetyFeatures … → TourFeatureOptions
    • Tura özel custom*Features (havuz dışı tek seferlik)
    • programItems[] — itinerary: activity / pickup / meal / boat / visit …
    📦

    TourPackage — "Ne zaman & kaça"

    • Zorunlu tour ilişkisi; name / description
    • periods[] — tarih aralığı, günler, saatler, buluşma/pickup noktaları
    • pricingModel: public (kişi başı) veya private_group (grup)
    • publicPrices[] — katılımcı tipi + fiyat + para birimi
    • supplierPaxPrices[] — tedarikçi maliyeti (kişi/tip bazlı)
    🧩 Özellikler ortak bir havuzdan (TourFeatureOptions) seçilir veya tura özel eklenir — yüzlerce turda tutarlılık + esneklik birlikte.
    src/collections/tours/*
    04 — Çok Dillilik & AI Çeviri

    7 dil, tek tıkla yapay zeka çevirisi Aktif

    İçerik 7 dilde tutulur (tr varsayılan, fallback açık). Bir dokümanı diğer dillere çevirmek için admin'de tek bir buton yeterli — arka planda TranslationService çalışır.

    • Sağlayıcı: OpenRouter veya OpenAI uyumlu API (env ile yapılandırılır).
    • Akıllı tarama: Koleksiyon şemasındaki tüm lokalize alanları (text, textarea, richText, array, group) özyinelemeli bulur.
    • Batch: Çevrilecek metinleri ≤6000 karakterlik parçalara böler; URL, HTML etiketi ve {{placeholder}}'ları korur.
    • Lexical desteği: Zengin metin (rich text) ağacını çözüp tekrar kurar.
    • Endpoint'ler: /api/<koleksiyon>/translate-single (tek dil) ve /translate (çoklu dil, varsayılan en,de,ru).
    src/lib/translation/TranslationService.ts
    05 — Blog & AI İçerik Üretimi

    Yapay zeka ile blog yazımı Yol Haritası

    Blog koleksiyonları ve AI içerik üretim akışı tasarlanmıştır. Editör "AI ile Oluştur" der, başlık + prompt girer; sistem yapılandırılmış içerik üretip mevcut taslağı doldurur.

    1

    Prompt gir

    Başlık + tema/prompt + dil seçilir.

    2

    AI üretir

    generateBlogPostContent() → JSON: title, excerpt, sections (h2+paragraflar), SSS, meta.

    3

    Lexical'a dönüştür

    buildBlogLexicalContent() editör formatına çevirir.

    4

    Taslak + çeviri

    Kayıt taslak doldurulur; ardından AI ile çoklu dile çevrilir.

    BlogPosts

    title, excerpt, heroImage, content (Lexical), metaTitle/metaDescription, zorunlu site, categories, authors, publishedAt, slug, draft/published durumu.

    BlogCategories

    Siteye bağlı kategoriler: name, description (çok dilli), slug. Aynı çeviri altyapısı kategorilerde de kullanılır.

    ✅ Bu özellik aktif aşamada — mevcut AI çeviri altyapısı (Bölüm 04) doğrudan yeniden kullanılmaktadır.
    06 — Medya Yönetimi

    S3 tabanlı, siteye duyarlı medya kütüphanesi Aktif

    Tüm görseller S3 / S3-uyumlu depolamada tutulur (yerelde RustFS/MinIO). Yükleme sırasında Sharp ile optimize edilir.

    ☁️

    S3 Depolama

    @payloadcms/storage-s3 ile bucket'a media/ önekiyle yazılır. Endpoint, bucket ve kimlik env'den gelir.

    🏷️

    Alt & Site

    Zorunlu alt (erişilebilirlik), opsiyonel site ile medya belirli bir siteye atanabilir.

    🖼️

    Bağlamlı kullanım

    Tours media[] (görsel + caption + sortOrder), Blog heroImage/metaImage. Public okuma, admin yükleme.

    src/collections/core/Media.ts · payload.config.ts (S3 plugin)
    07 — Tedarikçi Yönetimi

    Tedarikçi hesapları, ödemeler ve otomatik bakiye takibi Aktif

    Her tedarikçi için ayrı bir hesap tutulur. Yapılan her satış borç olarak, ödeme ise alacak olarak işlenir; bakiye otomatik güncellenir. Tüm tutarlar TCMB döviz kuruyla TL'ye çevrilerek raporlanır.

    1

    Tedarikçi & Hesap

    Tedarikçi kaydı açılır; sistem otomatik olarak sıfır bakiyeli bir hesap oluşturur.

    2

    Borç (debit)

    Bilet/transfer satışı bir SupplierTransaction üretir → bakiyeye eklenir.

    3

    Ödeme (credit)

    manual-payment ile nakit/havale ödeme → bakiyeden düşülür.

    4

    Mutabakat

    SupplierInvoice "paid" olunca otomatik mahsup işlemi oluşur, bakiye güncellenir.

    KoleksiyonRolÖnemli alanlar
    SuppliersTedarikçi kaydıname, currency (EUR/USD/GBP/TRY/RUB), services[]
    SupplierAccountsCari bakiyebalance (otomatik), currency (senkron), /manual-payment
    SupplierTransactionsBorç/alacak defteritype (debit/credit), amount, fxRateToTry, amountTry
    SupplierInvoicesMutabakat belgesiinvoiceNumber, tarih aralığı, status (unpaid/paid/cancelled)

    🧾 AccountDetails

    İşlem listesi, tarih filtresi, PDF export (jsPDF), manuel ödeme formu ve fatura oluşturma — hepsi tek panelde.

    📑 SupplierInvoiceTools

    Fatura sihirbazı: tarih/işlem otomatik prefill, PDF önizleme, mükerrer fatura kontrolü (çakışan dönem engellenir).

    src/collections/suppliers/* · src/components/SupplierAccount/ · SupplierInvoices/
    08 — Biletler & Müşteri Bildirimleri

    SMTP bağlantısı ve bilet üzerinden e-posta Aktif

    Birden çok SMTP hesabı tanımlanır; her hesabın bir önceliği ve yönlendirme kuralları vardır. Bilet detayından müşteriye dil seçerek e-posta gönderilir; sistem ilk başarısız hesaptan sonrakine düşer (fallback) ve sonucu loglar.

    ⚙️ NotificationEmailAccounts

    • smtp grubu: host, port, username, password, secure, ignoreTls
    • priority — düşük olan önce denenir
    • routing bayrakları: useForCustomerPrimary, useForSupplier*, useForGyg, useForSystemDefault

    📤 Gönderim akışı

    • Bilette CustomerNotificationActions → dil (tr/en/de/ru) + gönderici tercihi
    • Backend HTML gövde + PDF eki (pdfmake/jspdf) üretir
    • getNotificationEmailCandidates() → öncelikli hesap listesi
    • sendEmailUsingAccounts() sırayla dener (fallback)
    • Sonuç ReservationNotifications'a loglanır: status, deliveryLog, sentAt
    ℹ️ Güncel durum: SMTP altyapısı koleksiyon olarak mevcuttur. Haziran 2026 kararıyla gönderim akışında frontend tarafı Resend ile e-posta gönderir; yeni record-notification endpoint'i ise gönderimi yalnızca loglar.
    src/collections/core/NotificationEmailAccounts.ts · src/lib/notifications/ · src/components/Tickets/notify/
    09 — Transferler & Fiyatlandırma Motoru

    İki transfer fiyat modeli

    Transfer rotaları iki şekilde fiyatlanır: Araç bazlı sabit fiyat veya KM-bazlı dinamik fiyat. Google Maps API üzerinden enlem/boylam ile gerçek yol mesafesi hesaplanır; gece zammı ve sezon çarpanları otomatik uygulanır.

    📌

    Araç bazlı sabit fiyat

    Her araç tipi için önceden tanımlanmış rota fiyatı. Hızlı teklif, öngörülebilir maliyet.

    📐

    KM-bazlı dinamik fiyat

    Google Maps ile gerçek mesafe × km tarifesi + gece zammı + sezon çarpanı. Rota eklendikçe otomatik hesaplanır.

    BileşenAçıklama
    KmPricingConfig (global)km başı fiyat + minimum ücret, mesafe kademeleri, gece zammı (22:00–06:00), aylık seasonalMultipliers, round-trip indirimi
    VehicleTypespricingMode (private/shuttle), vehicleClass, maxCapacity, features
    TransferAddOnspricingType (per_booking / per_person), rota bazlı override (etkin/fiyat/tip)
    DistanceMatrixmesafe cache: google_maps / manual / haversine (yol faktörü ×1.3 fallback)
    TransferQuotes15 dk TTL, satır kalemleri, kur/fiyat snapshot, active/consumed/expired/cancelled
    src/lib/transfers/shared.ts (resolveTransferPrice) · dynamicPricing.ts · src/globals/KmPricingConfig.ts
    10 — API Erişimi

    Otomatik REST/GraphQL + public transfer API'leri Aktif

    Payload her koleksiyon için otomatik REST (/api/<koleksiyon>) ve GraphQL (/api/graphql) sunar — hepsi access-control korumalı. Üstüne, dış istemciler için özel public transfer API'leri vardır (30 istek/dk IP limiti).

    EndpointAmaç
    POST /api/transfers/priceFiyat teklifi (fixed / dynamic)
    POST /api/transfers/available-routesOrigin/destination'a uyan rotalar
    GET /api/transfers/locationsLokasyon arama (ad/kod)
    GET /api/transfers/vehicle-typesAraç tipi kataloğu
    POST /api/transfers/bookTeklifi bilete çevir (quote → ticket)
    POST /api/gyg/1/*GetYourGuide entegrasyonu (Basic Auth)

    Kimlik doğrulama yöntemleri: admin cookie · x-jobs-secret / Bearer / ?token= (automation) · tenant API key (Authorization: Bearer veya x-api-key) · GYG için Basic Auth.

    curl — fiyat teklifi al
    # Sabit rotada 2 yolcu için EUR teklif
    curl -X POST "http://localhost:3000/api/transfers/price" \
      -H "Authorization: Bearer <tenant-api-key>" \
      -H "Content-Type: application/json" \
      -d '{
        "mode": "fixed",
        "routeID": "12",
        "vehicleTypeID": "3",
        "transferDate": "2026-07-15",
        "passengerCount": 2,
        "isRoundTrip": false,
        "requestedCurrency": "EUR"
      }'
    src/app/api/transfers/* · src/app/api/gyg/* · src/lib/transfers/publicAccess.ts
    11 — Curl Console

    Tarayıcıdan API çağrısı Yol Haritası

    Admin panelinin içinde, tarayıcıda çalışan bir API konsolu (/admin/curl-console). Seed endpoint'lerini ve Payload REST API'sini terminal açmadan tetikler. API anahtarı yalnızca localStorage'da tutulur; istek/yanıt sunucuda loglanmaz.

    🎯

    Hedef seçici

    Same-origin / local dev / staging / prod. /api/curl-proxy sunucu-sunucu iletir (CORS/CSRF derdi yok).

    🛡️

    Güvenli proxy

    Admin-only, origin whitelist (SSRF koruması), 5MB body, 30sn timeout, 30 istek/dk.

    🕘

    Geçmiş & preset

    Method, query builder, header editörü, JSON body; son 20 istek geçmişi ve kayıtlı preset'ler.

    📌 Bu özellik planlanmış durumda — referans: .kilo/plans/curl-console.md. Districts/Regions için hazır REST sorgu örnekleri plan dosyasında mevcut.
    12 — Seed Registries & Veri Import

    Tek komutla, prod-dostu veri yükleme Aktif

    Seed işlemleri hem CLI script'leri hem de HTTP endpoint'leri olarak sunulur. Docker runtime'da pnpm bulunmadığı için, prod'da seed/cleanup tamamen curl ile yapılabilir. Çoğu işlem dryRun ile önce simüle edilir.

    Endpointİş
    /api/seed-registries/transfer-demo/seed13 demo transfer rotası + fiyat
    /api/seed-registries/transfer-routes/seedFiyat listesinden rotalar (kapasite bazlı)
    /api/seed-registries/pricing-zones/seedVarsayılan zone tarifeleri
    /api/seed-registries/tour-detail-defaults/seedTur özellik/program varsayılanları
    /api/seed-registries/vehicle-types/sync-codesAraç tipi kodlarını senkronla

    Yetki: x-jobs-secret header'ı (→ PAYLOAD_JOBS_SECRET / PAYLOAD_SECRET) veya admin oturumu. SeedRegistries koleksiyonu ne yapıldığını namespace bazlı kaydeder (entries, lastSeededAt).

    curl — önce dry-run, sonra commit
    # 1) Ne olacağını gör (DB'ye yazmaz)
    curl -X POST "http://localhost:3000/api/seed-registries/transfer-demo/seed" \
      -H "x-jobs-secret: $PAYLOAD_JOBS_SECRET" \
      -H "Content-Type: application/json" \
      -d '{"dryRun": true}'
    
    # 2) Çıktıyı onayladıktan sonra gerçekten yaz
    curl -X POST "http://localhost:3000/api/seed-registries/transfer-demo/seed" \
      -H "x-jobs-secret: $PAYLOAD_JOBS_SECRET" \
      -H "Content-Type: application/json" \
      -d '{"dryRun": false}'
    📥 JSON import: pnpm run import:payload-data REST üzerinden toplu kayıt yükler; datas/ klasöründe hazır referans veri setleri (ör. tur paketi import şablonu) bulunur.
    src/collections/core/SeedRegistries.ts · src/scripts/import-payload-data.ts · datas/
    13 — Otomasyon, Entegrasyon & Deploy

    Gözden kaçabilecek ama önemli parçalar

    Zamanlanmış işler

    sync-tcmb-rates (her gün 15:35) ve cleanup-old-currency-rates (aylık, 90 gün saklama). payload.config.ts cron ile.

    🔗

    Entegrasyonlar

    GetYourGuide & Tripadvisor siparişleri otomatik sisteme akar. Google Maps API ile enlem/boylam bazlı mesafe ve km fiyatlandırması.

    🐳

    Docker

    Standalone Next.js, Postgres 18, RustFS. Runtime image'da pnpm yok → seed/cleanup HTTP endpoint'leriyle yapılır.

    🔐

    Otomasyon yetkisi

    canAccessJobscanAccessAutomation: admin kullanıcı veya secret header/token.

    🗄️

    Güvenli migration

    Drizzle, push:false. Sadece açık migration (pnpm payload migrate); fresh/reset açık onay ister.

    💱

    TCMB kurları

    Merkez Bankası kurları senkronlanır; tedarikçi işlemleri ve transfer teklifleri bu kurlarla TRY'ye sabitlenir.

    src/jobs/currencyRatesJobs.ts · payload.config.ts · docker-compose.yml