Add invitation code validation and auto-generation for guests
All checks were successful
Build and Push Docker Images / changes (push) Successful in 4s
Build and Push Docker Images / build-backend (push) Successful in 50s
Build and Push Docker Images / build-frontend (push) Has been skipped

Validate uniqueness of invitation codes during guest creation to prevent duplicates. Automatically generate an 8-character code if none is provided, ensuring consistent data handling. Updated tests and schemas to support these changes.
This commit is contained in:
2025-03-15 20:34:38 +01:00
parent e41e7d0867
commit 3c196b1e91
4 changed files with 42 additions and 2 deletions

View File

@@ -13,6 +13,14 @@ router = APIRouter()
@router.post("/", response_model=GuestRead, operation_id="create_guest") @router.post("/", response_model=GuestRead, operation_id="create_guest")
def create_guest(guest_in: GuestCreate, db: Session = Depends(get_db)): def create_guest(guest_in: GuestCreate, db: Session = Depends(get_db)):
if guest_in.invitation_code:
existing_guest = guest_crud.get_by_invitation_code(db, guest_in.invitation_code)
if existing_guest:
raise HTTPException(
status_code=400, detail="Guest with this invitation code already exists"
)
else:
guest_in.invitation_code = str(uuid.uuid4())[:8]
guest = guest_crud.create(db, obj_in=guest_in) guest = guest_crud.create(db, obj_in=guest_in)
return guest return guest

View File

@@ -11,6 +11,10 @@ import uuid
class CRUDGuest(CRUDBase[Guest, GuestCreate, GuestUpdate]): class CRUDGuest(CRUDBase[Guest, GuestCreate, GuestUpdate]):
def create(self, db, obj_in: GuestCreate): def create(self, db, obj_in: GuestCreate):
if obj_in.invitation_code is None:
obj_in.invitation_code = str(uuid.uuid4())[:8]
db_guest = Guest( db_guest = Guest(
event_id=uuid.UUID(obj_in.event_id) if isinstance(obj_in.event_id, str) else obj_in.event_id, # explicit casting event_id=uuid.UUID(obj_in.event_id) if isinstance(obj_in.event_id, str) else obj_in.event_id, # explicit casting
invited_by=uuid.UUID(obj_in.invited_by) if isinstance(obj_in.invited_by, str) else obj_in.invited_by, invited_by=uuid.UUID(obj_in.invited_by) if isinstance(obj_in.invited_by, str) else obj_in.invited_by,

View File

@@ -21,7 +21,7 @@ class GuestBase(BaseModel):
class GuestCreate(GuestBase): class GuestCreate(GuestBase):
invitation_code: str invitation_code: Optional[str] = None
class GuestUpdate(BaseModel): class GuestUpdate(BaseModel):
@@ -45,4 +45,5 @@ class GuestRead(GuestBase):
response_date: Optional[datetime] = None response_date: Optional[datetime] = None
actual_additional_guests: int actual_additional_guests: int
is_blocked: bool is_blocked: bool
model_config = ConfigDict(from_attributes=True) model_config = ConfigDict(from_attributes=True)
invitation_code: str

View File

@@ -39,6 +39,33 @@ class TestGuestsRouter:
assert data["full_name"] == guest_data["full_name"] assert data["full_name"] == guest_data["full_name"]
assert data["email"] == guest_data["email"] assert data["email"] == guest_data["email"]
def test_create_guest_fails_on_duplicate_invitation_code(self, guest_data):
# First create the guest successfully
response_initial = self.client.post(self.endpoint, json=guest_data)
assert response_initial.status_code == 200
# Attempt to create another guest with the same invitation code
new_guest_data = guest_data.copy()
new_guest_data["email"] = "new.email@example.com"
response_duplicate = self.client.post(self.endpoint, json=new_guest_data)
assert response_duplicate.status_code == 400
assert response_duplicate.json()["detail"] == "Guest with this invitation code already exists"
def test_create_guest_generates_invitation_code_if_not_provided(self, guest_data):
# Remove invitation_code to test auto-generation
guest_data_without_code = guest_data.copy()
guest_data_without_code.pop("invitation_code", None)
response = self.client.post(self.endpoint, json=guest_data_without_code)
assert response.status_code == 200
data = response.json()
print(data)
assert "invitation_code" in data
assert len(data["invitation_code"]) == 8
def test_create_guest_missing_required_fields_fails(self): def test_create_guest_missing_required_fields_fails(self):
incomplete_payload = { incomplete_payload = {
"email": "john.doe@example.com" "email": "john.doe@example.com"