[Feature] Implementato sistema di valori default per campi mapping
- 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
This commit is contained in:
@@ -920,23 +920,80 @@
|
||||
<!-- Colonna Centrale: Controlli Mapping -->
|
||||
<div class="col-2 text-center">
|
||||
<div class="d-flex flex-column justify-content-center h-100">
|
||||
<button class="btn btn-success mb-2" @onclick="CreateMapping"
|
||||
disabled="@(string.IsNullOrEmpty(selectedDbColumn) || string.IsNullOrEmpty(selectedRestProperty))">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
<small class="d-block">Map</small>
|
||||
</button>
|
||||
<button class="btn btn-danger mb-2" @onclick="RemoveMapping"
|
||||
disabled="@(string.IsNullOrEmpty(selectedDbColumn) || !fieldMappings.ContainsKey(selectedDbColumn))">
|
||||
<i class="fas fa-times"></i>
|
||||
<small class="d-block">Remove</small>
|
||||
</button>
|
||||
<button class="btn btn-warning mb-2" @onclick="AutoMapFields">
|
||||
<i class="fas fa-magic"></i>
|
||||
<small class="d-block">Auto</small>
|
||||
</button>
|
||||
<!-- Toggle tra Mapping e Default Value -->
|
||||
<div class="btn-group mb-3" role="group">
|
||||
<button type="button"
|
||||
class="btn btn-sm @(isAddingDefaultValue ? "btn-outline-primary" : "btn-primary")"
|
||||
@onclick="@(() => isAddingDefaultValue = false)">
|
||||
<i class="fas fa-arrows-alt-h"></i>
|
||||
<small class="d-block">Mapping</small>
|
||||
</button>
|
||||
<button type="button"
|
||||
class="btn btn-sm @(isAddingDefaultValue ? "btn-warning" : "btn-outline-warning")"
|
||||
@onclick="@(() => isAddingDefaultValue = true)">
|
||||
<i class="fas fa-file-alt"></i>
|
||||
<small class="d-block">Default</small>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Controlli per Mapping Normale -->
|
||||
@if (!isAddingDefaultValue)
|
||||
{
|
||||
<button class="btn btn-success mb-2" @onclick="CreateMapping"
|
||||
disabled="@(string.IsNullOrEmpty(selectedDbColumn) || string.IsNullOrEmpty(selectedRestProperty))">
|
||||
<i class="fas fa-arrow-right"></i>
|
||||
<small class="d-block">Map</small>
|
||||
</button>
|
||||
<button class="btn btn-danger mb-2" @onclick="RemoveMapping"
|
||||
disabled="@(string.IsNullOrEmpty(selectedDbColumn) || !fieldMappings.ContainsKey(selectedDbColumn))">
|
||||
<i class="fas fa-times"></i>
|
||||
<small class="d-block">Remove</small>
|
||||
</button>
|
||||
<button class="btn btn-warning mb-2" @onclick="AutoMapFields">
|
||||
<i class="fas fa-magic"></i>
|
||||
<small class="d-block">Auto</small>
|
||||
</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<!-- Controlli per Default Value -->
|
||||
<div class="mb-2">
|
||||
<small class="text-muted d-block mb-1">Tipo Valore:</small>
|
||||
<select class="form-select form-select-sm mb-2" @bind="defaultValueType">
|
||||
<option value="string">String</option>
|
||||
<option value="int">Integer</option>
|
||||
<option value="decimal">Decimal</option>
|
||||
<option value="boolean">Boolean</option>
|
||||
<option value="datetime">DateTime</option>
|
||||
</select>
|
||||
<input type="text" class="form-control form-control-sm mb-2"
|
||||
placeholder="Valore default..."
|
||||
@bind="defaultValueInput" />
|
||||
<small class="text-muted d-block mb-2">
|
||||
@if (defaultValueType == "datetime")
|
||||
{
|
||||
<span>Es: @DateTime.Now.ToString("yyyy-MM-dd")</span>
|
||||
}
|
||||
else if (defaultValueType == "boolean")
|
||||
{
|
||||
<span>Es: true o false</span>
|
||||
}
|
||||
else if (defaultValueType == "decimal")
|
||||
{
|
||||
<span>Es: 100.50</span>
|
||||
}
|
||||
</small>
|
||||
</div>
|
||||
<button class="btn btn-warning mb-2" @onclick="CreateDefaultValue"
|
||||
disabled="@(string.IsNullOrEmpty(selectedRestProperty) || string.IsNullOrEmpty(defaultValueInput))">
|
||||
<i class="fas fa-check"></i>
|
||||
<small class="d-block">Set Default</small>
|
||||
</button>
|
||||
}
|
||||
|
||||
<button class="btn btn-secondary" @onclick="ClearAllMappings">
|
||||
<i class="fas fa-trash"></i>
|
||||
<small class="d-block">Clear</small>
|
||||
<small class="d-block">Clear All</small>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -965,6 +1022,10 @@
|
||||
{
|
||||
<span class="badge bg-success">Mapped</span>
|
||||
}
|
||||
@if (defaultValues.ContainsKey(property.Name))
|
||||
{
|
||||
<span class="badge bg-warning text-dark">Default</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@@ -1087,11 +1148,11 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Sezione Mappature Correnti --> @if (fieldMappings.Any())
|
||||
<!-- Sezione Mappature Correnti --> @if (fieldMappings.Any() || defaultValues.Any())
|
||||
{
|
||||
<div class="mt-4">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h6>Mappature Correnti (@fieldMappings.Count)</h6>
|
||||
<h6>Configurazione Mapping (@(fieldMappings.Count + defaultValues.Count) totali)</h6>
|
||||
@if (keyFields.Any())
|
||||
{
|
||||
<small class="text-info">
|
||||
@@ -1099,44 +1160,101 @@
|
||||
</small>
|
||||
}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Campo Database</th>
|
||||
<th>Tipo DB</th>
|
||||
<th>→</th>
|
||||
<th>Proprietà REST</th>
|
||||
<th>Tipo REST</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var mapping in fieldMappings)
|
||||
{
|
||||
DbColumnInfo? dbColumn = null;
|
||||
if (selectedSourceType == "database" && !string.IsNullOrEmpty(selectedTable))
|
||||
{
|
||||
dbColumn = databaseTables.ContainsKey(selectedTable) ?
|
||||
databaseTables[selectedTable].FirstOrDefault(c => c.Name == mapping.Key) : null;
|
||||
}
|
||||
var restProperty = restEntityDetails?.Properties.FirstOrDefault(p => p.Name == mapping.Value);
|
||||
<tr>
|
||||
<td><strong>@mapping.Key</strong></td>
|
||||
<td><small class="text-muted">@(dbColumn?.DataType ?? (selectedSourceType == "file" ? "Text" : "Unknown"))</small></td>
|
||||
<td><i class="fas fa-arrow-right text-success"></i></td>
|
||||
<td><strong>@mapping.Value</strong></td>
|
||||
<td><small class="text-muted">@(restProperty?.Type ?? "Unknown")</small></td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-danger" @onclick="@(() => RemoveSpecificMapping(mapping.Key))">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Tabella Mapping Campi -->
|
||||
@if (fieldMappings.Any())
|
||||
{
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-light">
|
||||
<i class="fas fa-arrows-alt-h"></i> <strong>Field Mappings</strong> (@fieldMappings.Count)
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Campo Sorgente</th>
|
||||
<th>Tipo Sorgente</th>
|
||||
<th>→</th>
|
||||
<th>Campo Destinazione</th>
|
||||
<th>Tipo Destinazione</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var mapping in fieldMappings)
|
||||
{
|
||||
DbColumnInfo? dbColumn = null;
|
||||
if (selectedSourceType == "database" && !string.IsNullOrEmpty(selectedTable))
|
||||
{
|
||||
dbColumn = databaseTables.ContainsKey(selectedTable) ?
|
||||
databaseTables[selectedTable].FirstOrDefault(c => c.Name == mapping.Key) : null;
|
||||
}
|
||||
var restProperty = restEntityDetails?.Properties.FirstOrDefault(p => p.Name == mapping.Value);
|
||||
<tr>
|
||||
<td><strong>@mapping.Key</strong></td>
|
||||
<td><small class="text-muted">@(dbColumn?.DataType ?? (selectedSourceType == "file" ? "Text" : "Unknown"))</small></td>
|
||||
<td><i class="fas fa-arrow-right text-success"></i></td>
|
||||
<td><strong>@mapping.Value</strong></td>
|
||||
<td><small class="text-muted">@(restProperty?.Type ?? "Unknown")</small></td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-danger" @onclick="@(() => RemoveSpecificMapping(mapping.Key))">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Tabella Default Values -->
|
||||
@if (defaultValues.Any())
|
||||
{
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-warning text-dark">
|
||||
<i class="fas fa-file-alt"></i> <strong>Default Values</strong> (@defaultValues.Count)
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Campo Destinazione</th>
|
||||
<th>Valore Default</th>
|
||||
<th>Tipo Valore</th>
|
||||
<th>Tipo Campo REST</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var defaultValue in defaultValues)
|
||||
{
|
||||
var restProperty = restEntityDetails?.Properties.FirstOrDefault(p => p.Name == defaultValue.Key);
|
||||
var (value, valueType) = defaultValue.Value;
|
||||
<tr>
|
||||
<td><strong>@defaultValue.Key</strong></td>
|
||||
<td><code>@(value?.ToString() ?? "null")</code></td>
|
||||
<td>
|
||||
<span class="badge bg-info">@valueType</span>
|
||||
</td>
|
||||
<td><small class="text-muted">@(restProperty?.Type ?? "Unknown")</small></td>
|
||||
<td>
|
||||
<button class="btn btn-sm btn-danger" @onclick="@(() => RemoveDefaultValue(defaultValue.Key))">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -1314,6 +1432,7 @@
|
||||
DestinationCredentialName="@selectedRestCredential"
|
||||
DestinationEndpoint="@selectedRestEntity?.Name"
|
||||
FieldMappings="@GetCurrentFieldMappings()"
|
||||
DefaultValues="@defaultValues"
|
||||
ExternalIdRelationships="@externalIdRelationships"
|
||||
SourceKeyField="@sourceKeyField"
|
||||
UseRecordAssociations="@useRecordAssociations"
|
||||
|
||||
@@ -51,10 +51,18 @@ public partial class DataCoupler : ComponentBase
|
||||
(int)Math.Ceiling((double)fileData[sheetName].Count / pageSize) : 0;
|
||||
|
||||
// Mapping campi
|
||||
private Dictionary<string, string> fieldMappings = new(); // DbColumn -> RestProperty
|
||||
private Dictionary<string, string> fieldMappings = new(); // DbColumn -> RestProperty (legacy)
|
||||
private List<FieldMappingEntry> fieldMappingEntries = new(); // New system: supporta sia mapping che default values
|
||||
private Dictionary<string, (object? Value, string? Type)> defaultValues = new(); // DestinationField -> (DefaultValue, Type)
|
||||
private HashSet<string> keyFields = new(); // REST properties marked as keys
|
||||
private string selectedDbColumn = "";
|
||||
|
||||
// UI per configurazione mapping/default value
|
||||
private bool isAddingDefaultValue = false; // Toggle tra mapping normale e default value
|
||||
private string defaultValueField = ""; // Campo destinazione per default value
|
||||
private string defaultValueInput = ""; // Input utente per default value
|
||||
private string defaultValueType = "string"; // Tipo del default value (string, int, decimal, boolean, datetime)
|
||||
|
||||
// External ID Relationships (Salesforce)
|
||||
private List<ExternalIdRelationshipDto> externalIdRelationships = new();
|
||||
private string selectedRelationshipObject = "";
|
||||
@@ -345,11 +353,13 @@ public partial class DataCoupler : ComponentBase
|
||||
|
||||
// Applica i mapping
|
||||
fieldMappings.Clear();
|
||||
fieldMappingEntries.Clear();
|
||||
keyFields.Clear();
|
||||
|
||||
foreach (var mapping in mappings)
|
||||
{
|
||||
fieldMappings[mapping.SourceField] = mapping.DestinationField;
|
||||
fieldMappingEntries.Add(FieldMappingEntry.CreateFieldMapping(mapping.SourceField, mapping.DestinationField));
|
||||
if (mapping.IsKey)
|
||||
{
|
||||
keyFields.Add(mapping.DestinationField);
|
||||
@@ -370,6 +380,42 @@ public partial class DataCoupler : ComponentBase
|
||||
{
|
||||
Logger.LogInformation("Nessun mapping campi da applicare");
|
||||
}
|
||||
|
||||
// Step 4.5: Applica default values se disponibili
|
||||
if (!string.IsNullOrEmpty(profile.DefaultValuesJson))
|
||||
{
|
||||
Logger.LogInformation("Step 4.5 - Applicazione default values...");
|
||||
try
|
||||
{
|
||||
var deserializedDefaults = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, DefaultValueDto>>(
|
||||
profile.DefaultValuesJson,
|
||||
new System.Text.Json.JsonSerializerOptions { PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase });
|
||||
|
||||
if (deserializedDefaults != null)
|
||||
{
|
||||
defaultValues.Clear();
|
||||
|
||||
foreach (var entry in deserializedDefaults)
|
||||
{
|
||||
defaultValues[entry.Key] = (entry.Value.Value, entry.Value.Type);
|
||||
fieldMappingEntries.Add(FieldMappingEntry.CreateDefaultValue(entry.Key, entry.Value.Value, entry.Value.Type));
|
||||
|
||||
Logger.LogInformation("Default value applicato: {Field} = {Value} ({Type})",
|
||||
entry.Key, entry.Value.Value, entry.Value.Type);
|
||||
}
|
||||
|
||||
Logger.LogInformation("Default values applicati - Totale: {Count}", defaultValues.Count);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning(ex, "Errore nel caricamento dei default values dal profilo");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation("Nessun default value da applicare");
|
||||
}
|
||||
|
||||
// Step 5: Applica configurazione chiave sorgente
|
||||
if (!string.IsNullOrEmpty(profile.SourceKeyField))
|
||||
@@ -721,6 +767,8 @@ public partial class DataCoupler : ComponentBase
|
||||
ResetSourceState();
|
||||
ResetDestinationState();
|
||||
fieldMappings.Clear();
|
||||
fieldMappingEntries.Clear();
|
||||
defaultValues.Clear();
|
||||
keyFields.Clear();
|
||||
externalIdRelationships.Clear(); // Reset relazioni
|
||||
transferResults.Clear();
|
||||
@@ -1328,6 +1376,17 @@ public partial class DataCoupler : ComponentBase
|
||||
// Crea il nuovo mapping
|
||||
fieldMappings[selectedDbColumn] = selectedRestProperty;
|
||||
|
||||
// Aggiorna anche la lista FieldMappingEntries
|
||||
var existingEntry = fieldMappingEntries.FirstOrDefault(e =>
|
||||
e.Type == CredentialManager.Models.MappingType.FieldMapping && e.SourceField == selectedDbColumn);
|
||||
|
||||
if (existingEntry != null)
|
||||
{
|
||||
fieldMappingEntries.Remove(existingEntry);
|
||||
}
|
||||
|
||||
fieldMappingEntries.Add(FieldMappingEntry.CreateFieldMapping(selectedDbColumn, selectedRestProperty));
|
||||
|
||||
Logger.LogInformation("Creato mapping: {DbColumn} -> {RestProperty}", selectedDbColumn, selectedRestProperty);
|
||||
|
||||
// Deseleziona i campi
|
||||
@@ -1335,14 +1394,108 @@ public partial class DataCoupler : ComponentBase
|
||||
selectedRestProperty = "";
|
||||
}
|
||||
|
||||
private void CreateDefaultValue()
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedRestProperty) || string.IsNullOrEmpty(defaultValueInput))
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
// Converti il valore nel tipo appropriato
|
||||
object? convertedValue = ConvertDefaultValue(defaultValueInput, defaultValueType);
|
||||
|
||||
// Rimuovi eventuale default value esistente per questo campo
|
||||
if (defaultValues.ContainsKey(selectedRestProperty))
|
||||
{
|
||||
defaultValues.Remove(selectedRestProperty);
|
||||
}
|
||||
|
||||
// Rimuovi anche dalla lista entries
|
||||
var existingEntry = fieldMappingEntries.FirstOrDefault(e =>
|
||||
e.Type == CredentialManager.Models.MappingType.DefaultValue && e.DestinationField == selectedRestProperty);
|
||||
|
||||
if (existingEntry != null)
|
||||
{
|
||||
fieldMappingEntries.Remove(existingEntry);
|
||||
}
|
||||
|
||||
// Aggiungi il nuovo default value
|
||||
defaultValues[selectedRestProperty] = (convertedValue, defaultValueType);
|
||||
fieldMappingEntries.Add(FieldMappingEntry.CreateDefaultValue(selectedRestProperty, convertedValue, defaultValueType));
|
||||
|
||||
Logger.LogInformation("Creato default value: {RestProperty} = {Value} ({Type})",
|
||||
selectedRestProperty, convertedValue, defaultValueType);
|
||||
|
||||
// Reset campi
|
||||
selectedRestProperty = "";
|
||||
defaultValueInput = "";
|
||||
isAddingDefaultValue = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Errore nella conversione del valore di default");
|
||||
transferMessage = $"Errore: {ex.Message}";
|
||||
transferMessageType = "error";
|
||||
}
|
||||
}
|
||||
|
||||
private object? ConvertDefaultValue(string input, string type)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
return null;
|
||||
|
||||
return type.ToLower() switch
|
||||
{
|
||||
"string" => input,
|
||||
"int" => int.Parse(input),
|
||||
"long" => long.Parse(input),
|
||||
"decimal" => decimal.Parse(input, System.Globalization.CultureInfo.InvariantCulture),
|
||||
"double" => double.Parse(input, System.Globalization.CultureInfo.InvariantCulture),
|
||||
"float" => float.Parse(input, System.Globalization.CultureInfo.InvariantCulture),
|
||||
"boolean" => bool.Parse(input),
|
||||
"datetime" => DateTime.Parse(input),
|
||||
"datetimeoffset" => DateTimeOffset.Parse(input),
|
||||
_ => input
|
||||
};
|
||||
}
|
||||
|
||||
private void RemoveMapping()
|
||||
{
|
||||
if (string.IsNullOrEmpty(selectedDbColumn) || !fieldMappings.ContainsKey(selectedDbColumn))
|
||||
return;
|
||||
|
||||
fieldMappings.Remove(selectedDbColumn);
|
||||
|
||||
// Rimuovi anche dalla lista entries
|
||||
var entry = fieldMappingEntries.FirstOrDefault(e =>
|
||||
e.Type == CredentialManager.Models.MappingType.FieldMapping && e.SourceField == selectedDbColumn);
|
||||
if (entry != null)
|
||||
{
|
||||
fieldMappingEntries.Remove(entry);
|
||||
}
|
||||
|
||||
Logger.LogInformation("Rimosso mapping per campo: {DbColumn}", selectedDbColumn);
|
||||
}
|
||||
|
||||
private void RemoveDefaultValue(string destinationField)
|
||||
{
|
||||
if (defaultValues.ContainsKey(destinationField))
|
||||
{
|
||||
defaultValues.Remove(destinationField);
|
||||
|
||||
// Rimuovi anche dalla lista entries
|
||||
var entry = fieldMappingEntries.FirstOrDefault(e =>
|
||||
e.Type == CredentialManager.Models.MappingType.DefaultValue && e.DestinationField == destinationField);
|
||||
if (entry != null)
|
||||
{
|
||||
fieldMappingEntries.Remove(entry);
|
||||
}
|
||||
|
||||
Logger.LogInformation("Rimosso default value per campo: {Field}", destinationField);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveSpecificMapping(string dbColumn)
|
||||
{
|
||||
if (fieldMappings.ContainsKey(dbColumn))
|
||||
@@ -1351,20 +1504,22 @@ public partial class DataCoupler : ComponentBase
|
||||
Logger.LogInformation("Rimosso mapping specifico per campo: {DbColumn}", dbColumn);
|
||||
}
|
||||
}
|
||||
Logger.LogInformation("Rimosso mapping specifico per campo: {DbColumn}", dbColumn);
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearAllMappings()
|
||||
{
|
||||
fieldMappings.Clear();
|
||||
fieldMappingEntries.Clear();
|
||||
defaultValues.Clear();
|
||||
selectedDbColumn = "";
|
||||
selectedRestProperty = "";
|
||||
sourceKeyField = "";
|
||||
transferMessage = "";
|
||||
transferMessageType = "";
|
||||
isAddingDefaultValue = false;
|
||||
defaultValueField = "";
|
||||
defaultValueInput = "";
|
||||
externalIdRelationships.Clear(); // Pulisce anche le relazioni
|
||||
Logger.LogInformation("Tutti i mapping e le configurazioni sono stati cancellati");
|
||||
Logger.LogInformation("Tutti i mapping, default values e le configurazioni sono stati cancellati");
|
||||
}
|
||||
|
||||
// External ID Relationships Methods
|
||||
@@ -2108,6 +2263,7 @@ public partial class DataCoupler : ComponentBase
|
||||
.Select(r => r.SourceField)
|
||||
.ToHashSet();
|
||||
|
||||
// STEP 1: Applica i mapping normali (campo sorgente -> campo destinazione)
|
||||
foreach (var mapping in fieldMappings)
|
||||
{
|
||||
string dbColumn = mapping.Key;
|
||||
@@ -2134,7 +2290,29 @@ public partial class DataCoupler : ComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiungi External ID Relationships (per Salesforce)
|
||||
// STEP 2: Applica i valori di default per i campi NON ancora popolati
|
||||
foreach (var defaultValue in defaultValues)
|
||||
{
|
||||
string destinationField = defaultValue.Key;
|
||||
var (value, valueType) = defaultValue.Value;
|
||||
|
||||
// Applica il default value solo se il campo non è già stato popolato dal mapping
|
||||
if (!restData.ContainsKey(destinationField))
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
restData[destinationField] = value;
|
||||
Logger.LogDebug("Applicato default value: {Field} = {Value} ({Type})",
|
||||
destinationField, value, valueType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogDebug("Campo {Field} già popolato da mapping, default value ignorato", destinationField);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP 3: Aggiungi External ID Relationships (per Salesforce)
|
||||
if (externalIdRelationships.Any())
|
||||
{
|
||||
foreach (var relationship in externalIdRelationships)
|
||||
@@ -2163,9 +2341,10 @@ public partial class DataCoupler : ComponentBase
|
||||
}
|
||||
}
|
||||
|
||||
Logger.LogDebug("Record trasformato: {DbColumns} → {RestProperties}",
|
||||
Logger.LogDebug("Record trasformato: {DbColumns} → {RestProperties} (inclusi {DefaultCount} default values)",
|
||||
string.Join(", ", dbRecord.Keys),
|
||||
string.Join(", ", restData.Keys));
|
||||
string.Join(", ", restData.Keys),
|
||||
defaultValues.Count(dv => restData.ContainsKey(dv.Key)));
|
||||
|
||||
return restData;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user