fix(pl24): bütçe kilitlenmesi, sabitlenmiş browse satırları, Volvo alanları + WMI kapsamı #268

Merged
root merged 6 commits from dev into main 2026-09-20 09:15:26 +03:00

6 Commits

Author SHA1 Message Date
c2f4d8f421 feat(pl24): WMI haritasını canlı servis taramasıyla genişlet, Renault'yu aç
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Prod'daki 4.799 aracın 1.406'sının WMI'si haritada yoktu. Hangilerinin
PL24'te gerçekten karşılığı olduğu tahmin edilmedi — canlı
`/pl24-wmi/ext/api/2.0/decode` servisine gerçek prod VIN'leriyle tek tek
soruldu (2026-09-20).

**Renault yeniden açıldı (450 araç).** İki gerekçe de artık geçersiz,
ikisi de prod'a karşı doğrulandı:
- Askı kalkmış: `/p5renault` directAccess, gerçek müşteri aracı
  VF14SRCL458170337 için `VEHICLE_IDENTIFIED` + "SYMBOL II/LOGAN II"
  döndü; WMI servisi de `{service: renault_parts, error: false}` diyor.
- Devre kesici artık kesin olumsuz yanıtları saymıyor, yalnız geçici
  taşıma hatalarını (`vehicles.service` `isTransient`).

**Yeni eşlemeler (toplam 730 araç):** NLH/TMA/NLJ/KMF → hyundai_parts,
KNE/KNC → kia_parts, MMC/XMC → mmc_parts, JSA → suzuki_parts,
NMB → **mercestrucks**_parts (servis binek Mercedes'e değil kamyon
kataloğuna çözüyor; bu 30 araç "Mercedes-Benz" etiketliydi ama binek
kataloğunda yok).

**Kasıtlı olarak EKLENMEYENLER** — servis HTTP 410 "no brands found"
dedi, tıpkı NM4 ve VR7 gibi: JHM/SHH/SHS/MAK/NLA (Honda), KL1
(Chevrolet). Eklemek yalnız boşuna istek üretir ve pcat/emex/vinpin
fallback'ini geciktirir. JMZ (Mazda) 410 değil ama fordp/fordt
döndürüyor (Ford-Mazda platform ortaklığı); marka tutarsız olduğu için
eklenmedi.

6 yeni test; "olmayanlar" da kilitlendi. Ayrıca her eşlemenin katalog
tanımı olduğunu doğrulayan bütünlük testi. api 623 test geçiyor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 08:53:07 +03:00
72f8c2a3e4 fix(pl24): Volvo alanlarında iç kodu değil okunur değeri kullan
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Volvo vinfoBasic aynı özniteliği iki kez veriyor: "Şanzıman kodu" = "B"
ile "Şanzıman" = "6-PSHIFT 2WD / MPS6", "Satis tipi" = "42" ile "Türü"
= "S80". VAG için doğru olan kod-önce sırası (VAG'ın "Şanzıman kodu"
zaten anlamlı: "MQ200") bu yüzden Volvo'da şanzımanı tek harf, seriyi
çıplak sayı yapıyordu.

`lookupDescriptive()` eklendi: listedeki ilk *açıklayıcı* değeri döner
(2 karakterden uzun ve salt rakam değil), hiçbiri açıklayıcı değilse
ilk mevcut değere düşer — yani yalnız kod üreten backend'ler aynen
eskisi gibi davranır. Şanzıman ve seri bu yardımcıya geçti.

Ayrıca eksik İngilizce etiketler eklendi: `transmission` (İngilizce
yanıtta şanzıman yine tek harfe düşüyordu) ve `body_style`.

Ölçüm (gerçek keşif yakalamaları, YV1AS84ABD1168166 S80):
- şanzıman "B" → "6-PSHIFT 2WD / MPS6"
- seri "42" → "S80"
- kaporta İngilizce yanıtta null → "Sedan"
- PSA İngilizce yanıtta şanzıman null → "BVM5"
PSA Türkçe, Subaru ve diğer markalarda çıktı değişmedi.

6 yeni test + iki dilde gerçek Volvo fixture'ı. api 617 test geçiyor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 08:45:16 +03:00
0928559ea4 fix(catalog): browse onarmasında yalnız bayat satırları sil
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Bir servis karışık olabilir: bazı satırları yeni mimariyle yeniden
listelenmiş, bazıları hâlâ eski. Silme servis adına göre yapıldığında
zaten taşınmış satırlar da gidiyordu — üstteki insert onları
`onConflictDoNothing` ile atladığı için geri gelmiyorlar, yani temelli
kayıp. Silme artık yalnız gerçekten bayat olan satırlara uygulanıyor.

