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