perf: batch scheduling reconciliation and add widget
This commit is contained in:
@@ -7,7 +7,8 @@ from datetime import datetime, timedelta, timezone
|
||||
from functools import lru_cache
|
||||
from typing import Any, cast
|
||||
|
||||
from sqlalchemy.orm import Session, object_session
|
||||
from sqlalchemy import func, or_
|
||||
from sqlalchemy.orm import Session, object_session, selectinload
|
||||
|
||||
from govoplan_core.core.calendar import (
|
||||
CalendarCapabilityError,
|
||||
@@ -1303,11 +1304,34 @@ def create_scheduling_request(
|
||||
return request, {}
|
||||
|
||||
|
||||
def list_scheduling_requests(session: Session, *, tenant_id: str, status: str | None = None) -> list[SchedulingRequest]:
|
||||
query = session.query(SchedulingRequest).filter(SchedulingRequest.tenant_id == tenant_id, SchedulingRequest.deleted_at.is_(None))
|
||||
def list_scheduling_requests(
|
||||
session: Session,
|
||||
*,
|
||||
tenant_id: str,
|
||||
status: str | None = None,
|
||||
limit: int = 100,
|
||||
) -> list[SchedulingRequest]:
|
||||
query = (
|
||||
session.query(SchedulingRequest)
|
||||
.options(
|
||||
selectinload(SchedulingRequest.slots),
|
||||
selectinload(SchedulingRequest.participants),
|
||||
)
|
||||
.filter(
|
||||
SchedulingRequest.tenant_id == tenant_id,
|
||||
SchedulingRequest.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
if status:
|
||||
query = query.filter(SchedulingRequest.status == status)
|
||||
return query.order_by(SchedulingRequest.created_at.desc(), SchedulingRequest.title.asc()).all()
|
||||
return (
|
||||
query.order_by(
|
||||
SchedulingRequest.created_at.desc(),
|
||||
SchedulingRequest.title.asc(),
|
||||
)
|
||||
.limit(max(1, min(limit, 200)))
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def _actor_ids(values: tuple[str, ...]) -> tuple[str, ...]:
|
||||
@@ -1369,12 +1393,53 @@ def list_visible_scheduling_requests(
|
||||
actor_ids: tuple[str, ...],
|
||||
can_manage: bool = False,
|
||||
status: str | None = None,
|
||||
limit: int = 100,
|
||||
) -> list[SchedulingRequest]:
|
||||
return [
|
||||
request
|
||||
for request in list_scheduling_requests(session, tenant_id=tenant_id, status=status)
|
||||
if scheduling_request_is_visible(request, actor_ids=actor_ids, can_manage=can_manage)
|
||||
]
|
||||
query = (
|
||||
session.query(SchedulingRequest)
|
||||
.options(
|
||||
selectinload(SchedulingRequest.slots),
|
||||
selectinload(SchedulingRequest.participants),
|
||||
)
|
||||
.filter(
|
||||
SchedulingRequest.tenant_id == tenant_id,
|
||||
SchedulingRequest.deleted_at.is_(None),
|
||||
)
|
||||
)
|
||||
if status:
|
||||
query = query.filter(SchedulingRequest.status == status)
|
||||
if not can_manage:
|
||||
ids = _actor_ids(actor_ids)
|
||||
email_ids = tuple(value.casefold() for value in ids if "@" in value)
|
||||
participant_exists = (
|
||||
session.query(SchedulingParticipant.id)
|
||||
.filter(
|
||||
SchedulingParticipant.tenant_id == tenant_id,
|
||||
SchedulingParticipant.request_id == SchedulingRequest.id,
|
||||
SchedulingParticipant.deleted_at.is_(None),
|
||||
or_(
|
||||
SchedulingParticipant.respondent_id.in_(ids or ("",)),
|
||||
func.lower(SchedulingParticipant.email).in_(
|
||||
email_ids or ("",)
|
||||
),
|
||||
),
|
||||
)
|
||||
.exists()
|
||||
)
|
||||
query = query.filter(
|
||||
or_(
|
||||
SchedulingRequest.organizer_user_id.in_(ids or ("",)),
|
||||
participant_exists,
|
||||
)
|
||||
)
|
||||
return (
|
||||
query.order_by(
|
||||
SchedulingRequest.created_at.desc(),
|
||||
SchedulingRequest.title.asc(),
|
||||
)
|
||||
.limit(max(1, min(limit, 200)))
|
||||
.all()
|
||||
)
|
||||
|
||||
|
||||
def get_scheduling_request(session: Session, *, tenant_id: str, request_id: str) -> SchedulingRequest:
|
||||
|
||||
Reference in New Issue
Block a user