4 Commits

Author SHA1 Message Date
david aa8f7af55d feat: implement offline sync endpoints with Last-Write-Wins strategy
Add comprehensive offline synchronization support for habits and entries:

## Infrastructure (Phase 1)
- Add UpdatedAt and DeletedAt timestamps to Habit and HabitEntry entities
- Implement soft delete with Delete(), Touch(), and IsDeleted() methods
- Create SQL migration with optimized composite indexes for sync queries
- Add GetChangesSince() and SoftDelete() to both repositories
- Update all Find* methods to exclude soft-deleted records
- 13 comprehensive TDD tests for sync repository methods

## HTTP Endpoints (Phase 2)
- GET /api/v1/sync/changes: retrieve all changes since timestamp
- POST /api/v1/sync/batch: apply client changes with conflict resolution
- Implement Last-Write-Wins strategy using UpdatedAt timestamps
- Add authentication and rate limiting (100 req/min)
- Validate user ownership for all sync operations
- 9 tests for sync handlers (3 queries + 6 commands)

## Technical Details
- Composite indexes: (user_id, updated_at) for optimal query performance
- No pagination: atomic sync operations for data consistency
- Upsert behavior: create resources if not found on server
- DTOs with full entity state including timestamps
- Swagger documentation updated for new endpoints

All 220+ tests passing ✓
2025-12-12 00:11:46 +01:00
david 10d45fc34e Add COUNTER type with auto-increment and IsNegative field
COUNTER type:
- Only accepts integer values (rejects decimals)
- Auto-increment behavior: each mark adds to existing value
- Supports decrement via negative values (e.g., -2)
- Enforces minimum value of 0 (never negative)
- Default increment is 1 if no value provided

VALUE type:
- Accepts decimal values
- Replaces value (no auto-increment)

IsNegative field:
- New boolean field on Habit entity
- Persisted in database (is_negative column)
- Available in all DTOs and HTTP responses
- Marks habits as "negative" (e.g., candy consumption)

Examples:
- COUNTER: 5 + (-2) = 3, 2 + (-3) = 0, 0 + (-1) = 0
- VALUE: 5000 → 12000 = 12000 (replacement)
2025-11-27 08:58:39 +01:00
david e87b7df979 Rename project to apocapoc-api
Update module name and all imports from habit-tracker-api to apocapoc-api.
This reflects the project's new branding as part of the apocapoc ecosystem
(apocapoc-api, apocapoc-web, apocapoc-android).
2025-11-26 11:21:17 +01:00
david 64bfe80806 Implement domain layer (TDD - Green phase)
Implementation to make all tests pass:

Value Objects:
- HabitType: BOOLEAN, COUNTER, VALUE with validation
- Frequency: DAILY, WEEKLY, MONTHLY with validation

Entities:
- User: email, password hash, timezone with defaults
- Habit: tracking habits with type, frequency, carry-over
- HabitEntry: recording habit completions with soft delete

Repositories (interfaces):
- UserRepository: CRUD operations for users
- HabitRepository: CRUD operations for habits
- HabitEntryRepository: CRUD operations for entries

Shared:
- Common error definitions for domain layer

All domain tests now pass.
2025-11-25 10:13:08 +01:00