From b9c9452e73402f76a32a55e32a62f707778a8666 Mon Sep 17 00:00:00 2001 From: georgegale228 Date: Wed, 19 Aug 2026 18:25:05 +0000 Subject: [PATCH 1/2] =?UTF-8?q?feedback=202026=20implement=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/core/settings.py | 2 +- app/database/migrations.py | 24 +++++++++ app/main.py | 2 + app/routers/api.py | 2 + app/routers/feedback_public.py | 27 ++++++++++ app/routers/feedbacks.py | 94 ++++++++++++++++++++++++++++++++++ app/schemas/models.py | 45 ++++++++++++++++ app/utils/feedback.py | 70 +++++++++++++++++++++++++ 8 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 app/routers/feedback_public.py create mode 100644 app/routers/feedbacks.py create mode 100644 app/utils/feedback.py diff --git a/app/core/settings.py b/app/core/settings.py index 5ff0b46..0a8eede 100644 --- a/app/core/settings.py +++ b/app/core/settings.py @@ -33,7 +33,7 @@ smtp_password=config("SMTP_PASSWORD", default="password"), # Admin SMTP settings for internal notification service admin_smtp_server=config("ADMIN_SMTP_SERVER", default=None), - admin_smtp_port=config("ADMIN_SMTP_PORT", default=None, cast=int), + admin_smtp_port=config("ADMIN_SMTP_PORT", default=None), admin_smtp_user=config("ADMIN_SMTP_USER", default=None), admin_smtp_password=config("ADMIN_SMTP_PASSWORD", default=None), paydunya_public_key=config("PAYDUNYA_PUBLIC_KEY", default=None), diff --git a/app/database/migrations.py b/app/database/migrations.py index 57d0882..0b2f6e6 100644 --- a/app/database/migrations.py +++ b/app/database/migrations.py @@ -521,6 +521,24 @@ REFERENCES events(id) ON DELETE CASCADE );""", + """ + CREATE TABLE IF NOT EXISTS feedbacks ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + sex VARCHAR(64), + age VARCHAR(32), + profession VARCHAR(255), + country VARCHAR(120), + python_level VARCHAR(120), + heard TEXT, + rating INTEGER CHECK (rating >= 1 AND rating <= 5), + overall TEXT, + favorite TEXT, + improvements TEXT, + comments TEXT, + is_resolved BOOLEAN NOT NULL DEFAULT FALSE, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + );""", ] @@ -539,6 +557,12 @@ ALTER_TABLE_QUERIES = [ "ALTER TABLE sponsors_partners ADD COLUMN IF NOT EXISTS package_tier package_tier_enum;", + "ALTER TABLE feedbacks DROP COLUMN IF EXISTS event_code;", + "ALTER TABLE feedbacks DROP COLUMN IF EXISTS name;", + "ALTER TABLE feedbacks DROP COLUMN IF EXISTS email;", + "ALTER TABLE feedbacks DROP COLUMN IF EXISTS subject;", + "ALTER TABLE feedbacks DROP COLUMN IF EXISTS message;", + "ALTER TABLE feedbacks ADD COLUMN IF NOT EXISTS days JSONB DEFAULT '[]'::jsonb;", ] diff --git a/app/main.py b/app/main.py index ba658d8..58c4766 100644 --- a/app/main.py +++ b/app/main.py @@ -8,6 +8,7 @@ from app.routers.api import api_routers from app.routers.notifications import api_router as notifications_router from app.webhooks.payments_callback import api_router as payments_callback_router +from app.routers.feedback_public import api_router as feedback_public_router from app.core.settings import logger, settings from pathlib import Path from datetime import datetime, timezone @@ -150,3 +151,4 @@ async def favicon(): app.include_router(api_routers) app.include_router(payments_callback_router) app.include_router(notifications_router) +app.include_router(feedback_public_router) diff --git a/app/routers/api.py b/app/routers/api.py index a925471..a6fbfed 100644 --- a/app/routers/api.py +++ b/app/routers/api.py @@ -16,6 +16,7 @@ from app.routers.vauchers import api_router as vauchers_router from app.routers.teams import api_router as teams_router from app.routers.access_grant import api_router as access_grant_router +from app.routers.feedbacks import api_router as feedbacks_router from fastapi import APIRouter from app.core.security import verify_api_key @@ -40,3 +41,4 @@ api_routers.include_router(vauchers_router) api_routers.include_router(teams_router) api_routers.include_router(access_grant_router) +api_routers.include_router(feedbacks_router) diff --git a/app/routers/feedback_public.py b/app/routers/feedback_public.py new file mode 100644 index 0000000..a0f053a --- /dev/null +++ b/app/routers/feedback_public.py @@ -0,0 +1,27 @@ +from fastapi import APIRouter, BackgroundTasks, Request, status, HTTPException + +from app.utils.feedback import add_feedback + +from app.schemas.models import ( + FeedbackBase, + MessageResponse, +) +from app.core.settings import logger + + +api_router = APIRouter(prefix="/api/feedback", tags=["feedback"]) + + +@api_router.post("/", response_model=MessageResponse, status_code=status.HTTP_201_CREATED) +async def submit_public_feedback(request: Request, background_tasks: BackgroundTasks, payload: FeedbackBase): + """Public endpoint to submit feedback without API key.""" + try: + background_tasks.add_task( + add_feedback, request.app.state.db_pool, payload.model_dump(mode="json")) + return {"message": "Feedback received successfully"} + except Exception as e: + logger.error(f"Error adding public feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error adding feedback") diff --git a/app/routers/feedbacks.py b/app/routers/feedbacks.py new file mode 100644 index 0000000..8205c72 --- /dev/null +++ b/app/routers/feedbacks.py @@ -0,0 +1,94 @@ +from fastapi import APIRouter, BackgroundTasks, Depends, Request, status, HTTPException + +from app.utils.feedback import ( + add_feedback, get_feedback_by_id, get_all_feedbacks, update_feedback, delete_feedback) + +from app.schemas.models import ( + FeedbackSummary, + MessageResponse, + FeedbackUpdate, + FeedbackBase, + +) +from app.database.connection import get_db_connection +from app.core.settings import logger + + +api_router = APIRouter(prefix="/feedbacks", tags=["feedbacks"]) + + +@api_router.get("/", response_model=list[FeedbackSummary]) +async def _get_all_feedbacks(db=Depends(get_db_connection)): + try: + feedbacks = await get_all_feedbacks(db) + if not feedbacks: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, + detail="No feedbacks found") + return feedbacks + except Exception as e: + logger.error(f"Error retrieving feedbacks: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error retrieving feedbacks") + + +@api_router.get("/{feedback_id}", response_model=FeedbackSummary) +async def _get_feedback_by_id(feedback_id: str, db=Depends(get_db_connection)): + try: + feedback = await get_feedback_by_id(db, feedback_id) + if not feedback: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, + detail=f"Feedback with id {feedback_id} not found") + return feedback + except Exception as e: + logger.error( + f"Error retrieving feedback with id {feedback_id}: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error retrieving feedback") + + +@api_router.post("/send", response_model=MessageResponse, status_code=status.HTTP_201_CREATED) +async def add_feedback_message(request: Request, payload: FeedbackBase, background_tasks: BackgroundTasks): + """Add a new feedback.""" + try: + background_tasks.add_task( + add_feedback, request.app.state.db_pool, payload.model_dump(mode="json")) + return {"message": "Feedback received successfully"} + except Exception as e: + logger.error(f"Error adding feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error adding feedback") + + +@api_router.put("/{feedback_id}", response_model=MessageResponse) +async def _update_feedback(feedback_id: str, payload: FeedbackUpdate, background_tasks: BackgroundTasks, db=Depends(get_db_connection)): + try: + data_to_update = {k: v for k, + v in payload.model_dump(mode="json").items() if v is not None} + + result = await update_feedback(db, feedback_id, data_to_update, background_tasks) + return result + except Exception as e: + logger.error(f"Error updating feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error updating feedback") + + +@api_router.delete("/{feedback_id}", response_model=MessageResponse) +async def _delete_feedback(feedback_id: str, background_tasks: BackgroundTasks, db=Depends(get_db_connection)): + try: + result = await delete_feedback(db, feedback_id, background_tasks) + return result + except Exception as e: + logger.error(f"Error deleting feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error deleting feedback") diff --git a/app/schemas/models.py b/app/schemas/models.py index 08208f0..d097fed 100644 --- a/app/schemas/models.py +++ b/app/schemas/models.py @@ -122,6 +122,51 @@ class ContactMessageUpdate(BaseModel): default_factory=lambda: datetime.now(timezone.utc)) +class FeedbackBase(BaseModel): + sex: str | None = None + age: str | None = None + profession: str | None = None + country: str | None = None + python_level: str | None = None + heard: str | None = None + rating: int | None = Field(default=None, ge=1, le=5) + overall: str | None = None + favorite: str | None = None + improvements: str | None = None + comments: str | None = None + days: List[str] = Field(default_factory=list) + + +class FeedbackSummary(FeedbackBase): + id: UUID + is_resolved: bool = False + created_at: datetime + updated_at: datetime + + +class FeedbacksList(BaseModel): + feedbacks: list[FeedbackSummary] = Field( + default_factory=list) + + +class FeedbackUpdate(BaseModel): + sex: str | None = None + age: str | None = None + profession: str | None = None + country: str | None = None + python_level: str | None = None + heard: str | None = None + rating: int | None = Field(default=None, ge=1, le=5) + overall: str | None = None + favorite: str | None = None + improvements: str | None = None + comments: str | None = None + days: List[str] | None = None + is_resolved: bool | None = None + updated_at: datetime = Field( + default_factory=lambda: datetime.now(timezone.utc)) + + class APIKeyResponse(BaseModel): api_key: str diff --git a/app/utils/feedback.py b/app/utils/feedback.py new file mode 100644 index 0000000..841ec66 --- /dev/null +++ b/app/utils/feedback.py @@ -0,0 +1,70 @@ +from fastapi import HTTPException, BackgroundTasks +from app.core.settings import logger + +from app.database.orm import select, insert, update, delete + + +async def add_feedback(db, payload: dict): + try: + await insert(db, "feedbacks", payload) + return {"message": "Feedback received successfully"} + except Exception as e: + logger.error(f"Error adding feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error adding feedback") + + +async def delete_feedback(db, feedback_id: str, background_tasks: BackgroundTasks): + try: + background_tasks.add_task( + delete, db, "feedbacks", filter={"id": feedback_id}) + return {"message": "Feedback deleted successfully"} + except Exception as e: + logger.error(f"Error deleting feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException(status_code=500, detail="Error deleting feedback") + + +async def get_feedback_by_id(db, feedback_id: str): + try: + feedback = await select(db, "feedbacks", filter={"id": feedback_id}) + if not feedback: + logger.error(f"Feedback with id {feedback_id} not found") + return feedback[0] + except Exception as e: + logger.error(f"Error retrieving feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException(status_code=500, detail="Error retrieving feedback") + + +async def get_all_feedbacks(db): + try: + feedbacks = await select(db, "feedbacks") + return feedbacks + except Exception as e: + logger.error(f"Error retrieving all feedbacks: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException( + status_code=500, detail="Error retrieving all feedbacks") + + +async def update_feedback(db, feedback_id: str, payload: dict, background_tasks: BackgroundTasks): + try: + existing = await select(db, "feedbacks", filter={"id": feedback_id}) + if not existing: + logger.error(f"Feedback with id {feedback_id} not found") + raise HTTPException( + status_code=404, detail=f"Feedback with id {feedback_id} not found") + background_tasks.add_task( + update, db, "feedbacks", payload, filter={"id": feedback_id}) + return {"message": "Feedback updated successfully"} + except Exception as e: + logger.error(f"Error updating feedback: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException(status_code=500, detail="Error updating feedback") From 276eb13f341835adc4c1bb5950190eec6907f689 Mon Sep 17 00:00:00 2001 From: georgegale228 Date: Sun, 23 Aug 2026 01:48:28 +0000 Subject: [PATCH 2/2] =?UTF-8?q?feat(Get=20/api/registration)=20pour=20recu?= =?UTF-8?q?p=C3=A9rer=20les=20inscrits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/core/security.py | 15 +++++++++++++-- app/core/settings.py | 2 +- app/database/orm.py | 22 ++++++---------------- app/routers/feedback_public.py | 9 ++++----- app/routers/feedbacks.py | 15 +++++++-------- app/routers/registrations.py | 19 ++++++++++++++++++- app/schemas/config.py | 1 + app/schemas/models.py | 1 + app/utils/feedback.py | 22 +++++++++++++--------- app/utils/registrations.py | 32 ++++++++++++++++++++++++++++++++ 10 files changed, 96 insertions(+), 42 deletions(-) diff --git a/app/core/security.py b/app/core/security.py index c56c43a..7a10090 100644 --- a/app/core/security.py +++ b/app/core/security.py @@ -1,10 +1,11 @@ -from fastapi import Depends, HTTPException, status +from fastapi import Depends, HTTPException, status, Request from fastapi.security import HTTPBearer, HTTPBasicCredentials from typing import Annotated from app.database.connection import get_db_connection, get_redis_client from app.database.orm import select from json import dumps, loads from app.schemas.models import APIKeyResponse, APIKeyVerificationResponse +from app.core.settings import settings security = HTTPBearer() @@ -31,7 +32,6 @@ async def verify_api_key(credentials: Annotated[HTTPBasicCredentials, Depends(se raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="API key not found") expected_api_key = expected_api_key[0] - # Cache for 1 hour api_key_data = { "name": expected_api_key["name"], "key_value": expected_api_key["key_value"], @@ -44,3 +44,14 @@ async def verify_api_key(credentials: Annotated[HTTPBasicCredentials, Depends(se raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid API key") return APIKeyVerificationResponse(is_valid=True, message="API key is valid") + + +async def require_admin_secret(request: Request): + if not settings.admin_api_key: + raise HTTPException( + status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Admin secret not configured") + admin_secret = request.headers.get("X-Admin-Secret") + if admin_secret != settings.admin_api_key: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, detail="Admin access required") + return True diff --git a/app/core/settings.py b/app/core/settings.py index 0a8eede..04b2f1d 100644 --- a/app/core/settings.py +++ b/app/core/settings.py @@ -31,7 +31,7 @@ smtp_port=config("SMTP_PORT", default=587, cast=int), smtp_user=config("SMTP_USER", default="user"), smtp_password=config("SMTP_PASSWORD", default="password"), - # Admin SMTP settings for internal notification service + admin_api_key=config("ADMIN_API_KEY", default=""), admin_smtp_server=config("ADMIN_SMTP_SERVER", default=None), admin_smtp_port=config("ADMIN_SMTP_PORT", default=None), admin_smtp_user=config("ADMIN_SMTP_USER", default=None), diff --git a/app/database/orm.py b/app/database/orm.py index d6128f5..4117f75 100644 --- a/app/database/orm.py +++ b/app/database/orm.py @@ -21,9 +21,8 @@ async def select(db: Connection, table, columns=None, filter=None): result = await cur.fetchall() return result except Exception as e: - logger.error(f"Error executing select query on {table}: {str(e)}") - # TODO: sent email to admin about error during select query execution + raise async def select_with_join(db: Connection, table, join_table, join_condition, columns=None, filter=None): @@ -36,15 +35,13 @@ async def select_with_join(db: Connection, table, join_table, join_condition, co return result except Exception as e: - logger.error( f"Error executing select with join query on {table} and {join_table}: {str(e)}") - # TODO: sent email to admin about error during select with join query execution + raise async def select_with_multiple_joins(db: Connection, table, joins, columns=None, filter=None): try: - query, values = generate_multiple_joins_query( table, joins, columns, filter) async with db.cursor(row_factory=dict_row) as cur: @@ -52,10 +49,9 @@ async def select_with_multiple_joins(db: Connection, table, joins, columns=None, result = await cur.fetchall() return result except Exception as e: - logger.error( f"Error executing select with multiple joins query on {table}: {str(e)}") - # TODO: sent email to admin about error during select with multiple joins query execution + raise async def insert(db: Connection, table, data): @@ -69,9 +65,8 @@ async def insert(db: Connection, table, data): await cur.execute(query, values) await db.commit() except Exception as e: - logger.error(f"Error inserting record into {table}: {str(e)}") - # TODO: sent email to admin about error during insert query execution + raise async def update(db: Connection, table, data, filter): @@ -79,14 +74,11 @@ async def update(db: Connection, table, data, filter): data = remove_null_values(data) query, values = generate_update_query(table, data, filter) async with db.cursor() as cur: - await cur.execute(query, values) await db.commit() except Exception as e: - logger.error(f"Error updating record in {table}: {str(e)}") - # TODO: Log the error can be done here - # TODO: sent email to admin about error during update query execution + raise async def delete(db: Connection, table, filter): @@ -96,7 +88,5 @@ async def delete(db: Connection, table, filter): await cur.execute(query, values) await db.commit() except Exception as e: - logger.error(f"Error deleting record from {table}: {str(e)}") - # TODO: Log the error can be done here - # TODO: sent email to admin about error during delete query execution + raise diff --git a/app/routers/feedback_public.py b/app/routers/feedback_public.py index a0f053a..7f2fdc6 100644 --- a/app/routers/feedback_public.py +++ b/app/routers/feedback_public.py @@ -1,4 +1,4 @@ -from fastapi import APIRouter, BackgroundTasks, Request, status, HTTPException +from fastapi import APIRouter, Request, status, HTTPException from app.utils.feedback import add_feedback @@ -13,12 +13,11 @@ @api_router.post("/", response_model=MessageResponse, status_code=status.HTTP_201_CREATED) -async def submit_public_feedback(request: Request, background_tasks: BackgroundTasks, payload: FeedbackBase): +async def submit_public_feedback(request: Request, payload: FeedbackBase): """Public endpoint to submit feedback without API key.""" try: - background_tasks.add_task( - add_feedback, request.app.state.db_pool, payload.model_dump(mode="json")) - return {"message": "Feedback received successfully"} + result = await add_feedback(request.app.state.db_pool, payload.model_dump(mode="json")) + return result except Exception as e: logger.error(f"Error adding public feedback: {str(e)}") if isinstance(e, HTTPException): diff --git a/app/routers/feedbacks.py b/app/routers/feedbacks.py index 8205c72..03bbcbe 100644 --- a/app/routers/feedbacks.py +++ b/app/routers/feedbacks.py @@ -51,12 +51,11 @@ async def _get_feedback_by_id(feedback_id: str, db=Depends(get_db_connection)): @api_router.post("/send", response_model=MessageResponse, status_code=status.HTTP_201_CREATED) -async def add_feedback_message(request: Request, payload: FeedbackBase, background_tasks: BackgroundTasks): +async def add_feedback_message(request: Request, payload: FeedbackBase): """Add a new feedback.""" try: - background_tasks.add_task( - add_feedback, request.app.state.db_pool, payload.model_dump(mode="json")) - return {"message": "Feedback received successfully"} + result = await add_feedback(request.app.state.db_pool, payload.model_dump(mode="json")) + return result except Exception as e: logger.error(f"Error adding feedback: {str(e)}") if isinstance(e, HTTPException): @@ -66,12 +65,12 @@ async def add_feedback_message(request: Request, payload: FeedbackBase, backgrou @api_router.put("/{feedback_id}", response_model=MessageResponse) -async def _update_feedback(feedback_id: str, payload: FeedbackUpdate, background_tasks: BackgroundTasks, db=Depends(get_db_connection)): +async def _update_feedback(feedback_id: str, payload: FeedbackUpdate, db=Depends(get_db_connection)): try: data_to_update = {k: v for k, v in payload.model_dump(mode="json").items() if v is not None} - result = await update_feedback(db, feedback_id, data_to_update, background_tasks) + result = await update_feedback(db, feedback_id, data_to_update) return result except Exception as e: logger.error(f"Error updating feedback: {str(e)}") @@ -82,9 +81,9 @@ async def _update_feedback(feedback_id: str, payload: FeedbackUpdate, background @api_router.delete("/{feedback_id}", response_model=MessageResponse) -async def _delete_feedback(feedback_id: str, background_tasks: BackgroundTasks, db=Depends(get_db_connection)): +async def _delete_feedback(feedback_id: str, db=Depends(get_db_connection)): try: - result = await delete_feedback(db, feedback_id, background_tasks) + result = await delete_feedback(db, feedback_id) return result except Exception as e: logger.error(f"Error deleting feedback: {str(e)}") diff --git a/app/routers/registrations.py b/app/routers/registrations.py index 76c2251..ed9d0ef 100644 --- a/app/routers/registrations.py +++ b/app/routers/registrations.py @@ -11,15 +11,18 @@ AttendeeID, TicketSubmissionPayload ) -from uuid import uuid4 +from uuid import uuid4, UUID import httpx from app.utils.tickets import get_ticket_by_id from app.database.orm import select, select_with_join from app.routers.helper import submit_ticket from app.utils.registrations import ( create_registration, + get_all_registrations, ) from app.payments.paydunya_service import create_invoice +from app.core.security import require_admin_secret +from app.database.orm import select as db_select api_router = APIRouter(tags=["registrations"]) @@ -145,3 +148,17 @@ async def _approve_student_registration(registration_id: AttendeeID, db=Depends( if isinstance(e, HTTPException): raise e raise HTTPException(status_code=500, detail="Internal server error") + + +@api_router.get("/registrations", dependencies=[Depends(require_admin_secret)]) +async def _list_registrations(request: Request, event_id: UUID | None = None, db=Depends(get_db_connection)): + try: + registrations = await get_all_registrations(db, event_id=event_id) + if not registrations: + return [] + return registrations + except Exception as e: + logger.error(f"Error listing registrations: {str(e)}") + if isinstance(e, HTTPException): + raise e + raise HTTPException(status_code=500, detail="Error listing registrations") diff --git a/app/schemas/config.py b/app/schemas/config.py index 65e2c05..8fb08a9 100644 --- a/app/schemas/config.py +++ b/app/schemas/config.py @@ -25,6 +25,7 @@ class Config(BaseModel): smtp_port: int = 587 smtp_user: str = "user" smtp_password: str = "password" + admin_api_key: str = "" admin_smtp_server: str | None = None admin_smtp_port: int | None = None admin_smtp_user: str | None = None diff --git a/app/schemas/models.py b/app/schemas/models.py index d097fed..40efd1f 100644 --- a/app/schemas/models.py +++ b/app/schemas/models.py @@ -576,6 +576,7 @@ class RegistrationCreate(RegistrationBase): class RegistrationSummary(RegistrationBase): id: UUID + event_id: UUID created_at: datetime updated_at: datetime diff --git a/app/utils/feedback.py b/app/utils/feedback.py index 841ec66..dff7c7f 100644 --- a/app/utils/feedback.py +++ b/app/utils/feedback.py @@ -4,9 +4,10 @@ from app.database.orm import select, insert, update, delete -async def add_feedback(db, payload: dict): +async def add_feedback(db_pool, payload: dict): try: - await insert(db, "feedbacks", payload) + async with db_pool.connection() as db: + await insert(db, "feedbacks", payload) return {"message": "Feedback received successfully"} except Exception as e: logger.error(f"Error adding feedback: {str(e)}") @@ -16,10 +17,13 @@ async def add_feedback(db, payload: dict): status_code=500, detail="Error adding feedback") -async def delete_feedback(db, feedback_id: str, background_tasks: BackgroundTasks): +async def delete_feedback(db, feedback_id: str): try: - background_tasks.add_task( - delete, db, "feedbacks", filter={"id": feedback_id}) + existing = await select(db, "feedbacks", filter={"id": feedback_id}) + if not existing: + raise HTTPException( + status_code=404, detail=f"Feedback with id {feedback_id} not found") + await delete(db, "feedbacks", filter={"id": feedback_id}) return {"message": "Feedback deleted successfully"} except Exception as e: logger.error(f"Error deleting feedback: {str(e)}") @@ -32,7 +36,8 @@ async def get_feedback_by_id(db, feedback_id: str): try: feedback = await select(db, "feedbacks", filter={"id": feedback_id}) if not feedback: - logger.error(f"Feedback with id {feedback_id} not found") + raise HTTPException( + status_code=404, detail=f"Feedback with id {feedback_id} not found") return feedback[0] except Exception as e: logger.error(f"Error retrieving feedback: {str(e)}") @@ -53,15 +58,14 @@ async def get_all_feedbacks(db): status_code=500, detail="Error retrieving all feedbacks") -async def update_feedback(db, feedback_id: str, payload: dict, background_tasks: BackgroundTasks): +async def update_feedback(db, feedback_id: str, payload: dict): try: existing = await select(db, "feedbacks", filter={"id": feedback_id}) if not existing: logger.error(f"Feedback with id {feedback_id} not found") raise HTTPException( status_code=404, detail=f"Feedback with id {feedback_id} not found") - background_tasks.add_task( - update, db, "feedbacks", payload, filter={"id": feedback_id}) + await update(db, "feedbacks", payload, filter={"id": feedback_id}) return {"message": "Feedback updated successfully"} except Exception as e: logger.error(f"Error updating feedback: {str(e)}") diff --git a/app/utils/registrations.py b/app/utils/registrations.py index ea04a26..553a566 100644 --- a/app/utils/registrations.py +++ b/app/utils/registrations.py @@ -11,6 +11,38 @@ from datetime import datetime, timezone +async def get_all_registrations(db, event_id: UUID | None = None): + try: + filter_data = {} + if event_id: + filter_data["event_id"] = str(event_id) + registrations = await select_with_join( + db, + table="registrations", + join_table="tickets", + join_condition="registrations.ticket_id = tickets.id", + filter=filter_data, + columns=[ + "registrations.id", + "registrations.full_name", + "registrations.email", + "registrations.ticket_type", + "registrations.ticket_quantity", + "registrations.attendance_status", + "registrations.payment_status", + "registrations.payment_reference", + "registrations.created_at", + "registrations.updated_at", + "registrations.event_id", + "tickets.name", + ], + ) + return registrations + except Exception as e: + logger.error(f"Error retrieving registrations: {str(e)}") + raise HTTPException(status_code=500, detail="Error retrieving registrations") + + def validate_registration_data(registration: RegistrationCreate, reg_existing, ticket): """ Validate the registration data.