diff --git a/src/fiber_package/entities/member.py b/src/fiber_package/entities/member.py index 1f32690..3499199 100644 --- a/src/fiber_package/entities/member.py +++ b/src/fiber_package/entities/member.py @@ -1,4 +1,4 @@ -from typing import Annotated +from typing import Literal from pydantic import Field from .non_members import FormerMemberModel @@ -7,7 +7,7 @@ from .submodels import Address, LoginInfo class MemberModel(FormerMemberModel): # requires that Membership equals member - membership: Annotated[Membership, Field(pattern="member")] + membership: Literal[Membership.member] = Membership.member login: LoginInfo address: Address diff --git a/src/fiber_package/entities/non_members.py b/src/fiber_package/entities/non_members.py index afc29bb..7eb3856 100644 --- a/src/fiber_package/entities/non_members.py +++ b/src/fiber_package/entities/non_members.py @@ -1,4 +1,4 @@ -from typing import Annotated +from typing import Literal from pydantic import Field from .person import PersonModel @@ -13,12 +13,12 @@ class FormerMemberModel(PersonModel): # company emails? class AlumnModel(FormerMemberModel): - membership: Annotated[Membership, Field(pattern="alumn")] + membership: Literal[Membership.alumn] = Membership.alumn graduated: bool = False receive_spam_mail: bool = True class ExternalModel(PersonModel): - membership: Annotated[Membership, Field(pattern="extern")] + membership: Literal[Membership.extern] = Membership.extern # TODO... payment??? # TODO require login info?? diff --git a/src/fiber_package/groups/association.py b/src/fiber_package/groups/association.py index 6a1011a..97c9753 100644 --- a/src/fiber_package/groups/association.py +++ b/src/fiber_package/groups/association.py @@ -4,9 +4,9 @@ from fiber_package.util import EntityList class AssociationModel(BaseModel): full_name: str - members: EntityList = EntityList("member", []) - # committees: GroupList("commmittee", 0) # type: ignore - # events: GroupList("event", 0) # type: ignore - # activities: GroupList("activity", 0) # type: ignore - # mailings: GroupList("mailing", 0) # type: ignore - # mailalias: GroupList("mailalias", 0) # type: ignore \ No newline at end of file + members: EntityList + committees: GroupList + guilds: GroupList + # events: GroupList + # activities: GroupList + # mailings: GroupList \ No newline at end of file diff --git a/src/fiber_package/groups/committees/committee.py b/src/fiber_package/groups/committees/committee.py index d81b183..a236cb4 100644 --- a/src/fiber_package/groups/committees/committee.py +++ b/src/fiber_package/groups/committees/committee.py @@ -1,10 +1,15 @@ -from pydantic import BaseModel +from pydantic import BaseModel, model_validator from fiber_package.util import EntityList, GroupList, GroupRef +from typing import Self +from datetime import date + from .enums import CommitteeType ''' -A committee represents any group of members +Committees are groups of members for a definite period. +Every committee has a list of editions. +An edition is a definite group of members with functions and a timespan. ''' class CommitteeModel(BaseModel): @@ -15,8 +20,8 @@ class CommitteeModel(BaseModel): active: bool = True - editions: GroupList("committee_edition", []) - current_edition: GroupRef("committee_edition", None) + editions: GroupList + current_edition: GroupRef @model_validator(mode='after') def current_edition_in_editions(self) -> Self: @@ -28,9 +33,12 @@ class CommitteeModel(BaseModel): return self class CommitteeEditionModel(BaseModel): - members: EntityList = EntityList("member", []) + members: EntityList functions: dict[UUID4, str] + start_date: date + end_date: date | None # None means ongoing + @model_validator(mode='after') def functions_to_members_only(self) -> Self: for uuid in self.functions.keys(): diff --git a/src/fiber_package/groups/committees/enums.py b/src/fiber_package/groups/committees/enums.py index fe78120..182ed6c 100644 --- a/src/fiber_package/groups/committees/enums.py +++ b/src/fiber_package/groups/committees/enums.py @@ -2,8 +2,7 @@ from enum import StrEnum class CommitteeType(StrEnum): board_committee: "Board committee" - GMM_committee: "GMM committee" - guild: "Guild" - subassociation_board: "Subassociation board" + gmm_committee: "GMM committee" + board: "board" diff --git a/src/fiber_package/groups/committees/guild.py b/src/fiber_package/groups/committees/guild.py new file mode 100644 index 0000000..e21e107 --- /dev/null +++ b/src/fiber_package/groups/committees/guild.py @@ -0,0 +1,42 @@ +from pydantic import BaseModel, model_validator +from fiber_package.util import EntityList + +from datetime import date + +from typing import Self + + +''' +Guilds are groups of members for an indefinite period. +They have a list of members. + +Removing old members from last_active is done in fiber +''' + +class GuildModel(BaseModel): + full_name_EN: str + full_name_NL: str + description_EN: str + description_NL: str + + members: EntityList + previous_members: EntityList + + guild_masters: EntityList + + last_active: dict[EntityRef, date] + + @model_validator(mode='after') + def current_members_not_previous(self) -> Self: + for member in self.members: + if member in self.previous_members: + raise ValueError("There can be no overlap between members and previous members!") + return self + + @model_validator(mode='after') + def guild_masters_are_members(self) -> Self: + for master in self.guild_masters: + if master not in self.members: + raise ValueError("All guild masters must be members!") + return self + \ No newline at end of file diff --git a/src/fiber_package/groups/root.py b/src/fiber_package/groups/root.py index 594962e..2d3bfbd 100644 --- a/src/fiber_package/groups/root.py +++ b/src/fiber_package/groups/root.py @@ -2,5 +2,5 @@ from pydantic import BaseModel from fiber_package.util import GroupList, EntityList class RootGroupModel(BaseModel): - associations: GroupList = GroupList("association", []) - sys_admins: EntityList = EntityList("login", []) \ No newline at end of file + associations: GroupList + sys_admins: EntityList \ No newline at end of file diff --git a/src/fiber_package/util.py b/src/fiber_package/util.py index 8973966..a851a38 100644 --- a/src/fiber_package/util.py +++ b/src/fiber_package/util.py @@ -2,22 +2,32 @@ from dataclasses import dataclass, field from pydantic import UUID4 +''' +(Entity/Group)(List/Ref) represents a list / single instance of entities / groups. +This is for fiber to know in which Mongo collection to look. + +the __iter__ function allows us to do things as + "for member in edition.members" +''' + @dataclass(slots=True) class EntityList: - template: str uuids: list[UUID4] = field(default_factory=list) + def __iter__(self): + return iter(self.uuids) + @dataclass(slots=True) class GroupList: - template: str uuids: list[UUID4] = field(default_factory=list) + def __iter__(self): + return iter(self.uuids) + @dataclass(slots=True) class EntityRef: - template: str - uuids: UUID4 | None = None + uuids: UUID4 @dataclass(slots=True) class GroupRef: - template: str - uuids: UUID4 | None = None \ No newline at end of file + uuids: UUID4 \ No newline at end of file