system for validating answers to signup forms
This commit is contained in:
parent
6d8b06dfc7
commit
f8c576263c
@ -1,5 +1,5 @@
|
|||||||
from typing import Literal, Self
|
from typing import Literal, Self, Annotated
|
||||||
from pydantic import model_validator
|
from pydantic import model_validator, Field
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
@ -8,8 +8,17 @@ from .submodels import ActivityPaymentInfo
|
|||||||
from .enums import CommunicationCategory
|
from .enums import CommunicationCategory
|
||||||
|
|
||||||
from fiber_package.refs import SignupRefList
|
from fiber_package.refs import SignupRefList
|
||||||
|
from fiber_package.signup.signup import SignupModel
|
||||||
|
from fiber_package.signup.util import validate_answer
|
||||||
|
|
||||||
from fiber_package.signup.elements.form_element import FormElement
|
from fiber_package.signup.element.form_base_text import FormBaseText
|
||||||
|
from fiber_package.signup.element.form_base_question import FormBaseQuestion
|
||||||
|
|
||||||
|
# Special type which uses enum category to decide type!
|
||||||
|
FieldUnionType = Annotated[
|
||||||
|
FormBaseText | FormBaseQuestion,
|
||||||
|
Field(discriminator="category")
|
||||||
|
]
|
||||||
|
|
||||||
class ActivityModel(CommunicationModel):
|
class ActivityModel(CommunicationModel):
|
||||||
category: Literal[CommunicationCategory.activity]
|
category: Literal[CommunicationCategory.activity]
|
||||||
@ -22,7 +31,7 @@ class ActivityModel(CommunicationModel):
|
|||||||
|
|
||||||
payment_info: ActivityPaymentInfo | None = None
|
payment_info: ActivityPaymentInfo | None = None
|
||||||
|
|
||||||
form: list[FormElement]
|
form: list[FieldUnionType]
|
||||||
|
|
||||||
signups: SignupRefList = SignupRefList([], "signup")
|
signups: SignupRefList = SignupRefList([], "signup")
|
||||||
|
|
||||||
@ -34,3 +43,37 @@ class ActivityModel(CommunicationModel):
|
|||||||
if self.end_time < self.start_time:
|
if self.end_time < self.start_time:
|
||||||
raise ValueError("End time cannot be earlier than start time")
|
raise ValueError("End time cannot be earlier than start time")
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
def validate_signup_form(self, signup: SignupModel) -> None:
|
||||||
|
required = set()
|
||||||
|
answerable = set()
|
||||||
|
|
||||||
|
question_dict: dict[str, FormBaseQuestion] = {}
|
||||||
|
|
||||||
|
for element in self.form:
|
||||||
|
if isinstance(element, FormBaseText):
|
||||||
|
continue
|
||||||
|
# so we know it is istance of FormBaseQuestion
|
||||||
|
answerable.add(element.name)
|
||||||
|
if element.required:
|
||||||
|
required.add(element.name)
|
||||||
|
question_dict[element.name] = element
|
||||||
|
|
||||||
|
answers = signup.answers
|
||||||
|
for answer in answers:
|
||||||
|
q_name = answer.question_name
|
||||||
|
if q_name not in answerable:
|
||||||
|
raise ValueError(
|
||||||
|
f"Form contains answer to "
|
||||||
|
f"non-existing question {q_name}."
|
||||||
|
)
|
||||||
|
answerable.remove(q_name)
|
||||||
|
if answer.question_name in required:
|
||||||
|
required.remove(q_name)
|
||||||
|
|
||||||
|
question = question_dict[q_name]
|
||||||
|
validate_answer(question, answer)
|
||||||
|
|
||||||
|
|
||||||
|
if len(required) > 0:
|
||||||
|
raise ValueError("Form does not answer all required questions.")
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
from .form_element import FormElement
|
from .form_element import FormElement
|
||||||
|
from fiber_package.signup.enums import FormQuestionCategory
|
||||||
|
|
||||||
class FormBaseQuestion(FormElement):
|
class FormBaseQuestion(FormElement):
|
||||||
|
category: FormQuestionCategory
|
||||||
|
|
||||||
required: bool
|
required: bool
|
||||||
|
|
||||||
title: str | None = None
|
title: str | None = None
|
||||||
|
|||||||
5
src/fiber_package/signup/element/form_base_text.py
Normal file
5
src/fiber_package/signup/element/form_base_text.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
from .form_element import FormElement
|
||||||
|
from fiber_package.signup.enums import FormTextCategory
|
||||||
|
|
||||||
|
class FormBaseText(FormElement):
|
||||||
|
category: FormTextCategory
|
||||||
@ -12,3 +12,8 @@ class FormElementCategory(StrEnum):
|
|||||||
FormQuestionCategory = Literal[
|
FormQuestionCategory = Literal[
|
||||||
FormElementCategory.open_questions
|
FormElementCategory.open_questions
|
||||||
]
|
]
|
||||||
|
|
||||||
|
FormTextCategory = Literal[
|
||||||
|
FormElementCategory.text_piece,
|
||||||
|
FormElementCategory.title_text
|
||||||
|
]
|
||||||
|
|||||||
18
src/fiber_package/signup/util.py
Normal file
18
src/fiber_package/signup/util.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from fiber_package.signup.element.form_base_question import FormBaseQuestion
|
||||||
|
from fiber_package.signup.element.form_open_questions import FormOpenQuestions
|
||||||
|
|
||||||
|
from fiber_package.signup.answer.answer_base import AnswerBase
|
||||||
|
from fiber_package.signup.enums import FormElementCategory
|
||||||
|
|
||||||
|
from fiber_package.signup.answer.answer_open_questions import AnswerOpenQuestions
|
||||||
|
|
||||||
|
def validate_answer(question: FormBaseQuestion, answer: AnswerBase) -> None:
|
||||||
|
if question.category != answer.category:
|
||||||
|
raise ValueError("Question and answer category do not match!")
|
||||||
|
|
||||||
|
if question.category == FormElementCategory.open_questions:
|
||||||
|
question_val = FormOpenQuestions.model_validate(question.model_dump())
|
||||||
|
answer_val = AnswerOpenQuestions.model_validate(answer.model_dump())
|
||||||
|
question_val.validate_answer(answer_val)
|
||||||
|
|
||||||
|
# TODO: implement
|
||||||
Loading…
x
Reference in New Issue
Block a user