1.6.0 foundation: dedup prevención completa + atributo isEstimated
Dedup prevención: UUIDs estables (StableID v5) asignados al default Account y a las categorías por defecto en createDefaultAccountIfNeeded, ensureDefaultCategoriesExist, createDefaultCategories y el reset de SettingsViewModel → CloudKit fusiona nativamente, no más acumulación de duplicados. isEstimated: nuevo atributo Bool opcional (default NO, syncable) en Snapshot para marcar snapshots interpolados del auto-relleno. Requiere deploy de schema CloudKit antes del release. Compila verde (verificado antes de que el agente de widgets empezara a editar). 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:
+1
@@ -100,6 +100,7 @@
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="date" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
|
||||
<attribute name="isEstimated" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="notes" optional="YES" attributeType="String"/>
|
||||
<attribute name="value" optional="YES" attributeType="Decimal"/>
|
||||
<relationship name="source" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="InvestmentSource" inverseName="snapshots" inverseEntity="InvestmentSource"/>
|
||||
|
||||
@@ -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") }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user