Commit Graph

26 Commits

Author SHA1 Message Date
furkanyigit34
9c5a85c589 fix(scraper): best seller siralamasi, tekrar eden urunler ve sosyal kanit bugu duzeltildi
Ne yaptik:
- scraper.py fetch_page: "sst": "BEST_SELLER" parametresi eklendi
- scraper.py fetch_page: "countryCode": "TR" parametresi eklendi
- scraper.py _normalize_search_product: socialProof (TEKIL) alanindan okunuyor,
  eski cogul socialProofs fallback olarak birakildi
- main.py _find_leaves: pathModel artik "<slug>-x-c<categoryId>" formatinda
  uretiliyor (queue_worker.py ile ayni mantik)

Neden yaptik:
- Trendyol Search API siralama parametresi verilmezse sayfalar arasi tutarsiz
  sonuc donuyordu: 240 urunluk cekimde sadece 134 benzersiz urun geliyordu,
  yani raporlarin %44'u ayni urunun tekrariydi. sst=BEST_SELLER ile tekrar
  tamamen sifirlandi (240/240 benzersiz)
- Sosyal kanit alani API'de TEKIL "socialProof" olarak geliyor ama kod cogul
  "socialProofs" diye okuyordu; bu yuzden satis/favori verisi hep bos donuyordu.
  Telafi icin cagrilan Top Rankings API ise Trendyol tarafinda kaldirildigi icin
  404 veriyor (K8s loglarinda dogrulandi). Duzeltmeden sonra 238/240 uruna
  orderCount ve favoriteCount geliyor
- countryCode zorunlu hale gelmis; yoksa API 400 "Required country information"
  donuyor
- main.py salt slug gonderiyordu (or. "yuz-kremi"), API 0 urun donuyordu.
  Dogru format "yuz-kremi-x-c1122"

Test:
- yuz-kremi-x-c1122, 10 sayfa: 240 urun / 240 benzersiz / 0 tekrar / 238 sosyal kanit
- Regresyon: 6 farkli kategori tipinde 6/6 basarili, tekrar yok

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 18:34:59 +03:00
furkanyigit34
016c540945 feat(sentry): CiroMarket backend'ine hata izleme eklendi
All checks were successful
ciromarket-backend-build-and-deploy / build (push) Successful in 3m25s
Ne yaptik:
- requirements.txt'e sentry-sdk[fastapi]==2.66.1 eklendi.
- main.py'de FastAPI uygulamasi olusturulmadan once sentry_sdk.init() cagriliyor.
- DSN os.getenv("SENTRY_DSN", "") ile okunuyor, ortam degiskeni yoksa bos string.
- send_default_pii=False, traces_sample_rate=0.0.

Neden yaptik:
- CiroMarket hicbir hata izleme sistemine bagli degildi. Backend cokerse ya da
  bir endpoint 500 donerse bunu ancak kullanici sikayet edince ogreniyorduk.
  SellerX'in kendi backend'i ve frontend'i Sentry'ye bagliydi, CiroMarket kor
  nokta olarak kalmisti.
- DSN bos oldugunda sentry_sdk hicbir sey gondermez, yani local calistirmada ve
  DSN set edilmemis ortamlarda tamamen no-op. Bu davranis SellerX backend'iyle
  ayni (application.yaml: dsn ${SENTRY_DSN_BACKEND:}).
- send_default_pii bilerek kapali: istek header'lari, cerezler ve IP adresi
  gonderilmiyor. CiroMarket satici verisi isliyor, KVKK acisindan varsayilan
  olarak acmak dogru degil. Sentry org'unda ayrica data scrubber ve IP
  maskeleme acik.
- traces_sample_rate=0.0 cunku su an sadece hata izleme istiyoruz; tracing
  ucretsiz kotayi hizla tuketiyor. Ihtiyac olursa sonra acilir.
- Sentry projesi: cironet org'unda ciromarket-api (EU region, sadece Error
  Monitoring urunu acik). SENTRY_DSN K8s'te ciromarket-backend-secrets
  secret'ina eklendi.
2026-08-10 00:31:40 +03:00
b1cad27330 fix(scrape): 0 ürünlü rapor FAILED olarak işaretleniyor
All checks were successful
ciromarket-backend-build-and-deploy / build (push) Successful in 2m8s
Ne yaptık:
- SSE endpoint: tüm subcategory'ler başarısız olursa type=failed event yield et, DB'ye kaydetme
- queue_worker: total_products==0 ve en az 1 kategori denendiyse _mark_failed() çağır

