Aggiunge un connettore completamente managed per database Visual FoxPro e dBase,
utilizzabile come sorgente dati in tutti i flussi dell'applicazione (discovery manuale,
esecuzione schedulata, hash/change-detection, backup/restore).
## Motivazione
Il provider OLE DB ufficiale (VFPOLEDB.1) è solo a 32-bit, deprecato e richiede
installazione separata. Il connettore managed usa DbfDataReader 1.0.0 (MIT), legge
direttamente i file .dbf/.fpt/.dbc a 64-bit senza dipendenze esterne e con streaming
efficiente (tabelle da centinaia di MB con uso di memoria contenuto).
## Nuovi file
- DataConnection/DB/FoxPro/FoxProConnectionInfo.cs
Classe sealed con le informazioni di connessione risolte (cartella, percorso .dbc,
encoding, flag IncludeDeleted). Proprietà di convenienza IsContainer e DisplayName.
- DataConnection/DB/FoxPro/FoxProReader.cs
Helper statico che registra CodePagesEncodingProvider, risolve la connection string
(path diretto, stile OLE DB con Provider=vfpoledb, chiave=valore), verifica l'accesso
al filesystem, legge il catalogo .dbc (il file .dbc è esso stesso un DBF; filtro su
OBJECTTYPE='Table' + cross-check esistenza fisica .dbf), enumera le tabelle free,
mappa i tipi VFP (Character, Memo, Numeric, Float, Double, Integer, Currency, Date,
DateTime, Logical, General) in descrizioni leggibili, esegue streaming dei record via
DbfDataReader, auto-rileva l'encoding dall'header DBF (language driver byte) con
fallback a code page 1252, e analizza query SELECT [TOP n] * FROM tabella.
- DataConnection/DB/FoxProDatabaseManager.cs
Implementa IDatabaseManager. Lettura: TestConnectionAsync, GetTableNamesAsync,
GetTableSchemaAsync, GetDatabaseSchemaAsync, GetAllRecordsAsync, ExecuteRawQueryAsync,
GetPrimaryKeyFieldAsync (ritorna null, selezione manuale chiave), GetAvailableDatabasesAsync,
ChangeDatabaseAsync (no-op per sorgenti file-based).
Scrittura: tutti i metodi di modifica (Insert/Update/Delete/Upsert/BulkInsert/
ExecuteCommand/ExecuteNonQuery) lanciano NotSupportedException con messaggio esplicito.
- DataConnection/DB/EF/SchemaProviders/FoxProSchemaProvider.cs
Implementa IDatabaseSchemaProvider delegando a FoxProReader. Gestione errori per tabella
in GetDatabaseSchemaAsync (una tabella non apribile non blocca la discovery).
- FOXPRO_CONNECTION.md
Guida utente: passo-passo per creare la credenziale, formato connection string,
tabella tipi VFP supportati, note su sola lettura e limitazioni query, tabella
risoluzione problemi (caratteri accentati, tabelle mancanti, ecc.).
## File modificati
- DataConnection/DataConnection.csproj
Aggiunto DbfDataReader 1.0.0 (porta transitivamente System.Text.Encoding.CodePages
>= 10.0.3; rimossa dipendenza esplicita alla versione 9.0.3 che causava NU1605).
- DataConnection/DB/Enums/DatabaseType.cs
Aggiunto valore Foxpro in fondo all'enum (preserva valori già persistiti).
- CredentialManager/Models/CredentialModels.cs
Aggiunto DatabaseType.Foxpro all'enum e metodo BuildFoxproConnectionString che genera
"Data Source=percorso[;CodePage=n][;IncludeDeleted=true]".
- DataConnection/CredentialManagement/Models/CredentialExtensions.cs
Mappatura bidirezionale Foxpro tra enum CredentialManager e DataConnection.
- DataConnection/CredentialManagement/Services/DataConnectionCredentialService.cs
Aggiunto TestFoxproConnection: verifica percorso accessibile, legge nomi tabelle,
restituisce messaggio con conteggio tabelle, encoding rilevato e nota sola lettura.
- DataConnection/DB/EF/DatabaseSchemaProviderFactory.cs
Caso Foxpro => new FoxProSchemaProvider().
- Data_Coupler/Services/DataConnectionFactory.cs
Branch Foxpro => new FoxProDatabaseManager(connectionString).
- Data_Coupler/Extensions/DataCoupler/DatabaseMethod.cs
Aggiunto IsFoxproConnection() e caso Foxpro in CreateLimitedQuery
(SELECT TOP n * FROM (query) AS subquery).
- CredentialManager/Integration/DataConnectionHelper.cs
ValidateDatabaseCredential: introdotto flag isFileBased (Sqlite || Foxpro) per
esonerare host/utente/password/porta; messaggio di errore specifico per il campo
percorso FoxPro.
- Data_Coupler/Pages/CredentialManagement.razor
Aggiunta opzione "Visual FoxPro (.dbc / .dbf)" nel selettore tipo database.
Sezione di configurazione dedicata: banner sola lettura, campo percorso con esempi
(.dbc e cartella), dropdown code page (Auto/1252/1250/1251/850/437/65001), checkbox
record cancellati, pannello tipi supportati, anteprima connection string.
Fix validazione form test-connessione: branch Foxpro che verifica solo DatabaseName
(non Host/Username/Password), eliminando il falso errore "Il campo Host è obbligatorio".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Aggiunto attributo [Required] al campo Name nelle classi DTO DatabaseCredential
e RestApiCredential in CredentialManager/Models/CredentialModels.cs.
Modifiche:
- Aggiunto `using System.ComponentModel.DataAnnotations` al file
- DatabaseCredential.Name: [Required(ErrorMessage = "Il nome è obbligatorio")]
- RestApiCredential.Name: [Required(ErrorMessage = "Il nome è obbligatorio")]
Il DataAnnotationsValidator già presente nelle EditForm di CredentialManagement.razor
intercetta automaticamente il vincolo e impedisce la submit mostrando il messaggio
di errore inline quando il campo è vuoto, senza modifiche alla logica di salvataggio.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Eliminati file e codice inutilizzati identificati durante l'analisi del codice morto:
File eliminati:
- Data_Coupler/Data/WeatherForecast.cs: classe demo del template Blazor, mai referenziata
- Data_Coupler/Data/WeatherForecastService.cs: servizio demo del template Blazor, mai iniettato
- DataConnection/CredentialManagement/Models/CredentialExtensions2.cs: file vuoto residuo di refactoring
- DataConnection/CredentialManagement/Models/CredentialExtensions_New.cs: file vuoto residuo di refactoring
- DataConnection/CredentialManagement/ServiceCollectionExtensions_New.cs: file vuoto residuo di refactoring
- CredentialManager/Services/KeyMappingService.cs: file vuoto senza implementazione
- DataConnection/DB/EF/ExistingDatabaseExample.cs: file vuoto di esempio non compilato
Interfaccia rimossa:
- DataConnection/CredentialManagement/ServiceCollectionExtensions.cs: rimossa IDataConnectionCredentialServiceConfiguration,
interfaccia mai implementata né utilizzata in alcuna parte del codebase
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
## Bulk Pre-Discovery e riduzione query SQLite/SOQL
### KeyAssociationService — FindAssociationsByKeyValuesBulkAsync (nuovo)
- Aggiunta query bulk 'WHERE KeyValue IN (...)' per recuperare N associazioni con 1 sola query SQLite
(chunking a 500 chiavi per rispettare il limite ~999 parametri di SQLite)
- Aggiunta interfaccia IKeyAssociationService e delegata in DataConnectionCredentialService / IDataConnectionCredentialService
### AssociationService — BatchFindOrCreateAssociationsAsync (nuovo)
- Nuovo metodo bulk che sostituisce i loop per-record durante l'analisi composite:
1) 1 query SQLite bulk per tutte le chiavi
2) Per le chiavi non trovate: SOQL 'IN (...)' su Salesforce in chunk da 200 via BatchExecuteQueriesAsync
(ceil(K/25) HTTP Composite call invece di K singole)
3) Salvataggio parallelo delle associazioni pre-discovery scoperte
- Fallback per-record automatico per client REST non Salesforce
- Aggiornata interfaccia IAssociationService con documentazione XML completa
### DataCoupler.razor.cs — STEP A/B nel flusso COMPOSITE
- Pre-Discovery spostata FUORI dal loop parallelo (STEP A, prima dell'analisi)
- associationsByKey pre-popolato con BatchFindOrCreateAssociationsAsync
- STEP B: il loop parallelo usa TryGetValue O(1) invece di query async per record
- Rimozione blocco ~40 righe di per-record lookup / fallback duplicati
## Salesforce Composite API — Batch Delete e Patch
### SalesforceServiceClient — metodi batch (nuovi)
- BatchDeleteEntitiesAsync: elimina N record con ceil(N/25) Composite call invece di N
- BatchPatchSingleFieldAsync: aggiorna un singolo campo su N record tramite BatchUpdateEntitiesAsync
### DeletionSyncService — refactoring batch
- ExecuteBatchedSalesforceDeletionsAsync: orchestrazione batch per Delete / Deactivate / Mark su Salesforce
- ExecuteSequentialDeletionsAsync: loop sequenziale esistente estratto in metodo riutilizzabile
- Dispatcher: Salesforce -> batch Composite, altri client REST -> sequenziale
## Supporto OLE DB (database)
### DatabaseSchemaProviderFactory
- Aggiunto case DatabaseType.OleDb -> new OleDbSchemaProvider() nel factory switch
### DatabaseMethod.cs
- Aggiunto metodo IsOleDbConnection() (parallelo a IsOdbcConnection())
- Query validation e manager temporaneo estesi a OLE DB oltre che ODBC
- GetLimitedQuery: aggiunto case OleDb -> 'SELECT TOP N FROM (subquery)'
## Salesforce OAuth2 — fix client_credentials
### CredentialService.cs
- Aggiunto 'GrantType' alla HashSet serviceSpecificKeys per preservarlo nella serializzazione AdditionalParameters
### DataConnectionCredentialService.cs
- Refactored BuildRestServiceOptions in helper statico riutilizzato da entrambi i metodi GetRestServiceOptions
- Mapping coerente ClientId/ClientSecret/GrantType per Salesforce (allineato a DataConnectionFactory)
- TestSalesforceOAuthLogin: branch esplicito per client_credentials (no username/password/token)
con validazione preventiva ClientId+ClientSecret obbligatori
- Log flow label (password|client_credentials) in tutti i messaggi di autenticazione
## VS Code tasks
### .vscode/tasks.json
- Rimosso task generico 'Publish Data_Coupler'
- Aggiunti due task separati: win-x64 e win-x86, entrambi SingleFile + Self-Contained + ReadyToRun
## Nuovi file
- DataConnection/DB/OleDbDatabaseManager.cs: Manager completo per connessioni OLE DB
con supporto Task.Run() per operazioni sincrone, parametri posizionali '?',
guard per piattaforma Windows, nessun supporto ChangeDatabaseAsync (no-op)
- DataConnection/DB/EF/SchemaProviders/OleDbSchemaProvider.cs: Schema provider per
OLE DB, usa OleDbSchemaGuid per tabelle/colonne/chiavi primarie, mapping tipi dati
- CredentialManager/Services/OleDbProviderDiscoveryService.cs: Servizio di discovery
provider OLE DB installati tramite registro Windows (HKEY_CLASSES_ROOT). Rileva
9 provider noti: VFPOLEDB.1, Microsoft.ACE.OLEDB.12.0, Jet 4.0, SQLOLEDB, ecc.
Mostra warning per provider solo 32-bit (VFPOLEDB, Jet)
- PUBLISH_32BIT_64BIT.md: Documentazione completa comandi pubblicazione per
win-x64, win-x86 (richiesto per VFP), linux-x64, osx-x64, osx-arm64.
Include prerequisiti VFPOLEDB, esempi connection string VFP, note Docker
## File modificati
- DataConnection/DB/Enums/DatabaseType.cs: Aggiunto valore OleDb dopo Odbc
- DataConnection/DataConnection.csproj: Aggiunto pacchetto System.Data.OleDb 9.0.3
- DataConnection/DB/OdbcDatabaseManager.cs: Fix bug ChangeDatabaseAsync con try-catch
- CredentialManager/Models/CredentialModels.cs: Aggiunto OleDb all'enum DatabaseType,
BuildOleDbConnectionString() con supporto provider da AdditionalParameters,
default VFPOLEDB.1, costruzione connection string con parametri VFP
- DataConnection/CredentialManagement/Models/CredentialExtensions.cs: Mappatura
OleDb in ToDataConnectionDatabaseType() e ToCredentialDatabaseType()
- DataConnection/CredentialManagement/Services/DataConnectionCredentialService.cs:
Aggiunto case OleDb in TestDatabaseConnectionAsync e metodo TestOleDbConnection()
con apertura connessione via Task.Run() e gestione OleDbException dettagliata
- Data_Coupler/Services/DataConnectionFactory.cs: Aggiunto case OleDb per creazione
OleDbDatabaseManager
- Data_Coupler/Program.cs: Registrazione IOleDbProviderDiscoveryService come Scoped
- Data_Coupler/Pages/CredentialManagement.razor: Aggiunta UI completa OLE DB con
sezione dedicata Visual FoxPro (percorso .dbc/.dbf, Collating Sequence, DELETED),
provider discovery con refresh, anteprima connection string, variabili di stato
e metodi nel codice Blazor, sincronizzazione AdditionalParameters al salvataggio
## Compatibilità
- VFP 8.0/9.0: testato con VFPOLEDB.1, connessione file-based .dbc e .dbf
- Richiede pubblicazione win-x86 per driver OLE DB 32-bit
- AnyCPU non supportato per VFP (COM 32-bit)
Implementata la possibilita' di usare Salesforce come fonte dati e un database relazionale come destinazione nel flusso di trasferimento dati.
## Modifiche principali
### Nuovi file partial class
- Data_Coupler/Extensions/DataCoupler/SalesforceSourceMethod.cs
- Stato e metodi per Salesforce come fonte (credenziali, connessione, discovery SObject)
- ConnectToSalesforceSource(): autenticazione parallela + discovery summaries/details
- SelectSalesforceSourceEntity(): selezione SObject e caricamento campi
- GetAllRecordsFromSalesforceSource(): estrazione via ExtractAllEntitiesAsync con solo i campi mappati
- Filtro/ricerca SObject in tempo reale
- Data_Coupler/Extensions/DataCoupler/DatabaseDestinationMethod.cs
- Stato e metodi per database come destinazione
- ConnectToDestinationDatabase(): connessione e discovery tabelle
- SelectDestinationTable(): caricamento schema tabella on-demand
- IsDestinationDatabaseReady: proprieta' calcolata per validazione
- Toggle UI tra destinazione REST e Database
### IDatabaseManager interface
- Aggiunto UpsertRecordAsync(tableName, keyField, keyValue, record):
- Esegue SELECT COUNT(*) per verificare esistenza record
- UPDATE se esiste, INSERT se non esiste
- Implementato in EFCoreDatabaseManager (parametri named @p0..@pN)
- Implementato in OdbcDatabaseManager (parametri posizionali ?)
### DataCoupler.razor (UI)
- Aggiunto 'Salesforce (REST API)' nel dropdown tipo fonte
- Sezione UI Salesforce fonte: selettore credenziali, bottone connessione, lista SObject con ricerca
- Toggle destinazione REST/Database nella card destra
- Sezione UI Database destinazione: selettore credenziali, bottone connessione, lista tabelle con ricerca
- Colonna destra mapping aggiornata: mostra colonne DB se destinazione e' database, proprieta' REST altrimenti
- Colonna sinistra mapping: aggiunta sezione campi SObject Salesforce
- isSourceReady aggiornato per includere fonte Salesforce
- isDestinationReady aggiornato per includere destinazione database
- Etichette mapping dinamiche in base ai tipi selezionati
### DataCoupler.razor.cs (logica)
- LoadCredentials(): aggiunto caricamento credenziali Salesforce fonte
- ResetSourceState(): aggiunto reset stato Salesforce fonte
- ResetDestinationState(): aggiunto reset stato database destinazione
- GetAllRecordsFromSource(): aggiunto branch Salesforce
- StartDataTransfer(): routing verso StartDataTransferToDatabase() se dest=database
- Aggiunto StartDataTransferToDatabase(): estrae record fonte, applica mapping e default values, chiama UpsertRecordAsync per ogni record
- Rimosso codice duplicato in StartDataTransfer()
Implementato il flusso OAuth2 grant_type=client_credentials come alternativa
al flusso password gia' esistente per l'autenticazione Salesforce server-to-server.
La modifica e' completamente retrocompatibile (default rimane Password).
## Dettaglio modifiche
### CredentialManager/Models/CredentialModels.cs
- Aggiunto enum SalesforceGrantType con valori Password e ClientCredentials
- Aggiunta proprieta' GrantType (default: Password) su RestApiCredential
- Aggiunta proprieta' GrantType (default: Password) su SalesforceCredential
### DataConnection/REST/Configuration/RestServiceOptions.cs
- Aggiunta proprieta' SalesforceGrantType per passare il tipo di flusso al client
### DataConnection/REST/Implementations/SalesforceServiceClient.cs
- Iniettato ILogger<SalesforceServiceClient> con NullLogger come fallback
- Sostituiti ~165 Console.WriteLine con chiamate ILogger appropriate
(LogDebug per dettagli, LogInformation per eventi, LogWarning/LogError per problemi)
- Aggiunto AuthenticateWithPasswordAsync: incapsula il flusso grant_type=password
- Aggiunto AuthenticateWithClientCredentialsAsync: implementa grant_type=client_credentials
(richiede solo ClientId e ClientSecret, nessun utente, URL My Domain obbligatorio)
- Aggiunto SendTokenRequestAsync: helper condiviso per la POST al token endpoint
- Aggiornato AuthenticateAsync() override: instrada al flusso corretto in base a GrantType
- Rimosso modificatore static da NormalizeNumericValues (usava _logger, causava CS0120)
### Data_Coupler/Services/DataConnectionFactory.cs
- Mappatura del campo GrantType dalle opzioni Salesforce a RestServiceOptions
- Passaggio dell'ILogger al costruttore di SalesforceServiceClient
### CredentialManager/Services/CredentialService.cs
- SaveRestApiCredentialAsync (blocco Salesforce): serializza GrantType in AdditionalParameters
- SaveSalesforceCredentialAsync: aggiunto GrantType nel dizionario iniziale
- MapToRestApiCredential: deserializza GrantType da AdditionalParameters con Enum.TryParse
- MapToSalesforceCredential: idem per il tipo SalesforceCredential
### DataConnection/CredentialManagement/Services/DataConnectionCredentialService.cs
- TestSalesforceOAuthLogin aggiornato: per ClientCredentials invia solo client_id e
client_secret (senza username/password/security_token); per Password comportamento invariato
### Data_Coupler/Pages/CredentialManagement.razor
- Aggiunto dropdown 'Tipo di Autenticazione OAuth2' nella sezione Salesforce
- I campi Username, Password e Security Token vengono nascosti quando si seleziona
il flusso ClientCredentials
- Alert contestuale: warning My Domain URL per ClientCredentials, info per Password
- GrantType propagato correttamente in EditRestApiCredential e TestRestApiConnectionFromModal
### AGENTS.md
- Aggiunta sezione di documentazione per la nuova funzionalita' OAuth2 client_credentials
- SchedulingHistory.razor / .cs: iniettato IWebHostEnvironment per nascondere
lo stack trace (con percorsi di file) in produzione; in produzione viene
mostrato solo il messaggio di errore sanitizzato e un avviso che invita a
consultare i log dell'applicazione; in sviluppo il dettaglio completo resta
visibile invariato.
- Scheduling.razor.cs (ExecuteScheduleManually): isolata la notifica JS
(ShowSuccessMessage / ShowErrorMessage) in un blocco try-catch separato per
TaskCanceledException / OperationCanceledException. In questo modo una
disconnessione del browser durante un'esecuzione lunga non sovrascrive più
il risultato già salvato correttamente come 'success' con uno stato 'failed'
e lo stack trace di un'eccezione JSInterop. L'evento viene registrato come
avviso di log senza impatto sul record storico.
- ScheduledJobService.cs: aggiunto commento esplicativo sul motivo per cui
il dettaglio completo (ex.ToString) è salvato nel DB ma la UI ne mostra
solo la versione sanitizzata in produzione.
- Nuovo progetto MachineGuard: libreria che verifica se la macchina corrente
è autorizzata all'esecuzione tramite DPAPI (Data Protection API di Windows)
- Nuovo progetto MachineGuardSetup: tool di configurazione da eseguire come
Amministratore per registrare la macchina autorizzata
- Data_Coupler.sln: aggiunti entrambi i nuovi progetti alla soluzione
- Data_Coupler.csproj: aggiunto riferimento al progetto MachineGuard
- Program.cs: integrazione MachineGuard all'avvio dell'applicazione;
se la macchina non è autorizzata l'app viene arrestata immediatamente
con log critico e scrittura nel Windows Event Log
Senza questo flag il target GenerateVersionJson nel .csproj veniva eseguito
dentro il container Docker Windows dove:
- Non esiste .git (fatal: not a git repository)
- version.json copiato da COPY e' read-only o protetto
→ MSB3491: Access to the path '...\wwwroot\version.json' is denied
Il Dockerfile Linux aveva gia /p:ContinuousIntegrationBuild=true.
La condizione nel .csproj e':
Condition="'' != 'true' AND '' != 'true'"
quindi con il flag il target viene saltato e version.json usa quello
generato dal workflow prima del docker build.
Il workflow GitHub non generava version.json sul runner prima del build,
quindi Docker copiava il file statico del repository (con versione vecchia 2.1.0).
La Gitea Actions usava gia questo approccio correttamente.
Fix applicato: lo step 'Calcola versione' ora genera anche version.json in
Data_Coupler/wwwroot/version.json per entrambi i job Linux e Windows,
con versione, commit SHA, branch, data build e ambiente (GitHub Actions).
Il VersionService legge version.json all'avvio per display nell'UI.
Problemi risolti:
- GitHub Windows: errore PowerShell 'Missing closing )' causato da (cd Dir; cmd)
sintassi bash non valida in PowerShell
- GitHub Linux: versione 1.0.0 invece di 2.3.2 perche il tag v2.3.2 esiste solo
su Gitea e non su GitHub, quindi MinVer trovava il vecchio tag v1.0.0
Soluzione:
- Sostituito dotnet msbuild -getProperty:Version con git describe --tags --abbrev=0
che e lo strumento nativo Git per ottenere l'ultimo tag raggiungibile
- Funziona identicamente su Linux (bash) e Windows (PowerShell)
- Non richiede dotnet installato ne accesso al .git dentro Docker
- Rimosso il dotnet build intermedio sul runner (non piu necessario)
- Corretti i percorsi version.json: ora usa Data_Coupler/wwwroot/version.json
dal root del repo invece di wwwroot/ relativo dopo cd
Il problema era che MinVer veniva eseguito dentro il container Docker dove la
directory .git non esiste, causando il warning MINVER1001 e l'uso di 0.0.0-alpha.0
(poi sostituito dal fallback hardcoded 2.1.0).
Soluzione:
- La versione viene calcolata sul runner CI/CD (dove git e' disponibile)
- Esportata come variabile d'ambiente APP_VERSION via GITHUB_ENV
- Passata al Docker build tramite --build-arg APP_VERSION
- Nei Dockerfile aggiunto ARG APP_VERSION e /p:MinVerVersionOverride per imporla
a MinVer senza che tenti di accedere a git (assente nel container)
- ARG ridichiarato dopo ogni FROM in multi-stage build (comportamento Docker)
Aggiunto fetch-depth: 0 al checkout in tutti i job dei workflow GitHub Actions e Gitea Actions.
Rimosso --depth 1 dal clone manuale del job Windows in Gitea.
MinVer necessita della storia completa per risalire ai tag Git e calcolare la versione corretta.
Senza questa correzione la versione risultava sempre 2.1.0 (fallback hardcoded).
Aggiornato anche il valore di fallback da 2.1.0 a 2.3.2.
- Salesforce Composite Batch API per describe SObject: le describe sono ora
raggruppate in chunk da 25 e inviate come singole POST a /composite/batch,
riducendo le chiamate API da N a ceil(N/25); per 200 SObject: da 201 a 9 chiamate.
- Discovery entita' REST in parallelo: DiscoverEntitySummariesAsync e
DiscoverEntitiesAsync avviate simultaneamente; la lista entita' diventa
interattiva subito dopo le summaries, i dettagli completano in background
con StateHasChanged() per aggiornare l'UI istantaneamente.
- Fix scheduler - preservazione ExternalIdRelationshipsJson e DefaultValuesJson:
in DataCoupler.razor.cs entrambi i blocchi di update profilo esistente
(riattivazione profilo inattivo e sovrascrittura profilo attivo) omettevano
questi campi nella copia, causandone l'azzeramento silenzioso ad ogni
re-salvataggio. Ora entrambi i percorsi propagano correttamente i campi JSON.
- Fix scheduler - esclusione campi sorgente External ID dal mapping normale:
in ScheduledProfileExecutionService.TransformRecordForRest i campi sorgente
usati nelle External ID Relationships venivano inclusi anche nel loop di
field mapping standard, generando dati duplicati nell'entita' destinazione.
Ora il comportamento e' allineato alla UI manuale (TransformRecordToRestEntity).
- Aggiornata documentazione: README.md, AGENTS.md, copilot-instructions.md
- Disabilitato target MSBuild GenerateVersionJson durante build CI/CD
- Aggiunta condizione: non esegue se ContinuousIntegrationBuild=true
- Aggiornato Dockerfile per usare /p:ContinuousIntegrationBuild=true
- Previene sovrascrittura del version.json generato dal workflow Gitea
- Risolve problema: container mostra v1.0.0-dev invece della versione da git tag
- Cambiato immagine base da Alpine a Debian per migliore compatibilità SQLite
- Aggiunto SQLitePCLRaw.bundle_e_sqlite3 per librerie native cross-platform
- Installato sqlite3 e libsqlite3-dev in Debian
- Risolve definitivamente: 'Error loading shared library libe_sqlite3.so'
- Aggiunto MSBuild target che genera version.json automaticamente prima di ogni build
- Versione estratta dal tag git più recente (git describe --tags)
- Rimosso version.json dal tracking git (file generato automaticamente)
- Aggiornato .gitignore per escludere version.json
- Il file viene ora rigenerato ad ogni build con versione, commit SHA, branch e timestamp corretti
- Aggiunto --runtime win-x64 al comando restore
- Specificato -r win-x64 --self-contained false nella publish
- Il restore ora genera project.assets.json per net9.0/win-x64
- Sintassi corretta: --self-contained false invece di /p:SelfContained=false
- Sostituito /p:UseAppHost=false con /p:SelfContained=false in entrambi i Dockerfile
- .NET 9.0 richiede AppHost per applicazioni self-contained
- SelfContained=false è appropriato per container Docker con runtime separato
- Fix applicato sia a Dockerfile (Linux) che Dockerfile.windows
- Creato modello FieldMappingEntry per gestione unificata di field mapping e default values
- Aggiunta colonna DefaultValuesJson alla tabella DataCouplerProfile (max 4000 caratteri)
- Implementata UI con toggle per selezionare modalità Mapping o Default
- Supporto per 9 tipi di dati: string, int, long, decimal, double, float, boolean, datetime, datetimeoffset
- Aggiornata logica TransformRecordToRestEntity per applicare valori default dopo field mapping
- Implementata serializzazione/deserializzazione DefaultValues in DataCouplerProfileService
- Sistema completo di salvataggio/caricamento valori default nei profili
- Migrazione database AddDefaultValuesJsonToProfile creata e applicata
- Implementata funzionalità completa External ID Relationships nell'interfaccia di mapping
- Corretto bug double-mapping: i campi sorgente usati per External ID non vengono più inclusi nei mapping normali
- Risolto errore MALFORMED_ID causato dall'invio duplicato di campi come proprietà dirette e nested objects
- Implementata logica corretta per relationship names: oggetti standard usano il nome diretto, custom objects usano suffisso __r
- Aggiunta UI a 3 colonne (Object, External ID Field, Source Field) per configurazione External ID Relationships
- Migrazione database per supporto External ID Relationships nei profili
- Aggiornato ProfileSaver.razor.cs per salvare/caricare External ID Relationships
- Aggiornato ScheduledProfileExecutionService.cs per gestire External ID nelle esecuzioni schedulate
- Formato JSON output corretto: { 'Account': { 'CardCode__c': 'V50000' } }
Documentazione: EXTERNAL_ID_RELATIONSHIPS_IMPLEMENTATION.md
- Disabilitato trimming per compatibilità con Blazor Server (risolve crash TypeLoadException)
- Configurati PublishSingleFile e ReadyToRun per deployment ottimizzato
- Rimosso controllo eccessivamente restrittivo sui commenti SQL in validazione query
- Ora permessi commenti -- e /* */ nelle query SELECT ODBC
- Mostra stato di tutte le variabili che controllano la visibilità del mapping
- Indica quale condizione non è soddisfatta (isSourceReady, isRestConnected, selectedRestEntity)
- Pannello visibile solo per connessioni ODBC
- Aiuta a identificare rapidamente il problema
- Modificata condizione isSourceReady in DataCoupler.razor
- Per ODBC: richiede solo useCustomQuery && isQueryValid (non isDatabaseConnected)
- Per altri DB: comportamento invariato (richiede isDatabaseConnected)
- Risolto: mapping non appariva dopo validazione query ODBC
- Modificato OnDatabaseCredentialChanged per rilevare connessioni ODBC e forzare useCustomQuery = true
- Aggiunto metodo helper IsOdbcConnection() per verificare tipo credenziale
- Modificata UI DataCoupler.razor:
* Nascosto pulsante 'Connetti e Scopri Schema' per ODBC
* Mostrato messaggio esplicativo per ODBC
* Resa sezione Query Custom sempre visibile per ODBC (senza discovery)
* Nascosta sezione Lista Tabelle per ODBC
- Modificato ValidateCustomQuery per creare temporaneamente DatabaseManager per ODBC
- ODBC ora bypassa completamente il discovery e va diretto a query custom
- Aggiunta persistenza campi ODBC (OdbcDsnName, OdbcMode) in CredentialEntity
- Creata migration EF Core per nuovi campi database
- Aggiornato mapping credenziali per caricare/salvare dati ODBC
- Creato OdbcDatabaseManager dedicato (bypass EF Core che non supporta ODBC)
- Aggiornato DataConnectionFactory per usare OdbcDatabaseManager con connessioni ODBC
- Fix auto-load DSN: sostituito @onchange con @bind-Value:after in dropdown tipo database
- Fix test connessione SAP HANA: rimossa query SELECT 1 che causava errori sintassi
- Implementati tutti i metodi IDatabaseManager in OdbcDatabaseManager
- Supporto completo per discovery schema, tabelle e query ODBC
Risolve problema DbContext non configurato per ODBC e abilita connessioni ODBC complete.
- Rimosso tag 'latest' da branch development, staging e dev
- Tag 'latest' ora riservato esclusivamente al branch main
- Altri branch mantengono tag specifici (development-latest, staging-latest, dev-latest)
- Modificati workflow GitHub Actions e Gitea Actions
- Semplifica la gestione delle versioni in produzione vs sviluppo
- 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)
- Migrato immagine runtime da Debian a Alpine (riduzione ~60% dimensione)
- Aggiunto suffisso -linux ai tag per manifest multi-platform
- Disabilitate attestations/provenance per ridurre overhead push
- Implementato retry automatico in caso di fallimento push
- Corretto utilizzo apk invece di apt-get per Alpine Linux
Risolve: HTTP 524 timeout durante push immagini al registry
- Aggiunto suffisso -linux ai tag delle immagini Linux per distinguerli
- Aggiornati i comandi del manifest per usare tag espliciti -linux e -windows
- Risolto errore 'not found' durante creazione manifest su branch staging
- Applicato fix a tutti i branch (main, development, dev, staging)
- 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