Built-in PagerDuty-equivalent system for on-call scheduling and alert escalation. Users can now manage schedules, rotation layers, overrides, and escalation policies directly in the app alongside PagerDuty. - On-call schedules with rotation layers (daily/weekly/custom), member management, and temporary overrides - Escalation policies with ordered rules, timeout-based escalation, and user/schedule targets - Automatic escalation via Oban worker with configurable repeat count - Email notifications via Swoosh for on-call alerts - Resolver computes who's on-call from layer stacking and overrides - AlertNotificationWorker integration: starts escalation alongside PagerDuty, acknowledges/resolves incidents on alert state changes - Device and organization schemas support escalation_policy_id - Escalation policy picker on device form - Schedules nav item with tabbed index (schedules + escalation policies) - Full CRUD UI for schedules, layers, members, overrides, rules, targets - 62 LiveView tests, 56 context/schema/resolver/escalation tests - 26 E2E Playwright tests for smoke and critical path coverage
34 lines
865 B
Elixir
34 lines
865 B
Elixir
defmodule Towerops.OnCall.LayerMember do
|
|
@moduledoc """
|
|
Schema for a user's position in a layer's rotation.
|
|
"""
|
|
use Ecto.Schema
|
|
|
|
import Ecto.Changeset
|
|
|
|
alias Towerops.Accounts.User
|
|
alias Towerops.OnCall.Layer
|
|
|
|
@primary_key {:id, :binary_id, autogenerate: true}
|
|
@foreign_key_type :binary_id
|
|
schema "on_call_layer_members" do
|
|
field :position, :integer, default: 0
|
|
|
|
belongs_to :layer, Layer
|
|
belongs_to :user, User
|
|
|
|
timestamps(type: :utc_datetime)
|
|
end
|
|
|
|
@required_fields ~w(position layer_id user_id)a
|
|
|
|
def changeset(member, attrs) do
|
|
member
|
|
|> cast(attrs, @required_fields)
|
|
|> validate_required(@required_fields)
|
|
|> validate_number(:position, greater_than_or_equal_to: 0)
|
|
|> foreign_key_constraint(:layer_id)
|
|
|> foreign_key_constraint(:user_id)
|
|
|> unique_constraint([:layer_id, :user_id])
|
|
end
|
|
end
|