From 5169cd25c8f460d4f2ceedc4f85aa874e3ace0ba Mon Sep 17 00:00:00 2001 From: Alessio Dal Santo Date: Thu, 22 Jan 2026 09:29:40 +0100 Subject: [PATCH 1/3] -Aggiunto copilot instructions -Modificata github actions per includere il ramo development --- .github/copilot-instructions.md | 430 +++++++++++++++++++++++++++++ .github/workflows/docker-build.yml | 2 +- 2 files changed, 431 insertions(+), 1 deletion(-) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..4a46459 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,430 @@ +# Data-Coupler - GitHub Copilot Instructions + +## 📋 Panoramica del Progetto + +**Data-Coupler** è una soluzione enterprise di integrazione dati sviluppata in .NET 9.0 con architettura Blazor Server. Il sistema facilita il trasferimento e la sincronizzazione di dati tra diverse tipologie di sorgenti: database relazionali, REST API, file Excel/CSV con funzionalità avanzate di mapping, scheduling e gestione associazioni. + +## 🏗️ Architettura del Sistema + +### Progetti Principali + +1. **CredentialManager** - Libreria per gestione sicura delle credenziali + - Crittografia dei dati sensibili con Data Protection API + - Persistenza su database SQLite + - Supporto per credenziali database e REST API + - Gestione profili Data Coupler e schedulazioni + +2. **DataConnection** - Libreria per connessioni dati + - **Database supportati**: SQL Server, MySQL, PostgreSQL, Oracle, SQLite, IBM DB2, SAP HANA + - **REST API**: Generic REST, Salesforce, SAP Business One Service Layer + - Factory pattern per gestione provider + - Operazioni batch e parallel processing + +3. **Data_Coupler** - Applicazione Blazor Server + - Interfaccia web per gestione credenziali e profili + - Sistema di trasferimento dati con mapping intelligente + - Schedulazione avanzata con background services + - Sistema di backup e ripristino completo + +4. **Components** - Libreria componenti UI riutilizzabili + - Componenti Blazor per gestione profili + - Selettori e editor configurazioni + - UI responsive con Bootstrap 5 + +## 🎯 Feature Implementate + +### 1. Gestione Credenziali Sicura + +#### Caratteristiche: +- **Crittografia**: Password e chiavi API crittografate con `IDataProtectionProvider` +- **Multi-piattaforma**: Supporto per database eterogenei e REST API +- **Test Connessioni**: Validazione credenziali prima del salvataggio +- **CRUD Completo**: Interfaccia web per gestione completa + +#### File Chiave: +- `CredentialManager/Services/ICredentialService.cs` +- `CredentialManager/Services/EncryptionService.cs` +- `Data_Coupler/Pages/CredentialManagement.razor` + +### 2. Sistema di Profili Data Coupler + +#### Caratteristiche: +- **Profili Riutilizzabili**: Configurazioni salvate per trasferimenti ricorrenti +- **Mapping Campi**: Sistema avanzato di mappatura tra sorgente e destinazione +- **Sorgenti Multiple**: Database, REST API, File (Excel/CSV) +- **Gestione Completa**: CRUD con validazione e test + +#### Componenti: +- **Sorgente**: Tipo (Database/REST/File), credenziale, tabella/endpoint/percorso file +- **Destinazione**: Tipo, credenziale, tabella/endpoint +- **Mapping**: Corrispondenza campi sorgente → destinazione +- **Chiave Sorgente**: Campo identificativo univoco per tracking + +#### File Chiave: +- `CredentialManager/Models/DataCouplerProfile.cs` +- `CredentialManager/Services/DataCouplerProfileService.cs` +- `Data_Coupler/Pages/ProfilesManagement.razor` + +### 3. Sistema di Associazioni Record (Key Associations) + +#### Caratteristiche: +- **Tracciamento ID**: Memorizza relazione tra chiavi sorgente e ID destinazione +- **Prevenzione Duplicati**: Verifica esistenza prima di creare nuovi record +- **Pre-Discovery**: Cerca record esistenti nella destinazione prima della creazione +- **Hash Comparison**: Rileva modifiche dati tramite hash SHA256 +- **Validazione Intelligente**: Verifica esistenza ID destinazione, cleanup automatico + +#### Flusso Operativo: +1. Estrazione record da sorgente +2. Verifica associazione esistente in locale +3. **PRE-DISCOVERY**: Se non esiste, cerca nella destinazione tramite chiave +4. Se trovato → Crea associazione + Aggiorna record +5. Se non trovato → Crea nuovo record + Associazione +6. Calcola hash dati per tracking modifiche future + +#### File Chiave: +- `CredentialManager/Models/KeyAssociation.cs` +- `CredentialManager/Services/KeyAssociationService.cs` +- `Data_Coupler/Pages/KeyAssociations.razor` +- `Data_Coupler/Services/AssociationService.cs` + +#### Gestione Avanzata: +- **Pulizia Selettiva**: Elimina associazioni per sorgente/destinazione specifica +- **Pulizia Totale**: Reset completo sistema associazioni +- **Validazione**: Trova e pulisce associazioni con ID non più validi +- **Export/Import**: CSV per backup e migrazione dati + +### 4. Trasferimento Dati Avanzato + +#### Caratteristiche Standard: +- **Mapping Automatico**: Trasformazione campi sorgente → destinazione +- **Batch Processing**: Elaborazione ottimizzata per grandi volumi +- **Error Handling**: Gestione errori robusta con retry logic +- **Logging Dettagliato**: Tracciamento completo operazioni + +#### Salesforce Composite API: +- **Batch Operations**: Fino a 25 operazioni per request (limite Salesforce) +- **Parallel Processing**: Elaborazione parallela batch multipli +- **Performance**: 10-25x più veloce per grandi dataset +- **Riduzione API Calls**: 60-90% in meno chiamate + +#### Metodi Batch Implementati: +- `BatchExecuteQueriesAsync`: Esecuzione parallela multiple query SOQL +- `BatchFindEntitiesByKeysAsync`: Ricerca batch entità con diverse chiavi +- `BatchGetEntitiesByIdsAsync`: Recupero batch tramite ID (max 200 per query) +- `ExtractAllEntitiesAsync`: Estrazione completa con paginazione automatica +- `ExtractEntitiesParallelAsync`: Estrazione parallela con deduplicazione +- `ExtractLargeDatasetAsync`: Estrattore intelligente con auto-detect strategia +- `ExtractRecentlyModifiedAsync`: Sincronizzazione incrementale + +#### File Chiave: +- `Data_Coupler/Pages/DataCoupler.razor.cs` +- `DataConnection/REST/Implementations/SalesforceServiceClient.cs` +- `Data_Coupler/Services/ScheduledProfileExecutionService.cs` + +### 5. Sistema di Schedulazione Avanzata + +#### Tipi di Schedulazione: +1. **Una Volta (Once)**: Esecuzione singola a data/ora specifica +2. **Giornaliera (Daily)**: Ogni giorno a orario specifico +3. **Settimanale (Weekly)**: Ogni settimana in giorno specifico +4. **Mensile (Monthly)**: Ogni mese in giorno specifico +5. **A Intervalli (Interval)**: Ricorrente ogni N unità di tempo + - Secondi, Minuti, Ore, Giorni, Settimane, Mesi + - Esempio: Ogni 5 minuti, ogni 2 ore, ogni 30 secondi + +#### Componenti Sistema: +- **ProfileSchedule**: Modello dati schedulazione +- **ScheduledExecutionBackgroundService**: Background service per esecuzione automatica +- **ScheduledProfileExecutionService**: Logica completa trasferimento schedulato +- **ProfileScheduleService**: CRUD e gestione schedule + +#### Funzionalità: +- **Esecuzione Automatica**: Background service sempre attivo +- **Gestione Stato**: Tracciamento esecuzioni (success, failed, running) +- **Storico Esecuzioni**: Log completo con timestamp, record processati, errori +- **Pausa/Riprendi**: Controllo dinamico schedulazioni +- **Override Database**: Possibilità di sovrascrivere sorgente/destinazione + +#### File Chiave: +- `CredentialManager/Models/ProfileSchedule.cs` +- `CredentialManager/Services/ProfileScheduleService.cs` +- `Data_Coupler/BackgroundServices/ScheduledExecutionBackgroundService.cs` +- `Data_Coupler/Pages/Scheduling.razor` +- `Data_Coupler/Pages/SchedulingHistory.razor` + +### 6. Sistema di Backup e Ripristino + +#### Funzionalità Export: +- **Configurazione Flessibile**: Export selettivo per componente +- **Componenti Supportati**: + - Profili Data Coupler + - Credenziali (senza dati sensibili) + - Associazioni Chiavi + - Schedulazioni +- **Formato JSON**: Leggibile e versionato +- **Metadati**: Timestamp, utente, descrizione, componenti inclusi + +#### Funzionalità Import: +- **Validazione Rigorosa**: Controllo formato, versione, integrità dati +- **Modalità Ripristino**: + - **Overwrite**: Sostituisce dati esistenti + - **Merge**: Integra con dati esistenti + - **Preview**: Mostra anteprima senza eseguire +- **Transazioni Sicure**: Rollback automatico in caso di errori + +#### Sicurezza: +- **Esclusione Dati Sensibili**: Password e API keys non inclusi in backup +- **Crittografia Opzionale**: Backup crittografati per sicurezza extra +- **Audit Logging**: Tracciamento completo operazioni backup/restore + +#### File Chiave: +- `Data_Coupler/Services/BackupService.cs` +- `Data_Coupler/Models/BackupModels.cs` +- `Data_Coupler/Pages/SettingsPage.razor` + +### 7. Sincronizzazione Eliminazioni (Deletion Sync) + +#### Caratteristiche: +- **Rilevamento Eliminazioni**: Identifica record eliminati da sorgente +- **Sincronizzazione Automatica**: Elimina corrispondenti in destinazione +- **Gestione Associazioni**: Aggiorna/elimina associazioni correlate +- **Modalità Sicura**: Preview eliminazioni prima dell'esecuzione +- **Logging Completo**: Traccia tutte le operazioni di eliminazione + +#### File Chiave: +- `Data_Coupler/Services/DeletionSyncService.cs` + +### 8. Sistema di Autenticazione + +#### Caratteristiche: +- **Login Protetto**: Autenticazione via credenziali o token +- **Session Management**: Gestione sessioni utente +- **Password Sicure**: Hashing con algoritmi moderni +- **Remember Me**: Persistenza login opzionale + +#### File Chiave: +- `Data_Coupler/Services/AuthenticationService.cs` +- `Data_Coupler/Pages/Login.razor` +- `Data_Coupler/Middleware/AuthenticationMiddleware.cs` + +### 9. Interfaccia Utente Avanzata + +#### Pagine Principali: +- **Dashboard** (`Index.razor`): Panoramica sistema e quick actions +- **Data Coupler** (`DataCoupler.razor`): Interfaccia principale trasferimento dati +- **Gestione Profili** (`ProfilesManagement.razor`): CRUD profili completo +- **Schedulazione** (`Scheduling.razor`): Gestione schedule con UI intuitiva +- **Storico Schedulazioni** (`SchedulingHistory.razor`): Visualizzazione esecuzioni +- **Associazioni** (`KeyAssociations.razor`): Gestione completa associazioni +- **Credenziali** (`CredentialManagement.razor`): CRUD credenziali +- **Impostazioni** (`SettingsPage.razor`): Backup, sistema, sicurezza, manutenzione + +#### Componenti UI: +- **ProfileSelector**: Selezione e caricamento profili +- **ProfileSaver**: Salvataggio profili con validazione +- **ProfileManagement**: CRUD profili completo +- **Toast Notifications**: Feedback utente in tempo reale +- **Modal Dialogs**: Conferme operazioni critiche +- **Progress Indicators**: Feedback operazioni lunghe + +#### Design: +- **Bootstrap 5**: Framework CSS responsive +- **Font Awesome**: Iconografia consistente +- **Dark/Light Mode**: Temi personalizzabili +- **Mobile Responsive**: Ottimizzato per dispositivi mobili + +### 10. Health Checks e Monitoraggio + +#### Caratteristiche: +- **Health Checks**: Endpoint per monitoraggio stato applicazione +- **Database Health**: Verifica connessione database +- **Background Services**: Stato background services +- **Memory Monitoring**: Tracciamento utilizzo memoria +- **Performance Metrics**: Statistiche performance sistema + +#### File Chiave: +- `Data_Coupler/HealthChecks/DatabaseHealthCheck.cs` +- `Data_Coupler/HealthChecks/BackgroundServiceHealthCheck.cs` + +## 🔐 Sicurezza + +### Gestione Credenziali: +- **Data Protection API**: Crittografia con chiavi managed da .NET +- **Key Rotation**: Supporto rotazione chiavi automatica +- **Secure Storage**: Persistenza sicura su SQLite + +### Input Validation: +- **SQL Injection Prevention**: Query parametrizzate ovunque +- **XSS Protection**: Sanitizzazione input utente +- **Whitelist Validation**: Validazione nomi tabelle/campi + +### Comunicazioni Sicure: +- **HTTPS**: Forzato in produzione +- **Certificate Validation**: Validazione certificati SSL/TLS +- **Secure Headers**: Security headers HTTP + +### Audit Logging: +- **Tracciamento Accessi**: Log accessi credenziali +- **Operazioni Sensibili**: Log modifiche configurazioni +- **Security Events**: Alert eventi sicurezza + +## 🛠️ Convenzioni di Codice + +### Naming: +- **Classes/Interfaces**: PascalCase (es. `DataConnectionFactory`) +- **Methods**: PascalCase (es. `GetDataAsync`) +- **Properties**: PascalCase (es. `ConnectionString`) +- **Private Fields**: camelCase con underscore (es. `_logger`) +- **Local Variables**: camelCase (es. `connectionName`) + +### Async/Await: +- Tutti i metodi I/O sono asincroni +- Naming convention: `*Async` suffix +- Uso di `CancellationToken` per operazioni cancellabili +- **MAI** usare `.Result` o `.Wait()` - rischio deadlock + +### Dependency Injection: +- **Singleton**: Servizi stateless (es. `IEncryptionService`) +- **Scoped**: Servizi con stato per request (es. `IDataConnectionFactory`) +- **Transient**: Servizi leggeri (es. validators) + +### Error Handling: +- Try-catch con logging specifico +- Messaggi utente user-friendly +- Dettagli tecnici nei log, non in UI +- Rollback transazioni in caso di errore + +## 📝 Pattern Architetturali Utilizzati + +### 1. Repository Pattern: +- Astrazione accesso dati +- `*Service` interfacce per business logic +- `*Repository` per accesso database + +### 2. Factory Pattern: +- `DataConnectionFactory`: Creazione connessioni database/REST +- `RestServiceClientFactory`: Creazione client REST specifici + +### 3. Strategy Pattern: +- Diversi provider database (SQL Server, MySQL, PostgreSQL, etc.) +- Diversi client REST (Generic, Salesforce, SAP B1) + +### 4. Observer Pattern: +- Background services per schedulazioni +- Event-driven processing + +## 🧪 Testing + +### Unit Tests: +- Copertura servizi core +- Mock di dipendenze esterne +- Test naming: `MethodName_Scenario_ExpectedBehavior` + +### Integration Tests: +- Test connessioni database reali +- Test API REST con server di test +- Test end-to-end UI con Playwright + +## 📦 Deployment + +### Docker Support: +- `Dockerfile`: Immagine Linux +- `Dockerfile.windows`: Immagine Windows +- `docker-compose.yml`: Orchestrazione multi-container +- Health checks integrati + +### Windows Service: +- Deploy come Windows Service +- Auto-start configurabile +- Logging Windows Event Log + +### Azure Deployment: +- App Service support +- Container Apps support +- Key Vault integration per secrets + +## 🔄 Workflow di Sviluppo + +### Branching Strategy: +- `main`: Produzione stabile +- `develop`: Sviluppo attivo +- `feature/*`: Nuove feature +- `hotfix/*`: Fix urgenti + +### Commit Messages: +- Formato: `[Tipo] Descrizione breve` +- Tipi: `[Feature]`, `[Fix]`, `[Refactor]`, `[Docs]`, `[Test]` +- Esempio: `[Feature] Implementato sistema schedulazione avanzata` + +### Code Review: +- Ogni PR richiede review +- Checklist: code style, tests, documentation +- CI/CD automatico + +## 📚 Documentazione Correlata + +### File di Documentazione nel Progetto: +- **AGENTS.md**: Guida completa per AI agents e Copilot +- **ADVANCED_SCHEDULING_SYSTEM.md**: Sistema schedulazione dettagliato +- **GESTIONE_ASSOCIAZIONI_AVANZATA.md**: Sistema associazioni completo +- **SALESFORCE_BATCH_EXTRACTION_IMPROVEMENTS.md**: Batch extraction Salesforce +- **PRE_DISCOVERY_SYSTEM.md**: Sistema pre-discovery associazioni +- **DELETION_SYNC_IMPLEMENTATION.md**: Sincronizzazione eliminazioni +- **DOCKER_DEPLOYMENT.md**: Guida deployment Docker +- **WINDOWS_SERVICE_DEPLOYMENT.md**: Deploy come Windows Service + +## 🎓 Best Practices per AI Assistants + +### Quando Modificare Codice: +1. **Leggere Documentazione**: Consultare file MD correlati +2. **Analizzare Pattern**: Seguire pattern esistenti nel codebase +3. **Validare Input**: Sempre validare parametri +4. **Error Handling**: Gestire tutti i possibili errori +5. **Logging**: Aggiungere log appropriati +6. **Testing**: Creare/aggiornare test correlati +7. **Documentazione**: Aggiornare XML comments e MD files + +### Quando Creare Nuove Feature: +1. **Progettare Prima**: Pianificare architettura +2. **Seguire Convenzioni**: Rispettare code style +3. **Dependency Injection**: Registrare nuovi servizi in `Program.cs` +4. **Database Changes**: Creare migration Entity Framework +5. **UI Consistency**: Seguire design pattern esistente +6. **Documentare**: Creare/aggiornare documentazione + +### Red Flags da Evitare: +- ❌ Hardcoded credentials o secrets +- ❌ SQL injection vulnerabilities +- ❌ Blocking calls in async methods +- ❌ Catch generico senza logging +- ❌ Modifiche database senza migration +- ❌ Breaking changes senza versioning +- ❌ Codice duplicato invece di refactoring + +## 🚀 Roadmap Futura + +### Feature in Pianificazione: +- [ ] Supporto file Excel/CSV avanzato +- [ ] Sistema di notifiche (email, webhook) +- [ ] Dashboard analytics avanzato +- [ ] Multi-tenant support +- [ ] API REST pubblica +- [ ] Plugin system per connectors custom +- [ ] Machine learning per mapping suggeriti +- [ ] Real-time data sync + +### Miglioramenti Tecnici: +- [ ] Migrazione a .NET 10 (quando disponibile) +- [ ] Caching distribuito (Redis) +- [ ] Message queue (RabbitMQ/Azure Service Bus) +- [ ] Elasticsearch per log search +- [ ] Prometheus/Grafana per monitoring + +--- + +**Versione**: 2.0 +**Ultimo Aggiornamento**: 22 Gennaio 2026 +**Framework**: .NET 9.0 +**Sviluppatore**: Alessio Dalsanto +**Repository**: https://github.com/AlessioDalsi/Data-Coupler diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 3f48edc..f3f33db 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -4,7 +4,7 @@ on: push: branches: - main - - dev + - development - staging workflow_dispatch: inputs: From e35de1614f01d4347ec17fd8edf312e664b7cb1c Mon Sep 17 00:00:00 2001 From: Alessio Dal Santo Date: Fri, 23 Jan 2026 15:52:15 +0100 Subject: [PATCH 2/3] [Feature] Disabilitata deletion sync nei trasferimenti manuali e aggiunta configurazione nelle schedulazioni MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Disabilitata completamente la sincronizzazione eliminazioni nei trasferimenti manuali (DataCoupler.razor.cs) - Aggiunto campo EnableDeletionSync al modello ProfileSchedule (default: false) - Implementata logica condizionale in ScheduledProfileExecutionService per deletion sync - Aggiunta sezione 'Opzioni Avanzate' nell'interfaccia schedulazione con warning - Creata migration Entity Framework AddEnableDeletionSyncToProfileSchedule - Aggiornato BackupModels per supporto backup/restore del nuovo campo - Aggiornata documentazione README.md e copilot-instructions.md - La deletion sync è ora disponibile solo per schedulazioni con configurazione esplicita per massima sicurezza --- .github/copilot-instructions.md | 15 + ...eDeletionSyncToProfileSchedule.Designer.cs | 585 ++++++++++++++++++ ..._AddEnableDeletionSyncToProfileSchedule.cs | 29 + .../CredentialDbContextModelSnapshot.cs | 3 + CredentialManager/Models/ProfileSchedule.cs | 3 + CredentialManager/design_time_temp.db | Bin 155648 -> 155648 bytes Data_Coupler/Models/BackupModels.cs | 3 + Data_Coupler/Pages/DataCoupler.razor.cs | 5 +- Data_Coupler/Pages/Scheduling.razor | 24 + .../IScheduledProfileExecutionService.cs | 7 + .../ScheduledExecutionBackgroundService.cs | 8 +- .../ScheduledProfileExecutionService.cs | 126 +++- README.md | 4 + 13 files changed, 796 insertions(+), 16 deletions(-) create mode 100644 CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.Designer.cs create mode 100644 CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.cs diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 4a46459..e0b2f96 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -145,6 +145,7 @@ - **Storico Esecuzioni**: Log completo con timestamp, record processati, errori - **Pausa/Riprendi**: Controllo dinamico schedulazioni - **Override Database**: Possibilità di sovrascrivere sorgente/destinazione +- **Deletion Sync Configurabile**: Opzione per abilitare sincronizzazione eliminazioni (disabilitata di default) #### File Chiave: - `CredentialManager/Models/ProfileSchedule.cs` @@ -191,9 +192,23 @@ - **Gestione Associazioni**: Aggiorna/elimina associazioni correlate - **Modalità Sicura**: Preview eliminazioni prima dell'esecuzione - **Logging Completo**: Traccia tutte le operazioni di eliminazione +- **Configurazione Granulare**: + - **Disabilitata** completamente nei trasferimenti manuali (DataCoupler.razor) + - **Configurabile** nelle schedulazioni tramite flag `EnableDeletionSync` + - **Default: false** per massima sicurezza + - Warning esplicito nell'UI per operazioni critiche + +#### Sicurezza: +- La funzionalità è **disabilitata di default** per evitare eliminazioni accidentali +- Disponibile **solo per le schedulazioni** con configurazione esplicita +- L'utente deve attivamente abilitare la funzione con piena consapevolezza +- Logging completo di tutte le operazioni di eliminazione per audit trail #### File Chiave: - `Data_Coupler/Services/DeletionSyncService.cs` +- `Data_Coupler/Services/ScheduledProfileExecutionService.cs` +- `CredentialManager/Models/ProfileSchedule.cs` (campo `EnableDeletionSync`) +- `Data_Coupler/Pages/Scheduling.razor` (UI configurazione) ### 8. Sistema di Autenticazione diff --git a/CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.Designer.cs b/CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.Designer.cs new file mode 100644 index 0000000..897a8d6 --- /dev/null +++ b/CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.Designer.cs @@ -0,0 +1,585 @@ +// +using System; +using CredentialManager.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace CredentialManager.Migrations +{ + [DbContext(typeof(CredentialDbContext))] + [Migration("20260123104841_AddEnableDeletionSyncToProfileSchedule")] + partial class AddEnableDeletionSyncToProfileSchedule + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("CredentialManager.Models.CredentialEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdditionalParameters") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("CommandTimeout") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(30); + + b.Property("ConnectionString") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DatabaseName") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DatabaseType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("EncryptedApiKey") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("EncryptedAuthToken") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("EncryptedPassword") + .HasColumnType("TEXT"); + + b.Property("Headers") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("Host") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("IgnoreSslErrors") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Port") + .HasColumnType("INTEGER"); + + b.Property("RestServiceType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("TimeoutSeconds") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.Property("Type") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.Property("Username") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("DatabaseType"); + + b.HasIndex("IsActive"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("Type"); + + b.ToTable("Credentials", (string)null); + }); + + modelBuilder.Entity("CredentialManager.Models.DataCouplerProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasDefaultValueSql("CURRENT_TIMESTAMP"); + + b.Property("CreatedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DeletionAction") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("DeletionMarkField") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DeletionMarkValue") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("DestinationCredentialId") + .HasColumnType("INTEGER"); + + b.Property("DestinationEndpoint") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("DestinationSchema") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DestinationTable") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DestinationType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("FieldMappingJson") + .HasMaxLength(4000) + .HasColumnType("TEXT"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("LastUsedAt") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SourceCredentialId") + .HasColumnType("INTEGER"); + + b.Property("SourceCustomQuery") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("SourceDatabaseName") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("SourceFilePath") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SourceKeyField") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("SourceSchema") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("SourceTable") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("SourceType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("SyncDeletions") + .HasColumnType("INTEGER"); + + b.Property("UseRecordAssociations") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("DestinationCredentialId"); + + b.HasIndex("DestinationType"); + + b.HasIndex("IsActive"); + + b.HasIndex("LastUsedAt"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("SourceCredentialId"); + + b.HasIndex("SourceType"); + + b.ToTable("DataCouplerProfiles", (string)null); + }); + + modelBuilder.Entity("CredentialManager.Models.KeyAssociation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdditionalInfo") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("Data_Hash") + .HasMaxLength(64) + .HasColumnType("TEXT"); + + b.Property("DeletedAt") + .HasColumnType("TEXT"); + + b.Property("DeletionSynced") + .HasColumnType("INTEGER"); + + b.Property("DeletionSyncedAt") + .HasColumnType("TEXT"); + + b.Property("DestinationEntity") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DestinationId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("DestinationKeyField") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("IsActive") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("IsSourceDeleted") + .HasColumnType("INTEGER"); + + b.Property("KeyValue") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("LastVerifiedAt") + .HasColumnType("TEXT"); + + b.Property("MappedDestinationField") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("RestCredentialName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SourceKeyField") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("SourcesInfo") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("CreatedAt"); + + b.HasIndex("DestinationEntity"); + + b.HasIndex("IsActive"); + + b.HasIndex("KeyValue") + .HasDatabaseName("IX_KeyAssociations_KeyValue"); + + b.HasIndex("LastVerifiedAt"); + + b.HasIndex("RestCredentialName"); + + b.HasIndex("KeyValue", "DestinationEntity", "RestCredentialName") + .IsUnique() + .HasDatabaseName("IX_KeyAssociations_Unique"); + + b.ToTable("KeyAssociations", (string)null); + }); + + modelBuilder.Entity("CredentialManager.Models.ProfileSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("CreatedBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("DailyTime") + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("DayOfMonth") + .HasColumnType("INTEGER"); + + b.Property("DayOfWeek") + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("DestinationDatabaseOverride") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("EnableDeletionSync") + .HasColumnType("INTEGER"); + + b.Property("ExecutionCount") + .HasColumnType("INTEGER"); + + b.Property("IntervalUnit") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("IntervalValue") + .HasColumnType("INTEGER"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.Property("LastExecutionMessage") + .HasMaxLength(1000) + .HasColumnType("TEXT"); + + b.Property("LastExecutionRecordCount") + .HasColumnType("INTEGER"); + + b.Property("LastExecutionStatus") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("LastExecutionTime") + .HasColumnType("TEXT"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("NextExecutionTime") + .HasColumnType("TEXT"); + + b.Property("ProfileId") + .HasColumnType("INTEGER"); + + b.Property("ScheduleType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("ScheduledDateTime") + .HasColumnType("TEXT"); + + b.Property("SourceDatabaseOverride") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("UpdatedAt") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.ToTable("ProfileSchedules"); + }); + + modelBuilder.Entity("CredentialManager.Models.ScheduleExecutionHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AdditionalInfo") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("CreatedAt") + .HasColumnType("TEXT"); + + b.Property("DestinationInfo") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("DestinationType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("ErrorDetails") + .HasMaxLength(5000) + .HasColumnType("TEXT"); + + b.Property("Message") + .HasMaxLength(2000) + .HasColumnType("TEXT"); + + b.Property("ProfileId") + .HasColumnType("INTEGER"); + + b.Property("ProfileName") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("RecordsProcessed") + .HasColumnType("INTEGER"); + + b.Property("RecordsWithErrors") + .HasColumnType("INTEGER"); + + b.Property("ScheduleId") + .HasColumnType("INTEGER"); + + b.Property("SourceInfo") + .HasMaxLength(500) + .HasColumnType("TEXT"); + + b.Property("SourceType") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("TriggerType") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("TriggeredBy") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ScheduleId"); + + b.HasIndex("StartTime"); + + b.HasIndex("Status"); + + b.HasIndex("TriggerType"); + + b.ToTable("ScheduleExecutionHistories", (string)null); + }); + + modelBuilder.Entity("CredentialManager.Models.DataCouplerProfile", b => + { + b.HasOne("CredentialManager.Models.CredentialEntity", "DestinationCredential") + .WithMany() + .HasForeignKey("DestinationCredentialId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("CredentialManager.Models.CredentialEntity", "SourceCredential") + .WithMany() + .HasForeignKey("SourceCredentialId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("DestinationCredential"); + + b.Navigation("SourceCredential"); + }); + + modelBuilder.Entity("CredentialManager.Models.ProfileSchedule", b => + { + b.HasOne("CredentialManager.Models.DataCouplerProfile", "Profile") + .WithMany() + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("CredentialManager.Models.ScheduleExecutionHistory", b => + { + b.HasOne("CredentialManager.Models.ProfileSchedule", "Schedule") + .WithMany() + .HasForeignKey("ScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Schedule"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.cs b/CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.cs new file mode 100644 index 0000000..d202b37 --- /dev/null +++ b/CredentialManager/Migrations/20260123104841_AddEnableDeletionSyncToProfileSchedule.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace CredentialManager.Migrations +{ + /// + public partial class AddEnableDeletionSyncToProfileSchedule : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "EnableDeletionSync", + table: "ProfileSchedules", + type: "INTEGER", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "EnableDeletionSync", + table: "ProfileSchedules"); + } + } +} diff --git a/CredentialManager/Migrations/CredentialDbContextModelSnapshot.cs b/CredentialManager/Migrations/CredentialDbContextModelSnapshot.cs index 885c024..64a742e 100644 --- a/CredentialManager/Migrations/CredentialDbContextModelSnapshot.cs +++ b/CredentialManager/Migrations/CredentialDbContextModelSnapshot.cs @@ -382,6 +382,9 @@ namespace CredentialManager.Migrations .HasMaxLength(100) .HasColumnType("TEXT"); + b.Property("EnableDeletionSync") + .HasColumnType("INTEGER"); + b.Property("ExecutionCount") .HasColumnType("INTEGER"); diff --git a/CredentialManager/Models/ProfileSchedule.cs b/CredentialManager/Models/ProfileSchedule.cs index 9de9e3c..593931f 100644 --- a/CredentialManager/Models/ProfileSchedule.cs +++ b/CredentialManager/Models/ProfileSchedule.cs @@ -70,6 +70,9 @@ public class ProfileSchedule [MaxLength(100)] public string? DestinationDatabaseOverride { get; set; } + // Configurazione sincronizzazione eliminazioni (default: disabilitata) + public bool EnableDeletionSync { get; set; } = false; + // Metadati [MaxLength(100)] public string? CreatedBy { get; set; } diff --git a/CredentialManager/design_time_temp.db b/CredentialManager/design_time_temp.db index 589aa35dca8550323b36f665b93becefa8b7e81e..0482876d9dc3d3ece5fbe504db118508dfc3599c 100644 GIT binary patch delta 337 zcmZoTz}awsbAq%WD+2?A8W6*P$3z`tM%Il9P4W(Ax(0^2M#c(;2395(R;I>!mc}OL zW|l_U1_o9J2E0HWyu5)7{JZ$O`2+Z6_+IiI;G4pi$!E&P$h)6+0&n1EK>>YUZChUE za&aRABQpa-BV$7Y6AKf=c*m3!*Sy4}oK%<8oYa!c{Jh}GyyTGl$qjlUnMl^9S(D@V(?az&C|2lh2fok#|4ugw28i1-zRl=$0_a z@bI2x;6K1WjX#0kke`|FKHm<$NqotCCcNKy&jOXLyST0{ diff --git a/Data_Coupler/Pages/DataCoupler.razor.cs b/Data_Coupler/Pages/DataCoupler.razor.cs index 6cf9b76..ff532e7 100644 --- a/Data_Coupler/Pages/DataCoupler.razor.cs +++ b/Data_Coupler/Pages/DataCoupler.razor.cs @@ -1496,8 +1496,10 @@ public partial class DataCoupler : ComponentBase recordNumber++; } - // 3.5 Sincronizza le cancellazioni (se abilitato) + // 3.5 Sincronizzazione cancellazioni (DISABILITATA per trasferimenti manuali) + // Questa funzionalità è disponibile solo per le schedulazioni con configurazione esplicita int deletedCount = 0; + /* DELETION SYNC DISABILITATA PER TRASFERIMENTI MANUALI if (useRecordAssociations && !string.IsNullOrEmpty(sourceKeyField)) { try @@ -1570,6 +1572,7 @@ public partial class DataCoupler : ComponentBase }); } } + */ // 4. Mostra risultati if (errorCount == 0) diff --git a/Data_Coupler/Pages/Scheduling.razor b/Data_Coupler/Pages/Scheduling.razor index d780b72..d6bd0b3 100644 --- a/Data_Coupler/Pages/Scheduling.razor +++ b/Data_Coupler/Pages/Scheduling.razor @@ -336,6 +336,30 @@ +
+
+
+ Opzioni Avanzate +
+
+
+
+ + +
+
+ + + Attenzione: Se abilitata, i record eliminati dalla sorgente saranno automaticamente eliminati anche dalla destinazione durante l'esecuzione schedulata. + Questa opzione è disabilitata di default per motivi di sicurezza. + Usare con cautela! + +
+
+
+