6 Commits

Author SHA1 Message Date
e4b45763b4 Phase 1: Schema and models for shared calendars
Migrations 047-051:
- 047: Add is_shared to calendars
- 048: Create calendar_members table (permissions, status, constraints)
- 049: Create event_locks table (5min TTL, permanent owner locks)
- 050: Expand notification CHECK (calendar_invite types)
- 051: Add updated_by to calendar_events + updated_at index

New models: CalendarMember, EventLock
Updated models: Calendar (is_shared, members), CalendarEvent (updated_by),
  Notification (3 new types)
New schemas: shared_calendar.py (invite, respond, member, lock, sync)
Updated schemas: calendar.py (is_shared, sharing response fields)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 03:22:44 +08:00
e7cb6de7d5 Add admin delete-user with full cascade cleanup
Migration 036 adds ondelete rules to 5 transitive FKs that would
otherwise block user deletion (calendar_events via calendars,
project_tasks via projects, todos via projects, etc.).

DELETE /api/admin/users/{user_id} with self-action guard, last-admin
guard, session revocation, and audit logging. Frontend gets a red
two-click confirm button in the IAM actions menu.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 19:20:47 +08:00
d89758fedf Add materialized recurring events backend
- Migration 007: parent_event_id (self-ref FK CASCADE), is_recurring, original_start columns on calendar_events
- CalendarEvent model: three new Mapped[] columns for recurrence tracking
- RecurrenceRule Pydantic model: typed schema for every_n_days, weekly, monthly_nth_weekday, monthly_date
- CalendarEventCreate/Update: accept structured RecurrenceRule (router serializes to JSON string for DB)
- CalendarEventUpdate: edit_scope field (this | this_and_future)
- CalendarEventResponse: exposes parent_event_id, is_recurring, original_start
- recurrence.py service: generates unsaved child ORM objects from parent rule up to 365-day horizon
- GET /: excludes parent template rows (children are displayed instead)
- POST /: creates parent + bulk children when recurrence_rule provided
- PUT /: scope=this detaches occurrence; scope=this_and_future deletes future siblings and regenerates
- DELETE /: scope=this deletes one; scope=this_and_future deletes future siblings; no scope deletes all (CASCADE)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:37:21 +08:00
093bceed06 Add multi-calendar backend support with virtual birthday events
- New Calendar model and calendars table with system/default flags
- Alembic migration 006: creates calendars, seeds Personal+Birthdays, migrates existing events
- CalendarEvent model gains calendar_id FK and calendar_name/calendar_color properties
- Updated CalendarEventCreate/Response schemas to include calendar fields
- New /api/calendars CRUD router (blocks system calendar deletion/rename)
- Events router: selectinload on all queries, default-calendar assignment on POST, virtual birthday event generation from People with birthdays when Birthdays calendar is visible

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 19:07:35 +08:00
ca8b654471 Dashboard Phase 2: weather widget, starred events, quick add, thinner events
- Add weather router with OpenWeatherMap integration and 1-hour cache
- Add is_starred column to calendar events with countdown widget
- Add weather_city setting with Settings page input
- Replace people/locations stats with open todos count + weather card
- Add quick-add dropdown (event/todo/reminder) to dashboard header
- Make CalendarWidget events single-line thin rows
- Add rain warnings to smart briefing when chance > 40%
- Invalidate dashboard/upcoming queries on form mutations
- Migration 004: is_starred + weather_city columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:15:43 +08:00
1f6519635f Initial commit 2026-02-15 16:13:41 +08:00