This commit is contained in:
Joyce
2026-02-06 08:36:40 -05:00
parent b1b92b445b
commit 8ea2987e3e
6 changed files with 271 additions and 220 deletions

View File

@@ -4,6 +4,7 @@ from uuid import UUID
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.config import settings
from app.models import BusyBlock, Participant
@@ -70,37 +71,41 @@ async def calculate_availability(
participants = {p.id: p for p in participants_result.scalars().all()}
days = ["Mon", "Tue", "Wed", "Thu", "Fri"]
hours = list(range(0, 24))
slot_interval = settings.slot_interval_minutes
slots_per_hour = 60 // slot_interval
slots = []
for day_offset, day_name in enumerate(days):
for hour in hours:
slot_start = week_start + timedelta(days=day_offset, hours=hour)
slot_end = slot_start + timedelta(hours=1)
for hour in range(24):
for slot_idx in range(slots_per_hour):
minute = slot_idx * slot_interval
slot_start = week_start + timedelta(days=day_offset, hours=hour, minutes=minute)
slot_end = slot_start + timedelta(minutes=slot_interval)
available_participants = []
for pid in participant_ids:
if is_participant_free(busy_map.get(pid, []), slot_start, slot_end):
participant = participants.get(pid)
if participant:
available_participants.append(participant.name)
available_participants = []
for pid in participant_ids:
if is_participant_free(busy_map.get(pid, []), slot_start, slot_end):
participant = participants.get(pid)
if participant:
available_participants.append(participant.name)
total = len(participant_ids)
available_count = len(available_participants)
total = len(participant_ids)
available_count = len(available_participants)
if available_count == total:
availability = "full"
elif available_count > 0:
availability = "partial"
else:
availability = "none"
if available_count == total:
availability = "full"
elif available_count > 0:
availability = "partial"
else:
availability = "none"
slots.append({
"day": slot_start.strftime("%Y-%m-%d"),
"hour": hour,
"start_time": slot_start,
"availability": availability,
"availableParticipants": available_participants,
})
slots.append({
"day": slot_start.strftime("%Y-%m-%d"),
"hour": hour,
"minute": minute,
"start_time": slot_start,
"availability": availability,
"availableParticipants": available_participants,
})
return slots

View File

@@ -5,6 +5,7 @@ class Settings(BaseSettings):
database_url: str = "postgresql+asyncpg://postgres:postgres@db:5432/availability"
sync_database_url: str = "postgresql://postgres:postgres@db:5432/availability"
ics_refresh_interval_minutes: int = 15
slot_interval_minutes: int = 15 # Time slot granularity (15, 30, or 60)
# SMTP Settings
smtp_host: str | None = None

View File

@@ -61,7 +61,8 @@ def send_zulip_notification(
f"📅 **Meeting Scheduled**\n"
f"**What:** {title}\n"
f"**When:** {zulip_time}\n"
f"**Who:** {people}"
f"**Who:** {people}\n"
f"*Booked via [Meetly](https://meetly.app.monadical.io/)*"
)
request = {