Categories Management
Relevant source files
The following files were used as context for generating this wiki page:
- Features/CategoriesFeature/Sources/CategoriesFeature/Views/CategoryList/CategoryListView.swift
- Features/CategoriesFeature/Sources/CategoriesFeature/Views/CategoryDetail/CategoryDetailView.swift
- Features/CategoriesFeature/Sources/CategoriesFeature/Views/SimplifiedCategoryList/SimplifiedCategoryListView.swift
- Trackurr/Dependencies/Persistence/Migration/SchemaV8.swift
- Trackurr/Dependencies/Persistence/Migration/AppMigrationPlan.swift
- Trackurr/Dependencies/Persistence/Store/DataExportServiceImpl.swift
- Features/CategoriesFeature/Tests/CategoriesFeatureTests/Views/CategoryForm/CategoryFormViewModelTests.swift
- TrackurrTests/Persistence/Stores/CategoryStoreTests.swift
- Packages/Domain/Tests/DomainTests/CategoryTests.swift
Categories Management in Trackurr is a core system responsible for organizing recurring subscriptions and providing financial insights. It differentiates between predefined System Categories (e.g., Finance, Entertainment) and user-created Custom Categories. This module handles the persistence, visualization of spending per category, and the critical separation of local and CloudKit-synced data.
Sources: README.md:16, Features/CategoriesFeature/Sources/CategoriesFeature/Views/CategoryList/CategoryListView.swift:51-125
Data Architecture and Models
The persistence layer uses SwiftData with a versioned schema. Starting with Schema V8, the system separates system-defined entities from user-generated ones to optimize CloudKit synchronization.
Entity Types
- Category (Custom): User-created categories. These are synced via CloudKit and have a direct relationship with subscriptions.
- SystemCategory: Local-only entities seeded from JSON. They are not synced to CloudKit to prevent duplication across devices.
- Subscription References: Subscriptions link to custom categories via a standard SwiftData
@Relationshipand to system categories via a stablesystemCategoryIdstring.
Sources: Trackurr/Dependencies/Persistence/Migration/SchemaV8.swift:14-40, Trackurr/Dependencies/Persistence/Migration/SchemaV8.swift:85-110
Relationship Schema
The following diagram illustrates how subscriptions associate with different category types within the persistence layer.
This structure ensures that even if a system category is deleted/re-seeded, the subscription's link remains stable via the systemId.
Sources: Trackurr/Dependencies/Persistence/Migration/SchemaV8.swift:34-45
Management Logic and Validation
Categories are managed through the CategoryFormViewModel, which enforces specific business rules during creation and editing.
Validation Rules
| Rule | Constraint | Implementation Detail |
|---|---|---|
| Name Length | Max 30 characters | Enforced in isNameValid property. |
| Empty Names | Disallowed | Trims whitespace; empty or whitespace-only is invalid. |
| System Category Editing | Restricted | Name is immutable for system categories; only icon and color can be changed. |
| Premium Access | Entitlement required | Custom category creation is restricted to users with the customCategories entitlement. |
Sources: Features/CategoriesFeature/Tests/CategoriesFeatureTests/Views/CategoryForm/CategoryFormViewModelTests.swift:65-115, Features/CategoriesFeature/Sources/CategoriesFeature/Views/CategoryList/CategoryListView.swift:150-160
User Interface and Interaction
The system provides multiple ways to view and interact with categories, ranging from high-level lists to detailed spending breakdowns.
Category List Views
Trackurr implements two primary list types:
- CategoryListView: A detailed management view showing spending totals and subscription counts. It supports sorting by name, spending amount, or subscription count.
- SimplifiedCategoryListView: A flexible view offering both a standard List mode and a Cards (Grid) mode, often used for selection or quick overviews.
Sources: Features/CategoriesFeature/Sources/CategoriesFeature/Views/CategoryList/CategoryListView.swift:14-48, Features/CategoriesFeature/Sources/CategoriesFeature/Views/SimplifiedCategoryList/SimplifiedCategoryListView.swift:15-38
Category Detail and Analytics
The CategoryDetailView aggregates financial data for a specific category. It calculates the Monthly Total by converting all associated active subscriptions into the user's base currency.
Data Migration and Portability
Schema V7 to V8 Migration
A critical architectural shift occurred in the V7 to V8 migration. The system moved from a unified category table to separate entities to accommodate CloudKit's requirements and avoid system data collision.
Migration Steps:
- Fetch all existing subscriptions.
- Identify those linked to system categories via name matching (e.g., "Finance").
- Update
systemCategoryIdon the subscription and nullify the old relationship. - Delete old system category records from the CloudKit-synced
Categorytable.
Sources: Trackurr/Dependencies/Persistence/Migration/AppMigrationPlan.swift:65-105
Export and Import
The DataExportServiceImpl ensures data portability. During export, only Custom Categories are included in the JSON backup, as system categories are re-seeded automatically on the new installation. During import, the service performs deduplication by checking both ID and name to prevent duplicate entries.
Sources: Trackurr/Dependencies/Persistence/Store/DataExportServiceImpl.swift:24-40, Trackurr/Dependencies/Persistence/Store/DataExportServiceImpl.swift:103-115
Summary
Categories Management provides the organizational backbone of the application. By utilizing a hybrid model of local system entities and synced custom entities, Trackurr maintains a consistent user experience across devices while allowing for personal customization. The integration of currency conversion and billing cycle normalization allows this module to provide accurate, real-time financial insights within the category detail and list views.