diff --git a/src/fiber_package/groups/communication.py b/src/fiber_package/groups/communication.py new file mode 100644 index 0000000..13c3d24 --- /dev/null +++ b/src/fiber_package/groups/communication.py @@ -0,0 +1,74 @@ +from pydantic import BaseModel, model_validator, Field, HttpUrl +from enum import StrEnum +from typing import Annotated, Self +from fiber_package.util import GroupRef +from datetime import datetime + + +# may be moved to another file if used elsewhere +''' +The category is only used to place the communication correctly in the weekly +mailing and the board-website, it is not visible (or relevant) to readers +''' +class CommunicationCategory(StrEnum): + announcement = "announcement" + news = "news" + activity = "activity" + + +''' +A "communication" is a piece of communication/promotion to be shared with +members, which may appear on the website and in the weekly mailing. +''' +class CommunicationModel(BaseModel): + category: CommunicationCategory + + name_en: str + name_nl: str + + subtitle_en: str + subtitle_nl: str + # subtitles currently (2026) appear only in the table of contents in the + # weekly mailing; they are meant to be a short catchy flavour text + + description_en: str + description_nl: str + + image: HttpUrl | None + # often, a poster comes associated with a communication (in particular if + # it's an activity). In that case, the poster is uploaded to the cloud and + # the share link is attached to the communication + # TODO: potentially rethink the way images are attached to communications + + visibility: bool + # should this communication be shown to members at all? Useful for + # temporarily hiding a communication + + only_members: bool + # is this communication only visible to members? This refers to visibility + # on the website, i.e. is this only visible to visitors who are logged in? + + archived: bool + # an archived communication cannot be edited, only viewed for future + # reference + + + +class ActivityModel(CommunicationModel): + category: Annotated[ + CommunicationCategory, + Field(pattern=CommunicationCategory.activity) + ] + + signuplist: GroupRef = GroupRef("signuplist", None) + # TODO: validate that a signuplist can only be attached if category is + # activity? Or should this not be validated? + + start_time: datetime + end_time: datetime + + @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 diff --git a/src/fiber_package/groups/signuplist.py b/src/fiber_package/groups/signuplist.py new file mode 100644 index 0000000..042c2a4 --- /dev/null +++ b/src/fiber_package/groups/signuplist.py @@ -0,0 +1,12 @@ +from pydantic import BaseModel + +from fiber_package.util import GroupRef + + +''' +A sign-up list is a list of members that have signed up for a given activity. +''' +class SignuplistModel(BaseModel): + activity: GroupRef = GroupRef("communication", None) + # TODO: validate that the communication is indeed an activity (or should + # this be done?) diff --git a/src/fiber_package/util.py b/src/fiber_package/util.py index 8973966..6077523 100644 --- a/src/fiber_package/util.py +++ b/src/fiber_package/util.py @@ -15,9 +15,9 @@ class GroupList: @dataclass(slots=True) class EntityRef: template: str - uuids: UUID4 | None = None + uuid: UUID4 | None = None @dataclass(slots=True) class GroupRef: template: str - uuids: UUID4 | None = None \ No newline at end of file + uuid: UUID4 | None = None