Commit Graph

175 Commits

Author SHA1 Message Date
Ulas Kalayci 761408ae7c fix: correct housekeeping module bugs after merge
- Restore migration order: remove spurious v30 birthday-reminders entry
  inserted before CardDAV (v30) and birthday-reminders (v31), which caused
  a duplicate v31 on fresh installs
- Restore birthdayReminderAt() offsetMin handling (regression from merge)
- Fix check-in INSERT: check_out was set to checkIn instead of NULL,
  making sessions invisible to loadOpenSession (IS NULL query)
- Implement check-out path in toggleSession() — only check-in was reachable
- Wrap GET /task-templates in try/catch per project convention
- Fix DELETE response envelopes: { ok: true } → { data: ... }
- Remove housekeeping worker exclusion from GET /auth/users
- Replace toISOString() with local-date helper to avoid UTC date shift
- Use user currency preference in money() instead of hardcoded BRL
- Replace hardcoded #7C3AED fallbacks in style attrs with CSS token
- Add German translations for documents folder and settings housekeeping keys
- Remove DESIGN.md and IMPLEMENTATION.md (AI planning artifacts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-08 20:18:26 +02:00
Rafael Foster 22ec13e559 feat: add housekeeping module for household staff management
* Adding flexible reminder options to birthdays

* Fix database migration merge conflict

* Truncate calendar popup descriptions

* Log app version on backend startup

* Add host-mounted data and backup folders

* feat: add housekeeping module

* fix: align housekeeping UI and add task creation

* refactor: rebuild housekeeping experience

* feat: support multiple housekeeping staff

* feat: integrate housekeeping visits with calendar

* feat: refine housekeeping visits and payments

* feat: add housekeeping staff visit logs

* feat: add housekeeping receipts and document folders

* feat: localize housekeeping folders and chores

* feat: refine housekeeping tabs and document folders

* fix: sync housekeeping tab active state

* feat: use configured app name in onboarding and manifest
2026-05-08 20:14:51 +02:00
Ulas Kalayci 2a48fb7af0 feat: multi-person assignment for tasks and calendar events
- DB migration v32: task_assignments and event_assignments join tables
  with CASCADE delete; existing assigned_to data migrated automatically
- Tasks API: accepts assigned_to as array, returns assigned_users[]
  with json_group_array; filter uses EXISTS on task_assignments
- Calendar API: same pattern via event_assignments; serializeEvent
  includes assigned_users array
- Recurring task completion copies all assignments to the new instance
- Frontend: shared UserMultiSelect component with avatar stack display
  (renderAvatarStack, renderUserMultiSelect, getSelectedUserIds,
  bindUserMultiSelect); tasks.js and calendar.js use it in modals
  and card/agenda views
- CSS: user-multi-select.css with avatar-stack and user-ms classes
- 14 new tests covering CRUD, JSON aggregation, EXISTS filter,
  and CASCADE behavior for both task and event assignments

Closes #125
2026-05-06 10:04:41 +02:00
Ulas Kalayci b545d83f64 fix: modal onClose callback, calendar popup truncation, datetime validation
- modal.js: add onClose callback to openModal(), fix _initialFormTimeout
  cleanup, deduplicate escape/overlay-click handlers in confirmModal,
  promptModal, selectModal using the new callback
- calendar.js: replace popup.innerHTML with insertAdjacentHTML (constraint),
  add truncateDescription() to cap long event descriptions at 500 chars
- validate.js: extend DATETIME_RE to cover ISO 8601 with ms/timezone,
  normalise datetime values to YYYY-MM-DDTHH:MM on input
- index.js: include app version in startup log message
- docker-compose.yml / .env.example: switch from named volume to
  host-mounted DATA_DIR/BACKUP_DIR with sane defaults
- docs/installation.md: document host-mount data paths

Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-06 07:00:07 +02:00
Ulas Kalayci 82a1f2c239 feat: add flexible reminder options for birthdays
Add support for customizable birthday reminders with preset offsets
(none, at time, 15min, 1h, 1d, 2d, 1w, 2w) and custom intervals.
Users can now configure when to be reminded of upcoming birthdays.

- Add migration 31: reminder_offset, reminder_custom_amount, reminder_custom_unit to birthdays table
- Update POST/PUT /birthdays routes to accept reminder fields
- Add getOffsetMinutes() helper in birthday service
- Update birthdayReminderAt() to calculate reminder time with offset
- Modify syncBirthdayReminder() to handle empty offset (no reminder)
- Add renderBirthdayReminderSection() UI component
- Move reminder-custom CSS from calendar.css to reminders.css
- Add protocol check to service worker (non-http protocol guard)

All translations already present in de.json.
Tests: 109 passing, 0 failing.

Co-Authored-By: Rafael Foster <rafaelfoster@users.noreply.github.com>
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 20:31:42 +02:00
Ulas Kalayci 9c4f876c5b Merge branch 'feature/cardav-contacts'
# Conflicts:
#	package-lock.json
2026-05-04 19:10:13 +02:00
Ulas Kalayci 8891097c7b feat(server): mount CardDAV router at /api/v1/contacts/cardav
Import and mount cardavRouter with requireAuth middleware. All
CardDAV management routes now accessible under /api/v1/contacts/cardav.

Router mounted BEFORE contacts router to ensure /api/v1/contacts/cardav
paths match before /api/v1/contacts.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 18:37:56 +02:00
Ulas Kalayci d0eb63840f docs(openapi): add CardDAV routes and update contacts routes
Document 8 CardDAV management routes (accounts, addressbooks, sync)
and update 3 existing contacts routes to reflect multi-value field
support.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 18:37:05 +02:00
Ulas Kalayci 0dc303b81a feat(contacts): add multi-value fields support to PUT /contacts/:id
Extend PUT /contacts/:id route to support updating phones, emails, and
addresses arrays with replacement semantics. Uses atomic transactions
to DELETE all existing multi-values then INSERT new ones. Validates
all multi-value fields before updating. Response includes full contact
with multi-value fields via loadMultiValueFields() helper.

Backward compatible: multi-value fields only replaced when present in
request body. Scalar fields (name, category, etc.) continue to work
independently.

Tests added:
- Update with multi-value fields (replacement semantics verified)
- Validation error on invalid phone data (400)
- Backward compatibility: update without multi-values preserves them

All 109 tests pass.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 18:31:01 +02:00
Ulas Kalayci 966a6d46e3 feat(contacts): add POST /contacts with multi-value fields
Implements Task 12: Extend POST /contacts to accept and persist phones,
emails, and addresses arrays. Uses atomic transactions to ensure all
related records are created together or rolled back on error.

- Validation: validatePhones/Emails/Addresses before insert
- Transaction: db.transaction() for atomic Contact + Multi-Values
- Backward compatible: Multi-value fields are optional
- Refactoring: Extracted loadMultiValueFields() helper (DRY)
- Response includes all multi-value fields with generated IDs

Tests: 3 new tests (create with multi-values, validation, backward compat)
TDD workflow: RED → GREEN → REFACTOR → Commit

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 18:25:18 +02:00
Ulas Kalayci fe8af33568 feat(contacts): add GET /contacts/:id with multi-value fields
Implements Task 11: Extend GET /contacts/:id to include phones, emails,
and addresses arrays. Each multi-value field is queried from its respective
table (contact_phones, contact_emails, contact_addresses) and mapped to
camelCase response format with isPrimary boolean conversion.

Tests: 2 new tests (contact with multi-values, empty arrays)
TDD workflow: RED → GREEN → Commit

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 18:18:07 +02:00
Ulas Kalayci 674fe796b3 feat(cardav): implement POST /accounts/:id/sync endpoint
Adds route to sync all enabled addressbooks for an account with mock support for tests.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:54:03 +02:00
Ulas Kalayci 9ec7fda6b0 feat(cardav): implement PUT /addressbooks/:id endpoint
Adds route to toggle addressbook enabled/disabled state with bool validation.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:47:26 +02:00
Ulas Kalayci 362f711290 feat(validate): add bool validator
Add boolean field validator for use in CardDAV addressbook toggle
route and other boolean validation needs.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:13:54 +02:00
Ulas Kalayci c078a48884 feat(cardav): implement POST /accounts/:id/addressbooks/refresh endpoint
Add addressbook refresh route. Loads account from DB, delegates to
CardDAVSync.discoverAddressbooks() to run PROPFIND, then returns
updated addressbook list from DB.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:13:14 +02:00
Ulas Kalayci 12e8edf4c3 feat(cardav): implement GET /accounts/:id/addressbooks endpoint
Add addressbook listing route. Queries carddav_addressbook_selection
table directly, ordered by name. Returns empty array if account has
no addressbooks.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:11:53 +02:00
Ulas Kalayci dd5ac8812c feat(cardav): implement POST /accounts/:id/test endpoint
Add connection test route. Loads account from DB and delegates to
CardDAVSync.testConnection() to verify credentials and discover
addressbooks without saving.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:10:25 +02:00
Ulas Kalayci ca92cb2a86 feat(cardav): implement DELETE /accounts/:id endpoint
Add account deletion route with ID validation. Delegates to
CardDAVSync.deleteAccount() which cascades to addressbooks and
contacts via foreign key constraints.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 17:04:39 +02:00
Ulas Kalayci f7eb73b835 feat(cardav): implement POST /accounts endpoint
Add account creation route with validation. Delegates to
CardDAVSync.addAccount() which creates account and discovers
addressbooks. Returns 201 with account + addressbooks array.

Add _mockTestConnection() helper for testing CardDAV routes without
real server connections.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 16:54:52 +02:00
Ulas Kalayci 930800eed9 fix(cardav): improve router security and test coverage
- Remove error message leakage (return generic 'Interner Fehler')
- Remove unused imports (str, collectErrors, MAX_TITLE, MAX_URL)
- Add _resetTestDatabase() for proper test cleanup
- Add test for populated accounts case with shape validation
- Import 'after' from node:test for proper teardown

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 16:51:21 +02:00
Ulas Kalayci cf68bff25f feat(cardav): create cardav router with GET /accounts
Add CardDAV API router with GET /accounts endpoint. Returns all
CardDAV accounts from database via cardav-sync service. Added test
infrastructure with _setTestDatabase helper for isolated API testing.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-04 16:47:24 +02:00
Copilot 21c85fd418 fix: remap apple external_source during CalDAV migration
Fixes #119

Moves apple→caldav conversion into table rebuild to avoid CHECK constraint violation during migration to v0.44.0.
2026-05-04 16:38:07 +02:00
Ulas Kalayci a71547562e feat(contacts): add multi-value array validators
Add validatePhones, validateEmails, validateAddresses for CardDAV
multi-value contact fields. Validates array structure, required
fields, type checks, and max lengths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 13:01:22 +02:00
Ulas Kalayci c4b8b76221 Fix critical database issues in CardDAV sync service
Issue #1: Wrapped DELETE + INSERT operations in updateContactMultiValues in transaction to prevent inconsistent state if INSERT fails after DELETE.

Issue #2: Replaced N+1 query pattern with batch INSERT statements using VALUES list for phones, emails, and addresses. Also optimized primary entry check queries to use SELECT 1 instead of COUNT(*).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 11:45:07 +02:00
Ulas Kalayci 689b479b2d Implement CardDAV sync service with account and contact management
- Add server/services/cardav-sync.js with full CardDAV functionality
- Implement account management (add, delete, list, test connection)
- Implement addressbook discovery and selection toggle
- Add vCard parser with support for all standard fields (FN, N, TEL, EMAIL, ADR, ORG, TITLE, URL, BDAY, PHOTO, NICKNAME, NOTE, CATEGORIES)
- Implement smart merge logic for contact deduplication (UID match, email/phone match)
- Handle multi-value fields (phones, emails, addresses) with primary flag preservation
- Add comprehensive tests for vCard parsing and database operations
- All 46 tests passing

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 11:34:25 +02:00
Ulas Kalayci 3f77fdb11d Fix Migration 30 code quality issues
C1 (CRITICAL): Refactor test-carddav.js to import migrations
- Import MIGRATIONS from server/db.js instead of duplicating SQL
- Export MIGRATIONS array from server/db.js
- Use better-sqlite3 to apply Migration 30 dynamically
- Ensures future changes to Migration 30 are reflected in tests

I1 (IMPORTANT): Add UNIQUE index on carddav_uid
- Create idx_contacts_carddav_uid_unique partial index
- Prevents duplicate CardDAV contacts per account+addressbook
- WHERE clause excludes NULL values (manual contacts allowed)
- Add test to verify unique constraint enforcement

I3 (IMPORTANT): Rename cardav → carddav (RFC 6352 compliance)
- Table: cardav_accounts → carddav_accounts
- Table: cardav_addressbook_selection → carddav_addressbook_selection
- Column: contacts.cardav_* → contacts.carddav_*
- Index: idx_cardav_* → idx_carddav_*
- Test file: test-cardav.js → test-carddav.js
- Package.json: test:cardav → test:carddav
- All test assertions updated

All 25 tests pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 10:55:30 +02:00
Ulas Kalayci 18310dbfe5 feat(cardav): add Migration 30 for CardDAV contacts schema
Add comprehensive database schema for CardDAV multi-account contacts sync:

New tables:
- cardav_accounts: Store CardDAV server credentials
- cardav_addressbook_selection: Per-account addressbook enable/disable
- contact_phones: Multiple phone numbers per contact with labels
- contact_emails: Multiple email addresses per contact with labels
- contact_addresses: Multiple postal addresses per contact with labels

Extended contacts table with 9 new columns:
- organization, job_title, birthday, website, photo, nickname
- cardav_account_id (FK to cardav_accounts, ON DELETE SET NULL)
- cardav_uid (vCard UID from server)
- cardav_addressbook_url (source addressbook URL)

Features:
- UNIQUE constraints on (cardav_url, username) and (account_id, addressbook_url)
- CASCADE delete for addressbook selection and contact sub-tables
- Performance indices for cardav_uid and email lookups
- Support for manual contacts (NULL cardav_account_id)
- is_primary flag for phone/email/address selection

Test coverage:
- 23 comprehensive tests verify all tables, constraints, indices
- FK CASCADE delete behavior validated
- UNIQUE constraints enforced
- Data integrity scenarios tested

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 10:47:16 +02:00
Ulas Kalayci c5a9799983 feat(caldav): add calendar selection, sync, and API routes
- Add getCalendars() and updateCalendarSelection() to caldav-sync.js
- Add sync() function for bidirectional CalDAV synchronization
- Add getStatus() to report on all accounts and enabled calendars
- Add 8 new API routes to calendar.js for CalDAV account and calendar management
- All routes require admin role for security

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 08:32:46 +02:00
Ulas Kalayci 01ccf715e5 feat(caldav): add account management functions (add, list, update, delete) 2026-05-04 08:20:17 +02:00
Ulas Kalayci 59773bd797 feat(caldav): implement account CRUD operations
Add createAccount, updateAccount, deleteAccount functions with validation, error handling, and logging. Implements Task 3 from the CalDAV multi-account spec.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 08:00:49 +02:00
Ulas Kalayci 7b91fa5136 Fix caldav-sync.js imports to match Task 2 spec
Remove buildICS, escapeICS, unescapeICS imports - these will be
needed in Task 5 (Sync Functions), not in Task 2. Keep only the
4 functions specified in the Task 2 spec: parseICS, formatICSDate,
tzLocalToUTC, applyDuration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 07:56:57 +02:00
Ulas Kalayci a159a57e9c feat(caldav): add caldav-sync service base structure with helpers
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 07:53:39 +02:00
Ulas Kalayci 4eb7e852fd feat: add DB migration for CalDAV multi-account support
- caldav_accounts table for account credentials
- caldav_calendar_selection table for calendar selection
- Migrate Apple CalDAV data to caldav tables
- Add target_caldav_* columns to calendar_events
- Update external_source CHECK to include 'caldav'
- Update external_calendars.source CHECK to include 'caldav'
- Enhance migration runner to support function-based migrations

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 07:42:57 +02:00
Ulas Kalayci 9b29d1847c feat: automatische geplante Backups mit Rotation
Phase 1.3 - Automatische Backups:
- Cron-basierter Scheduler (Standard: täglich 2 Uhr)
- Konfigurierbar über .env (Zeitplan, Verzeichnis, Anzahl)
- Automatische Rotation: behält nur letzte N Backups (Standard: 7)
- UI in Settings → Backup: Status-Anzeige und manueller Trigger
- Tests: 7 erfolgreiche Tests für Scheduler-Funktionalität

Neue Umgebungsvariablen:
- BACKUP_ENABLED (Standard: true)
- BACKUP_SCHEDULE (Standard: 0 2 * * *)
- BACKUP_DIR (Standard: ./backups)
- BACKUP_KEEP (Standard: 7)
- TZ (für Zeitzone)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 07:02:38 +02:00
Ulas Kalayci 99a2280c02 chore: release v0.42.0
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-04 06:52:35 +02:00
Ulas Kalayci f3dbbb37d7 fix: preserve dmy=DD.MM.YYYY, add dmy_slash for DD/MM/YYYY
The PR changed dmy from dots to slashes, breaking existing users.
Revert dmy to dots (backward compat), add dmy_slash for DD/MM/YYYY.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-01 15:28:18 +02:00
Rafael Foster f5377bd2f1 Improve dashboard widget sizing controls 2026-05-01 09:05:20 -03:00
Rafael Foster 9c5f8c9a99 Add dashboard widget customization 2026-05-01 08:53:25 -03:00
Rafael Foster e34ba33f9b Refine loan tab filtering and date formats 2026-05-01 08:24:39 -03:00
Rafael Foster 79f55cbfbc Improve loan dashboard interactions 2026-05-01 08:09:12 -03:00
Rafael Foster 977bee8a3a Separate budget and loan views 2026-05-01 07:52:43 -03:00
Rafael Foster ce107c80a4 Add budget loan tracking 2026-04-30 23:12:38 -03:00
Ulas Kalayci e59a9818a9 fix(i18n): add time format translations to all 13 missing locales
Also translate server error message to English and remove stale
comment from calendar.js catch block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 19:54:12 +02:00
Rafael Foster 8c9a5c6aa2 feat(settings): add time format preference 2026-04-30 13:48:35 -03:00
Ulas Kalayci 4a050e92a8 chore: release v0.38.2
Fix recurring events with FREQ=WEEKLY;INTERVAL=N;BYDAY ignoring the
interval when crossing a week boundary (e.g. Friday → Monday).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-30 10:51:01 +02:00
Rafael Foster 4aa9bc2a48 fix(calendar): tighten modal and attachment rendering 2026-04-29 22:44:25 -03:00
Rafael Foster 6e177bb8c4 docs(api): document family documents endpoints 2026-04-29 18:07:18 -03:00
Rafael Foster 0cbd93e4e0 feat(settings): add database backup management 2026-04-29 14:04:04 -03:00
Rafael Foster d9218a4941 feat(calendar): add overlapping layout and event attachments 2026-04-29 08:53:07 -03:00
Rafael Foster 72fca92066 feat(documents): add family document management 2026-04-29 06:14:29 -03:00