fix: Correzione salvataggio campo MappedDestinationField in KeyAssociations
- 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
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
# Troubleshooting MappedDestinationField NULL
|
||||
|
||||
## Data: 20 Ottobre 2025
|
||||
|
||||
## Problema Segnalato
|
||||
|
||||
Il campo `MappedDestinationField` rimane sempre `NULL` nelle associazioni anche quando viene fatto un mapping.
|
||||
|
||||
## Analisi del Problema
|
||||
|
||||
### Come Dovrebbe Funzionare
|
||||
|
||||
1. L'utente crea un mapping: `CardCode` (sorgente) → `cardcode__c` (destinazione)
|
||||
2. L'utente seleziona `CardCode` come campo chiave sorgente
|
||||
3. Durante il trasferimento, il sistema dovrebbe:
|
||||
- Cercare `CardCode` nel dizionario `fieldMappings`
|
||||
- Trovare il valore mappato `cardcode__c`
|
||||
- Salvarlo in `MappedDestinationField`
|
||||
|
||||
### Struttura Dati
|
||||
|
||||
```csharp
|
||||
// fieldMappings è un Dictionary<string, string>
|
||||
// Chiave: nome colonna sorgente (es. "CardCode")
|
||||
// Valore: nome campo destinazione (es. "cardcode__c")
|
||||
|
||||
Dictionary<string, string> fieldMappings = new()
|
||||
{
|
||||
{ "CardCode", "cardcode__c" },
|
||||
{ "CardName", "Name" },
|
||||
{ "City", "BillingCity" }
|
||||
};
|
||||
|
||||
// sourceKeyField è la colonna selezionata come chiave
|
||||
string sourceKeyField = "CardCode";
|
||||
|
||||
// Logica di ricerca
|
||||
if (fieldMappings.ContainsKey(sourceKeyField))
|
||||
{
|
||||
mappedDestinationField = fieldMappings[sourceKeyField]; // Dovrebbe essere "cardcode__c"
|
||||
}
|
||||
```
|
||||
|
||||
## Possibili Cause
|
||||
|
||||
### 1. Campo Chiave Non Mappato ❌
|
||||
|
||||
**Scenario**: L'utente seleziona un campo chiave che NON è stato mappato.
|
||||
|
||||
**Esempio**:
|
||||
```
|
||||
Mappings creati:
|
||||
- CardName → Name
|
||||
- City → BillingCity
|
||||
|
||||
Campo chiave selezionato: CardCode ← NON MAPPATO!
|
||||
|
||||
Risultato: MappedDestinationField = NULL
|
||||
```
|
||||
|
||||
**Soluzione**: Verificare che il campo chiave selezionato sia presente nei mappings.
|
||||
|
||||
### 2. Case Sensitivity Issues ⚠️
|
||||
|
||||
**Scenario**: Il nome del campo chiave non corrisponde esattamente alla chiave nel dizionario.
|
||||
|
||||
**Esempio**:
|
||||
```
|
||||
Mapping creato: "cardcode" → "cardcode__c"
|
||||
Campo chiave: "CardCode" ← Diverso per maiuscole!
|
||||
|
||||
Risultato: ContainsKey restituisce false
|
||||
```
|
||||
|
||||
**Soluzione**: Verificare che il nome sia identico (case-sensitive).
|
||||
|
||||
### 3. Spazi o Caratteri Nascosti 🔍
|
||||
|
||||
**Scenario**: Presenza di spazi all'inizio/fine del nome campo.
|
||||
|
||||
**Esempio**:
|
||||
```
|
||||
Mapping: "CardCode " → "cardcode__c" (nota lo spazio finale)
|
||||
Campo chiave: "CardCode"
|
||||
|
||||
Risultato: Non corrisponde
|
||||
```
|
||||
|
||||
**Soluzione**: Trim dei nomi campo durante la creazione del mapping.
|
||||
|
||||
## Logging Diagnostico Aggiunto
|
||||
|
||||
Ho aggiunto logging dettagliato per diagnosticare il problema:
|
||||
|
||||
```csharp
|
||||
Logger.LogDebug("MAPPING DEBUG: Tentativo di trovare mapping per sourceKeyField: '{SourceKeyField}'", sourceKeyField);
|
||||
Logger.LogDebug("MAPPING DEBUG: Mappings disponibili: {Mappings}",
|
||||
string.Join(", ", fieldMappings.Select(m => $"{m.Key} -> {m.Value}")));
|
||||
|
||||
if (fieldMappings.ContainsKey(sourceKeyField))
|
||||
{
|
||||
mappedDestinationField = fieldMappings[sourceKeyField];
|
||||
Logger.LogDebug("MAPPING DEBUG: Trovato mapping: '{SourceKeyField}' -> '{MappedField}'",
|
||||
sourceKeyField, mappedDestinationField);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("MAPPING DEBUG: Campo chiave '{SourceKeyField}' NON trovato nei mappings!",
|
||||
sourceKeyField);
|
||||
}
|
||||
```
|
||||
|
||||
## Procedura di Diagnosi
|
||||
|
||||
### Step 1: Abilitare Logging Debug
|
||||
|
||||
In `appsettings.Development.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Data_Coupler.Pages.DataCoupler": "Debug"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: Eseguire un Trasferimento Dati
|
||||
|
||||
1. Creare almeno un mapping che include il campo chiave
|
||||
2. Selezionare il campo chiave
|
||||
3. Eseguire il trasferimento
|
||||
4. Monitorare i log
|
||||
|
||||
### Step 3: Analizzare i Log
|
||||
|
||||
Cercare le righe `MAPPING DEBUG`:
|
||||
|
||||
#### Caso 1: Campo Trovato ✅
|
||||
```
|
||||
[Debug] MAPPING DEBUG: Tentativo di trovare mapping per sourceKeyField: 'CardCode'
|
||||
[Debug] MAPPING DEBUG: Mappings disponibili: CardCode -> cardcode__c, CardName -> Name
|
||||
[Debug] MAPPING DEBUG: Trovato mapping: 'CardCode' -> 'cardcode__c'
|
||||
[Info] COMPOSITE: Associazione creata con ID: 42 - MappedField: cardcode__c
|
||||
```
|
||||
|
||||
**Risultato**: `MappedDestinationField` dovrebbe essere popolato correttamente.
|
||||
|
||||
#### Caso 2: Campo Non Trovato ❌
|
||||
```
|
||||
[Debug] MAPPING DEBUG: Tentativo di trovare mapping per sourceKeyField: 'CardCode'
|
||||
[Debug] MAPPING DEBUG: Mappings disponibili: CardName -> Name, City -> BillingCity
|
||||
[Warning] MAPPING DEBUG: Campo chiave 'CardCode' NON trovato nei mappings!
|
||||
[Info] COMPOSITE: Associazione creata con ID: 42 - MappedField: N/A
|
||||
```
|
||||
|
||||
**Problema**: Il campo chiave non è stato mappato!
|
||||
|
||||
**Soluzione**: Creare un mapping per il campo chiave.
|
||||
|
||||
### Step 4: Verificare il Database
|
||||
|
||||
```sql
|
||||
-- Verifica le associazioni create
|
||||
SELECT
|
||||
Id,
|
||||
KeyValue,
|
||||
SourceKeyField,
|
||||
DestinationKeyField,
|
||||
MappedDestinationField,
|
||||
DestinationEntity,
|
||||
CreatedAt
|
||||
FROM KeyAssociations
|
||||
ORDER BY CreatedAt DESC
|
||||
LIMIT 10;
|
||||
```
|
||||
|
||||
**Cosa Cercare**:
|
||||
- `SourceKeyField`: Dovrebbe essere il nome del campo chiave (es. "CardCode")
|
||||
- `MappedDestinationField`:
|
||||
- Se NULL → il campo non era nei mappings
|
||||
- Se valorizzato → tutto OK
|
||||
|
||||
## Soluzione Temporanea
|
||||
|
||||
Se il problema persiste, puoi verificare manualmente nel database:
|
||||
|
||||
```sql
|
||||
-- Trova associazioni senza campo mappato
|
||||
SELECT COUNT(*)
|
||||
FROM KeyAssociations
|
||||
WHERE MappedDestinationField IS NULL;
|
||||
|
||||
-- Verifica un'associazione specifica
|
||||
SELECT
|
||||
KeyValue,
|
||||
SourceKeyField,
|
||||
MappedDestinationField,
|
||||
AdditionalInfo
|
||||
FROM KeyAssociations
|
||||
WHERE Id = [ID_ASSOCIAZIONE];
|
||||
```
|
||||
|
||||
## Test Case
|
||||
|
||||
Per testare la funzionalità:
|
||||
|
||||
### Test 1: Campo Mappato ✅
|
||||
|
||||
```
|
||||
1. Crea mapping: CardCode → cardcode__c
|
||||
2. Seleziona campo chiave: CardCode
|
||||
3. Esegui trasferimento
|
||||
4. Verifica: MappedDestinationField = "cardcode__c"
|
||||
```
|
||||
|
||||
### Test 2: Campo Non Mappato ❌
|
||||
|
||||
```
|
||||
1. Crea mapping: CardName → Name (NON mappare CardCode)
|
||||
2. Seleziona campo chiave: CardCode
|
||||
3. Esegui trasferimento
|
||||
4. Verifica: MappedDestinationField = NULL
|
||||
5. Log: "Campo chiave 'CardCode' NON trovato nei mappings!"
|
||||
```
|
||||
|
||||
### Test 3: Controllo Validazione
|
||||
|
||||
Il sistema dovrebbe impedire il trasferimento se il campo chiave non è mappato (controllo aggiunto precedentemente).
|
||||
|
||||
## Prossimi Passi
|
||||
|
||||
1. **Eseguire un test con logging abilitato**
|
||||
2. **Catturare i log durante il trasferimento**
|
||||
3. **Analizzare l'output del MAPPING DEBUG**
|
||||
4. **Determinare se il problema è**:
|
||||
- Campo non mappato (normale, warning utente)
|
||||
- Bug nel codice di lookup (da fixare)
|
||||
- Problema di encoding/spazi (sanitizzare input)
|
||||
|
||||
## File Modificati
|
||||
|
||||
- ✅ `Data_Coupler/Pages/DataCoupler.razor.cs` - Aggiunto logging diagnostico
|
||||
|
||||
## Status: 🔍 IN DIAGNOSI
|
||||
|
||||
Logging aggiunto, in attesa di eseguire test per identificare la causa esatta.
|
||||
Reference in New Issue
Block a user