Etkilenen bileşen: Sunucu (ASP.NET Core) Mobil tarafta değişiklik gerekmez.
user_settings tablosunda her kullanıcı için bir satır olması gerekiyor, ancak bu satır
kullanıcı oluşturulurken açılmıyor. Kayıt yalnızca iki yerde, geç (lazy) olarak yaratılıyor:
| Metot | Dosya | Tetikleyen uç |
|---|---|---|
UserService.GetSetting() |
Services/UserService.cs (satır 81-97) |
GET /api/AccountApi/Settings |
UserService.UpdateSetting() |
Services/UserService.cs (satır 111-130) |
POST /api/AccountApi/Settings |
Mobil uygulamada bu ucu çağıran tek yer Ayarlar ekranıdır (lib/pages/settings_page.dart).
Giriş akışında çağrılmaz. Yani satır, kullanıcı mobil uygulamada Ayarlar ekranını ilk kez
açtığında oluşur. Yönetim panelinden açılan kullanıcıda hiç oluşmaz.
Asıl sorun eksik satırın kendisi değil, sonucudur. Services/UserService.cs satır 48-52:
var setting = await _context.UserSettings.FirstOrDefaultAsync(x => x.UserId == userId);
if (setting == null)
{
return false; // ← kayıt yoksa "bildirim istemiyor" sayılıyor
}UserSetting modelinde tüm alanların varsayılanı true'dur (bildirimler açık), ama kayıt
yokken bu metot false döner. MessageService de bunu bir kapı olarak kullanır.
Sonuç: Yeni açılan bir kullanıcı, mobil uygulamada Ayarlar ekranını bir kez açana kadar hiçbir bildirim almaz — yalnızca
NotifikasyonTip.Alwaysile gönderilenler geçer. "Kullanıcı Oluşturuldu" SMS'iAlwaysolduğu için gider, sonrası sessiz kalır.
Üç değişiklik var. Üçü de uygulanmalıdır:
- Değişiklik A — kalıcı çözüm (yeni kullanıcılarda satır oluşsun)
- Değişiklik B — emniyet supabı (satır yoksa bile bildirim gitsin)
- Değişiklik C — mevcut kullanıcıları onarır (tek seferlik SQL)
Dosya: Sunucu/Sivasbeltr.WorkCollab.Web/Controllers/AppUsersController.cs
Yer: Create metodu, satır 104'ün hemen ÖNCESİNE (rol atamasını yapan if bloğu
bittikten sonra, var message = ... satırından önce).
Mevcut kod şöyle görünüyor (satır 103-105):
}
var message = $"Randevu sisteminde kullanıcı kaydınız oluşturuldu. Kullanıcı adı: {user.UserName} Şifre: {model.Password}";
await _messageService.CreateAsync(Araya eklenecek kod — sonuç şöyle olmalı:
}
// Kullanici icin varsayilan bildirim ayarlarini olustur.
// UserSetting modelindeki tum alanlarin varsayilani true'dur (bildirimler acik).
if (!await _context.UserSettings.AnyAsync(x => x.UserId == user.Id))
{
_context.UserSettings.Add(new UserSetting { UserId = user.Id });
await _context.SaveChangesAsync();
}
var message = $"Randevu sisteminde kullanıcı kaydınız oluşturuldu. Kullanıcı adı: {user.UserName} Şifre: {model.Password}";
await _messageService.CreateAsync(Not: Gerekli
usingsatırları dosyada zaten mevcuttur (Microsoft.EntityFrameworkCoresatır 10,Sivasbeltr.WorkCollab.Application.Modelssatır 12)._contextalanı da sınıfta hazırdır (satır 25). Ekusinggerekmez.
Dosya: Sunucu/Sivasbeltr.WorkCollab.Web/Data/DataSeeder.cs
Yer: EnsureAdmin metodu, satır 71'den sonra (rol atamalarının hemen ardından,
} kapanışından önce).
Mevcut kod (satır 69-72):
await userManager.CreateAsync(user, AdminPassword);
await userManager.AddToRoleAsync(user, UserRoles.Admin);
await userManager.AddToRoleAsync(user, UserRoles.Sistem);
}Şu hale getirin:
await userManager.CreateAsync(user, AdminPassword);
await userManager.AddToRoleAsync(user, UserRoles.Admin);
await userManager.AddToRoleAsync(user, UserRoles.Sistem);
// Varsayilan bildirim ayarlarini olustur.
var context = serviceProvider.GetRequiredService<AppDbContext>();
if (!await context.UserSettings.AnyAsync(x => x.UserId == user.Id))
{
context.UserSettings.Add(new UserSetting { UserId = user.Id });
await context.SaveChangesAsync();
}
}Not:
DataSeeder.csdosyasının başındausing Microsoft.EntityFrameworkCore;(satır 2) veusing Sivasbeltr.WorkCollab.Application.Models;(satır 4) zaten var.AppDbContextaynı namespace'te (Sivasbeltr.WorkCollab.Web.Data) olduğu için ekusinggerekmez.
Dosya: Sunucu/Sivasbeltr.WorkCollab.Web/Services/UserService.cs
Yer: HasReceiveNotification metodu, satır 48-52.
Mevcut kod:
var setting = await _context.UserSettings.FirstOrDefaultAsync(x => x.UserId == userId);
if (setting == null)
{
return false;
}Yeni hali:
var setting = await _context.UserSettings.FirstOrDefaultAsync(x => x.UserId == userId);
if (setting == null)
{
// Ayar kaydi yoksa kullanici henuz hicbir tercihte bulunmamis demektir.
// UserSetting modelindeki varsayilanlar true oldugu icin bildirim GONDERILIR.
// (Onceki davranis false idi; bu, ayar kaydi olusmamis kullanicilarin
// hicbir bildirim almamasina yol aciyordu.)
return true;
}
⚠️ Bu bir davranış değişikliğidir. Bu düzeltmeden sonra,user_settingssatırı olmayan mevcut kullanıcılar bildirim almaya başlayacaktır. Beklenen ve doğru davranış budur, ancak kullanıcılar için ani bir değişiklik olacağı için bilgilendirme yapmanız iyi olur. Değişiklik C uygulanırsa zaten satırsız kullanıcı kalmaz ve bu kod yolu bir daha çalışmaz; B yine de ileride oluşabilecek durumlara karşı emniyet supabı olarak kalmalıdır.
A ve B kod değişiklikleridir, geçmişte açılmış kullanıcıları düzeltmezler. Aşağıdaki SQL, satırı eksik olan tüm kullanıcılar için varsayılan ayar kaydını oluşturur.
Önce yedek alın:
pg_dump -U <kullanici> -d workcollab > workcollab_yedek_$(date +%F).sqlArdından PostgreSQL üzerinde çalıştırın:
INSERT INTO user_settings (
user_id,
hide_old_agendas,
agenda_on_created, agenda_on_organized, agenda_on_deleted, agenda_on_updated,
agenda_on_status_change, agenda_on_image_upload, agenda_on_note_added,
agenda_on_postponed, agenda_on_flower_sent, agenda_on_flower_deleted,
request_on_created, request_on_organized, request_on_deleted, request_on_updated,
request_on_file_attached, request_on_status_change, request_on_note_added,
request_on_remittance, request_on_added_to_agenda
)
SELECT
u.id,
true,
true, true, true, true,
true, true, true,
true, true, true,
true, true, true, true,
true, true, true,
true, true
FROM "AspNetUsers" u
WHERE NOT EXISTS (
SELECT 1 FROM user_settings s WHERE s.user_id = u.id
);Tablo adı notu: Kullanıcı tablosunun adı
"AspNetUsers"şeklinde büyük harflidir ve PostgreSQL'de çift tırnak içinde yazılmalıdır. Kolon adları ise snake_case'tir (u.id).
Doğrulama — aşağıdaki sorgu 0 dönmelidir:
SELECT COUNT(*)
FROM "AspNetUsers" u
WHERE NOT EXISTS (SELECT 1 FROM user_settings s WHERE s.user_id = u.id);Kullanıcı ve ayar sayılarının eşitliğini de kontrol edebilirsiniz:
SELECT (SELECT COUNT(*) FROM "AspNetUsers") AS kullanici_sayisi,
(SELECT COUNT(*) FROM user_settings) AS ayar_sayisi;- Veritabanı yedeği alın.
- Değişiklik C'deki SQL'i çalıştırın (mevcut kullanıcılar onarılır).
- Değişiklik A ve B'yi koda uygulayın.
- Derleyin:
dotnet build→ hata olmamalı. - Uygulamayı yeniden yayına alın (
dotnet publish+ servis restart).
- Yönetim panelinden yeni bir kullanıcı oluşturun.
- Veritabanında satırın oluştuğunu doğrulayın:
→ Bir satır dönmeli, tüm boolean alanlar
SELECT * FROM user_settings WHERE user_id = <yeni_kullanici_id>;
trueolmalı. - Bu kullanıcıyla mobil uygulamaya giriş yapın (FCM token'ın sunucuya gitmesi için).
- Bu kullanıcıya bildirim üretecek bir işlem yapın (örn. ajanda oluşturma).
messagestablosunda kaydın oluştuğunu veis_success = trueolduğunu doğrulayın:SELECT id, title, is_success, fail_message FROM messages ORDER BY id DESC LIMIT 5;
- Mobil uygulamada Ayarlar ekranını açın — ayarlar görünmeli, değiştirip
kaydettiğinizde
user_settingssatırı güncellenmeli (yeni satır oluşmamalı).
UserSetting.UserId için tanımlı bir foreign key / ilişki yoktur — AppDbContext.cs
satır 31'de yalnızca DbSet<UserSetting> tanımlıdır. Bu nedenle:
- Bir kullanıcı silindiğinde
user_settingssatırı öksüz kalır (silinmez). - Veritabanı düzeyinde bütünlük garantisi yoktur.
İleride düzeltmek isterseniz AppDbContext.OnModelCreating içinde AppUser ile UserSetting
arasında HasOne/WithOne ilişkisi ve OnDelete(DeleteBehavior.Cascade) tanımlayıp yeni bir
migration üretmeniz gerekir. Bu, mevcut sorunu çözmek için gerekli değildir; yukarıdaki
A/B/C değişiklikleri bağımsız olarak çalışır.
Öksüz kalmış satırları temizlemek isterseniz:
DELETE FROM user_settings s
WHERE NOT EXISTS (SELECT 1 FROM "AspNetUsers" u WHERE u.id = s.user_id);