diff --git a/PortfolioJournal/Models/CoreData/PortfolioJournal.xcdatamodeld/PortfolioJournal.xcdatamodel/contents b/PortfolioJournal/Models/CoreData/PortfolioJournal.xcdatamodeld/PortfolioJournal.xcdatamodel/contents index 1487447..1b72142 100644 --- a/PortfolioJournal/Models/CoreData/PortfolioJournal.xcdatamodeld/PortfolioJournal.xcdatamodel/contents +++ b/PortfolioJournal/Models/CoreData/PortfolioJournal.xcdatamodeld/PortfolioJournal.xcdatamodel/contents @@ -100,6 +100,7 @@ + diff --git a/PortfolioJournal/Models/CoreData/Snapshot+CoreDataClass.swift b/PortfolioJournal/Models/CoreData/Snapshot+CoreDataClass.swift index 9d39c26..2758719 100644 --- a/PortfolioJournal/Models/CoreData/Snapshot+CoreDataClass.swift +++ b/PortfolioJournal/Models/CoreData/Snapshot+CoreDataClass.swift @@ -18,6 +18,10 @@ public class Snapshot: NSManagedObject, Identifiable { @NSManaged public var value: NSDecimalNumber? @NSManaged public var contribution: NSDecimalNumber? @NSManaged public var notes: String? + /// True for auto-generated (interpolated) snapshots that fill a gap between two + /// real snapshots. Estimated snapshots are shown with a distinct marker and can + /// be removed in bulk. Defaults to false (model default) for all real snapshots. + @NSManaged public var isEstimated: Bool @objc public var createdAt: Date { get { safeValue(forKey: "createdAt", fallback: .distantPast) } set { setManagedValue(newValue, forKey: "createdAt") } diff --git a/PortfolioJournal/Repositories/AccountRepository.swift b/PortfolioJournal/Repositories/AccountRepository.swift index 396bbe9..5002017 100644 --- a/PortfolioJournal/Repositories/AccountRepository.swift +++ b/PortfolioJournal/Repositories/AccountRepository.swift @@ -96,9 +96,12 @@ class AccountRepository: ObservableObject { return existing } - // No accounts exist, create Default account + // No accounts exist, create Default account. + // Use a DETERMINISTIC id so every device creates the same CloudKit record + // instead of a per-device duplicate (root-cause fix for the dedup pile-up). let defaultCurrency = AppSettings.getOrCreate(in: context).currency let account = Account(context: context) + account.id = Account.defaultAccountStableID account.name = Account.defaultAccountName account.currency = defaultCurrency account.inputMode = InputMode.simple.rawValue diff --git a/PortfolioJournal/Repositories/CategoryRepository.swift b/PortfolioJournal/Repositories/CategoryRepository.swift index 5ee5db6..1435caf 100644 --- a/PortfolioJournal/Repositories/CategoryRepository.swift +++ b/PortfolioJournal/Repositories/CategoryRepository.swift @@ -109,6 +109,8 @@ class CategoryRepository: ObservableObject { } let category = Category(context: context) + // Deterministic id → same CloudKit record on every device (no duplicates). + category.id = Category.stableID(for: categoryData.name) category.name = categoryData.name category.colorHex = categoryData.colorHex category.icon = categoryData.icon diff --git a/PortfolioJournal/ViewModels/SettingsViewModel.swift b/PortfolioJournal/ViewModels/SettingsViewModel.swift index 4c62bc1..c172dbc 100644 --- a/PortfolioJournal/ViewModels/SettingsViewModel.swift +++ b/PortfolioJournal/ViewModels/SettingsViewModel.swift @@ -353,6 +353,7 @@ class SettingsViewModel: ObservableObject { if accountCount == 0 { let defaultCurrency = AppSettings.getOrCreate(in: context).currency let account = Account(context: context) + account.id = Account.defaultAccountStableID account.name = Account.defaultAccountName account.currency = defaultCurrency account.inputMode = InputMode.simple.rawValue