Desactiva auto-dedup (pérdida de datos cross-device) + forward-fill en gráficas de evolution
CRÍTICO: el auto-dedup de build 68 borraba entidades padre con regla Cascade (Account/Category). Al propagarse el delete por CloudKit, otros dispositivos aplicaban la cascada al importar ANTES de la reasignación de hijos → wipe de sources/snapshots. Vació iPhone y iPad. Quitadas las llamadas automáticas a cleanupLogicalDuplicates() en processRemoteChanges y en la carga; el UUID-dedup seguro se mantiene. Métodos quedan definidos para un rediseño CloudKit-safe. Gráficas: forward-fill por source en evolution/allocation/period para que el total de cada mes refleje el último valor de CADA source (no solo las actualizadas ese mes) y el último punto coincida con el total del portfolio. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L2p3gUZRNWW388rWFRjiU7
This commit is contained in:
@@ -213,11 +213,12 @@ class CoreDataStack: ObservableObject {
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
self?.isLoaded = true
|
||||
// Collapse any logical duplicates already sitting in the local store
|
||||
// (per-device default accounts/categories piled up by earlier syncs).
|
||||
// Runs once at launch so an existing mess is cleaned even if no new
|
||||
// remote change arrives this session.
|
||||
self?.cleanupLogicalDuplicates()
|
||||
// NOTE: automatic logical dedup DISABLED. Deleting cascade-parent
|
||||
// entities (Account/Category) and letting those deletes propagate via
|
||||
// CloudKit can trigger the Cascade delete rule on OTHER devices before
|
||||
// the child-reassignment transaction imports — cascade-wiping sources
|
||||
// and snapshots. This caused total data loss across devices on build 68.
|
||||
// Dedup must be redesigned to be CloudKit-safe before re-enabling.
|
||||
MonthlyCheckInStore.migrateIfNeeded()
|
||||
// Migrate device-local UserDefaults data into Core Data so it syncs via iCloud.
|
||||
MonthlyContributionStore.migrateIfNeeded(context: container.viewContext)
|
||||
@@ -506,14 +507,9 @@ class CoreDataStack: ObservableObject {
|
||||
if removed > 0 {
|
||||
print("[RemoteChanges] Removed \(removed) duplicate objects after CloudKit import")
|
||||
}
|
||||
// Then collapse *logical* duplicates (same entity, different UUIDs) —
|
||||
// e.g. per-device default accounts/categories, or a dataset that was
|
||||
// seeded independently in two environments. UUID dedup above can't see
|
||||
// these because the UUIDs differ.
|
||||
let logical = self.cleanupLogicalDuplicates()
|
||||
if logical > 0 {
|
||||
print("[RemoteChanges] Removed \(logical) logical duplicate objects after CloudKit import")
|
||||
}
|
||||
// NOTE: automatic logical dedup DISABLED here on purpose — see the load
|
||||
// block. Deleting cascade-parent entities and propagating those deletes
|
||||
// via CloudKit cascade-wiped children on other devices (build 68 incident).
|
||||
// Notify repositories to re-fetch unconditionally.
|
||||
NotificationCenter.default.post(name: .cloudKitForceReload, object: nil)
|
||||
self.objectWillChange.send()
|
||||
|
||||
Reference in New Issue
Block a user