Hangi satırların silindiğini doğrulayan test eklendi (drizzle
`inArray` parametrelerini okuyarak).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 08:40:26 +03:00
eb18c9a122 fix(catalog): sabitlenmiş browse satırlarını görüntülendikçe yenile
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
`catalog_vehicles` kalıcı bir cache: `getModels` markanın tek bir satırı
varsa erken dönüyor, dolayısıyla `fetchVehicleList` o marka için bir
daha hiç çağrılmıyor. PSA ve Volvo hâlâ P4 iken listelenmiş 188 satır
(prod 2026-09-20: 127 LEGACY_PSA + 61 LEGACY_VOLVO) bu yüzden kalıcı
olarak çakılı kalmıştı:

- Peugeot/Citroën browse donmuş 2024-02-13 anlık görüntüsünü sunuyor,
- Volvo/Polestar browse HTTP 503 dönen bir uca gidiyor.

Kod düzeltmesi bu satırlara hiçbir zaman ulaşmıyordu.

`isStaleBrowseArchitecture()` + `CatalogService.healStaleBrowseRows()`:
satırın kayıtlı mimarisi servis tablosundakiyle uyuşmuyorsa marka bir
kez yeniden listeleniyor, yeni satırlar yazılıp eskiler aynı
transaction'da siliniyor. VIN tarafındaki onarma ile aynı temkinli
kurallar: marka başına günde bir deneme (Redis kilidi), başarısız veya
boş listede eski satırlar korunuyor, silme ancak yenisi elde edilince
ve servis bazında yapılıyor.

8 yeni test; api paketi 610 test geçiyor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 08:35:09 +03:00
ae8a8046bf refactor(prefetch): kapı sırasını en ucuzdan pahalıya diz
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Pencere kontrolü saf saat aritmetiği, hiç I/O yapmıyor ve pencere
dışındaki iş zaten hiçbir faydalı iş yapamıyor — dolayısıyla dakikalık
Redis sayacından da önce gelmeli. Yeni sıra: pencere → cooldown →
dakikalık tavan → günlük bütçe. Böylece pencere dışında uyanan iş
hiçbir sayacı kirletmiyor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 08:31:55 +03:00
7644d91407 fix(prefetch): PL24 bütçe/iş-saati kilitlenmesini kır
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Prod'da PL24 prefetch tamamen durmuştu: günlük bütçe 600/600 dolu
görünürken gün boyunca SIFIR katalog isteği ve SIFIR yeni kategori
üretiliyordu (ölçüm 2026-09-20).

İki hata birlikte kapalı bir döngü kuruyordu:

1. Günlük bütçe `process()` içinde düşülüyor, iş-saati (ve cooldown)
   kapısı ise her handler'ın başında duruyordu. Pencere dışında uyanan
   bir iş önce bütçeden bir birim yiyor, sonra `time-window` fırlatıp
   hiçbir iş yapmadan erteleniyordu.

2. Bütçesi biten kaynak "bir sonraki UTC gece yarısı"na erteleniyordu.
   PREFETCH_PL24_START=9 ile bu an 03:00 Europe/Istanbul'a denk gelir —
   pencere açılmadan altı saat önce. Uyanan iş yine pencereye takılıyor,
   yine erteleniyor; taze günlük bütçe daha pencere açılmadan bu boş
   uyanmalarla tükeniyordu.

Düzeltme:
- cooldown + iş-saati kapıları `process()` içinde, bütçe düşülmeden
  ÖNCE çalışıyor; handler'lardaki kopyaları kaldırıldı.
- `alignToWindow()` eklendi: bütçe ertelemesi pencerenin içine
  hizalanıyor. Pencere tanımlı değilse (varsayılan 0–24) no-op.
- `currentIstanbulHour` artık `istanbulHourAt`'e deleg ediyor ve h24
  döngüsünün gece yarısı için ürettiği "24" değeri `% 24` ile
  normalleniyor (aksi halde saat hiçbir pencereye düşmez).

8 yeni regresyon testi; api paketi 602 test geçiyor.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-20 08:29:55 +03:00