InvestmentTrackerApp/InvestmentTracker/Models/CoreData/InvestmentSource+CoreDataCl...

145 lines
4.1 KiB
Swift

import Foundation
import CoreData
@objc(InvestmentSource)
public class InvestmentSource: NSManagedObject, Identifiable {
@nonobjc public class func fetchRequest() -> NSFetchRequest<InvestmentSource> {
return NSFetchRequest<InvestmentSource>(entityName: "InvestmentSource")
}
@NSManaged public var id: UUID
@NSManaged public var name: String
@NSManaged public var notificationFrequency: String
@NSManaged public var customFrequencyMonths: Int16
@NSManaged public var isActive: Bool
@NSManaged public var createdAt: Date
@NSManaged public var category: Category?
@NSManaged public var snapshots: NSSet?
public override func awakeFromInsert() {
super.awakeFromInsert()
id = UUID()
createdAt = Date()
isActive = true
notificationFrequency = NotificationFrequency.monthly.rawValue
customFrequencyMonths = 1
name = ""
}
}
// MARK: - Notification Frequency
enum NotificationFrequency: String, CaseIterable, Identifiable {
case monthly = "monthly"
case quarterly = "quarterly"
case semiannual = "semiannual"
case annual = "annual"
case custom = "custom"
case never = "never"
var id: String { rawValue }
var displayName: String {
switch self {
case .monthly: return "Monthly"
case .quarterly: return "Quarterly"
case .semiannual: return "Semi-Annual"
case .annual: return "Annual"
case .custom: return "Custom"
case .never: return "Never"
}
}
var months: Int {
switch self {
case .monthly: return 1
case .quarterly: return 3
case .semiannual: return 6
case .annual: return 12
case .custom, .never: return 0
}
}
}
// MARK: - Computed Properties
extension InvestmentSource {
var snapshotsArray: [Snapshot] {
let set = snapshots as? Set<Snapshot> ?? []
return set.sorted { $0.date > $1.date }
}
var sortedSnapshotsByDateAscending: [Snapshot] {
let set = snapshots as? Set<Snapshot> ?? []
return set.sorted { $0.date < $1.date }
}
var latestSnapshot: Snapshot? {
snapshotsArray.first
}
var latestValue: Decimal {
latestSnapshot?.value?.decimalValue ?? Decimal.zero
}
var snapshotCount: Int {
snapshots?.count ?? 0
}
var frequency: NotificationFrequency {
NotificationFrequency(rawValue: notificationFrequency) ?? .monthly
}
var nextReminderDate: Date? {
guard frequency != .never else { return nil }
let months = frequency == .custom ? Int(customFrequencyMonths) : frequency.months
guard let lastSnapshot = latestSnapshot else {
return Date() // Remind now if no snapshots
}
return Calendar.current.date(byAdding: .month, value: months, to: lastSnapshot.date)
}
var needsUpdate: Bool {
guard let nextDate = nextReminderDate else { return false }
return Date() >= nextDate
}
// MARK: - Performance Metrics
var totalReturn: Decimal {
guard let first = sortedSnapshotsByDateAscending.first,
let last = snapshotsArray.first,
let firstValue = first.value?.decimalValue,
firstValue != Decimal.zero else {
return Decimal.zero
}
let lastValue = last.value?.decimalValue ?? Decimal.zero
return ((lastValue - firstValue) / firstValue) * 100
}
var totalContributions: Decimal {
snapshotsArray.reduce(Decimal.zero) { result, snapshot in
result + (snapshot.contribution?.decimalValue ?? Decimal.zero)
}
}
}
// MARK: - Generated accessors for snapshots
extension InvestmentSource {
@objc(addSnapshotsObject:)
@NSManaged public func addToSnapshots(_ value: Snapshot)
@objc(removeSnapshotsObject:)
@NSManaged public func removeFromSnapshots(_ value: Snapshot)
@objc(addSnapshots:)
@NSManaged public func addToSnapshots(_ values: NSSet)
@objc(removeSnapshots:)
@NSManaged public func removeFromSnapshots(_ values: NSSet)
}