using InnovEnergy.App.Backend.DataTypes; using InnovEnergy.App.Backend.DataTypes.Methods; using InnovEnergy.App.Backend.Relations; namespace InnovEnergy.App.Backend.Database; public static partial class Db { //Since we do not want to stress the memory in the VM a lot, we make a snapshot of the database every 100 transactions. private static int _backupCounter = 0; private static void Backup() { _backupCounter++; if (_backupCounter > 100) { _backupCounter = 0; BackupDatabase(); } } public static Boolean Delete(Folder folder) { var deleteSuccess= RunTransaction(DeleteFolderAndAllItsDependencies); if (deleteSuccess) { Backup(); } return deleteSuccess; Boolean DeleteFolderAndAllItsDependencies() { return folder .DescendantFoldersAndSelf() .All(DeleteDescendantFolderAndItsDependencies); } Boolean DeleteDescendantFolderAndItsDependencies(Folder f) { FolderAccess .Delete(r => r.FolderId == f.Id); Installations.Delete(r => r.ParentId == f.Id); var delete = Folders.Delete(r => r.Id == f.Id); return delete>0; } } public static Boolean Delete(Error errorToDelete) { var deleteSuccess = RunTransaction(DeleteError); if (deleteSuccess) Backup(); return deleteSuccess; Boolean DeleteError() { return Errors.Delete(error => error.Id == errorToDelete.Id) >0; } } public static Boolean Delete(UserAction actionToDelete) { var deleteSuccess = RunTransaction(DeleteAction); if (deleteSuccess) Backup(); return deleteSuccess; Boolean DeleteAction() { return UserActions.Delete(action => action.Id == actionToDelete.Id) >0; } } public static Boolean Delete(Warning warningToDelete) { var deleteSuccess = RunTransaction(DeleteWarning); if (deleteSuccess) Backup(); return deleteSuccess; Boolean DeleteWarning() { return Warnings.Delete(warning => warning.Id == warningToDelete.Id) >0; } } public static Boolean Delete(Installation installation) { var deleteSuccess = RunTransaction(DeleteInstallationAndItsDependencies); if (deleteSuccess) Backup(); return deleteSuccess; Boolean DeleteInstallationAndItsDependencies() { InstallationAccess.Delete(i => i.InstallationId == installation.Id); if (installation.Product == (int)ProductType.Salimax) { //For Salimax, delete the OrderNumber2Installation entries associated with this installation id. OrderNumber2Installation.Delete(i => i.InstallationId == installation.Id); } return Installations.Delete(i => i.Id == installation.Id) > 0; } } public static Boolean Delete(User user) { var deleteSuccess = RunTransaction(DeleteUserAndHisDependencies); if (deleteSuccess) Backup(); return deleteSuccess; Boolean DeleteUserAndHisDependencies() { FolderAccess .Delete(u => u.UserId == user.Id); InstallationAccess.Delete(u => u.UserId == user.Id); return Users.Delete(u => u.Id == user.Id) > 0; } } #pragma warning disable CS0618 // private!! private static Boolean Delete(Session session) { var delete = Sessions.Delete(s => s.Id == session.Id) > 0; if (delete) Backup(); return delete; } public static void Delete(OrderNumber2Installation relation) { OrderNumber2Installation.Delete(s => s.InstallationId == relation.InstallationId && s.OrderNumber == relation.OrderNumber); } public static void DeleteWeeklyReportsForMonth(Int64 installationId, Int32 year, Int32 month) { var monthStart = $"{year:D4}-{month:D2}-01"; var monthEnd = month == 12 ? $"{year + 1:D4}-01-01" : $"{year:D4}-{month + 1:D2}-01"; // SQLite-net doesn't support string comparison in Delete lambda, // so fetch matching IDs first, then delete by ID. var ids = WeeklyReports .Where(r => r.InstallationId == installationId) .ToList() .Where(r => String.Compare(r.PeriodStart, monthStart, StringComparison.Ordinal) >= 0 && String.Compare(r.PeriodStart, monthEnd, StringComparison.Ordinal) < 0) .Select(r => r.Id) .ToList(); foreach (var id in ids) WeeklyReports.Delete(r => r.Id == id); if (ids.Count > 0) Backup(); } public static void DeleteMonthlyReportsForYear(Int64 installationId, Int32 year) { MonthlyReports.Delete(r => r.InstallationId == installationId && r.Year == year); Backup(); } public static void DeleteMonthlyReport(Int64 installationId, Int32 year, Int32 month) { var count = MonthlyReports.Delete(r => r.InstallationId == installationId && r.Year == year && r.Month == month); if (count > 0) Backup(); } public static void DeleteYearlyReport(Int64 installationId, Int32 year) { var count = YearlyReports.Delete(r => r.InstallationId == installationId && r.Year == year); if (count > 0) Backup(); } /// /// Deletes all report records older than 1 year. Called annually on Jan 2 /// after yearly reports are created. Uses fetch-then-delete for string-compared /// date fields (SQLite-net doesn't support string comparisons in Delete lambdas). /// public static void CleanupOldData() { var cutoff = DateOnly.FromDateTime(DateTime.UtcNow).AddYears(-1).ToString("yyyy-MM-dd"); var prevYear = DateTime.UtcNow.Year - 1; // Daily records older than 1 year var oldDailyIds = DailyRecords .ToList() .Where(r => String.Compare(r.Date, cutoff, StringComparison.Ordinal) < 0) .Select(r => r.Id) .ToList(); foreach (var id in oldDailyIds) DailyRecords.Delete(r => r.Id == id); // Weekly summaries older than 1 year var oldWeeklyIds = WeeklyReports .ToList() .Where(r => String.Compare(r.PeriodEnd, cutoff, StringComparison.Ordinal) < 0) .Select(r => r.Id) .ToList(); foreach (var id in oldWeeklyIds) WeeklyReports.Delete(r => r.Id == id); // Monthly summaries older than 1 year var oldMonthlyIds = MonthlyReports .ToList() .Where(r => String.Compare(r.PeriodEnd, cutoff, StringComparison.Ordinal) < 0) .Select(r => r.Id) .ToList(); foreach (var id in oldMonthlyIds) MonthlyReports.Delete(r => r.Id == id); // Yearly summaries — keep current and previous year only YearlyReports.Delete(r => r.Year < prevYear); // AI insight cache entries older than 1 year var oldCacheIds = AiInsightCaches .ToList() .Where(c => String.Compare(c.CreatedAt, cutoff, StringComparison.Ordinal) < 0) .Select(c => c.Id) .ToList(); foreach (var id in oldCacheIds) AiInsightCaches.Delete(c => c.Id == id); Backup(); Console.WriteLine($"[Db] Cleanup: {oldDailyIds.Count} daily, {oldWeeklyIds.Count} weekly, {oldMonthlyIds.Count} monthly, {oldCacheIds.Count} insight cache records deleted (cutoff {cutoff})."); } }