feat: Implementazione completa sistema schedulazione con intervalli personalizzati
- Aggiunto supporto schedulazione con intervalli flessibili (secondi/minuti/ore/giorni/settimane/mesi) - Esteso modello ProfileSchedule con campi IntervalValue e IntervalUnit - Ottimizzato ScheduledJobService per controlli ogni 30s con esecuzione parallela - Implementata interfaccia UI completa con anteprima real-time in italiano - Aggiunta migrazione database AddIntervalSchedulingFields - Implementati metodi calcolo NextExecutionTime per intervalli - Aggiunta gestione tracking anti-duplicati e cleanup automatico - Creata documentazione completa (6 file, 2500+ righe) Modifiche tecniche: - ProfileSchedule.cs: Nuovi campi e metodi CalculateNextInterval/GetScheduleDescription - ScheduledJobService.cs: Ridotto check interval a 30s, aggiunto parallel processing - ProfileScheduleService.cs: Supporto calcolo intervalli in UpdateNextExecutionTimeAsync - Scheduling.razor: Aggiunta sezione UI per configurazione intervalli - Scheduling.razor.cs: Implementato GetIntervalPreview() e gestione stato campi
This commit is contained in:
@@ -0,0 +1,334 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.Json.Serialization;
|
||||
using CredentialManager.Models;
|
||||
|
||||
namespace Data_Coupler.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Modello per l'export/import completo dei dati di backup
|
||||
/// </summary>
|
||||
public class SystemBackupData
|
||||
{
|
||||
[JsonPropertyName("metadata")]
|
||||
public BackupMetadata Metadata { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("profiles")]
|
||||
public List<DataCouplerProfileBackup> Profiles { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("credentials")]
|
||||
public List<CredentialBackup> Credentials { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("keyAssociations")]
|
||||
public List<KeyAssociationBackup> KeyAssociations { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("profileSchedules")]
|
||||
public List<ProfileScheduleBackup> ProfileSchedules { get; set; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Metadati del backup
|
||||
/// </summary>
|
||||
public class BackupMetadata
|
||||
{
|
||||
[JsonPropertyName("version")]
|
||||
public string Version { get; set; } = "1.0";
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
[JsonPropertyName("createdBy")]
|
||||
public string? CreatedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("applicationVersion")]
|
||||
public string ApplicationVersion { get; set; } = "1.0.0";
|
||||
|
||||
[JsonPropertyName("totalRecords")]
|
||||
public BackupRecordCount RecordCounts { get; set; } = new();
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Conteggio record nel backup
|
||||
/// </summary>
|
||||
public class BackupRecordCount
|
||||
{
|
||||
[JsonPropertyName("profiles")]
|
||||
public int Profiles { get; set; }
|
||||
|
||||
[JsonPropertyName("credentials")]
|
||||
public int Credentials { get; set; }
|
||||
|
||||
[JsonPropertyName("keyAssociations")]
|
||||
public int KeyAssociations { get; set; }
|
||||
|
||||
[JsonPropertyName("profileSchedules")]
|
||||
public int ProfileSchedules { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backup di un profilo DataCoupler
|
||||
/// </summary>
|
||||
public class DataCouplerProfileBackup
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceType")]
|
||||
public string SourceType { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sourceCredentialName")]
|
||||
public string? SourceCredentialName { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceDatabaseName")]
|
||||
public string? SourceDatabaseName { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceSchema")]
|
||||
public string? SourceSchema { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceTable")]
|
||||
public string? SourceTable { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceCustomQuery")]
|
||||
public string? SourceCustomQuery { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceFilePath")]
|
||||
public string? SourceFilePath { get; set; }
|
||||
|
||||
[JsonPropertyName("destinationType")]
|
||||
public string DestinationType { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("destinationCredentialName")]
|
||||
public string? DestinationCredentialName { get; set; }
|
||||
|
||||
[JsonPropertyName("destinationSchema")]
|
||||
public string? DestinationSchema { get; set; }
|
||||
|
||||
[JsonPropertyName("destinationTable")]
|
||||
public string? DestinationTable { get; set; }
|
||||
|
||||
[JsonPropertyName("destinationEndpoint")]
|
||||
public string? DestinationEndpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("fieldMappings")]
|
||||
public List<FieldMappingDto>? FieldMappings { get; set; }
|
||||
|
||||
[JsonPropertyName("sourceKeyField")]
|
||||
public string? SourceKeyField { get; set; }
|
||||
|
||||
[JsonPropertyName("useRecordAssociations")]
|
||||
public bool UseRecordAssociations { get; set; }
|
||||
|
||||
[JsonPropertyName("createdBy")]
|
||||
public string? CreatedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("lastUsedAt")]
|
||||
public DateTime? LastUsedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("isActive")]
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backup di una credenziale (dati sensibili esclusi per sicurezza)
|
||||
/// </summary>
|
||||
public class CredentialBackup
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("type")]
|
||||
public string Type { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("databaseType")]
|
||||
public string? DatabaseType { get; set; }
|
||||
|
||||
[JsonPropertyName("host")]
|
||||
public string? Host { get; set; }
|
||||
|
||||
[JsonPropertyName("port")]
|
||||
public int? Port { get; set; }
|
||||
|
||||
[JsonPropertyName("databaseName")]
|
||||
public string? DatabaseName { get; set; }
|
||||
|
||||
[JsonPropertyName("username")]
|
||||
public string? Username { get; set; }
|
||||
|
||||
// NOTA: Password, API Keys e Token NON vengono inclusi nel backup per sicurezza
|
||||
|
||||
[JsonPropertyName("commandTimeout")]
|
||||
public int CommandTimeout { get; set; } = 30;
|
||||
|
||||
[JsonPropertyName("timeoutSeconds")]
|
||||
public int TimeoutSeconds { get; set; } = 100;
|
||||
|
||||
[JsonPropertyName("ignoreSslErrors")]
|
||||
public bool IgnoreSslErrors { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("restServiceType")]
|
||||
public string? RestServiceType { get; set; }
|
||||
|
||||
[JsonPropertyName("headers")]
|
||||
public string? Headers { get; set; }
|
||||
|
||||
[JsonPropertyName("additionalParameters")]
|
||||
public string? AdditionalParameters { get; set; }
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("updatedAt")]
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("createdBy")]
|
||||
public string? CreatedBy { get; set; }
|
||||
|
||||
[JsonPropertyName("isActive")]
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backup di un'associazione chiave
|
||||
/// </summary>
|
||||
public class KeyAssociationBackup
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("keyValue")]
|
||||
public string KeyValue { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("sourceKeyField")]
|
||||
public string SourceKeyField { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("destinationKeyField")]
|
||||
public string DestinationKeyField { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("destinationEntity")]
|
||||
public string DestinationEntity { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("destinationId")]
|
||||
public string DestinationId { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("restCredentialName")]
|
||||
public string RestCredentialName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("updatedAt")]
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("lastVerifiedAt")]
|
||||
public DateTime? LastVerifiedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("isActive")]
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("dataHash")]
|
||||
public string? DataHash { get; set; }
|
||||
|
||||
[JsonPropertyName("sourcesInfo")]
|
||||
public string? SourcesInfo { get; set; }
|
||||
|
||||
[JsonPropertyName("additionalInfo")]
|
||||
public string? AdditionalInfo { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Backup di una schedule profilo
|
||||
/// </summary>
|
||||
public class ProfileScheduleBackup
|
||||
{
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonPropertyName("profileName")]
|
||||
public string ProfileName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("scheduleType")]
|
||||
public string ScheduleType { get; set; } = string.Empty; // "daily", "weekly", "monthly"
|
||||
|
||||
[JsonPropertyName("dailyExecutionTime")]
|
||||
public TimeSpan? DailyExecutionTime { get; set; }
|
||||
|
||||
[JsonPropertyName("weeklyDayOfWeek")]
|
||||
public int? WeeklyDayOfWeek { get; set; } // 0 = Sunday, 1 = Monday, etc.
|
||||
|
||||
[JsonPropertyName("monthlyDayOfMonth")]
|
||||
public int? MonthlyDayOfMonth { get; set; } // 1-31
|
||||
|
||||
[JsonPropertyName("isActive")]
|
||||
public bool IsActive { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("isPaused")]
|
||||
public bool IsPaused { get; set; } = false;
|
||||
|
||||
[JsonPropertyName("lastExecuted")]
|
||||
public DateTime? LastExecuted { get; set; }
|
||||
|
||||
[JsonPropertyName("nextExecution")]
|
||||
public DateTime? NextExecution { get; set; }
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTime CreatedAt { get; set; }
|
||||
|
||||
[JsonPropertyName("createdBy")]
|
||||
public string? CreatedBy { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Risultato dell'operazione di backup/restore
|
||||
/// </summary>
|
||||
public class BackupOperationResult
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string? Message { get; set; }
|
||||
public TimeSpan Duration { get; set; }
|
||||
public BackupRecordCount ProcessedCounts { get; set; } = new();
|
||||
public List<string> Warnings { get; set; } = new();
|
||||
public List<string> Errors { get; set; } = new();
|
||||
public string? FilePath { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opzioni per l'operazione di backup
|
||||
/// </summary>
|
||||
public class BackupOptions
|
||||
{
|
||||
public bool IncludeProfiles { get; set; } = true;
|
||||
public bool IncludeCredentials { get; set; } = true;
|
||||
public bool IncludeKeyAssociations { get; set; } = true;
|
||||
public bool IncludeProfileSchedules { get; set; } = true;
|
||||
public bool IncludeOnlyActiveRecords { get; set; } = true;
|
||||
public string? Description { get; set; }
|
||||
public string? CreatedBy { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opzioni per l'operazione di restore
|
||||
/// </summary>
|
||||
public class RestoreOptions
|
||||
{
|
||||
public bool RestoreProfiles { get; set; } = true;
|
||||
public bool RestoreCredentials { get; set; } = false; // Default false per sicurezza
|
||||
public bool RestoreKeyAssociations { get; set; } = true;
|
||||
public bool RestoreProfileSchedules { get; set; } = true;
|
||||
public bool OverwriteExisting { get; set; } = false;
|
||||
public bool CreateBackupBeforeRestore { get; set; } = true;
|
||||
public string? ImportedBy { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user