feat: Implementato sistema di associazioni chiave per prevenire duplicati nel data coupling

BREAKING CHANGE: Rimosso completamente il vecchio sistema RecordAssociation

Modifiche principali:
- Sostituito RecordAssociation con KeyAssociation basato sui valori delle chiavi
- Implementata logica robusta di UPDATE vs INSERT basata su associazioni esistenti
- Aggiunta normalizzazione delle chiavi (.Trim()) per consistenza
- Implementato fallback nella ricerca associazioni per maggiore affidabilità
- Sostituita verifica pre-UPDATE con tentativo diretto più efficiente

Componenti modificati:
- Nuovo modello: KeyAssociation.cs con campi ottimizzati
- Nuovo servizio: KeyAssociationService.cs con metodi completi
- Aggiornato: DataCoupler.razor con logica migliorata di gestione associazioni
- Aggiornato: CredentialDbContext per gestire solo KeyAssociations
- Aggiornati: tutti i servizi di interfaccia per supportare il nuovo sistema
- Creata: pagina KeyAssociations.razor per gestione associazioni
- Aggiornato: NavMenu.razor con link alla gestione associazioni

Miglioramenti tecnici:
- Logica di UPDATE più robusta: tenta direttamente l'aggiornamento invece di verificare prima l'esistenza
- Gestione errori migliorata con cleanup automatico delle associazioni non valide
- Debug logging estensivo per troubleshooting
- Fallback nella ricerca associazioni se parametri specifici falliscono
- Normalizzazione valori chiave per prevenire problemi di whitespace

Risultato:
Il sistema ora previene correttamente i duplicati utilizzando le associazioni per decidere
se fare INSERT (nuovo record) o UPDATE (record esistente) basandosi sui valori delle chiavi.

Database:
- Creata migrazione EF per rimuovere RecordAssociations e aggiungere KeyAssociations
- Eliminati file e codice legacy non più necessari
This commit is contained in:
2025-06-29 20:44:20 +02:00
parent 2238ddc4bf
commit 04f0403f12
23 changed files with 2051 additions and 1161 deletions
@@ -1,4 +1,5 @@
using CredentialManager.Models;
using CredentialManager.Services;
namespace DataConnection.CredentialManagement.Interfaces;
@@ -57,17 +58,20 @@ public interface IDataConnectionCredentialService
Task<(bool Success, string Message)> TestSalesforceConnectionAsync(string credentialName);
Task<(bool Success, string Message)> TestSalesforceConnectionAsync(SalesforceCredential credential);
// Record associations
Task<int> SaveRecordAssociationAsync(RecordAssociation association);
Task<RecordAssociation?> FindRecordAssociationAsync(string sourceName, string sourceKey, string destinationEntity);
Task<List<RecordAssociation>> GetRecordAssociationsBySourceAsync(string sourceName, string sourceType);
Task<List<RecordAssociation>> GetRecordAssociationsByDestinationAsync(string destinationEntity, string restCredentialName);
Task<List<RecordAssociation>> GetAllActiveRecordAssociationsAsync();
Task<bool> UpdateRecordAssociationAsync(RecordAssociation association);
Task<bool> DeactivateRecordAssociationAsync(int id);
Task<bool> DeleteRecordAssociationAsync(int id);
Task<int> ClearRecordAssociationsAsync(string sourceName, string destinationEntity, string restCredentialName);
Task<int> ClearAllRecordAssociationsAsync();
Task<List<RecordAssociation>> GetInvalidRecordAssociationsAsync(string destinationEntity, string restCredentialName);
Task<int> CleanupInvalidRecordAssociationsAsync(string destinationEntity, string restCredentialName);
// Key associations
Task<int> SaveKeyAssociationAsync(KeyAssociation association);
Task<KeyAssociation?> FindKeyAssociationByValueAsync(string keyValue, string destinationEntity, string restCredentialName);
Task<KeyAssociation?> FindKeyAssociationByValueAsync(string keyValue);
Task<List<KeyAssociation>> GetKeyAssociationsByDestinationAsync(string destinationEntity, string restCredentialName);
Task<List<KeyAssociation>> GetAllActiveKeyAssociationsAsync();
Task<List<KeyAssociation>> GetAllKeyAssociationsAsync();
Task<bool> UpdateKeyAssociationAsync(KeyAssociation association);
Task<bool> DeactivateKeyAssociationAsync(int id);
Task<bool> DeleteKeyAssociationAsync(int id);
Task<int> ClearKeyAssociationsAsync(string destinationEntity, string restCredentialName);
Task<int> ClearAllKeyAssociationsAsync();
Task<List<KeyAssociation>> GetInvalidKeyAssociationsAsync(string destinationEntity, string restCredentialName);
Task<int> CleanupInvalidKeyAssociationsAsync(string destinationEntity, string restCredentialName);
Task<bool> UpdateKeyAssociationLastVerifiedAsync(int id);
Task<AssociationStatistics> GetKeyAssociationStatisticsAsync();
}