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