Neden yaptık:
- Trendyol rate limit (HTTP 556) durumunda tüm subcategory'ler success=False dönüyor
- Sistem bunu hata olarak değil "0 ürünlü başarılı rapor" olarak kaydediyordu
- Kullanıcıya "Bu kategoride ürün bulunamadı / Farklı kategori deneyin" mesajı çıkıyordu — tamamen yanıltıcı
- Artık FAILED → Spring Boot CiromarketSseConsumer/QueuePoller → SellerX DB FAILED → frontend hata mesajı
2026-07-23 00:55:25 +03:00
2b0e83f2eb fix(enrichment): progress_cb parametresi eklendi
All checks were successful
ciromarket-backend-build-and-deploy / build (push) Successful in 2m42s
Ne yaptık:
- _enrich_report_task fonksiyonuna progress_cb=None default parametresi eklendi
- Queue worker progress_cb ile çağırıyordu ama fonksiyon kabul etmiyordu

Neden yaptık:
- Queue üzerinden oluşturulan tüm raporlarda TypeError ile enrichment fail oluyordu
- Bu yüzden sipariş/görüntülenme/sepet verileri hiç çekilemiyordu, hep 0 görünüyordu
2026-07-23 00:05:13 +03:00
furkanyigit34
eba9709962 fix(auth): CiroMarket kategori 401 kalıcı düzeltme — router-based auth
Ne yaptık:
- PUBLIC_PATHS whitelist tamamen kaldırıldı
- protected_router = APIRouter(dependencies=[Depends(verify_api_key)]) eklendi
- 33 korunan route @protected_router.*'a taşındı
- 6 public route (/health, /, category-tree×4) @app.*'de kaldı
- verify_api_key sadeleşti: request.url.path artık kontrol edilmiyor
- test_auth_routing.py: regresyon guard — PUBLIC_PATHS geri gelirse CI fail eder

Neden yaptık:
- PUBLIC_PATHS her deploy/merge'de kayboluyordu → tekrarlayan 401
- Yapısal çözüm: ayrım kod mimarisinde, whitelist config'de değil
2026-07-22 00:10:22 +03:00
furkanyigit34
0fa034c67d fix(ciromarket): sosyal kanit asamasinda queue progress guncelle
Ne yaptik:
- _enrich_report_task fonksiyonu progress_cb parametresi aldi
- social_proof calismasi sirasinda daemon monitor thread baslatiyor
- Her 30 saniyede enrichment_progress izleyip queue'yu 96-99% araliginda guncelliyor
- queue_worker.py: _progress_cb lambda ile self._update_progress bagladi

Neden yaptik:
- Sosyal kanit asamasi (5000+ urun, ~12 dk) boyunca progress
  yuzde 95'te donuyordu, kullanici rapor takildi saniyordu.
- Artik UI gercek ilerlemeyi 96-99% araliginda gosterecek.
2026-07-16 13:47:55 +03:00
furkanyigit34
4c6320f710 security: auth hatasi 401 yerine 404 don
Ne yaptik:
- verify_api_key: HTTPException 401 -> 404, detail 'Not Found'

Neden yaptik:
- API key'siz erisimde JSON hata mesaji gorunuyordu
- 404 ile endpoint yokmus gibi gozukur, domain ifsa olmaz
2026-05-18 12:37:07 +03:00
5af14c8d80 fix(api): category-tree endpoint'lerini public yap (revert+fix encoding corruption)
Ne yaptık:
- PUBLIC_PATHS setine /api/category-tree, /api/category-tree/roots,
  /api/category-tree/search eklendi
- Önceki commit base64 round-trip nedeniyle dosyayı bozmuştu, bu commit
  doğru encoding ile yazıldı

Neden yaptık:
- API_KEY env var set olduğunda tüm endpoint'ler auth gerektiriyor
- Frontend X-API-Key header göndermiyordu → 401 → 'Kategoriler yükleniyor...'
- Category tree read-only, herkese açık veri — auth gerekmez
2026-05-04 11:43:15 +03:00
a2317bdec0 fix(api): category-tree endpoint'lerini public yap
Ne yaptık:
- PUBLIC_PATHS setine /api/category-tree, /api/category-tree/roots,
  /api/category-tree/search eklendi

