- Aggiunto MinVer per calcolo automatico versione da git tags
- Creato modello VersionInfo e servizio VersionService
- Integrato display versione nel NavMenu (Data_Coupler v2.1.0)
- Aggiornato workflow Gitea Actions (Linux e Windows) per generare version.json
- Risolto problema inconsistenza versioning tra container Linux e Windows
- Documentazione completa: VERSIONING_SYSTEM.md e MINVER_SETUP.md
- Versione ora calcolata automaticamente da git tags (Semantic Versioning)
- Aggiunta validazione percorsi file prima del salvataggio profili
- Implementati metodi di lettura file CSV e Excel per schedulazioni
- Supporto doppia modalità: caricamento browser (preview) e percorso manuale (schedulazione)
- Gestione completa deletion sync anche per file CSV/Excel
- Rilevamento automatico separatori CSV (virgola, punto e virgola, tab, pipe)
- Supporto formati Excel legacy (.xls) e moderni (.xlsx)
- Abilitati profili file nella UI di schedulazione
- Logging dettagliato per troubleshooting
- Documentazione completa in CSV_SCHEDULING_IMPLEMENTATION.md
- Aggiornati README.md e copilot-instructions.md con nuove feature
- Rimosso testo 'TEST' dalla pagina di login
- 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
Creato AssociationService per eliminare duplicazione codice e migliorare manutenibilità
Nuovo servizio:
- Data_Coupler/Services/AssociationService.cs (276 righe)
* Interfaccia IAssociationService con metodi pubblici
* PreDiscoveryRequest DTO per parametri configurabili
* FindOrCreateAssociationAsync(): ricerca locale + Pre-Discovery REST
* IsPreDiscoveryAssociation(): verifica marker associazioni Pre-Discovery
Refactoring DataCoupler.razor.cs:
- Injected IAssociationService nel componente
- StartDataTransferOriginal(): ridotto da 98 a 20 righe (-78)
- StartDataTransferWithComposite(): ridotto da 93 a 20 righe (-73)
- Verifica Pre-Discovery: ridotto da 20 a 2 righe (-18)
- Sostituito logica inline con chiamate al servizio centralizzato
Refactoring ScheduledProfileExecutionService.cs:
- Injected IAssociationService nel costruttore
- ExecuteDataTransferWithCompositeAsync(): ridotto da 99 a 20 righe (-79)
- Verifica Pre-Discovery: ridotto da 20 a 2 righe (-18)
- Parametro IsScheduledTransfer=true per tracciabilità
Dependency Injection:
- Registrato IAssociationService in Program.cs come Scoped
- Disponibile per dependency injection in tutti i componenti
Vantaggi:
- Eliminata duplicazione: 3 implementazioni → 1 servizio centralizzato
- Codice ridotto di 266 righe (330 → 64 nelle chiamate)
- Manutenibilità: modifiche future in un solo file
- Testabilità: interfaccia facilmente mockabile per unit test
- Riusabilità: servizio disponibile per futuri componenti
- Separazione responsabilità: logica associazioni isolata
Comportamento invariato:
- Nessuna modifica alla logica Pre-Discovery esistente
- Compatibilità completa con database e API
- Stessi marker e metadata nelle associazioni create
Docs: PRE_DISCOVERY_REFACTORING.md
Build: ✅ Successo (0 errori, 25 warning pre-esistenti)
- Fix FindEntitiesByKeysAsync: SOQL query universale al posto di External ID GET
* Disabilitato External ID GET (funziona solo per campi marcati External ID)
* Query SOQL come metodo primario funzionante per tutti i campi
* Logging dettagliato per diagnostica ricerche Salesforce
- Pre-Discovery nei trasferimenti manuali (DataCoupler.razor.cs)
* Ricerca automatica nella destinazione quando KeyAssociation non esiste
* Creazione associazione con marker CreatedBy="PreDiscovery"
* Aggiornamento forzato senza controllo hash per associazioni Pre-Discovery
* Supporto parallel processing thread-safe
- Pre-Discovery nei trasferimenti schedulati (ScheduledProfileExecutionService.cs)
* Logica identica a trasferimenti manuali
* Marker aggiuntivo ScheduledTransfer=true per tracciabilità
* Aggiornamento forzato per prima sincronizzazione
- Sistema aggiornamento forzato
* Verifica AdditionalInfo per identificare associazioni Pre-Discovery
* Skip controllo hash per associazioni appena scoperte
* Garantisce sincronizzazione dati al primo trasferimento
Vantaggi:
- Prevenzione automatica duplicati in Salesforce
- Recupero record esistenti senza associazioni
- Parità funzionale tra esecuzioni manuali e schedulate
- Performance ottimizzate con controllo hash per esecuzioni successive
Docs: PRE_DISCOVERY_SYSTEM.md, PRE_DISCOVERY_FORCED_UPDATE.md, SALESFORCE_FIND_ENTITIES_FIX.md
- Aggiunto campo MappedDestinationField al modello KeyAssociation per tracciare il campo destinazione mappato alla chiave sorgente
- Creata migration AddMappedDestinationFieldToKeyAssociation per aggiungere la colonna al database
- Implementata logica di popolamento in CreateAssociationAsync e StartDataTransferOriginal per salvare il campo destinazione mappato
- Aggiornato SaveAssociationParallelAsync per includere MappedDestinationField nelle query SQL UPDATE e INSERT
- Corretti indici parametri nella query UPDATE (da {7-9} a {8-10}) per includere il nuovo campo
- Aggiunta visualizzazione campo nell'interfaccia KeyAssociations (tabella, dettagli, export CSV)
- Implementato controllo validazione per impedire trasferimenti se il campo chiave non è mappato
- Aggiunto logging diagnostico dettagliato per debug del mapping dei campi
- Aggiornato ScheduledProfileExecutionService per popolare MappedDestinationField nelle esecuzioni schedulate
- Rimosso file BackgroundServices.cs obsoleto
- Documentazione completa creata (4 markdown files)
Fixes: Campo MappedDestinationField rimaneva NULL perché le query SQL raw non includevano il nuovo campo
BREAKING CHANGE: Tutte le pagine ora richiedono autenticazione
Nuove funzionalità:
- Sistema di login con password hardcoded (admin123)
- Form di login full-screen con gradiente viola
- Protezione automatica di tutte le route
- Pulsante logout visibile in tutte le pagine
- Gestione thread-safe eventi autenticazione con InvokeAsync()
Componenti:
- AuthenticationService: servizio Singleton per gestione stato
- Login.razor: pagina login con validazione e messaggi errore
- App.razor: routing condizionale basato su autenticazione
- MainLayout.razor: pulsante logout integrato
Fix tecnici:
- Risolto errore "Dispatcher not associated" usando InvokeAsync()
- Implementato pattern corretto per eventi cross-thread in Blazor Server
- Aggiunto Dispose per prevenire memory leak
- Aggiunge classe CachedRestClient per tracciare client con hash delle credenziali
- Implementa verifica automatica delle credenziali dal database tramite hash SHA256
- Mantiene cache dei client REST autenticati preservando lo stato di autenticazione
- Invalida automaticamente la cache quando le credenziali cambiano nel database
- Aggiunge logging dettagliato per debug dell'autenticazione Salesforce
- Migliora mappatura credenziali Salesforce con validazione Password e ClientSecret
BREAKING CHANGE: Le credenziali REST vengono sempre verificate dal database
mantenendo performance attraverso cache intelligente basata su hash crittografico
Fixes: risolve problemi di "invalid_client_id" intermittenti e _accessToken null
- Modificato GetAllRecordsAsync per utilizzare la stessa connection string del discovery schema
- Aggiunto metodo CreateConnection per creare connessioni DB appropriate per tipo
- Migliorata gestione nomi tabelle con schema (es. "dbo.OCRD")
- Rimossi metodi obsoleti di creazione entità (UpdateEntityData, CreateNewEntity)
- Eliminati riferimenti a variabili non dichiarate (newEntityData, isCreatingEntity)
- Aggiunto logging debug per connection string e query SQL
- Completata implementazione trasferimento dati da database a REST API
Il trasferimento dati ora utilizza la stessa connessione per discovery e estrazione,
risolvendo problemi di accesso alle tabelle durante l'operazione di upsert.