Skip to content

Task domain model and data layer #120

Description

@MessiasLima

Description

Replace the placeholder Task data class and stub repository with a full Room entity that also serves as the domain model, plus the complete data layer (DAO, database migration, CRUD repository).

The current Task is a stub with only id: String. The repository (TaskRepository) only has findTodaysTasks() returning emptyList(). The database is at version 1 with fallbackToDestructiveMigration(false), so this change requires an explicit migration from version 1 to 2.

This ticket creates the foundation that all Phase 1 task features depend on — without it, no task screen, no list, no interactions are possible.

  • Scope and constraints

    • In scope: Task entity/domain model, TaskDao, database migration (v1 → v2), TaskRepositoryImpl with CRUD + reactive queries, Koin wiring, unit tests
    • Out of scope: UI, ViewModel, screen navigation, cloud sync, separate domain model or mappers
  • References

    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/domain/Task.kt — placeholder to be removed
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/data/task/TaskRepository.kt — current stub interface
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/data/task/TaskRepositoryImpl.kt — current stub implementation
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/database/FoliaryDatabase.kt — database at version 1
    • foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/database/DatabaseModule.kt — Koin DI for database and DAOs

Scope

In scope: Task entity (acts as domain model), TaskDao, migration from DB v1 to v2, TaskRepositoryImpl with full CRUD and reactive queries, Koin module wiring, unit tests. Out of scope: any UI, ViewModel, or screen work. No separate domain layer or mappers.

Acceptance criteria

  • Task entity defined as a Room @entity data class with fields: id (String @PrimaryKey), title (String), description (String?), dueDate (Instant?), creationDate (Instant), completionDate (Instant?), priority (Priority enum: LOW, MEDIUM, HIGH), url (String?), latitude (Double?), longitude (Double?)
  • Priority enum defined with Room @TypeConverter for persistence
  • Type converters registered for Instant serialization
  • TaskDao provides: insert, update, delete, getById, getTodaysTasks (Flow), getByDueDate (Flow)
  • FoliaryDatabase updated to version 2, TaskEntity and TaskDao registered, migration v1→v2 defined
  • FoliaryDatabaseConstructor updated to reflect new schema
  • TaskRepository interface expanded with CRUD + reactive query methods, using the entity directly (no separate domain model)
  • TaskRepositoryImpl implements all repository methods, annotated with @single and @OPEN
  • Koin module provides TaskDao via database.taskDao() and scans TaskRepositoryImpl via ComponentScan
  • Placeholder domain/Task.kt removed
  • Unit tests for TaskRepositoryImpl cover: create, read, update, delete, find tasks by today, find tasks by due date

Additional information

Follow existing project conventions: room3 imports, @Entity/@Dao/@database annotations, data class with val properties, @Single/@OPEN on repository, entity in data/task/model/ package, DAO in data/task/ package. Use DaoTest base class for DAO tests. Use Kotest assertions (shouldBe, shouldHaveSize). Use kotlinx.datetime.Instant for all date/time fields — no LocalDate since we use pure Kotlin classes. No hardcoded strings in UI (not applicable here since this ticket is data-layer only).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions