Files
iddaai-be/mds/DATABASE_SCHEMA_FULL.md
fahricansecer 2f0b85a0c7
Deploy Iddaai Backend / build-and-deploy (push) Failing after 18s
first (part 2: other directories)
2026-04-16 15:11:25 +03:00

595 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Suggest-Bet-BE — Veritabanı Şemas ve Proje Tam Referansı
> **Tarih:** 2026-03-13
> Google Gemini 3.1 Pro Deep Think ile çözüm üretimi için hazırlanmış kapsamlı referans dokümanıdır.
---
## 1. Proje Özeti
**Suggest-Bet-BE**, yapay zeka destekli bir spor bahis tahmin ve analiz platformu backend servisidir.
| Katman | Teknoloji | Port |
|--------|-----------|------|
| **Backend API** | NestJS 11 (TypeScript) | `3005` |
| **AI Engine** | Python FastAPI, XGBoost, LightGBM Ensemble | `8000` |
| **Veritabanı** | PostgreSQL 16 + Prisma ORM | `5432` |
| **Kuyruk/Cache** | BullMQ + Redis (opsiyonel) | `6379` |
| **Auth** | JWT + Passport (Access 15dk + Refresh 7gün) | — |
| **Scraping** | Axios + Cheerio (Mackolik.com) | — |
| **AI** | Google Gemini API (yorum üretimi) | — |
**Temel Akış:**
1. Mackolik API'den canlı maç verisi çekilir (15dk cron)
2. Kullanıcı maç seçer → AI Engine'e gönderilir
3. V20+ model çoklu market tahmin paketi üretir (MS, OU, BTTS, DC, HT/FT)
4. İsteğe bağlı akıllı kupon önerilir (5 strateji: SAFE, BALANCED, AGGRESSIVE, VALUE, MIRACLE)
---
## 2. Veritabanı Şeması (PostgreSQL — 27 Tablo, 6 Enum)
### 2.1 Enum Tanımları
```sql
-- Spor türleri
enum Sport { football, basketball }
-- Kullanıcı rolleri
enum UserRole { user, superadmin }
-- Abonelik durumu
enum SubscriptionStatus { free, active, expired }
-- Oyuncu pozisyonları (futbol)
enum PlayerPosition { goalkeeper, defender, midfielder, striker }
-- Maç olayı türleri
enum EventType { goal, card, substitute }
-- Maç pozisyonu (ev sahibi/deplasman)
enum MatchPosition { home, away }
```
### 2.2 Tablo Detayları
---
#### `countries` — Ülkeler (160 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `String` PK | Mackolik ülke ID |
| `name` | `String` UNIQUE | Ülke adı |
| `flag_url` | `String?` | Bayrak görseli URL |
| `created_at` | `DateTime` | — |
**İlişkiler:**`leagues[]`
---
#### `leagues` — Ligler (1,505 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `String` PK | Mackolik lig ID |
| `name` | `String` | Lig adı |
| `country_id` | `String?` FK → countries | Ülke |
| `sport` | `Sport` | football / basketball |
| `competition_slug` | `String?` | URL slug |
| `code` | `String?` | Kısa kod |
| `logo_url` | `String?` | Logo URL |
| `created_at` | `DateTime` | — |
**Unique:** `(name, country_id, sport)`
**İndeksler:** `sport`, `country_id`
**İlişkiler:**`matches[]`, `live_matches[]`
---
#### `teams` — Takımlar (19,595 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `String` PK | Mackolik takım ID |
| `name` | `String` | Takım adı |
| `slug` | `String?` | URL slug |
| `sport` | `Sport` | football / basketball |
| `logo_url` | `String?` | Logo URL. CDN: `https://file.mackolikfeeds.com/teams/{id}` |
| `created_at` | `DateTime` | — |
**İndeksler:** `sport`, `name`
**İlişkiler:** → home/away matches, participations, events, stats
---
#### `players` — Oyuncular (217,040 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `String` PK | Mackolik oyuncu ID |
| `name` | `String` | Oyuncu adı |
| `slug` | `String?` UNIQUE | URL slug |
| `created_at` | `DateTime` | — |
**İndeksler:** `name`
**İlişkiler:** → participations, events (scorer, assist, out), stats
---
#### `matches` — Kalıcı Maç Kayıtları (236,859 kayıt, 100 MB)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `String` PK | Mackolik maç ID |
| `league_id` | `String?` FK → leagues | Lig |
| `home_team_id` | `String?` FK → teams | Ev sahibi |
| `away_team_id` | `String?` FK → teams | Deplasman |
| `sport` | `Sport` | football / basketball |
| `match_name` | `String?` | "Galatasaray vs Fenerbahçe" |
| `match_slug` | `String?` | URL slug |
| `mst_utc` | `BigInt` | Maç zamanı (Unix ms) |
| `status` | `String?` | Durum |
| `state` | `String?` | postGame, preGame, live, etc. |
| `score_home` | `Int?` | Ev sahibi skor |
| `score_away` | `Int?` | Deplasman skor |
| `ht_score_home` | `Int?` | İlk yarı ev sahibi skor |
| `ht_score_away` | `Int?` | İlk yarı deplasman skor |
| `winner` | `String?` | Kazanan |
| `iddaa_code` | `String?` | İddaa maç kodu |
| `created_at` | `DateTime` | — |
| `updated_at` | `DateTime` | — |
**İndeksler:** `mst_utc DESC`, `sport`, `state`, `league_id`, `home_team_id`, `away_team_id`, `iddaa_code`
**İlişkiler:** → oddCategories, teamStats, playerParticipations, playerEvents, playerStats, officials, prediction, aiFeatures, couponItems
---
#### `live_matches` — Canlı/Yaklaşan Maçlar (82 kayıt, döngüsel)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `String` PK | Mackolik maç ID |
| `league_id` | `String?` FK → leagues | Lig |
| `home_team_id` | `String?` FK → teams | Ev sahibi |
| `away_team_id` | `String?` FK → teams | Deplasman |
| `sport` | `String?` | football / basketball |
| `match_name` | `String?` | Maç adı |
| `match_slug` | `String?` | URL slug |
| `mst_utc` | `BigInt?` | Maç zamanı (Unix ms) |
| `status` | `String?` | Durum |
| `state` | `String?` | pre, live, post |
| `substate` | `String?` | Alt durum |
| `score_home` | `Int?` | Ev sahibi skor |
| `score_away` | `Int?` | Deplasman skor |
| `updated_at` | `DateTime` | Son güncelleme |
| **`odds`** | **`Json?`** | **Tüm bahis oranları (JSON blob)** |
| `odds_updated_at` | `DateTime?` | Oran güncelleme zamanı |
| `referee_name` | `String?` | Hakem adı |
| **`lineups`** | **`Json?`** | **Kadro (JSON blob, home/away dizileri)** |
| **`sidelined`** | **`Json?`** | **Sakatlar/Cezalılar (JSON blob)** |
**İndeksler:** `mst_utc`, `state`
**Not:** Maç bitince `live_matches``matches` tablosuna migrate edilir (30dk cron).
---
#### `odd_categories` — Bahis Kategorileri (3,161,172 kayıt, 689 MB)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `db_id` | `Int` PK autoincrement | — |
| `match_id` | `String` FK → matches | Maç |
| `category_json_id` | `Int?` | Mackolik kategori ID |
| `name` | `String?` | "Maç Sonucu", "2,5 Alt/Üst", "Karşılıklı Gol" vb. |
| `created_at` | `DateTime` | — |
**Unique:** `(match_id, name)`
**İndeksler:** `match_id`
---
#### `odd_selections` — Bahis Seçimleri ve Oranları (8,511,132 kayıt, 1 GB)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `db_id` | `Int` PK autoincrement | — |
| `odd_category_db_id` | `Int` FK → odd_categories | Kategori |
| `name` | `String?` | "1", "X", "2", "Alt", "Üst", "1-X", vb. |
| `odd_value` | `String?` | Oran değeri ("1.85", "3.04") |
| `position` | `String?` | Sıralama pozisyonu |
| `sov` | `Float?` | — |
| `state` | `String?` | — |
| `created_at` | `DateTime` | — |
| `updated_at` | `DateTime` | — |
**Unique:** `(odd_category_db_id, name)`
**İndeksler:** `odd_category_db_id`
---
#### `odds_history` — Oran Değişim Geçmişi (0 kayıt, henüz aktif değil)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `BigInt` PK autoincrement | — |
| `selection_id` | `Int` FK → odd_selections | Seçim |
| `match_id` | `String` | Maç ID |
| `previous_value` | `Float` | Önceki oran |
| `new_value` | `Float` | Yeni oran |
| `bookmaker` | `String?` default "MACKOLIK" | — |
| `change_time` | `DateTime` | Değişim zamanı |
**İndeksler:** `(match_id, change_time)`, `selection_id`
---
#### `match_team_stats` — Takım İstatistikleri (310,991 kayıt, 91 MB)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `match_id` | `String` FK → matches | Maç |
| `team_id` | `String` FK → teams | Takım |
| **Futbol Alanları:** | | |
| `possession_percentage` | `Float?` | Topla oynama % |
| `shots_on_target` | `Int?` | İsabetli şut |
| `shots_off_target` | `Int?` | İsabetsiz şut |
| `total_shots` | `Int?` | Toplam şut |
| `total_passes` | `Int?` | Toplam pas |
| `corners` | `Int?` | Korner |
| `fouls` | `Int?` | Faul |
| `offsides` | `Int?` | Ofsayt |
| **Basketbol Alanları:** | | |
| `points` | `Int?` | Toplam sayı |
| `rebounds` | `Int?` | Ribaund |
| `assists` | `Int?` | Asist |
| `fg_made` / `fg_attempted` | `Int?` | Field goal |
| `three_pt_made` / `three_pt_attempted` | `Int?` | 3 sayı |
| `ft_made` / `ft_attempted` | `Int?` | Serbest atış |
| `steals` | `Int?` | Top çalma |
| `blocks` | `Int?` | Blok |
| `turnovers` | `Int?` | Top kaybı |
| `q1_score` ... `q4_score`, `ot_score` | `Int?` | Periyot skorları |
**Unique:** `(match_id, team_id)`
---
#### `match_player_participation` — Oyuncu Kadro Katılımları (3,342,839 kayıt, 1 GB)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `match_id` | `String` FK → matches | Maç |
| `player_id` | `String` FK → players | Oyuncu |
| `team_id` | `String` FK → teams | Takım |
| `position` | `PlayerPosition?` | goalkeeper, defender, midfielder, striker |
| `shirt_number` | `Int?` | Forma numarası |
| `is_starting` | `Boolean` default true | İlk 11'de mi? |
| `created_at` | `DateTime` | — |
**Unique:** `(match_id, player_id, team_id)`
---
#### `match_player_events` — Maç Olayları (1,453,227 kayıt, 356 MB)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `match_id` | `String` FK → matches | Maç |
| `player_id` | `String` FK → players | Olay yapan oyuncu |
| `team_id` | `String` FK → teams | Takım |
| `event_type` | `EventType` | goal, card, substitute |
| `event_subtype` | `String?` | "yellow", "red", "penalty", vb. |
| `time_minute` | `String` | Dakika ("45+2") |
| `time_seconds` | `Int?` | Saniye |
| `period_id` | `Int?` | Periyot |
| `assist_player_id` | `String?` FK → players | Asist yapan oyuncu |
| `score_after` | `String?` | Olay sonrası skor ("1-0") |
| `player_out_id` | `String?` FK → players | Çıkan oyuncu (değişiklik için) |
| `position` | `MatchPosition?` | home / away |
**İndeksler:** `match_id`, `player_id`, `team_id`, `event_type`, `assist_player_id`
**Dağılım:** substitute: 787K, card: 409K, goal: 257K
---
#### `match_player_stats` — Oyuncu İstatistikleri (344,688 kayıt, basketbol odaklı)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `match_id` | `String` FK → matches | Maç |
| `player_id` | `String` FK → players | Oyuncu |
| `team_id` | `String` FK → teams | Takım |
| `minutes` | `String?` | Oynanan süre |
| `points`, `rebounds`, `assists` | `Int?` | Temel istatistikler |
| `steals`, `blocks`, `turnovers`, `fouls` | `Int?` | Detay istatistikler |
| `fg_made/attempted`, `three_pt_made/attempted`, `ft_made/attempted` | `Int?` | Şut istatistikleri |
**Unique:** `(match_id, player_id, team_id)`
---
#### `match_officials` — Hakem Bilgileri (340,824 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `match_id` | `String` FK → matches | Maç |
| `name` | `String` | Hakem adı |
| `role_id` | `Int` FK → official_roles | Hakem rolü |
**Unique:** `(match_id, name, role_id)`
---
#### `official_roles` — Hakem Rolleri (5 kayıt)
| id | Rol |
|----|-----|
| 1 | Orta Hakem |
| 2 | Yardımcı Hakem |
| 3 | 4. Hakem |
| 4 | VAR |
| 5 | AVAR |
---
#### `match_ai_features` — AI Feature Cache (279 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `match_id` | `String` PK FK → matches | Maç |
| `home_elo` | `Float` default 1500 | Ev sahibi ELO |
| `away_elo` | `Float` default 1500 | Deplasman ELO |
| `home_form_score` | `Float` default 50 | Ev sahibi form skoru |
| `away_form_score` | `Float` default 50 | Deplasman form skoru |
| `missing_players_impact` | `Float` default 0 | Eksik oyuncu etkisi |
| `calculator_ver` | `String` default "v1.0" | Hesaplama versiyonu |
| `updated_at` | `DateTime` | — |
---
#### `predictions` — AI Tahmin Cache (3 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `match_id` | `String` PK FK → matches | Maç |
| `prediction_json` | `Json` | Tam tahmin paketi (SingleMatchPredictionPackage) |
| `created_at` | `DateTime` | — |
| `updated_at` | `DateTime` | TTL: 6 saat |
---
#### `ai_predictions_log` — AI Tahmin Loglama (0 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `match_id` | `String` | Maç ID |
| `model_version` | `String` | "v20plus.X" |
| `recommended_bets` | `Json?` | Önerilen bahisler |
| `confidence_score` | `Float?` | Güven skoru |
| `is_resolved` | `Boolean` default false | Sonuçlandı mı? |
| `actual_result` | `String?` | Gerçek sonuç |
| `is_correct` | `Boolean?` | Doğru mu? |
| `accuracy_score` | `Float?` | Doğruluk puanı |
---
#### `users` — Kullanıcılar (1 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `UUID` PK | — |
| `email` | `String` UNIQUE | — |
| `password_hash` | `String` | bcrypt (12 rounds) |
| `first_name` | `String?` | — |
| `last_name` | `String?` | — |
| `role` | `UserRole` default user | user / superadmin |
| `subscription_status` | `SubscriptionStatus` default free | free / active / expired |
| `subscription_expires_at` | `DateTime?` | — |
| `encrypted_api_key` | `String?` | — |
| `is_active` | `Boolean` default true | — |
| `deleted_at` | `DateTime?` | Soft delete |
**Limitler:** Free: 10 analiz + 3 kupon/gün, Active: 50 analiz + 10 kupon/gün
---
#### `user_coupons` — Kullanıcı Kuponları (0 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `UUID` PK | — |
| `user_id` | `String` FK → users | Kullanıcı |
| `strategy` | `String` | SAFE, BALANCED, AGGRESSIVE, VALUE, MIRACLE |
| `total_odds` | `Float` | Toplam oran |
| `status` | `String` default "PENDING" | PENDING, WON, LOST |
| `is_public` | `Boolean` default false | Herkes görebilir mi? |
---
#### `user_coupon_items` — Kupon Bahisleri (0 kayıt)
| Kolon | Tip | Açıklama |
|-------|-----|----------|
| `id` | `Int` PK autoincrement | — |
| `coupon_id` | `String` FK → user_coupons | Kupon |
| `match_id` | `String` FK → matches | Maç |
| `selection` | `String` | "MS 1", "2.5 Üst", "KG Var" vb. |
| `odd_at_time` | `Float` | Kayıt anındaki oran |
| `is_correct` | `Boolean?` | Sonuç |
---
#### `usage_limits`, `analyses`, `refresh_tokens`, `app_settings`, `translations`
Bu tablolar standart destek tablolarıdır (kullanım limiti, analiz geçmişi, JWT refresh token, key-value ayarlar, çeviri verileri).
---
## 3. İlişki Diyagramı (ER)
```
Country 1──N League 1──N Match N──1 Team (home/away)
├──N OddCategory 1──N OddSelection 1──N OddsHistory
├──N MatchTeamStats N──1 Team
├──N MatchPlayerParticipation N──1 Player, N──1 Team
├──N MatchPlayerEvents N──1 Player (scorer, assist, out), N──1 Team
├──N MatchPlayerStats N──1 Player, N──1 Team
├──N MatchOfficial N──1 OfficialRole
├──1 MatchAiFeature
└──1 Prediction
User 1──N Analysis
User 1──N UserCoupon 1──N UserCouponItem N──1 Match
User 1──1 UsageLimit
User 1──N RefreshToken
League 1──N LiveMatch N──1 Team (home/away)
```
---
## 4. Canlı Veritabanı İstatistikleri (2026-03-12)
| Tablo | Kayıt | Boyut |
|-------|-------|-------|
| `odd_selections` | 8,511,132 | 1,070 MB |
| `match_player_participation` | 3,342,839 | 1,077 MB |
| `odd_categories` | 3,161,172 | 689 MB |
| `match_player_events` | 1,453,227 | 356 MB |
| `match_player_stats` | 344,688 | 120 MB |
| `match_officials` | 340,824 | 75 MB |
| `match_team_stats` | 310,991 | 91 MB |
| `matches` | 236,859 | 100 MB |
| `players` | 217,040 | 64 MB |
| `teams` | 19,595 | 5.2 MB |
| `leagues` | 1,505 | 760 KB |
| **Toplam DB** | — | **3,658 MB** |
### Spor Dağılımı
| Spor | Maç | Lig | Ort. Ev Skor | Ort. Dep. Skor |
|------|-----|-----|-------------|---------------|
| Futbol | 189,291 | 1,094 | 1.55 | 1.27 |
| Basketbol | 47,568 | 304 | 84.36 | 81.57 |
---
## 5. AI Engine V20+ Tahmin Çıktısı (SingleMatchPredictionPackage)
```json
{
"model_version": "v20plus.X",
"match_info": { "match_id", "match_name", "home_team", "away_team", "league", "match_date_ms" },
"data_quality": { "label": "HIGH|MEDIUM|LOW", "score": 0-1, "flags": [], "home_lineup_count", "away_lineup_count" },
"risk": { "level": "LOW|MEDIUM|HIGH|EXTREME", "score", "is_surprise_risk", "surprise_type", "warnings" },
"engine_breakdown": { "team", "player", "odds", "referee" },
"main_pick": { "market", "pick", "probability", "confidence", "odds", "raw_confidence", "calibrated_confidence", "min_required_confidence", "edge", "play_score", "playable", "bet_grade": "A|B|C|PASS", "stake_units", "decision_reasons" },
"value_pick": { same as main_pick, odds >= 1.60 },
"bet_advice": { "playable", "suggested_stake_units", "reason" },
"bet_summary": [{ "market", "pick", "raw_confidence", "calibrated_confidence", "bet_grade", "playable", "stake_units", "play_score", "reasons" }],
"supporting_picks": [pick objects],
"aggressive_pick": { "market", "pick", "probability", "confidence", "odds" },
"scenario_top5": [{ "score", "prob" }],
"score_prediction": { "ft", "ht", "xg_home", "xg_away", "xg_total" },
"market_board": { "MS": {pick, confidence, probs}, "DC", "OU15", "OU25", "OU35", "BTTS", "HT", "HTFT": {probs: {"1/1": n, ...}} },
"reasoning_factors": ["..."]
}
```
---
## 6. API Endpointleri (50 Toplam)
### Auth (4) — Public
- `POST /api/auth/register` — Kayıt ol
- `POST /api/auth/login` — Giriş yap
- `POST /api/auth/refresh` — Token yenile
- `POST /api/auth/logout` — Çıkış yap
### Matches (4) — Public
- `GET /api/matches` — Maç listesi (paginated, matches tablosundan)
- `POST /api/matches/query` — Gelişmiş maç sorgusu (sport, league, status, date, team filtresi, live_matches tablosundan)
- `GET /api/matches/leagues/active` — Aktif ligler (cached 1dk)
- `GET /api/matches/:id` — Maç detayı (kadro, stat, oran, olaylar)
### Leagues (8) — Public
- `GET /api/leagues` — Tüm ligler
- `GET /api/leagues/:id` — Lig detay
- `GET /api/leagues/countries` — Ülke listesi
- `GET /api/leagues/countries/:id` — Ülke detay + ligleri
- `GET /api/leagues/teams/search` — Takım arama
- `GET /api/leagues/teams/:id` — Takım detay
- `GET /api/leagues/teams/:id/matches` — Takım son maçları
- `GET /api/leagues/teams/h2h` — Head-to-head
### Coupon (6) — Mixed
- `POST /api/coupon/analyze-match` — Tekil maç analizi (Public)
- `POST /api/coupon/daily-banko` — Günün bankosu (Public)
- `POST /api/coupon/suggest` — Akıllı kupon öner (Public)
- `POST /api/coupon/create` — Kupon kaydet (Auth)
- `GET /api/coupon/my-stats` — Kullanıcı istatistikleri (Auth)
- `GET /api/coupon/history` — Kupon geçmişi (Auth)
### Predictions (7) — Requires Redis
- `GET /api/predictions/health` — AI Engine health
- `GET /api/predictions/upcoming` — Yaklaşan tahminler
- `GET /api/predictions/value-bets` — EV+ fırsatları
- `GET /api/predictions/history` — Tahmin geçmişi
- `GET /api/predictions/:matchId` — Tekil tahmin (cached 6 saat)
- `POST /api/predictions/generate` — Tahmin üret
- `POST /api/predictions/smart-coupon` — Smart Coupon
### Admin (11) — Superadmin
- Kullanıcı CRUD, rol/abonelik güncelleme, ayarlar, analytics
### Analysis (2) — Auth
- `POST /api/analysis/analyze-matches` — Çoklu maç analizi
- `GET /api/analysis/history` — Analiz geçmişi
### Users (5) — Auth
- CRUD + restore
### Health (3) — Public
- `GET /api/health` — Readiness
- `GET /api/health/live` — Liveness
- `GET /api/health/detail` — Detaylı sağlık
---
## 7. Cron/Zamanlanmış Görevler
| Görev | Cron | Açıklama |
|-------|------|----------|
| `fetchLiveMatches()` | `*/15 * * * *` | Mackolik API'den futbol maçlarını çek → live_matches |
| `fetchOddsForPreMatches()` | `*/15 * * * *` | Başlamamış maçların oranlarını çek |
| `fetchBasketballMatches()` | Manuel | Basketbol maçlarını çek |
| `updateLiveScores()` | `*/15 * * * *` | Canlı maç skorlarını güncelle |
| `finalizeFinishedMatches()` | `*/30 * * * *` | Bitmiş maçları live_matches → matches'e migrate et |
| `resetUsageLimits()` | `0 3 * * *` | Günlük kullanım limitlerini sıfırla |
| `cleanupOldData()` | `0 4 * * *` | 30 günlük AI logları sil |
| `checkSubscriptions()` | `0 0 * * *` | Süresi dolmuş abonelikleri expired yap |
---
## 8. Standart API Response Formatı
```json
{
"success": true,
"status": 200,
"message": "Success",
"data": { ... },
"errors": []
}
```
**Not:** Global Exception Filter tüm hataları HTTP 200 olarak döner, gerçek status body içindedir.