Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
Extract events/calendar functionality into standalone microservice: - app.py and events_api.py from apps/events/ - Calendar blueprints (calendars, calendar, calendar_entries, calendar_entry, day, slots, slot, ticket_types, ticket_type) - Templates for all calendar/event views including admin - Dockerfile (APP_MODULE=app:app, IMAGE=events) - entrypoint.sh (no Alembic - migrations managed by blog app) - Gitea CI workflow for build and deploy Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
116 lines
3.7 KiB
Python
116 lines
3.7 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from sqlalchemy import select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from models.calendars import CalendarEntry
|
|
|
|
|
|
@dataclass
|
|
class VisibleEntries:
|
|
"""
|
|
Result of applying calendar visibility rules for a given period.
|
|
"""
|
|
user_entries: list[CalendarEntry]
|
|
confirmed_entries: list[CalendarEntry]
|
|
admin_other_entries: list[CalendarEntry]
|
|
merged_entries: list[CalendarEntry] # sorted, deduped
|
|
|
|
|
|
async def get_visible_entries_for_period(
|
|
sess: AsyncSession,
|
|
calendar_id: int,
|
|
period_start: datetime,
|
|
period_end: datetime,
|
|
user: Optional[object],
|
|
session_id: Optional[str],
|
|
) -> VisibleEntries:
|
|
"""
|
|
Visibility rules (same as your fixed month view):
|
|
|
|
- Non-admin:
|
|
- sees all *confirmed* entries in the period (any user)
|
|
- sees all entries for current user/session in the period (any state)
|
|
- Admin:
|
|
- sees all confirmed + provisional + ordered entries in the period (all users)
|
|
- sees pending only for current user/session
|
|
"""
|
|
|
|
user_id = user.id if user else None
|
|
is_admin = bool(user and getattr(user, "is_admin", False))
|
|
|
|
# --- Entries for current user/session (any state, in period) ---
|
|
user_entries: list[CalendarEntry] = []
|
|
if user_id or session_id:
|
|
conditions_user = [
|
|
CalendarEntry.calendar_id == calendar_id,
|
|
CalendarEntry.deleted_at.is_(None),
|
|
CalendarEntry.start_at >= period_start,
|
|
CalendarEntry.start_at < period_end,
|
|
]
|
|
if user_id:
|
|
conditions_user.append(CalendarEntry.user_id == user_id)
|
|
elif session_id:
|
|
conditions_user.append(CalendarEntry.session_id == session_id)
|
|
|
|
result_user = await sess.execute(select(CalendarEntry).where(*conditions_user))
|
|
user_entries = result_user.scalars().all()
|
|
|
|
# --- Confirmed entries for everyone in period ---
|
|
result_conf = await sess.execute(
|
|
select(CalendarEntry).where(
|
|
CalendarEntry.calendar_id == calendar_id,
|
|
CalendarEntry.state == "confirmed",
|
|
CalendarEntry.deleted_at.is_(None),
|
|
CalendarEntry.start_at >= period_start,
|
|
CalendarEntry.start_at < period_end,
|
|
)
|
|
)
|
|
confirmed_entries = result_conf.scalars().all()
|
|
|
|
# --- For admins: ordered + provisional for everyone in period ---
|
|
admin_other_entries: list[CalendarEntry] = []
|
|
if is_admin:
|
|
result_admin = await sess.execute(
|
|
select(CalendarEntry).where(
|
|
CalendarEntry.calendar_id == calendar_id,
|
|
CalendarEntry.state.in_(("ordered", "provisional")),
|
|
CalendarEntry.deleted_at.is_(None),
|
|
CalendarEntry.start_at >= period_start,
|
|
CalendarEntry.start_at < period_end,
|
|
)
|
|
)
|
|
admin_other_entries = result_admin.scalars().all()
|
|
|
|
# --- Merge with de-duplication and keep chronological order ---
|
|
entries_by_id: dict[int, CalendarEntry] = {}
|
|
|
|
# Everyone's confirmed
|
|
for e in confirmed_entries:
|
|
entries_by_id[e.id] = e
|
|
|
|
# Admin-only: everyone's ordered/provisional
|
|
if is_admin:
|
|
for e in admin_other_entries:
|
|
entries_by_id[e.id] = e
|
|
|
|
# Always include current user/session entries (includes their pending)
|
|
for e in user_entries:
|
|
entries_by_id[e.id] = e
|
|
|
|
merged_entries = sorted(
|
|
entries_by_id.values(),
|
|
key=lambda e: e.start_at or period_start,
|
|
)
|
|
|
|
return VisibleEntries(
|
|
user_entries=user_entries,
|
|
confirmed_entries=confirmed_entries,
|
|
admin_other_entries=admin_other_entries,
|
|
merged_entries=merged_entries,
|
|
)
|