from datetime import datetime from enum import Enum from pydantic import BaseModel, ConfigDict, EmailStr class BaseResponse(BaseModel): model_config = ConfigDict(from_attributes=True) class BaseObjectResponse(BaseResponse): id: str created_at: datetime updated_at: datetime class AccessTokenResponse(BaseResponse): token_type: str access_token: str expires_at: int issued_at: int refresh_token: str refresh_token_expires_at: int refresh_token_issued_at: int # ---- Organization ---- class OrganizationResponse(BaseResponse): id: str name: str class MembershipUserResponse(BaseResponse): id: str email: EmailStr name: str class OrganizationMembershipResponse(BaseResponse): user_id: str organization_id: str role: str user: MembershipUserResponse class OrganizationDetailResponse(OrganizationResponse): name: str memberships: list[OrganizationMembershipResponse] = [] class UserOrganizationResponse(BaseResponse): organization_id: str organization: OrganizationResponse role: str class UserResponse(BaseResponse): id: str email: EmailStr name: str phone_number: str | None = None global_role: str organizations: list[UserOrganizationResponse] = [] class CommissionContactResponse(BaseResponse): name: str phone_number: str | None = None class CommissionResponse(BaseObjectResponse): name: str contacts: list[CommissionContactResponse] = [] templates_id: list[str] = [] # Commission model doesn't currently expose a hybrid `templates_id` -- # add one alongside `contacts` on the model (mirrors the pattern already # used by SlotTemplate.tags_id / Volunteer.slots_id) if this is needed. class VolunteerGroupResponse(BaseObjectResponse): name: str color: str | None = None volunteers_id: list[str] = [] class VolunteerResponse(BaseObjectResponse): name: str surname: str email: str phone_number: str automatic_sms: bool slots_id: list[str] = [] groups_id: list[str] = [] comment: str class SlotResponse(BaseObjectResponse): title: str starting_time: datetime ending_time: datetime required_volunteers: int volunteers_id: list[str] = [] template_id: str | None class SMSResponse(BaseObjectResponse): volunteer_id: str | None content: str phone_number: str sending_time: datetime send_time: datetime | None class TemplateResponse(BaseObjectResponse): title: str description: str place: str responsible_override: str | None = None commission_id: str | None = None tags_id: list[str] = [] comment: str class TagResponse(BaseObjectResponse): title: str templates_id: list[str] = [] class ProjectResponse(BaseObjectResponse): name: str organization_id: str volunteers: list[VolunteerResponse] sms: list[SMSResponse] slots: list[SlotResponse] tags: list[TagResponse] templates: list[TemplateResponse] groups: list[VolunteerGroupResponse] = [] is_public: bool class ProjectListResponse(BaseResponse): id: str created_at: datetime updated_at: datetime name: str organization_id: str is_public: bool class EnumServerStatus(Enum): ACTIVE = "active" INVALID = "invalid (heartbeat missing)" INACTIVE = "inactive (stale)" class SMSServerStatus(BaseResponse): updated_at: datetime host: str user_agent: str message: EnumServerStatus