Ne yaptık:
- queue_worker.py: TrendyolSearchScraper 0 ürün döndürdüğünde TrendyolScraper
(Top Rankings API) ile fallback yap — abiye gibi kategoriler için kritik
- logging_config.py: varsayılan log dizinini /tmp/logs olarak değiştir,
container restart'ta /logs permission hatası düzeldi
- main.py: API_KEY env var yoksa auth'u gerçekten atla (uyarıyla uyumlu hale getir)
Neden yaptık:
- TrendyolSearchScraper pathModel ile bazı kategoriler (abiye-elbise gibi)
0 ürün döndürüyor; eski Top Rankings API categoryId ile çalışıyor
- /logs dizini container restart'ta izin hatası veriyordu
- API_KEY yoksa tüm istekler 401 dönüyordu (yorum ile çelişki)
Ne yaptık:
- build_consolidated_report(): normalized_products boş olunca
None yerine empty=true içeren boş dashboard döndürüyor
- normalize_product(): seller_count, has_buybox, is_trendyol_product alanları eklendi
- Social proof: metrik bazında en doğru kaynak seçimi (inline vs enrichment API)
Neden yaptık:
- Boş kategorilerde dashboard-data endpoint 500 fırlatıyordu,
kullanıcı loading skeleton'dan çıkamıyordu
- Satıcı sayısı ve buybox bilgisi Ürünler tablosu için gerekli
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ne yaptik:
- ReportQueue modeli + Alembic migration (report_queue tablosu)
- QueueWorker: SELECT FOR UPDATE SKIP LOCKED ile tek worker polling
- 3 yeni endpoint: POST /api/queue/submit, GET /api/queue/{id}/status, GET /api/queue/active
- Startup hook ile worker otomatik basliyor, shutdown'da duruyor
- Stuck task recovery: 15 dk'dan eski PROCESSING tasklar PENDING'e donuyor
Neden yaptik:
- Esanli SSE rapor isteklerinde IP ban riski ve veri kaybi vardi
- Tek worker ile sirayla isleniyor, rate limit korunuyor
- Sifir yeni dependency: sadece PostgreSQL + mevcut scraper'lar
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- CLAUDE.md'ye "URL Mimarisi" ve "Container/Traefik Sorunları" bölümleri eklendi
Neden yaptık:
- "Failed to fetch" hatasının kök nedeni (VITE_API_URL Coolify build ARG vs .env çakışması)
ve container'ı Traefik label'sız başlatınca "Bad Gateway" olması belgelendi
- Bir dahaki seferde aynı hata dizisine girmeyelim diye
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ne yaptık:
- VITE_API_URL http:// → https:// olarak değiştirildi
- CORS whitelist'e https:// origin'ler eklendi
Neden yaptık:
- Coolify/Traefik HTTPS'e yönlendiriyor, frontend https:// üzerinden yükleniyor
- Tarayıcı http:// API isteklerini Mixed Content olarak blokluyordu
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- Sahibinden.com tarzı Miller Columns kategori seçici (CategorySelector.jsx)
- Trendyol API'den 3971 kategori ağacı çekildi (Playwright ile)
- Backend: JSON tree tabanlı kategori endpoint'leri (/api/category-tree/*)
- Backend: Rapor oluşturma artık DB kategorilerine bağımlı değil
- Report tablosundaki category_id FK constraint kaldırıldı
- Dockerfile'a trendyol_category_tree.json eklendi
Neden yaptık:
- DB'deki kategori tablosu boştu, Trendyol API ID'leri ile Excel ID'leri farklıydı
- Playwright ile Trendyol'un kendi kategori ağacını çektik (3971 kategori, gerçek API ID'leri)
- Miller Columns ile kullanıcı adım adım derinleşerek kategori seçebiliyor
- Arama özelliği ile kelime bazlı kategori bulma da mümkün
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- /app/../logs yazılamadığında /tmp/logs'a fallback eklendi
Neden yaptık:
- Docker container'da /logs dizinine yazma izni olmadığı için backend başlatılamıyordu
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- data_consolidator.py: Tüm normalizasyon ve hesaplama mantığını main.py'den çıkardık
- Dashboard endpoint 1150 satırdan 25 satıra düştü (main.py -1730/+1880 net)
- Enrichment bitince otomatik konsolide dosya oluşturuluyor (report_{id}_data.json)
- Eski raporlar ilk dashboard isteğinde lazy migration ile konsolide ediliyor
- Trendyol API artık order-count döndürmediği için baskets fallback eklendi
- Inline socialProofs (scrape) > enrichment API öncelik sırası uygulandı
- Frontend KPI başlıkları orders/baskets durumuna göre dinamik değişiyor
- logging_config.py, category_seeder.py, alembic migration eklendi
- Playwright ile 9 tab test edildi, tüm veriler doğru
Neden yaptık:
- 3 farklı kaynaktan her istekte birleştirme yapılması veri tutarsızlığına ve yavaşlığa yol açıyordu
- Tek konsolide JSON dosyası ile dashboard anında yükleniyor
- Trendyol API değişikliği nedeniyle sipariş verisi kayboluyordu, baskets fallback ile çözüldü
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- Helper fonksiyonlar endpoint seviyesinde tanımlıydı ama json modülü progress_stream() içinde import ediliyordu
- import json as _json_mod ile endpoint seviyesinde import eklendi
Neden yaptık:
- _write_json her kategori scraping sonrası "name 'json' is not defined" hatası veriyordu
- Tüm kategoriler fail oluyordu bu yüzden
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- json.dump/json.load ve db.commit çağrılarını asyncio.to_thread() ile sardık
- 5 ayrı blocking I/O noktası: kategori scraping yazma, kategori okuma (sosyal kanıt için), rapor JSON yazma, DB kaydetme, sosyal kanıt JSON yazma
- _write_json, _read_json, _db_save helper fonksiyonları eklendi
Neden yaptık:
- Büyük raporlarda (15K+ ürün) sosyal kanıt tamamlandıktan sonra rapor kaydetme aşamasında senkron I/O event loop'u blokluyordu
- Backend health check fail oluyordu, container "unhealthy" durumuna düşüyordu
- "Tamamlandı" modalı frontend'e ulaşamıyordu çünkü SSE stream donuyordu
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- Fonksiyon artık her zaman çocuk kategorilere iniyor
- Sadece leaf (yaprak) kategorileri toplıyor — children'ı olan kategorileri atılıyor
- Önceki davranış: trendyol_category_id varsa duruyordu, alt kategorilere inmiyordu
Neden yaptık:
- "Kadın" kategorisinde 17 üst kategori seçildiğinde sadece 17 kategori taranıyordu
- Oysa bu 17 kategorinin altında yüzlerce leaf kategori var (ör: Ayakkabı→10, Aksesuar→35)
- Şimdi tüm ağacın en dibine kadar inip tüm leaf kategorileri tarayacak
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- Service label adlarını Coolify'ın oluşturduğu router adlarıyla eşleştirdik
- frontend: frontend → http-0-x4c08gc84kcw4oow0ggg44cg-frontend
- backend: backend → http-0-x4c08gc84kcw4oow0ggg44cg-backend
Neden yaptık:
- Traefik router adı ile service adı eşleşmediğinde 502 Bad Gateway dönüyordu
- Coolify router'ları kendi UUID formatında oluşturuyor, service adları da aynı formatta olmalı
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- Frontend service'ine traefik.http.services.frontend.loadbalancer.server.port=80 label'ı eklendi
Neden yaptık:
- Traefik frontend container'ın hangi portta çalıştığını bilmiyordu (502 Bad Gateway)
- Backend'de bu label vardı ama frontend'de eksikti
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ne yaptık:
- "Tümünü Seç" artık arama filtresi aktifken bile tüm alt kategorileri seçiyor
- Tüm alt kategoriler seçiliyse subcategory_ids gönderilmiyor (backend zaten tümünü tarıyor)
- URL uzunluk limitine takılma riski ortadan kalktı
- Label'a seçili/toplam sayacı eklendi (ör: 45/105)
Neden yaptık:
- Kozmetik gibi 105 alt kategorili ana kategoride "Tümünü Seç" sadece
filtrelenmiş kategorileri seçiyordu, bu yüzden raporda 1 kategori (~100 ürün)
taranıyordu. Şimdi 105 kategori (~10.500 ürün) taranacak.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Traefik defaults to port 80 when no loadbalancer port is specified.
Backend listens on 8001, causing the trendyol-api domain to timeout.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The chown was running before cp seeded categories from initial-categories,
so the copied files remained owned by root. Now permissions are fixed
after all file operations complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When subcategories don't have a trendyol_category_id (organizational nodes),
recursively collect their leaf descendants that do have valid IDs.
This fixes "No valid Trendyol IDs found" for categories like Elektronik
whose children (e.g. Bilgisayar & Tablet) are organizational.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Run container as root initially to fix volume mount permissions
- Use gosu to drop to appuser before starting uvicorn
- chown /data directories at startup (Coolify mounts volumes as root)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add POST /categories/bulk-import endpoint for hierarchical category import
- Add parent_id field to CategoryUpdate model
- Support parent-child relationships in category updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All ../categories and ../reports references replaced with the
configurable CATEGORIES_DIR and REPORTS_DIR variables. This fixes
the Docker deployment where data directories are at /data/ not ../
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Coolify remaps volume mounts to its own managed directories, so
./categories was mapped to an empty dir instead of the repo data.
Changes:
- Backend build context changed to repo root (.) so categories/ is accessible
- Dockerfile copies categories into /data/initial-categories/
- startup.sh seeds /data/categories from bundled data if empty
- Removed categories volume mount (reports still persisted via volume)
- Added root .dockerignore (categories NOT excluded)
- Updated CI workflow to match new build context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use nullish coalescing (??) in api.js to support empty VITE_API_URL
- Set VITE_API_URL to backend's sslip.io Traefik domain
- Add sslip.io domains to CORS allowed origins
- Update FRONTEND_URL to sslip.io domain
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix docker-compose.yml for production: use postgres:15-alpine, remove
container names, remove postgres external port, set FRONTEND_URL to
server IP, use empty VITE_API_URL for nginx proxy
- Add production server CORS origins to backend
- Add deploy job to GitHub Actions CI/CD pipeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>