API Reference¶
REST endpoints¶
Full endpoint documentation: On-Call Groups on ReDoc ⧉
| Method | Path | Description |
|---|---|---|
GET |
/oncall-groups/ |
List all active on-call groups (with slack_handle set) |
POST |
/oncall-groups/ |
Create a new on-call group |
GET |
/oncall-groups/<id> |
Get a single on-call group |
PATCH |
/oncall-groups/<id> |
Update an on-call group |
GET |
/oncall-groups/<id>/shifts |
List shifts (query params: start_date, end_date) |
POST |
/oncall-groups/<id>/shifts/update-request |
Trigger schedule update |
PUT |
/oncall-groups/<id>/shifts/<date>/<alaner_id> |
Add an alaner to a shift |
DELETE |
/oncall-groups/<id>/shifts/<date>/<alaner_id> |
Remove an alaner from a shift |
PATCH |
/oncall-groups/<id>/shifts/<date> |
Set load estimation for a date |
PUT |
/oncall-groups/<id>/roster/<alaner_id> |
Add an alaner to the roster |
DELETE |
/oncall-groups/<id>/roster/<alaner_id> |
Remove an alaner from the roster |
GET |
/oncall-groups/<id>/pending-members |
Get pending roster members (requested + approved but not yet synced) |
Code reference¶
apps.eu_tools.alan_home.models.oncall_group.OncallGroup ¶
Bases: BaseAlanGroup
__notion_database_id__
class-attribute
instance-attribute
¶
area
class-attribute
instance-attribute
¶
area_id
class-attribute
instance-attribute
¶
assembled_integration
class-attribute
instance-attribute
¶
bank_holiday_countries
class-attribute
instance-attribute
¶
calendar_invite_description
class-attribute
instance-attribute
¶
calendar_next_sync_token
class-attribute
instance-attribute
¶
calendar_watch_channel_id
class-attribute
instance-attribute
¶
calendar_watch_resource_id
class-attribute
instance-attribute
¶
disabled
class-attribute
instance-attribute
¶
external_users
class-attribute
instance-attribute
¶
external_users = relationship(
"ExternalUser",
secondary="oncall_group_shift",
primaryjoin="and_(OncallGroup.id == OncallGroupShift.oncall_group_id, cast(OncallGroupShift.date, Date) == func.current_date(), OncallGroupShift.declined_on.is_(None))",
secondaryjoin="and_(OncallGroupShift.external_user_id == ExternalUser.id, not_(ExternalUser.is_ended))",
back_populates="current_oncall_groups",
uselist=True,
order_by="ExternalUser.email",
viewonly=True,
)
external_users_roster
class-attribute
instance-attribute
¶
external_users_roster = relationship(
"ExternalUser",
secondary="oncall_group_membership",
primaryjoin="and_(OncallGroup.id == OncallGroupMembership.oncall_group_id, OncallGroupMembership.is_active)",
secondaryjoin="OncallGroupMembership.external_user_id == ExternalUser.id",
back_populates="oncall_groups",
uselist=True,
order_by="ExternalUser.email",
)
grace_period_after_long_ooo
class-attribute
instance-attribute
¶
grace_period_after_long_ooo = mapped_column(
Boolean,
default=True,
server_default=true(),
nullable=False,
)
has_load_estimation
class-attribute
instance-attribute
¶
included_days
class-attribute
instance-attribute
¶
included_days_validator ¶
Source code in apps/eu_tools/alan_home/models/oncall_group.py
is_active ¶
members
class-attribute
instance-attribute
¶
members = relationship(
"Alaner",
secondary="oncall_group_shift",
primaryjoin="and_(OncallGroup.id == OncallGroupShift.oncall_group_id, cast(OncallGroupShift.date, Date) == func.current_date(), OncallGroupShift.declined_on.is_(None))",
secondaryjoin="and_(OncallGroupShift.alaner_id == Alaner.id, not_(Alaner.is_ended))",
back_populates="current_oncall_groups",
uselist=True,
order_by="Alaner.slack_handle",
viewonly=True,
)
ownership
class-attribute
instance-attribute
¶
ownership = relationship(
"Ownership",
foreign_keys="Ownership.oncall_group_id",
primaryjoin="Ownership.oncall_group_id == OncallGroup.id",
back_populates="oncall_group",
uselist=True,
order_by="Ownership.created_at.asc()",
)
roster
class-attribute
instance-attribute
¶
roster = relationship(
"Alaner",
secondary="oncall_group_membership",
primaryjoin="and_(OncallGroup.id == OncallGroupMembership.oncall_group_id, OncallGroupMembership.is_active)",
secondaryjoin="OncallGroupMembership.alaner_id == Alaner.id",
back_populates="oncall_groups",
uselist=True,
order_by="Alaner.slack_handle",
)
roster_smart_group_id
class-attribute
instance-attribute
¶
rotation_size
class-attribute
instance-attribute
¶
rotation_type
class-attribute
instance-attribute
¶
scheduling_strategy_id
class-attribute
instance-attribute
¶
shifts
class-attribute
instance-attribute
¶
shifts = relationship(
"OncallGroupShift",
primaryjoin="OncallGroup.id == foreign(OncallGroupShift.oncall_group_id)",
back_populates="oncall_group",
uselist=True,
lazy="dynamic",
order_by="OncallGroupShift.date",
viewonly=True,
)
smart_roster
class-attribute
instance-attribute
¶
smart_roster = relationship(
"Alaner",
secondary="smart_group_membership",
primaryjoin="and_(OncallGroup.roster_smart_group_id == SmartGroupMembership.smart_group_id, SmartGroupMembership.is_active)",
secondaryjoin="SmartGroupMembership.alaner_id == Alaner.id",
back_populates="smart_oncall_groups",
uselist=True,
order_by="Alaner.slack_handle",
viewonly=True,
)
use_calendar_invite
class-attribute
instance-attribute
¶
use_calendar_invite = mapped_column(
Boolean,
default=True,
server_default=true(),
nullable=False,
)
validate_rotation_type
class-attribute
instance-attribute
¶
validate_slack_channel_name ¶
Source code in apps/eu_tools/alan_home/models/oncall_group.py
wrap_up_additional_message
class-attribute
instance-attribute
¶
apps.eu_tools.alan_home.models.oncall_group.OncallRotationType ¶
apps.eu_tools.alan_home.models.oncall_group_shift.OncallGroupShift ¶
Bases: BaseModel
__table_args__
class-attribute
instance-attribute
¶
__table_args__ = (
UniqueConstraint(
"oncall_group_id",
"date",
"alaner_id",
name="oncall_group_shift_oncall_group_id_date_alaner_id_key",
),
UniqueConstraint(
"oncall_group_id",
"date",
"external_user_id",
name="oncall_group_shift_oncall_group_id_date_external_user_id_key",
),
CheckConstraint(
"(alaner_id IS NULL) != (external_user_id IS NULL)",
name="oncall_group_shift_user_is_not_null",
),
)
alaner
class-attribute
instance-attribute
¶
alaner = relationship(
"Alaner",
foreign_keys=alaner_id,
primaryjoin="Alaner.id == OncallGroupShift.alaner_id",
uselist=False,
)
alaner_id
class-attribute
instance-attribute
¶
external_user
class-attribute
instance-attribute
¶
external_user = relationship(
"ExternalUser",
foreign_keys=external_user_id,
primaryjoin="ExternalUser.id == OncallGroupShift.external_user_id",
uselist=False,
)
external_user_id
class-attribute
instance-attribute
¶
oncall_group
class-attribute
instance-attribute
¶
oncall_group = relationship(
"OncallGroup",
foreign_keys=[oncall_group_id],
back_populates="shifts",
uselist=False,
)
oncall_group_id
class-attribute
instance-attribute
¶
apps.eu_tools.alan_home.models.oncall_group_membership.OncallGroupMembership ¶
Bases: HistorizableAlanerRelation, HistorizableExternalUserRelation
__table_args__
class-attribute
instance-attribute
¶
__table_args__ = (
CheckConstraint(
"(alaner_id IS NULL) != (external_user_id IS NULL)",
name="oncall_group_membership_user_is_not_null",
),
ExcludeConstraint(
("alaner_id", "="),
("external_user_id", "="),
("oncall_group_id", "="),
(
text("daterange(start_date, end_date, '[]')"),
"&&",
),
where="is_cancelled = false",
name="non_overlapping_active_membership_per_alaner_and_oncall_group",
),
*(__table_args__),
)
oncall_group
class-attribute
instance-attribute
¶
oncall_group = relationship(
"OncallGroup",
foreign_keys=[oncall_group_id],
uselist=False,
viewonly=True,
)
oncall_group_id
class-attribute
instance-attribute
¶
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.ASSEMBLED_EMAIL
module-attribute
¶
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.DAYS_BACKWARD
module-attribute
¶
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.DAYS_FORWARD
module-attribute
¶
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.TRIDUUM_SHIFT_GENESIS
module-attribute
¶
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.create_or_update_schedule ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/scheduling.py
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.find_shift_dates ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/scheduling.py
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.find_shift_for_swap ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/scheduling.py
505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | |
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.get_scheduling_strategy ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/scheduling.py
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.get_shift_dates ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/scheduling.py
apps.eu_tools.alan_home.business_logic.oncall_groups.scheduling.get_shifts_following_long_ooo ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/scheduling.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.OncallSchedulingStrategy ¶
Bases: ABC
fill_schedule_gap
abstractmethod
classmethod
¶
Fill gaps in a shift
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.build_candidate_pool ¶
build_candidate_pool(
oncall_group,
schedule,
oncall_date,
shift_start_date,
shift_end_date,
all_excluded_users,
)
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.get_alaners_back_from_long_ooo ¶
Returns list of Alaners who are on their first day back after being OOO for at least days_threshold consecutive days
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.get_candidates_pool_excluding_other_shifts ¶
get_candidates_pool_excluding_other_shifts(
schedule,
oncall_date,
shift_start_date,
shift_end_date,
oncall_group,
)
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.get_default_sorted_candidates_pool ¶
get_default_sorted_candidates_pool(
schedule,
oncall_date,
shift_start_date,
shift_end_date,
oncall_group,
)
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.get_last_shift_date_for_duty_person ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.get_next_shift_date_for_duty_person ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.get_number_of_days_to_closest_shift_date_for_duty_person ¶
get_number_of_days_to_closest_shift_date_for_duty_person(
duty_person,
oncall_group,
current_date,
pending_schedule,
)
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.helpers.has_refused_shift_on ¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/helpers.py
apps.eu_tools.alan_home.business_logic.oncall_groups.strategies.default.DefaultOncallSchedulingStrategy ¶
Bases: OncallSchedulingStrategy
description
class-attribute
instance-attribute
¶
description = "Randomly select available duty persons prioritizing those who have been on-call the least recently"
fill_schedule_gap
classmethod
¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/strategies/default.py
apps.eu_tools.alan_home.business_logic.oncall_groups.strategies.distinct.DistinctOncallSchedulingStrategy ¶
Bases: OncallSchedulingStrategy
description
class-attribute
instance-attribute
¶
description = "Randomly select available duty persons, prioritizing those who have been on-call least recently. The stategy ensures that Alaners will not be assigned to multiple shifts simultaneously."
fill_schedule_gap
classmethod
¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/strategies/distinct.py
apps.eu_tools.alan_home.business_logic.oncall_groups.strategies.manual.ManualOncallSchedulingStrategy ¶
Bases: OncallSchedulingStrategy
description
class-attribute
instance-attribute
¶
fill_schedule_gap
classmethod
¶
Manual strategy: do not fill gaps automatically
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/strategies/manual.py
apps.eu_tools.alan_home.business_logic.oncall_groups.strategies.part_time.PartTimeOncallSchedulingStrategy ¶
Bases: OncallSchedulingStrategy
description
class-attribute
instance-attribute
¶
description = "Randomly select available duty persons prioritizing those who have been on-call the least recently and replacing part time persons if needed"
fill_schedule_gap
classmethod
¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/strategies/part_time.py
apps.eu_tools.alan_home.business_logic.oncall_groups.strategies.part_time.get_sorted_candidates_pool_for_the_shift ¶
get_sorted_candidates_pool_for_the_shift(
schedule,
oncall_date,
shift_start_date,
shift_end_date,
oncall_group,
)
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/strategies/part_time.py
apps.eu_tools.alan_home.business_logic.oncall_groups.strategies.office.OfficeOncallSchedulingStrategy ¶
Bases: OncallSchedulingStrategy
fill_schedule_gap
classmethod
¶
Source code in apps/eu_tools/alan_home/business_logic/oncall_groups/strategies/office.py
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | |