--- description: "Implement the EF Core entity classes and enums for Account, AccountYear, Entry, TransferLink, and EntryType" agent: "agent" --- # Step 2: Domain Model Implement the domain entities under `src/Duempelkas.Domain`. ## Entities ### Account (`Entities/Account.cs`) - `int Id` (PK) - `string Name` (required, max 200) - `DateTime CreatedUtc` - `ICollection AccountYears` (navigation) ### AccountYear (`Entities/AccountYear.cs`) - `int Id` (PK) - `int AccountId` (FK → Account) - `int Year` (e.g. 2026) - `decimal OpeningBalance` — explicit carryover from the previous year, user-entered - `DateTime CreatedUtc` - `Account Account` (navigation) - `ICollection Entries` (navigation) Constraint: unique on `(AccountId, Year)`. ### Entry (`Entities/Entry.cs`) - `int Id` (PK) - `int AccountYearId` (FK → AccountYear) - `EntryType Type` — Income or Expense - `DateTime Date` - `string Title` (required, max 500) - `decimal Amount` — always positive; sign determined by Type - `int? TransferLinkId` (FK → TransferLink, nullable) - `DateTime CreatedUtc` - `AccountYear AccountYear` (navigation) - `TransferLink? TransferLink` (navigation) ### TransferLink (`Entities/TransferLink.cs`) - `int Id` (PK) - `int SourceEntryId` (FK → Entry, unique) - `int TargetEntryId` (FK → Entry, unique) - `string? Note` - `DateTime CreatedUtc` - `Entry SourceEntry` (navigation) - `Entry TargetEntry` (navigation) Invariants enforced at service level: - SourceEntry.Type must be Expense - TargetEntry.Type must be Income - Both share the same Amount and Date ### EntryType (`Enums/EntryType.cs`) ```csharp public enum EntryType { Income = 0, Expense = 1 } ``` ## Conventions - Use `decimal` for all monetary amounts. - Store amounts as positive; behaviour (add/subtract) comes from `EntryType`. - File-scoped namespaces, nullable enabled.