76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
from typing import Literal, Self
|
|
from pydantic import model_validator
|
|
|
|
from datetime import datetime
|
|
|
|
from .communication import CommunicationModel
|
|
from .submodels import ActivityPaymentInfo
|
|
from .enums import CommunicationCategory
|
|
|
|
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.enums import is_question_category
|
|
|
|
from fiber_package.signup.element.form_base_question import FormBaseQuestion
|
|
|
|
from fiber_package.signup.element.types import FormElementUnion, FormTextUnion
|
|
|
|
class ActivityModel(CommunicationModel):
|
|
category: Literal[CommunicationCategory.activity]
|
|
|
|
slug: str
|
|
# unique short name used in the public URL
|
|
|
|
start_time: datetime
|
|
end_time: datetime
|
|
|
|
payment_info: ActivityPaymentInfo | None = None
|
|
|
|
form: list[FormElementUnion]
|
|
|
|
signups: SignupRefList = SignupRefList([], "signup")
|
|
|
|
# TODO: see Felt 'activiteiten' DB schema. Things like:
|
|
# email, target group, maximal attendees ....
|
|
|
|
@model_validator(mode='after')
|
|
def check_end_after_start(self) -> Self:
|
|
if self.end_time < self.start_time:
|
|
raise ValueError("End time cannot be earlier than start time")
|
|
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 not is_question_category(element.category):
|
|
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.")
|