From 632a762d648e1263615c6a0f10fb3be63fb667cb Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Sat, 15 Mar 2025 02:20:36 +0100 Subject: [PATCH] Add CRUD and schema for RSVP management Introduce CRUD operations and Pydantic schemas to manage RSVP entries, including creation, updates, retrieval, and deletion. This enables comprehensive handling of RSVP data with validation and support for guest and event IDs. --- backend/app/crud/rsvp.py | 75 +++++++++++++++++++++++++++++++++++++ backend/app/schemas/rsvp.py | 61 ++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 backend/app/crud/rsvp.py create mode 100644 backend/app/schemas/rsvp.py diff --git a/backend/app/crud/rsvp.py b/backend/app/crud/rsvp.py new file mode 100644 index 0000000..dc12f67 --- /dev/null +++ b/backend/app/crud/rsvp.py @@ -0,0 +1,75 @@ +import uuid +from datetime import datetime, timezone +from typing import Optional, Any + +from sqlalchemy.orm import Session + +from app.crud.base import CRUDBase +from app.models.rsvp import RSVP +from app.schemas.rsvp import RSVPSchemaCreate, RSVPSchemaUpdate, RSVPStatus + + +class CRUDRSVP(CRUDBase[RSVP, RSVPSchemaCreate, RSVPSchemaUpdate]): + + def create(self, db: Session, *, obj_in: RSVPSchemaCreate) -> RSVP: + """ + Creates a new RSVP entry, ensuring event_id and guest_id UUID validation + """ + event_uuid = uuid.UUID(obj_in.event_id) if isinstance(obj_in.event_id, str) else obj_in.event_id + guest_uuid = uuid.UUID(obj_in.guest_id) if isinstance(obj_in.guest_id, str) else obj_in.guest_id + rsvp_obj = RSVP( + id=str(uuid.uuid4()), + event_id=event_uuid, + guest_id=guest_uuid, + status=obj_in.status, + number_of_guests=max(1, obj_in.number_of_guests), + response_message=obj_in.response_message, + dietary_requirements=obj_in.dietary_requirements, + additional_info=obj_in.additional_info, + response_date=datetime.now(timezone.utc), + ) + db.add(rsvp_obj) + db.commit() + db.refresh(rsvp_obj) + return rsvp_obj + + @staticmethod + def get_rsvp_by_event_and_guest(db: Session, *, event_id: str | uuid.UUID, guest_id: str | uuid.UUID) -> \ + Optional[RSVP]: + event_uuid = uuid.UUID(event_id) if isinstance(event_id, str) else event_id + guest_uuid = uuid.UUID(guest_id) if isinstance(guest_id, str) else guest_id + return db.query(RSVP).filter( + RSVP.event_id == event_uuid, + RSVP.guest_id == guest_uuid + ).first() + + def update_rsvp_status( + self, + db: Session, + *, + db_obj: RSVP, + status: RSVPStatus, + number_of_guests: Optional[int] = None, + response_message: Optional[str] = None, + dietary_requirements: Optional[str] = None, + additional_info: Optional[dict[str, Any]] = None + ) -> RSVP: + db_obj = super().update(db, db_obj=db_obj, obj_in={ + "status": status, + "number_of_guests": max(1, number_of_guests) if number_of_guests else db_obj.number_of_guests, + "response_message": response_message, + "dietary_requirements": dietary_requirements, + "additional_info": additional_info + }) + return db_obj + + def delete_by_event_and_guest(self, db: Session, *, event_id: str | uuid.UUID, guest_id: str | uuid.UUID) -> RSVP: + db_obj = self.get_rsvp_by_event_and_guest(db, event_id=event_id, guest_id=guest_id) + if not db_obj: + raise ValueError("RSVP not found") + db.delete(db_obj) + db.commit() + return db_obj + + +crud_rsvp = CRUDRSVP(RSVP) diff --git a/backend/app/schemas/rsvp.py b/backend/app/schemas/rsvp.py new file mode 100644 index 0000000..e45ba1b --- /dev/null +++ b/backend/app/schemas/rsvp.py @@ -0,0 +1,61 @@ +from uuid import UUID +from typing import Optional, Any +from pydantic import BaseModel, Field, ConfigDict +from datetime import datetime +from enum import Enum + + +class RSVPStatus(str, Enum): + ATTENDING = "attending" + NOT_ATTENDING = "not_attending" + MAYBE = "maybe" + + +class RSVPSchemaBase(BaseModel): + status: RSVPStatus = Field(...) + number_of_guests: int = Field(default=1, ge=1) + response_message: str | None = None + dietary_requirements: str | None = None + additional_info: Any = None + + +class RSVPSchemaCreate(RSVPSchemaBase): + event_id: UUID + guest_id: UUID + number_of_guests: int = Field(default=1, ge=1) + + +class RSVPSchemaUpdate(BaseModel): + status: RSVPStatus | None = None + number_of_guests: int | None = Field(default=None, ge=1) + response_message: str | None = None + dietary_requirements: str | None = None + additional_info: dict[str, Any] | None = None + + model_config = ConfigDict(from_attributes=True) + + +class RSVPSchemaInDBBase(RSVPSchemaBase): + id: UUID + response_message: str | None = None + dietary_requirements: str | None = None + additional_info: dict[str, Any] | None = None + response_date: datetime + created_at: datetime + updated_at: datetime + model_config = ConfigDict(from_attributes=True) + + +class RSVPSchema(RSVPSchemaBase): + id: UUID + response_date: datetime + created_at: datetime + updated_at: datetime + model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True) + + +class RSVPSchemaInDB(RSVPSchemaBase): + id: str + created_at: datetime + updated_at: datetime + model_config = ConfigDict(from_attributes=True) \ No newline at end of file