Sync monthly contributions y allocation targets vía iCloud (CoreData)
Ambos vivían en UserDefaults (device-local, no sincroniza). Migrados a atributos CoreData en entidades ya syncable=YES, así que ahora sincronizan por CloudKit: - InvestmentSource.monthlyContribution (Decimal, opcional) - Category.allocationTarget (Double, opcional) Los stores mantienen su API por UUID (0 cambios en call sites) pero ahora leen/escriben del atributo CoreData vía fetch por id. migrateIfNeeded(context:) mueve una sola vez los valores del diccionario UserDefaults legacy al modelo y borra la clave; enganchado en CoreDataStack.loadPersistentStores junto a MonthlyCheckInStore. DashboardLayoutStore se mantiene en UserDefaults a propósito (preferencia de UI por dispositivo: el columnSpan solo aplica en iPad). NOTA: requiere desplegar el schema CloudKit a producción (CD_monthlyContribution, CD_allocationTarget) antes de que sincronice en TestFlight/App Store. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015qUZrBusG82T37R7PeokqJ
This commit is contained in:
@@ -14,6 +14,7 @@ public class Category: NSManagedObject, Identifiable {
|
||||
@NSManaged public var icon: String
|
||||
@NSManaged public var sortOrder: Int16
|
||||
@NSManaged public var createdAt: Date
|
||||
@NSManaged public var allocationTarget: NSNumber?
|
||||
@NSManaged public var sources: NSSet?
|
||||
|
||||
public override func awakeFromInsert() {
|
||||
|
||||
@@ -12,6 +12,7 @@ public class InvestmentSource: NSManagedObject, Identifiable {
|
||||
@NSManaged public var notificationFrequency: String
|
||||
@NSManaged public var customFrequencyMonths: Int16
|
||||
@NSManaged public var isActive: Bool
|
||||
@NSManaged public var monthlyContribution: NSDecimalNumber?
|
||||
@NSManaged public var createdAt: Date
|
||||
@NSManaged public var category: Category?
|
||||
@NSManaged public var account: Account?
|
||||
|
||||
+2
@@ -25,6 +25,7 @@
|
||||
<relationship name="sources" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="InvestmentSource" inverseName="account" inverseEntity="InvestmentSource"/>
|
||||
</entity>
|
||||
<entity name="Category" representedClassName="Category" syncable="YES">
|
||||
<attribute name="allocationTarget" optional="YES" attributeType="Double" usesScalarValueType="NO"/>
|
||||
<attribute name="colorHex" attributeType="String" defaultValueString="#3B82F6"/>
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="icon" attributeType="String" defaultValueString="chart.pie.fill"/>
|
||||
@@ -38,6 +39,7 @@
|
||||
<attribute name="customFrequencyMonths" attributeType="Integer 16" defaultValueString="1" usesScalarValueType="YES"/>
|
||||
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
|
||||
<attribute name="isActive" attributeType="Boolean" defaultValueString="YES" usesScalarValueType="YES"/>
|
||||
<attribute name="monthlyContribution" optional="YES" attributeType="Decimal"/>
|
||||
<attribute name="name" attributeType="String" defaultValueString=""/>
|
||||
<attribute name="notificationFrequency" attributeType="String" defaultValueString="monthly"/>
|
||||
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="sources" inverseEntity="Account"/>
|
||||
|
||||
@@ -187,6 +187,9 @@ class CoreDataStack: ObservableObject {
|
||||
DispatchQueue.main.async {
|
||||
self?.isLoaded = true
|
||||
MonthlyCheckInStore.migrateIfNeeded()
|
||||
// Migrate device-local UserDefaults data into Core Data so it syncs via iCloud.
|
||||
MonthlyContributionStore.migrateIfNeeded(context: container.viewContext)
|
||||
AllocationTargetStore.migrateIfNeeded(context: container.viewContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user