Skip to content

API Reference

REST endpoints

Full endpoint documentation: Smart Groups on ReDoc ⧉

Method Path Description
GET /smart-groups/ List all smart groups
GET /smart-groups/<smart_group_id> Get a single smart group
GET /smart-groups/<smart_group_id>/members Get current members
GET /smart-groups/<smart_group_id>/members/<date> Get members on a specific date (past: from DB history, future: computed from definition)

Code reference

apps.eu_tools.alan_home.models.smart_group.SmartGroup

Bases: BaseAlanGroup

__alan_home_path__ class-attribute instance-attribute

__alan_home_path__ = 'team/smart-groups'

__tablename__ class-attribute instance-attribute

__tablename__ = 'smart_group'

can_be_used_as_smart_roster class-attribute instance-attribute

can_be_used_as_smart_roster = mapped_column(
    Boolean,
    default=True,
    server_default=true(),
    nullable=False,
)

external_users class-attribute instance-attribute

external_users = relationship(
    "ExternalUser",
    secondary="smart_group_membership",
    primaryjoin="and_(SmartGroup.id == SmartGroupMembership.smart_group_id, SmartGroupMembership.is_active)",
    secondaryjoin="SmartGroupMembership.external_user_id == ExternalUser.id",
    back_populates="smart_groups",
    uselist=True,
)

github_parent_group_id class-attribute instance-attribute

github_parent_group_id = mapped_column(Integer)

github_url class-attribute instance-attribute

github_url = mapped_column(Text)

members class-attribute instance-attribute

members = relationship(
    "Alaner",
    secondary="smart_group_membership",
    primaryjoin="and_(SmartGroup.id == SmartGroupMembership.smart_group_id, SmartGroupMembership.is_active)",
    secondaryjoin="SmartGroupMembership.alaner_id == Alaner.id",
    back_populates="smart_groups",
    uselist=True,
)

members_query class-attribute instance-attribute

members_query = mapped_column(Text)

ownership class-attribute instance-attribute

ownership = relationship(
    "Ownership",
    foreign_keys="Ownership.smart_group_id",
    primaryjoin="Ownership.smart_group_id == SmartGroup.id",
    back_populates="smart_group",
    uselist=True,
    order_by="Ownership.created_at.asc()",
)

smart_group_definition_id class-attribute instance-attribute

smart_group_definition_id = mapped_column(
    Text, nullable=False, unique=True
)

apps.eu_tools.alan_home.models.smart_group_membership.SmartGroupMembership

Bases: HistorizableAlanerRelation

__table_args__ class-attribute instance-attribute

__table_args__ = (
    ExcludeConstraint(
        ("alaner_id", "="),
        ("smart_group_id", "="),
        (
            text("daterange(start_date, end_date, '[]')"),
            "&&",
        ),
        where="is_cancelled = false",
        name="non_overlapping_active_membership_per_alaner_and_smart_group",
    ),
    ExcludeConstraint(
        ("external_user_id", "="),
        ("smart_group_id", "="),
        (
            text("daterange(start_date, end_date, '[]')"),
            "&&",
        ),
        where="is_cancelled = false",
        name="non_overlapping_active_membership_per_external_and_smart_group",
    ),
    CheckConstraint(
        "num_nonnulls(alaner_id, external_user_id) = 1",
        name="smart_group_membership_alaner_xor_external_user_id_set",
    ),
    *(__table_args__),
)

__tablename__ class-attribute instance-attribute

__tablename__ = 'smart_group_membership'

external_user class-attribute instance-attribute

external_user = relationship(
    "ExternalUser",
    primaryjoin="foreign(SmartGroupMembership.external_user_id) == ExternalUser.id",
    uselist=False,
)

external_user_id class-attribute instance-attribute

external_user_id = mapped_column(
    UUID(as_uuid=True), nullable=True, index=True
)

smart_group class-attribute instance-attribute

smart_group = relationship(
    SmartGroup, foreign_keys=[smart_group_id], uselist=False
)

smart_group_id class-attribute instance-attribute

