Activity system #3

Merged
tscholten merged 23 commits from tiago/activities into master 2026-10-17 15:51:00 +00:00
6 changed files with 79 additions and 5 deletions
Showing only changes of commit f8c576263c - Show all commits

View File

@ -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.")

View File

@ -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

View File

@ -0,0 +1,5 @@
from .form_element import FormElement
from fiber_package.signup.enums import FormTextCategory
class FormBaseText(FormElement):
category: FormTextCategory

View File

@ -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
]

View 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