diff --git a/backend/app/crud.py b/backend/app/crud.py index 4f0f61f0eaca99d8b2c6b6f97173114144422cd3..088d63418c9280369285eb3063dc720c45cd883d 100644 --- a/backend/app/crud.py +++ b/backend/app/crud.py @@ -187,9 +187,131 @@ def create_test_typing_entry( return db_entry -def create_test_vocabulary(db: Session, test: schemas.TestVocabularyCreate): - db_test = models.TestVocabulary(**test.dict()) - db.add(db_test) +def create_survey(db: Session, survey: schemas.SurveyCreate): + db_survey = models.Survey(**survey.dict()) + db.add(db_survey) + db.commit() + db.refresh(db_survey) + return db_survey + + +def get_survey(db: Session, survey_id: int): + return db.query(models.Survey).filter(models.Survey.id == survey_id).first() + + +def get_surveys(db: Session, skip: int = 0, limit: int = 100): + return db.query(models.Survey).offset(skip).limit(limit).all() + + +def delete_survey(db: Session, survey_id: int): + db.query(models.Survey).filter(models.Survey.id == survey_id).delete() + db.commit() + + +def create_survey_group( + db: Session, survey_id: int, survey_group: schemas.SurveyGroupCreate +): + db_survey_group = models.SurveyGroup(survey_id=survey_id, **survey_group.dict()) + db.add(db_survey_group) + db.commit() + db.refresh(db_survey_group) + return db_survey_group + + +def get_survey_group(db: Session, survey_group_id: int): + return ( + db.query(models.SurveyGroup) + .filter(models.SurveyGroup.id == survey_group_id) + .first() + ) + + +def get_survey_groups(db: Session, survey_id: int, skip: int = 0, limit: int = 100): + return ( + db.query(models.SurveyGroup) + .filter(models.SurveyGroup.survey_id == survey_id) + .offset(skip) + .limit(limit) + .all() + ) + + +def delete_survey_group(db: Session, survey_group_id: int): + db.query(models.SurveyGroup).filter( + models.SurveyGroup.id == survey_group_id + ).delete() + db.commit() + + +def create_survey_question( + db: Session, survey_group_id: int, survey_question: schemas.SurveyQuestionCreate +): + db_survey_question = models.SurveyQuestion( + group_id=survey_group_id, **survey_question.dict() + ) + db.add(db_survey_question) + db.commit() + db.refresh(db_survey_question) + return db_survey_question + + +def get_survey_question(db: Session, survey_question_id: int): + return ( + db.query(models.SurveyQuestion) + .filter(models.SurveyQuestion.id == survey_question_id) + .first() + ) + + +def get_survey_questions(db: Session, group_id: int, skip: int = 0, limit: int = 100): + return ( + db.query(models.SurveyQuestion) + .filter(models.SurveyQuestion.group_id == group_id) + .offset(skip) + .limit(limit) + .all() + ) + + +def delete_survey_question(db: Session, survey_question_id: int): + db.query(models.SurveyQuestion).filter( + models.SurveyQuestion.id == survey_question_id + ).delete() + db.commit() + + +def create_survey_option( + db: Session, survey_question_id: int, survey_option: schemas.SurveyOptionCreate +): + db_survey_option = models.SurveyOption( + question_id=survey_question_id, **survey_option.dict() + ) + db.add(db_survey_option) + db.commit() + db.refresh(db_survey_option) + return db_survey_option + + +def get_survey_option(db: Session, survey_option_id: int): + return ( + db.query(models.SurveyOption) + .filter(models.SurveyOption.id == survey_option_id) + .first() + ) + + +def get_survey_options(db: Session, question_id: int, skip: int = 0, limit: int = 100): + return ( + db.query(models.SurveyOption) + .filter(models.SurveyOption.question_id == question_id) + .offset(skip) + .limit(limit) + .all() + ) + + +def delete_survey_option(db: Session, survey_option_id: int): + db.query(models.SurveyOption).filter( + models.SurveyOption.id == survey_option_id + ).delete() db.commit() - db.refresh(db_test) - return db_test diff --git a/backend/app/main.py b/backend/app/main.py index 3436696f7ad7cc20eb7a6c810f59b26eb398eb09..645564d5050daf2d8fab0b9d9f11054a4e8ef697 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -68,7 +68,7 @@ usersRouter = APIRouter(prefix="/users", tags=["users"]) sessionsRouter = APIRouter(prefix="/sessions", tags=["sessions"]) websocketRouter = APIRouter(prefix="/ws", tags=["websocket"]) webhookRouter = APIRouter(prefix="/webhooks", tags=["webhook"]) -stats = APIRouter(prefix="/stats", tags=["stats"]) +surveyRouter = APIRouter(prefix="/surveys", tags=["surveys"]) @v1Router.get("/health", status_code=status.HTTP_204_NO_CONTENT) @@ -604,13 +604,6 @@ def propagate_presence( return -@v1Router.post("/tests/vocabulary", status_code=status.HTTP_201_CREATED) -def create_test_vocabulary( - content: schemas.TestVocabularyCreate, db: Session = Depends(get_db) -): - return crud.create_test_vocabulary(db, content).id - - @websocketRouter.websocket("/sessions/{session_id}") async def websocket_session( session_id: int, @@ -691,10 +684,308 @@ async def webhook_session( raise HTTPException(status_code=400, detail="Invalid trigger event") +@surveyRouter.post("", status_code=status.HTTP_201_CREATED) +def create_survey( + survey: schemas.SurveyCreate, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, detail="You do not have permission to create a survey" + ) + + return crud.create_survey(db, survey).id + + +@surveyRouter.get("", response_model=list[schemas.Survey]) +def get_surveys( + db: Session = Depends(get_db), +): + return crud.get_surveys(db) + + +@surveyRouter.get("/{survey_id}", response_model=schemas.Survey) +def get_survey( + survey_id: int, + db: Session = Depends(get_db), +): + survey = crud.get_survey(db, survey_id) + if survey is None: + raise HTTPException(status_code=404, detail="Survey not found") + + return survey + + +@surveyRouter.delete("/{survey_id}", status_code=status.HTTP_204_NO_CONTENT) +def delete_survey( + survey_id: int, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, detail="You do not have permission to delete a survey" + ) + + crud.delete_survey(db, survey_id) + + +@surveyRouter.post("/{survey_id}/groups", status_code=status.HTTP_201_CREATED) +def create_survey_group( + survey_id: int, + group: schemas.SurveyGroupCreate, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, + detail="You do not have permission to create a survey group", + ) + + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + return crud.create_survey_group(db, survey_id, group).id + + +@surveyRouter.get("/{survey_id}/groups", response_model=list[schemas.SurveyGroup]) +def get_survey_groups( + survey_id: int, + db: Session = Depends(get_db), +): + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + return crud.get_survey_groups(db, survey_id) + + +@surveyRouter.get("/{survey_id}/groups/{group_id}", response_model=schemas.SurveyGroup) +def get_survey_group( + survey_id: int, + group_id: int, + db: Session = Depends(get_db), +): + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + group = crud.get_survey_group(db, group_id) + if group is None: + raise HTTPException(status_code=404, detail="Survey group not found") + + return group + + +@surveyRouter.delete( + "/{survey_id}/groups/{group_id}", status_code=status.HTTP_204_NO_CONTENT +) +def delete_survey_group( + survey_id: int, + group_id: int, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, + detail="You do not have permission to delete a survey group", + ) + + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + crud.delete_survey_group(db, group_id) + + +@surveyRouter.post( + "/{survey_id}/groups/{group_id}/questions", status_code=status.HTTP_201_CREATED +) +def create_survey_question( + survey_id: int, + group_id: int, + question: schemas.SurveyQuestionCreate, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, + detail="You do not have permission to create a survey question", + ) + + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + return crud.create_survey_question(db, group_id, question).id + + +@surveyRouter.get( + "/{survey_id}/groups/{group_id}/questions", + response_model=list[schemas.SurveyQuestion], +) +def get_survey_questions( + survey_id: int, + group_id: int, + db: Session = Depends(get_db), +): + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + return crud.get_survey_questions(db, group_id) + + +@surveyRouter.get( + "/{survey_id}/groups/{group_id}/questions/{question_id}", + response_model=schemas.SurveyQuestion, +) +def get_survey_question( + survey_id: int, + group_id: int, + question_id: int, + db: Session = Depends(get_db), +): + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + question = crud.get_survey_question(db, question_id) + if question is None: + raise HTTPException(status_code=404, detail="Survey question not found") + + return question + + +@surveyRouter.delete( + "/{survey_id}/groups/{group_id}/questions/{question_id}", + status_code=status.HTTP_204_NO_CONTENT, +) +def delete_survey_question( + survey_id: int, + group_id: int, + question_id: int, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, + detail="You do not have permission to delete a survey question", + ) + + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + if not crud.get_survey_question(db, question_id): + raise HTTPException(status_code=404, detail="Survey question not found") + + crud.delete_survey_question(db, question_id) + + +@surveyRouter.post( + "/{survey_id}/groups/{group_id}/questions/{question_id}/options", + status_code=status.HTTP_201_CREATED, +) +def create_survey_option( + survey_id: int, + group_id: int, + question_id: int, + option: schemas.SurveyOptionCreate, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, + detail="You do not have permission to create a survey option", + ) + + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + if not crud.get_survey_question(db, question_id): + raise HTTPException(status_code=404, detail="Survey question not found") + + return crud.create_survey_option(db, question_id, option).id + + +@surveyRouter.get( + "/{survey_id}/groups/{group_id}/questions/{question_id}/options", + response_model=list[schemas.SurveyOption], +) +def get_survey_options( + survey_id: int, + group_id: int, + question_id: int, + db: Session = Depends(get_db), +): + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + if not crud.get_survey_question(db, question_id): + raise HTTPException(status_code=404, detail="Survey question not found") + + return crud.get_survey_options(db, question_id) + + +@surveyRouter.delete( + "/{survey_id}/groups/{group_id}/questions/{question_id}/options/{option_id}", + status_code=status.HTTP_204_NO_CONTENT, +) +def delete_survey_option( + survey_id: int, + group_id: int, + question_id: int, + option_id: int, + db: Session = Depends(get_db), + current_user: schemas.User = Depends(get_jwt_user), +): + if not check_user_level(current_user, models.UserType.ADMIN): + raise HTTPException( + status_code=401, + detail="You do not have permission to delete a survey option", + ) + + if not crud.get_survey(db, survey_id): + raise HTTPException(status_code=404, detail="Survey not found") + + if not crud.get_survey_group(db, group_id): + raise HTTPException(status_code=404, detail="Survey group not found") + + if not crud.get_survey_question(db, question_id): + raise HTTPException(status_code=404, detail="Survey question not found") + + if not crud.get_survey_option(db, option_id): + raise HTTPException(status_code=404, detail="Survey option not found") + + crud.delete_survey_option(db, option_id) + + v1Router.include_router(authRouter) v1Router.include_router(usersRouter) v1Router.include_router(sessionsRouter) v1Router.include_router(websocketRouter) v1Router.include_router(webhookRouter) +v1Router.include_router(surveyRouter) apiRouter.include_router(v1Router) app.include_router(apiRouter) diff --git a/backend/app/models.py b/backend/app/models.py index 56f44030d81ce5c7484576ddd5bd4a3b95ed1e5b..e337c2f91770a7cdf2a592a8ca85bd4b1c213574 100644 --- a/backend/app/models.py +++ b/backend/app/models.py @@ -131,8 +131,39 @@ class TestTypingEntry(Base): keyValue = Column(String) -class TestVocabulary(Base): - __tablename__ = "test_vocabulary" +class SurveyOption(Base): + __tablename__ = "survey_options" id = Column(Integer, primary_key=True, index=True) - content = Column(String) + question_id = Column(Integer, ForeignKey("survey_questions.id")) + correct = Column(Boolean) + type = Column(String) + value = Column(String) + + +class SurveyQuestion(Base): + __tablename__ = "survey_questions" + + id = Column(Integer, primary_key=True, index=True) + group_id = Column(Integer, ForeignKey("survey_groups.id")) + title = Column(String) + question_type = Column(String) + question_value = Column(String) + options = relationship("SurveyOption", backref="question") + + +class SurveyGroup(Base): + __tablename__ = "survey_groups" + + id = Column(Integer, primary_key=True, index=True) + survey_id = Column(Integer, ForeignKey("surveys.id")) + title = Column(String) + questions = relationship("SurveyQuestion", backref="group") + + +class Survey(Base): + __tablename__ = "surveys" + + id = Column(Integer, primary_key=True, index=True) + title = Column(String) + groups = relationship("SurveyGroup", backref="survey") diff --git a/backend/app/schemas.py b/backend/app/schemas.py index c41e7692fa1cb022c4e5aa3fa8d51ea8fa4d40a1..d0398d68ac2ce546f67340777bfc3996798b4b46 100644 --- a/backend/app/schemas.py +++ b/backend/app/schemas.py @@ -140,3 +140,52 @@ class CalComWebhook(BaseModel): triggerEvent: str createdAt: datetime.datetime payload: dict + + +class SurveyOption(BaseModel): + id: int + question_id: int + correct: bool + type: str + value: str + + +class SurveyOptionCreate(BaseModel): + correct: bool + type: str + value: str + + +class SurveyQuestionCreate(BaseModel): + title: str + question_type: str + question_value: str + + +class SurveyQuestion(BaseModel): + id: int + group_id: int + title: str + question_type: str + question_value: str + options: list[SurveyOption] + + +class SurveyGroupCreate(BaseModel): + title: str + + +class SurveyGroup(BaseModel): + id: int + survey_id: int + title: str + questions: list[SurveyQuestion] + + +class SurveyCreate(BaseModel): + title: str + + +class Survey(BaseModel): + id: int + groups: list[SurveyGroup]