smart_group_id = mapped_column(
    UUID(as_uuid=True),
    ForeignKey(id),
    nullable=False,
    index=True,
)

apps.eu_tools.alan_home.commands.smart_groups.smart_group_definition.BaseSmartGroupDefinition

Bases: ABC

active_external_users classmethod

active_external_users()
Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
def active_external_users(cls) -> set[ExternalUser]:
    return {
        external_user
        for external_user in cls.external_users()
        if external_user and not external_user.is_ended
    }

active_members classmethod

active_members()
Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
def active_members(cls) -> set[Alaner]:
    return {
        alaner
        for alaner in cls.members_on(utctoday())
        if alaner and not alaner.is_ended
    }

can_be_used_as_smart_roster class-attribute instance-attribute

can_be_used_as_smart_roster = True

description instance-attribute

description

external_users classmethod

external_users()
Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
def external_users(cls) -> set[ExternalUser]:
    return set()

external_users_on classmethod

external_users_on(date)
Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
def external_users_on(cls, date: datetime.date) -> set[ExternalUser]:  # noqa: ARG003
    return set()

github_handle class-attribute instance-attribute

github_handle = None

github_parent_group_id class-attribute instance-attribute

github_parent_group_id = None

google_group class-attribute instance-attribute

google_group = None

members classmethod

members()

Deprecated: Override members_on instead. This default implementation delegates to members_on with today's date.

Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
@deprecated("Use members_on instead", category=AlanDeprecationWarning)
def members(cls) -> set[Alaner]:
    """
    Deprecated: Override members_on instead.
    This default implementation delegates to members_on with today's date.
    """
    return cls.members_on(utctoday())

members_on classmethod

members_on(date)

Default implementation delegates to legacy members() method. New classes should override this method instead of members().

Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
def members_on(cls, date: datetime.date) -> set[Alaner]:  # noqa: ARG003
    """
    Default implementation delegates to legacy members() method.
    New classes should override this method instead of members().
    """
    if cls.members.__func__ is not BaseSmartGroupDefinition.members.__func__:  # type: ignore[attr-defined]
        # Legacy class: delegate to members()
        return cls.members()
    else:
        # Child class that hasn't implemented either method
        raise NotImplementedError(
            f"{cls.__name__} must implement members_on(cls, date: datetime.date)"
        )

name instance-attribute

name

sanity_check classmethod

sanity_check()

Override to perform a custom sanity check and raise an exception (e.g. ValueError) if the group members should NOT be updated

Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
def sanity_check(cls) -> None:
    """Override to perform a custom sanity check and raise an exception (e.g. ValueError) if the group members should NOT be updated"""
    return

slack_handle class-attribute instance-attribute

slack_handle = None

sync_with_sana class-attribute instance-attribute

sync_with_sana = False

apps.eu_tools.alan_home.commands.smart_groups.smart_group_definition.SmartGroupDefinition

apps.eu_tools.alan_home.commands.smart_groups.smart_group_definition.SmartGroupGenerator

Bases: ABC

smart_groups abstractmethod classmethod

smart_groups()
Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
@classmethod
@abstractmethod
def smart_groups(cls) -> Collection[type[BaseSmartGroupDefinition]]:
    pass

apps.eu_tools.alan_home.commands.smart_groups.smart_group_definition.get_all_smart_group_definitions

get_all_smart_group_definitions()
Source code in apps/eu_tools/alan_home/commands/smart_groups/smart_group_definition.py
def get_all_smart_group_definitions() -> dict[str, type[BaseSmartGroupDefinition]]:
    smart_group_definitions: dict[str, type[BaseSmartGroupDefinition]] = {
        slugify(smart_group_definition.name): smart_group_definition
        for smart_group_definition in SmartGroupDefinition.__subclasses__()
    }

    smart_group_definitions.update(
        {
            slugify(smart_group_definition.name): smart_group_definition
            for smart_group_definition_generator in SmartGroupGenerator.__subclasses__()
            for smart_group_definition in smart_group_definition_generator.smart_groups()
        }
    )

    return smart_group_definitions