Neden yaptık:
- API_KEY env var set olduğunda tüm endpoint'ler auth gerektiriyor
- Frontend X-API-Key header göndermiyordu → 401 → 'Kategoriler yükleniyor...'
- Category tree read-only, herkese açık veri — auth gerektirmesi hata
2026-05-04 11:35:05 +03:00
furkanyigit34
982ad96f3f feat: /api/product/lookup endpoint eklendi
Ne yaptık:
- product_lookup_cache (BoundedCache 500 item, 1h TTL) eklendi
- IP rate limiter: 10 istek/IP/dakika
- _TRENDYOL_URL_RE regex ile URL'den ürün ID'si çekme
- GET /api/product/lookup endpoint: orderCount/favoriteCount/pageViewCount/basketCount döner
- Circuit breaker ve cache entegrasyonu

Neden yaptık:
- "Ne Kadar Sattı?" sayfası için gerekli Python servisi altyapısı.
  Kullanıcı Trendyol URL'si yapıştırıyor, sosyal kanıt verisi alıyor.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 12:35:45 +03:00
furkanyigit34
942c8d1244 fix: scraper Search API fallback + logging + auth
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)
2026-04-15 01:53:45 +03:00
furkanyigit34
8cbe100035 feat: PostgreSQL kuyruk sistemi (SSE yerine queue+poll)
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>
2026-04-14 16:41:19 +03:00
furkanyigit34
5d976b26f4 fix: Mixed Content hatası - HTTPS API URL ve CORS
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>
2026-03-29 02:40:13 +03:00
furkanyigit34
bb333208ab fix: Python 3.11 f-string syntax hatası (dict key erişimi)
Ne yaptık:
- f-string içindeki main_cat["name"] tırnak çakışmasını düzelttik
- Python 3.12+ destekler ama Docker'daki 3.11 desteklemiyor
- main_cat_name değişkenine atayarak çözdük

Neden yaptık:
- Production'da backend crash ediyordu (SyntaxError)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-29 02:33:04 +03:00
furkanyigit34
1c10a701cf feat: Miller Columns kategori seçici + JSON tree tabanlı mimari
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>
2026-03-29 02:24:22 +03:00
furkanyigit34
ce1dc1e25f feat: tek birleştirilmiş JSON yapısına geçiş + sosyal kanıt fallback
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>
2026-03-28 22:25:25 +03:00
furkanyigit34
187c59ec9b fix: json module not in scope for _write_json/_read_json helpers
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>
2026-03-27 18:14:18 +03:00
furkanyigit34
1baaa6fbce fix: move blocking file I/O to threads to prevent event loop stall
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>
2026-03-27 18:01:40 +03:00
furkanyigit34
dc1f8fcfb2 fix: SSE timeout during social proof collection
Ne yaptık:
- time.sleep() → await asyncio.sleep() ile event loop bloklanması engellendi
- Sosyal kanıt batch size 5 → 20 (1115 istek → 279 istek, %75 azalma)
- SSE keepalive heartbeat eklendi (her 10 batch'te bir)
- Nginx proxy timeout 180s → 600s (10 dakika)
- Rate limit sleep süreleri optimize edildi (2s→1.5s, 0.5s→0.3s)

Neden yaptık:
- Kadın kategorisi gibi büyük raporlarda (82 yaprak kategori, 5576 ürün)
  sosyal kanıt aşamasında SSE bağlantısı kopuyordu. Kök neden:
  senkron time.sleep() async generator içinde event loop'u blokluyor,
  proxy idle timeout'a takılıyor ve bağlantıyı kesiyordu.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 17:01:14 +03:00
furkanyigit34
f5562e2135 fix: collect_scrapable_categories should recurse to leaf categories
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>
2026-03-27 16:05:01 +03:00
furkanyigit34
1bcb88a941 fix: recursively resolve categories without trendyol_category_id for report creation
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>
2026-03-08 01:13:22 +03:00
furkanyigit34
344474e763 feat: add bulk category import endpoint and parent_id update support
- 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>
2026-03-08 00:35:10 +03:00
furkanyigit34
e6d47b89ee fix: use CATEGORIES_DIR and REPORTS_DIR env vars instead of hardcoded paths
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>
2026-03-07 23:45:21 +03:00
furkanyigit34
99a132879f fix: configure sslip.io domains for Coolify Traefik proxy
- 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>
2026-03-07 18:09:13 +03:00
furkanyigit34
0079313708 feat: configure Coolify deployment for production
- 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>
2026-03-07 17:45:01 +03:00
furkanyigit34
c7be57064b Initial commit: Trendyol Analiz platform
- FastAPI backend with Python
- React + Vite admin panel
- PostgreSQL database
- Trendyol marketplace analytics
- GitHub Actions CI/CD workflow

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 00:14:38 +03:00