added form submission

This commit is contained in:
Alexander Karpov 2022-12-09 12:09:22 +03:00
parent 145c322fb5
commit d9f084d48f
5 changed files with 175 additions and 11 deletions

View File

@ -145,3 +145,12 @@ class UserFormFieldSubmission(Base):
"UserFormSubmission", "UserFormSubmission",
foreign_keys="UserFormFieldSubmission.submission_id", foreign_keys="UserFormFieldSubmission.submission_id",
) )
# question
question_id: int = Column(Integer, ForeignKey(FormQuestion.id), primary_key=True)
question: FormQuestion = relationship(
"FormQuestion",
foreign_keys="UserFormFieldSubmission.question_id",
)
answer: str = Column(String)

View File

@ -3,14 +3,22 @@ from typing import List
from fastapi import HTTPException from fastapi import HTTPException
from sqlalchemy import select, update from sqlalchemy import select, update
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload
from med_backend.db.models.forms import ( from med_backend.db.models.forms import (
FormAssignment, FormAssignment,
FormQuestion, FormQuestion,
FormScheme, FormScheme,
UserFormFieldSubmission,
UserFormSubmission,
UserRevQuestion, UserRevQuestion,
) )
from med_backend.forms.schemas import BaseForm, CreateFormField from med_backend.forms.schemas import (
BaseForm,
CreateFormField,
FullAnswer,
FullSubmission,
)
from med_backend.users.crud import get_user from med_backend.users.crud import get_user
@ -166,3 +174,84 @@ async def create_user_form_rev_question(
await session.commit() await session.commit()
await session.refresh(rev) await session.refresh(rev)
return rev return rev
async def create_submission(session: AsyncSession, form_id: int, user_id: int):
user = await get_user(session, user_id)
if not user:
raise HTTPException(status_code=422, detail="User can't be used")
form = await get_form(session, form_id)
if not form:
raise HTTPException(status_code=422, detail="Form can't be used")
obj = UserFormSubmission(form_id=form_id, user_id=user_id)
session.add(obj)
await session.commit()
await session.refresh(obj)
return obj
async def create_submission_answer(
session: AsyncSession,
sumb_id: int,
field_id: int,
data: str,
):
r = await session.execute(select(FormQuestion).where(FormQuestion.id == field_id))
field = r.scalars().first()
if not field:
raise HTTPException(status_code=422, detail="Such field doesn't exist")
obj = UserFormFieldSubmission(
submission_id=sumb_id,
question_id=field_id,
answer=data,
)
session.add(obj)
await session.commit()
await session.refresh(obj)
return obj
async def get_submissions(session: AsyncSession, form_id: int) -> List[FullSubmission]:
r = await session.execute(
select(UserFormSubmission)
.options(selectinload(UserFormSubmission.answers))
.options(selectinload(UserFormSubmission.user))
.where(UserFormSubmission.form_id == form_id),
)
submissions = r.scalars().all()
res: List[FullSubmission] = []
for submission in submissions:
answers: List[FullAnswer] = []
for answer in submission.answers:
r = await session.execute(
select(UserRevQuestion)
.where(UserRevQuestion.user_id == submission.user.id)
.where(UserRevQuestion.question_id == answer.question_id),
)
obj = r.scalars().first()
ref_min = None
ref_max = None
if obj:
ref_min = obj.ref_min
ref_max = obj.ref_max
r = await session.execute(
select(FormQuestion).where(FormQuestion.id == answer.question_id),
)
obj = r.scalars().first()
answers.append(
FullAnswer(
field_id=obj.id,
question=obj.question,
type=obj.type,
answer=answer.answer,
ref_min=ref_min if ref_min else obj.ref_min,
ref_max=ref_max if ref_max else obj.ref_max,
),
)
res.append(FullSubmission(fio=submission.user.fullname, answers=answers))
return res

View File

@ -2,8 +2,6 @@ from typing import List
from pydantic import BaseModel from pydantic import BaseModel
from med_backend.auth.schemas import UserPublicInfo
class Question(BaseModel): class Question(BaseModel):
id: int id: int
@ -40,6 +38,25 @@ class FormAssigment(BaseModel):
question_refs: List[QuestionRef] question_refs: List[QuestionRef]
class FormAnswer(BaseModel):
field_id: int
answer: str
class FullAnswer(BaseModel):
field_id: int
question: str
type: str
answer: str
ref_min: int | None
ref_max: int | None
class FullSubmission(BaseModel):
fio: str
answers: List[FullAnswer]
class BaseForm(BaseModel): class BaseForm(BaseModel):
name: str name: str
@ -57,7 +74,6 @@ class ListForm(BaseForm):
class Form(BaseForm): class Form(BaseForm):
id: int id: int
user: UserPublicInfo
questions: List[Question] questions: List[Question]
class Config: class Config:

View File

@ -1,15 +1,18 @@
from typing import List
from fastapi import HTTPException from fastapi import HTTPException
from pydantic import parse_obj_as
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from med_backend.auth.schemas import UserPublicInfo
from med_backend.forms.crud import ( from med_backend.forms.crud import (
create_form_assigment, create_form_assigment,
create_submission,
create_submission_answer,
create_user_form_rev_question, create_user_form_rev_question,
get_form, get_form,
get_questions, get_questions,
get_submissions,
) )
from med_backend.forms.schemas import Form, FormAssigment, Question from med_backend.forms.schemas import Form, FormAnswer, FormAssigment, Question
async def get_full_form(session: AsyncSession, form_id: int) -> Form: async def get_full_form(session: AsyncSession, form_id: int) -> Form:
@ -21,7 +24,6 @@ async def get_full_form(session: AsyncSession, form_id: int) -> Form:
return Form( return Form(
id=form_id, id=form_id,
name=form.name, name=form.name,
user=parse_obj_as(UserPublicInfo, form.user),
questions=[ questions=[
Question(id=q.id, type=q.type, question=q.question) for q in questions Question(id=q.id, type=q.type, question=q.question) for q in questions
], ],
@ -41,3 +43,22 @@ async def assign_form(session: AsyncSession, data: FormAssigment, form_id: int):
field.ref_min, field.ref_min,
field.ref_max, field.ref_max,
) )
async def submit_form(
session: AsyncSession,
data: List[FormAnswer],
form_id: int,
user_id: int,
):
subm = await create_submission(session, form_id, user_id)
for answer in data:
await create_submission_answer(session, subm.id, answer.field_id, answer.answer)
async def get_form_submissions(session: AsyncSession, form_id: int):
form = await get_form(session, form_id)
if not form:
raise HTTPException(status_code=404, detail="Form doesn't exist")
submissions = await get_submissions(session, form_id)
return submissions

View File

@ -12,11 +12,13 @@ from med_backend.forms.schemas import (
BaseForm, BaseForm,
CreateFormField, CreateFormField,
Form, Form,
FormAnswer,
FormAssigment, FormAssigment,
FormField, FormField,
FullSubmission,
ListForm, ListForm,
) )
from med_backend.forms.services import assign_form from med_backend.forms.services import assign_form, submit_form
from med_backend.users.services import get_current_active_manager from med_backend.users.services import get_current_active_manager
router = APIRouter() router = APIRouter()
@ -34,7 +36,7 @@ async def get_all_forms(
@router.get("/list", response_model=list[ListForm]) @router.get("/list", response_model=list[ListForm])
async def get_all_forms( async def get_all_user_forms(
skip: int = 0, skip: int = 0,
limit: int = 100, limit: int = 100,
current_user: User = Depends(get_current_active_user), current_user: User = Depends(get_current_active_user),
@ -65,13 +67,29 @@ async def get_form(
return form return form
@router.get("/{form_id}/answers", response_model=List[FullSubmission])
async def get_form(
form_id: int,
current_user: User = Depends(get_current_active_manager),
session: AsyncSession = Depends(get_db_session),
):
form = await crud.get_form(session, form_id)
if form.user.id != current_user.id:
raise HTTPException(
status_code=401,
detail="You are not allowed to access this form",
)
submissions = await services.get_form_submissions(session, form_id)
return submissions
@router.get("/{form_id}/fields", response_model=List[FormField]) @router.get("/{form_id}/fields", response_model=List[FormField])
async def create_form_field_view( async def create_form_field_view(
form_id: int, form_id: int,
current_user: User = Depends(get_current_active_manager), current_user: User = Depends(get_current_active_manager),
session: AsyncSession = Depends(get_db_session), session: AsyncSession = Depends(get_db_session),
): ):
form = await services.get_form(session, form_id) form = await crud.get_form(session, form_id)
if form.user.id != current_user.id: if form.user.id != current_user.id:
raise HTTPException( raise HTTPException(
status_code=401, status_code=401,
@ -107,3 +125,14 @@ async def create_assigment_view(
) )
await assign_form(session, data, form_id) await assign_form(session, data, form_id)
return {"message": "created"} return {"message": "created"}
@router.post("/{form_id}/submit")
async def submit_form_view(
form_id: int,
data: List[FormAnswer],
current_user: User = Depends(get_current_active_user),
session: AsyncSession = Depends(get_db_session),
):
await submit_form(session, data, form_id, current_user.id)
return {"message": "created"}