namespace Lagerbestand.Models; /// /// Site-wide settings stored in the database /// public class SiteSettings { public Guid Id { get; set; } = Guid.NewGuid(); /// /// Unique key for the setting (e.g., "PromoBanner") /// public string Key { get; set; } = string.Empty; /// /// JSON-serialized value of the setting /// public string Value { get; set; } = string.Empty; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime? UpdatedAt { get; set; } } /// /// Promotion banner settings /// public class PromoBannerSettings { public bool IsEnabled { get; set; } public string Title { get; set; } = string.Empty; public string Message { get; set; } = string.Empty; public DateTime? StartDate { get; set; } public DateTime? EndDate { get; set; } public bool ShowContactButton { get; set; } = true; /// /// Check if banner should be shown based on current date and content /// public bool ShouldShow() { // Must be enabled if (!IsEnabled) return false; // Must have content if (string.IsNullOrWhiteSpace(Title) && string.IsNullOrWhiteSpace(Message)) return false; var now = DateTime.UtcNow.Date; // Check date range if specified if (StartDate.HasValue && now < StartDate.Value.Date) return false; if (EndDate.HasValue && now > EndDate.Value.Date) return false; return true; } } /// /// Lexware API connection settings for customer data synchronization /// public class LexwareApiSettings { public bool IsEnabled { get; set; } /// /// Lexware API base URL (e.g., https://api.lexoffice.io/v1) /// public string BaseUrl { get; set; } = string.Empty; /// /// API key for authentication /// public string ApiKey { get; set; } = string.Empty; /// /// Whether automatic daily sync is enabled /// public bool AutoSyncEnabled { get; set; } = true; /// /// Time of day for automatic sync (HH:mm format) /// public string AutoSyncTime { get; set; } = "02:00"; /// /// Timestamp of the last successful sync /// public DateTime? LastSyncAt { get; set; } /// /// Result message from the last sync /// public string? LastSyncResult { get; set; } /// /// Number of customers synced in last run /// public int LastSyncCount { get; set; } /// /// Whether the API connection is configured /// public bool IsConfigured => !string.IsNullOrWhiteSpace(BaseUrl) && !string.IsNullOrWhiteSpace(ApiKey); } /// /// Two-Factor Authentication settings stored in SiteSettings /// public class TwoFactorSettings { /// /// Global toggle: when false, no 2FA is used at all /// public bool IsEnabled { get; set; } /// /// Issuer name shown in authenticator apps (e.g. "Reifen Späth") /// public string Issuer { get; set; } = "Reifen Späth Lagerverwaltung"; /// /// Whether email fallback codes are enabled /// public bool EmailFallbackEnabled { get; set; } } /// /// Session / long-duration usage settings (idle lock, circuit retention). /// Editable by admins in the Status page. /// public class SessionSettings { public const int DefaultIdleTimeoutMinutes = 60; public const int MaxIdleTimeoutMinutes = 60; public const int MinIdleTimeoutMinutes = 1; public const double DefaultCircuitRetentionHours = 2.0; public const double MaxCircuitRetentionHours = 4.0; public const double MinCircuitRetentionHours = 0.5; /// /// Minutes of inactivity before the browser tab shows a "Confirm to continue" lock overlay. /// Range: 1 – 60. Default: 60. /// public int IdleTimeoutMinutes { get; set; } = DefaultIdleTimeoutMinutes; /// /// Hours a disconnected Blazor Server circuit is retained on the server /// before being discarded (allows reconnect without state loss). /// Range: 0.5 – 4. Default: 2. Applied at next app restart. /// public double CircuitRetentionHours { get; set; } = DefaultCircuitRetentionHours; public int GetSafeIdleTimeoutMinutes() { if (IdleTimeoutMinutes < MinIdleTimeoutMinutes) return MinIdleTimeoutMinutes; if (IdleTimeoutMinutes > MaxIdleTimeoutMinutes) return MaxIdleTimeoutMinutes; return IdleTimeoutMinutes; } public double GetSafeCircuitRetentionHours() { if (CircuitRetentionHours < MinCircuitRetentionHours) return MinCircuitRetentionHours; if (CircuitRetentionHours > MaxCircuitRetentionHours) return MaxCircuitRetentionHours; return CircuitRetentionHours; } } /// /// SMTP settings for sending email-based 2FA codes and notifications /// public class SmtpSettings { public bool IsEnabled { get; set; } public string Host { get; set; } = string.Empty; public int Port { get; set; } = 587; public string Username { get; set; } = string.Empty; public string Password { get; set; } = string.Empty; public string FromEmail { get; set; } = string.Empty; public string FromName { get; set; } = "Reifen Späth Lagerverwaltung"; public bool UseSsl { get; set; } = true; public bool IsConfigured => !string.IsNullOrWhiteSpace(Host) && !string.IsNullOrWhiteSpace(Username) && !string.IsNullOrWhiteSpace(FromEmail); }