using FinlyticNews.Database; using FinlyticNews.Entities; using Microsoft.EntityFrameworkCore; namespace FinlyticNews.Services; /// /// Service interface for retrieving and persisting runtime settings in PostgreSQL for FinlyticNews. /// public interface ISettingsDbService { /// /// Retrieves current news settings from database, initializing default values if empty. /// Task GetSettingsAsync(); /// /// Persists updated settings to PostgreSQL. /// Task SaveSettingsAsync(NewsSettingsEntity settings); /// /// Updates settings from a key-value dictionary received via Admin Panel MQTT events. /// Task UpdateSettingsFromDictionaryAsync(Dictionary dictionary); } /// /// EF Core implementation of . /// public class SettingsDbService : ISettingsDbService { private readonly NewsDbContext _context; /// /// Initializes a new instance of the class. /// /// The database context mapping database tables. public SettingsDbService(NewsDbContext context) { _context = context; } /// public async Task GetSettingsAsync() { var settings = await _context.Settings.AsNoTracking().FirstOrDefaultAsync(); if (settings == null) { settings = new NewsSettingsEntity { Id = Guid.NewGuid() }; _context.Settings.Add(settings); await _context.SaveChangesAsync(); _context.ChangeTracker.Clear(); } return settings; } /// public async Task SaveSettingsAsync(NewsSettingsEntity settings) { var existing = await _context.Settings.FirstOrDefaultAsync(); if (existing == null) { if (settings.Id == Guid.Empty) settings.Id = Guid.NewGuid(); _context.Settings.Add(settings); } else { existing.PollingFrequencyMinutes = settings.PollingFrequencyMinutes; existing.ArticleRetentionDays = settings.ArticleRetentionDays; existing.DefaultPageSize = settings.DefaultPageSize; existing.ScrapingIntervalMinutes = settings.ScrapingIntervalMinutes; existing.N8nWebhookUrl = settings.N8nWebhookUrl; existing.UpdatedAt = settings.UpdatedAt; _context.Settings.Update(existing); } await _context.SaveChangesAsync(); return settings; } /// public async Task UpdateSettingsFromDictionaryAsync(Dictionary dictionary) { var settings = await GetSettingsAsync(); foreach (var (key, value) in dictionary) { if (string.Equals(key, "PollingFrequencyMinutes", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var pfm)) settings.PollingFrequencyMinutes = pfm; else if (string.Equals(key, "ArticleRetentionDays", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var ard)) settings.ArticleRetentionDays = ard; else if (string.Equals(key, "DefaultPageSize", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var dps)) settings.DefaultPageSize = dps; else if (string.Equals(key, "ScrapingIntervalMinutes", StringComparison.OrdinalIgnoreCase) && int.TryParse(value, out var sim)) settings.ScrapingIntervalMinutes = sim; else if (string.Equals(key, "N8nWebhookUrl", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(value)) settings.N8nWebhookUrl = value.Trim(); } settings.UpdatedAt = DateTime.UtcNow; await SaveSettingsAsync(settings); } }