diff --git a/docs/quality/qa-subscription-lifecycle.json b/docs/quality/qa-subscription-lifecycle.json new file mode 100644 index 0000000..6694efd --- /dev/null +++ b/docs/quality/qa-subscription-lifecycle.json @@ -0,0 +1,12 @@ +{ + "checks": { + "loadError": true, + "firstSaved": true, + "independentTopics": true, + "failedDeletePreservesBoth": true, + "deleteOnlySelected": true, + "persistedAfterReload": true + }, + "scope": "Local browser UI, real subscription API and SQLite; synthetic read/delete errors; no email delivery", + "snapshot": "Sonuç Sorgula\n- button \"İhale Takvimi\":\n - generic: İhale Takvimi\n- button \"Sözleşme Sorgula\":\n - generic: Sözleşme Sorgula\n- button \"KDV Hesapla\":\n - generic: KDV Hesapla\n- button \"Sınır Değer\":\n - generic: Sınır Değer\n- button \"Fiyat Analizi\":\n - generic: Fiyat Analizi\n- button \"Kanban Pano Sürükle Takip\":\n - generic: Kanban Pano\n - generic: Sürükle Takip\n- button \"Rakip Radar Canlı Uyar\":\n - generic: Rakip Radar\n - generic: Canlı Uyar\n- button \"Doküman Deposu\":\n - generic: Doküman Deposu\n- button \"Analitik Dashboard\":\n - generic: Analitik Dashboard\n- button \"Kırmızı Bayrak Şeffaflık\":\n - generic: Kırmızı Bayrak\n - generic: Şeffaflık\n- button \"KİK Kurul Kararları\":\n - generic: KİK Kurul Kararları\n- button \"AB İhaleleri (TED)\":\n - generic: AB İhaleleri (TED)\n- button \"Planlar\":\n - generic: Planlar\n- button \"API & Webhooks\":\n - generic: API & Webhooks\n- button \"Mobil PWA\" [active]:\n - generic: Mobil PWA\n- main:\n - heading \"Mobil uygulama ve bağlantı durumu\" [level=2]\n - paragraph: Uygulama kabuğu önbellekten açılabilir. İhale güncelleme, belge erişimi ve hazırlık kaydı için internet bağlantısı gerekir.\n - heading \"Çevrimdışı (Offline) Önbellek\" [level=3]:\n - text: Çevrimdışı (Offline) Önbellek\n - generic: Bağlantı var\n - paragraph:\n - generic: \"İhale Kayıtları (bellekte):\"\n - strong: 5 ihale\n - paragraph:\n - generic: \"Önbelleğe alınmış istek:\"\n - strong: 0 kayıt\n - paragraph:\n - generic: \"Uygulama sürümü önbelleği:\"\n - strong: —\n - button \"Önbellek durumunu kontrol et\"\n - paragraph: Bağlantı durumu sunucuya erişimi garanti etmez. Çevrimdışı değişiklikler otomatik gönderim kuyruğuna alınmaz; kayıt sonucunu kontrol edin.\n - heading \"Anlık Bildirimler\" [level=3]:\n - text: Anlık Bildirimler\n - generic: Reddedildi\n - paragraph: Tarayıcı bildirimlerine izin verin; yeni ihale ve son tarih uyarıları gerçek bildirim olarak gelir.\n - button \"Bildirimlere İzin Ver\"\n - text: Sessiz Saatler\n - checkbox \"Sessiz Saatler\"\n - heading \"E-posta Bildirimi\" [level=3]:\n - text: E-posta Bildirimi\n - generic: Yapılandırılmadı\n - paragraph: E-posta göndermek için sunucuya RESEND_API_KEY ekleyin (Coolify → Environment). Ayrıca gönderen domainini Resend’de DNS ile doğrulayın.\n - generic: E-posta bildirimleri açık\n - checkbox \"E-posta bildirimleri açık\" [checked]\n - button \"Kendime Test E-postası Gönder\" [disabled]:\n - text: Kendime Test E-postası Gönder\n - heading \"İhaleist Mobil / Masaüstü\" [level=3]:\n - text: İhaleist Mobil / Masaüstü\n - generic: PWA 2.0\n - paragraph: İhaleist'i iOS, Android, Windows veya Mac cihazınıza bir tıklama ile uygulama olarak kurun.\n - button \"İhaleist Uygulamasını Cihaza Yükle\":\n - generic: İhaleist Uygulamasını Cihaza Yükle\n - heading \"Haftalık Brief\" [level=3]:\n - text: Haftalık Brief\n - paragraph: \"Her Pazartesi 08:00: bu hafta yapılacak takipli ihaleler ve geçen hafta sonuçlanan takipliler — Telegram (bağlıysa) ve e-posta ile tek mesaj.\"\n - button \"Önizle\":\n - text: Önizle\n - switch [checked]\n - heading \"Telegram Bildirimi\" [level=3]:\n - text: Telegram Bildirimi\n - generic: bağlı değil\n - paragraph:\n - text: Yeni ihale özetleri, takipteki ihalede\n - strong: zeyilname/düzeltme ilanı\n - text: ve\n - strong: sonuç\n - text: (\"X firması Y'ye aldı, %Z kırım\") e-postanın yanında Telegram'a da gelir.\n - paragraph: \"Sunucuda Telegram botu henüz tanımlı değil. Kurulum (yönetici, bir kez):\"\n - list:\n - text: Telegram'da\n - strong: \"@BotFather\"\n - text: \"'a yazın:\"\n - code: /newbot\n - text: → bir ad ve\n - code: …bot\n - text: ile biten kullanıcı adı verin.\n - text: BotFather'ın verdiği tokenı Coolify → ihaleist → Environment'a\n - code: TELEGRAM_BOT_TOKEN\n - text: olarak ekleyin, Redeploy.\n - listitem: Bu sayfa yeniden açıldığında aşağıdaki bağlama adımları görünür.\n - paragraph: Token yalnızca sunucuda durur; uygulamaya girilmez.\n - heading \"Otomatik E-posta Bildirimi\" [level=3]:\n - text: Otomatik E-posta Bildirimi\n - generic: 1 kayıt\n - paragraph:\n - text: Hangi\n - strong: konularda\n - text: ihale alabiliyorsanız onları seçin —\n - strong: tüm Türkiye\n - text: taranır, yalnızca size uyan yeni ihaleler\n - strong: browser-qa@example.test\n - text: adresine gelir. Gereksiz ilan gönderilmez.\n - paragraph: Test cihazı\n - paragraph: ilk tur bekleniyor\n - 'button \"Aboneliği sil: Test cihazı\"':\n - paragraph:\n - text: Sitenizi tarayıp konuları otomatik önerelim\n - textbox \"firmasitesi.com\"\n - button \"Tara\" [disabled]:\n - text: Tara\n - paragraph: Seçilen konular\n - paragraph: Henüz konu seçilmedi.\n - textbox \"Kendi konunuzu yazın ve Enter'a basın\"\n - button \"Ekle\"\n - paragraph: \"Hazır sektörler:\"\n - button \"+ Akaryakıt & Yakıt\"\n - button \"+ Altyapı & Yol\"\n - button \"+ Asansör & Yürüyen Sistem\"\n - button \"+ Atölye & Makine Ekipmanı\"\n - button \"+ Bilişim & Yazılım\"\n - button \"+ Danışmanlık & Proje\"\n - button \"+ Elektrik & Enerji\"\n - button \"+ Gıda & Catering\"\n - button \"+ Güvenlik Sistemleri\"\n - button \"+ Isıtma & İklimlendirme\"\n - button \"+ İnşaat & Bakım\"\n - button \"+ Kırtasiye & Büro\"\n - button \"+ Laboratuvar & Ölçüm\"\n - button \"+ Mobilya & Donatı\"\n - button \"+ Otomotiv & İş Makinesi\"\n - button \"+ Personel Hizmet Alımı\"\n - button \"+ Peyzaj & Park\"\n - button \"+ Reklam & Organizasyon\"\n - button \"+ Sağlık / Tıbbi Malzeme\"\n - button \"+ Sigorta\"\n - button \"+ Spor Tesisleri\"\n - button \"+ Su & Arıtma\"\n - button \"+ Tarım & Hayvancılık\"\n - button \"+ Taşımacılık & Kiralama\"\n - button \"+ Taşınmaz & Kiralama\"\n - button \"+ Tekstil & Giyim\"\n - button \"+ Temizlik & Hijyen\"\n - button \"+ Yayın & Arşiv\"\n - button \"+ Genel\"\n - 'button \"Daha da daralt (isteğe bağlı) — varsayılan: tüm Türkiye\"':\n - text: \"Daha da daralt (isteğe bağlı) — varsayılan: tüm Türkiye\"\n - button \"Bildirimi Kaydet\" [disabled]:\n - text: Bildirimi Kaydet\n - paragraph:\n - text: İlk kayıtta mevcut ihaleler\n - strong: bildirilmez\n - text: — yalnızca temel alınır, sonrasında çıkan yeni ihaleler gönderilir. Aynı ihale iki kez gönderilmez; sonuçlanmış arşiv kayıtları bildirime girmez.\n- button \"Kullanım kılavuzu (? tuşu)\":" +} \ No newline at end of file diff --git a/docs/quality/uygulama-durumu.md b/docs/quality/uygulama-durumu.md index 2adad0f..f9e866c 100644 --- a/docs/quality/uygulama-durumu.md +++ b/docs/quality/uygulama-durumu.md @@ -793,3 +793,9 @@ Taslak türü seçicisine erişilebilir ad eklendi. Üretim derlemesi geçti. Ö - Legacy tablo tek transaction ile taşınır. Kimlikler, gönderim/görülen ihale alanları, aktiflik ve AUTOINCREMENT üst sınırı korunur. Normalleştirmeyle eşdeğer olan eski kayıtlar kayıpsız bırakılır; bozuk eski JSON'da geçiş rollback olur. - 177 otomatik test geçti: farklı kümeler, eşdeğer kayıt tekrarları, gönderim geçmişi, legacy tekrarlar/id sırası, index yeniden kurulması ve hatada rollback/integrity doğrulandı. Sunucu kodu değişti; arayüz değişmediği için önceki derleme tekrarlanmadı. - Eski koda geri dönüşün veritabanı yedeğiyle eşleştirilmesi runbook'a eklendi. Üretim migration uygulanmadı. Yeni abonelik formunun tarayıcı kayıt/sil/hata kabulü açık. + +### Abonelik formu tarayıcı kabulü — 6 Eylül 2026 +- Yerel 5181 ortamında gerçek API/notify.sqlite ile liste GET503→yeniden yükle, Laboratuvar sarfı ve Test cihazı için aynı daraltmayla iki ayrı kayıt, DELETE503→iki kaydın korunması, başarılı silme→yalnız hedefin kaldırılması ve sayfa yenilemede kalıcılık doğrulandı. +- `qa-subscription-lifecycle.json`: 6 kontrol doğru. Hata yanıtları yalnız QA middleware'de üretilir; gerçek kayıt/sil/liste endpointleri kullanıldı. E-posta teslimi yapılmadı. +- Ekrandaki koşulsuz gönderim ve yinelenmeme vaadi değiştirildi: e-posta hizmetinin etkin olması gerektiği ve abonelik kaydının teslim kanıtı olmadığı açıklandı. Derleme geçti; salt UI metni/test altyapısı değiştiği için önceki 177 test yeniden çalıştırılmadı. +- Dış e-posta/Telegram teslimi, provider hata sonrası yeniden deneme ve planın diğer kabul maddeleri açık. diff --git a/src/components/tools/NotifySubscriptions.jsx b/src/components/tools/NotifySubscriptions.jsx index f2d6d84..126227e 100644 --- a/src/components/tools/NotifySubscriptions.jsx +++ b/src/components/tools/NotifySubscriptions.jsx @@ -109,7 +109,7 @@ const SubscriptionForm = () => {
Hangi konularda ihale alabiliyorsanız onları seçin — tüm Türkiye taranır, - yalnızca size uyan yeni ihaleler {authUser.email} adresine gelir. Gereksiz ilan gönderilmez. + E-posta gönderim hizmeti etkin olduğunda, eşleşen yeni ihaleler {authUser.email} adresine gönderilir.
{/* Mevcut kayıtlar */} @@ -251,7 +251,7 @@ const SubscriptionForm = () => {İlk kayıtta mevcut ihaleler bildirilmez — yalnızca temel alınır, sonrasında çıkan - yeni ihaleler gönderilir. Aynı ihale iki kez gönderilmez; sonuçlanmış arşiv kayıtları bildirime girmez. + yeni ihaleler gönderilir. Sonuçlanmış arşiv kayıtları bildirime girmez. Aboneliği kaydetmek, e-postanın teslim edildiği anlamına gelmez.
diff --git a/tests/browser-qa.mjs b/tests/browser-qa.mjs index 710fdc2..491b725 100644 --- a/tests/browser-qa.mjs +++ b/tests/browser-qa.mjs @@ -33,7 +33,11 @@ const qaNotifications=await import('../server/zeyilname.mjs'); qaNotifications.bildirimYaz({email:user.email,tur:'zeyilname',ikn:'2026/1582991',baslik:'QA tarih değişikliği',metin:'Sentetik bildirim: ihale tarihi güncellendi.'}); qaNotifications.bildirimYaz({email:user.email,tur:'sonuc',ikn:'2026/1534665',baslik:'QA sonuç bildirimi',metin:'Sentetik sonuç inceleme bildirimi.'}); let notificationFailure='read'; +let subscriptionFailure='read'; const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{target:'http://127.0.0.1:'+port}}},plugins:[{name:'qa-fixtures',configureServer(server){server.middlewares.use(async(req,res,next)=>{ + if(req.url==='/qa-subscription-controls'){res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`