feat: Implementa sistema completo di gestione associazioni record

- Aggiunge modello RecordAssociation con migrazione database
- Implementa servizio CRUD completo per gestione associazioni
- Crea interfaccia utente avanzata per visualizzazione e gestione
- Aggiunge funzionalità di filtro, paginazione e ricerca
- Implementa azioni di massa (eliminazione, validazione, pulizia)
- Aggiunge esportazione CSV delle associazioni
- Integra validazione automatica degli ID destinazione
- Implementa logica upsert robusta con controllo validità associazioni
- Aggiunge selezione manuale chiavi per sorgenti non-database
- Migliora UI con statistiche, modali di conferma e feedback operazioni
- Refactoring completo logica trasferimento dati per utilizzare associazioni
This commit is contained in:
2025-06-28 02:22:46 +02:00
parent 51c61eabf7
commit 34b47a2bd4
9 changed files with 707 additions and 1 deletions
+64 -1
View File
@@ -1893,7 +1893,40 @@
if (existingAssociation != null && existingAssociation.IsActive)
{
// Prova ad aggiornare il record esistente
// VALIDAZIONE: Verifica se l'ID di destinazione esiste ancora nel sistema target
bool destinationExists = false;
try
{
// Usa il campo ID appropriato per cercare l'entità
var idField = GetEntityIdField(); // Potrebbe essere "DocEntry", "id", "Id", etc.
var searchKeys = new Dictionary<string, object> { { idField, existingAssociation.DestinationId } };
var foundEntities = await currentRestClient.FindEntitiesByKeysAsync(
selectedRestEntity.Name, searchKeys);
destinationExists = foundEntities != null && foundEntities.Any();
}
catch (Exception ex)
{
Logger.LogWarning(ex, "Errore nella verifica dell'esistenza dell'entità {EntityId} - assumo che non esista", existingAssociation.DestinationId);
destinationExists = false;
}
if (!destinationExists)
{
// L'ID di destinazione non esiste più - elimina l'associazione non valida
Logger.LogWarning("ID destinazione {DestinationId} non più valido per associazione {AssociationId} - eliminazione associazione",
existingAssociation.DestinationId, existingAssociation.Id);
await CredentialService.DeleteRecordAssociationAsync(existingAssociation.Id);
transferResult.Status = "error";
transferResult.Message = $"Associazione non valida eliminata (ID destinazione {existingAssociation.DestinationId} non esiste più) - creazione nuovo record";
// Procedi con la creazione di un nuovo record
goto CreateNewRecord;
}
// L'ID di destinazione esiste - procedi con l'aggiornamento
var updateResult = await currentRestClient.UpdateEntityAsync(
selectedRestEntity.Name, existingAssociation.DestinationId, restData);
@@ -2393,4 +2426,34 @@
selectedDatabase = "";
StateHasChanged();
}
/// <summary>
/// Ottiene il nome del campo ID per l'entità corrente
/// </summary>
private string GetEntityIdField()
{
// Fallback predefiniti in base al tipo di servizio/entità
if (selectedRestEntity?.Name != null)
{
// Per SAP B1, la maggior parte delle entità usa DocEntry
if (selectedRestEntity.Name.Contains("BusinessPartner") ||
selectedRestEntity.Name.Contains("Customer") ||
selectedRestEntity.Name.Contains("Vendor"))
{
return "CardCode";
}
if (selectedRestEntity.Name.Contains("Item") ||
selectedRestEntity.Name.Contains("Product"))
{
return "ItemCode";
}
}
// Usa campi ID comuni come fallback
var commonIdFields = new[] { "DocEntry", "Id", "ID", "id", "Key", "key", "Code", "code" };
// Per ora usa DocEntry come default per SAP B1
return "DocEntry";
}
}