Add "Dubletten zusammenfuehren" (merge duplicates) per profile
Neuer Button "Dubletten" im Hauptfenster fuehrt doppelte Kontakte fuer das ausgewaehlte Profil zusammen - je Seite (Telefonanlage + Outlook) getrennt. - Matching in ContactMatcher extrahiert (Sync UND Dedupe nutzen exakt dieselbe Erkennung). - ContactMerger.FillEmptyInto / FilledFieldCount: leere Felder des Gewinners auffuellen (kein Datenverlust), Gewinner-Wahl nach Zuordnung/Vollstaendigkeit. - DedupeService: Analyse (Vorschau) + Ausfuehrung (Merge, Loeschen der Dubletten, Bereinigen verwaister Zuordnungen). - SyncCoordinator.RunExclusiveAsync: Dedupe laeuft unter demselben Guard + Lock-Datei wie ein Sync (nie gleichzeitig; kein Konflikt zwischen Clients). - DedupeForm: Vorschau mit optionaler Detailliste, Bestaetigung, Live-Log; danach Hinweis, einmal zu synchronisieren. - MainForm: Button "Dubletten" (Profil-Auswahl noetig), Fenster verbreitert. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -46,6 +46,34 @@ namespace StarfaceOutlookSync.Services
|
||||
new FieldDef { Key = "Birthday", Label = "Geburtstag", Get = c => c.Birthday, Set = (c, v) => c.Birthday = v },
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Fuellt LEERE Felder von target aus den sources auf (erste nicht-leere
|
||||
/// Quelle gewinnt). Vorhandene Werte von target bleiben unveraendert -
|
||||
/// kein Datenverlust. Gibt true zurueck, wenn sich etwas geaendert hat.
|
||||
/// </summary>
|
||||
public static bool FillEmptyInto(UnifiedContact target, IEnumerable<UnifiedContact> sources)
|
||||
{
|
||||
bool changed = false;
|
||||
var list = sources?.ToList() ?? new List<UnifiedContact>();
|
||||
foreach (var f in Fields)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(f.Get(target))) continue;
|
||||
foreach (var s in list)
|
||||
{
|
||||
var v = f.Get(s);
|
||||
if (!string.IsNullOrEmpty(v)) { f.Set(target, v); changed = true; break; }
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/// <summary>Anzahl gefuellter Inhaltsfelder - fuer die Wahl des "Gewinners".</summary>
|
||||
public static int FilledFieldCount(UnifiedContact c)
|
||||
{
|
||||
if (c == null) return 0;
|
||||
return Fields.Count(f => !string.IsNullOrEmpty(f.Get(c)));
|
||||
}
|
||||
|
||||
/// <summary>Liest den Wert eines Feldes per stabilem Schluessel.</summary>
|
||||
public static string GetValue(UnifiedContact c, string key)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user