Packages
phoenix_kit
1.7.145
1.7.208
1.7.207
1.7.206
1.7.205
1.7.204
1.7.203
1.7.202
1.7.201
1.7.200
1.7.199
1.7.198
1.7.197
1.7.196
1.7.194
1.7.193
1.7.192
1.7.191
1.7.190
1.7.189
1.7.187
1.7.186
1.7.185
1.7.184
1.7.183
1.7.182
1.7.181
1.7.180
1.7.179
1.7.178
1.7.177
1.7.176
1.7.175
1.7.174
1.7.173
1.7.172
1.7.171
1.7.170
1.7.169
1.7.168
1.7.167
1.7.166
1.7.165
1.7.164
1.7.162
1.7.161
1.7.160
1.7.159
1.7.157
1.7.156
1.7.155
1.7.154
1.7.153
1.7.152
1.7.151
1.7.150
1.7.149
1.7.146
1.7.145
1.7.144
1.7.143
1.7.138
1.7.133
1.7.132
1.7.131
1.7.130
1.7.128
1.7.126
1.7.125
1.7.121
1.7.120
1.7.119
1.7.118
1.7.117
1.7.116
1.7.115
1.7.114
1.7.113
1.7.112
1.7.111
1.7.110
1.7.109
1.7.108
1.7.107
1.7.106
1.7.105
1.7.104
1.7.103
1.7.102
1.7.101
1.7.100
1.7.99
1.7.98
1.7.97
1.7.96
1.7.95
1.7.94
1.7.93
1.7.92
1.7.91
1.7.90
1.7.89
1.7.88
1.7.87
1.7.86
1.7.85
1.7.84
1.7.83
1.7.82
1.7.81
1.7.80
1.7.79
1.7.78
1.7.77
1.7.76
1.7.75
1.7.74
1.7.71
1.7.70
1.7.69
1.7.66
1.7.65
1.7.64
1.7.63
1.7.62
1.7.61
1.7.59
1.7.58
1.7.57
1.7.56
1.7.55
1.7.54
1.7.53
1.7.52
1.7.51
1.7.49
1.7.44
1.7.43
1.7.42
1.7.41
1.7.39
1.7.38
1.7.37
1.7.36
1.7.34
1.7.33
1.7.31
1.7.30
1.7.29
1.7.28
1.7.27
1.7.26
1.7.25
1.7.24
1.7.23
1.7.22
1.7.21
1.7.20
1.7.19
1.7.18
1.7.17
1.7.16
1.7.15
1.7.14
1.7.13
1.7.12
1.7.11
1.7.10
1.7.9
1.7.8
1.7.7
1.7.6
1.7.5
1.7.4
1.7.3
1.7.2
1.7.1
1.7.0
1.6.20
1.6.19
1.6.18
1.6.17
1.6.16
1.6.15
1.6.14
1.6.13
1.6.12
1.6.11
1.6.10
1.6.9
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.5.2
1.5.1
1.5.0
1.4.9
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.10
1.2.9
1.2.8
1.2.7
1.2.5
1.2.4
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more
Current section
Files
Jump to
Current section
Files
lib/phoenix_kit/migrations/postgres/v128.ex
defmodule PhoenixKit.Migrations.Postgres.V128 do
@moduledoc """
V128: Assignee on projects (and sub-projects).
Lets a whole project be assigned to a Department / Team / Person, exactly like
a task (`phoenix_kit_project_assignments`) already can. Because a sub-project
*is* a project (V127), this single set of columns covers both top-level
projects and sub-projects — a sub-project's assignee lives on its own project
row.
Adds to `phoenix_kit_projects`:
* `assigned_team_uuid` → FK `phoenix_kit_staff_teams(uuid) ON DELETE SET NULL`
* `assigned_department_uuid` → FK `phoenix_kit_staff_departments(uuid) ON DELETE SET NULL`
* `assigned_person_uuid` → FK `phoenix_kit_staff_people(uuid) ON DELETE SET NULL`
* `CHECK num_nonnulls(team, department, person) <= 1` — at most one assignee
(the same single-assignee rule the assignments table uses).
* a partial index per FK for "what's assigned to X" lookups.
`ON DELETE SET NULL` so removing a team/department/person un-assigns the
project rather than deleting it. Idempotent DO-blocks throughout.
"""
use Ecto.Migration
def up(opts) do
prefix = Map.get(opts, :prefix, "public")
p = prefix_str(prefix)
schema = schema_for(prefix)
add_assignee_column(p, schema, "assigned_team_uuid", "phoenix_kit_staff_teams")
add_assignee_column(p, schema, "assigned_department_uuid", "phoenix_kit_staff_departments")
add_assignee_column(p, schema, "assigned_person_uuid", "phoenix_kit_staff_people")
add_single_assignee_check(p, schema)
create_assignee_index(p, schema, "assigned_team_uuid", "team")
create_assignee_index(p, schema, "assigned_department_uuid", "department")
create_assignee_index(p, schema, "assigned_person_uuid", "person")
execute("COMMENT ON TABLE #{p}phoenix_kit IS '128'")
end
def down(opts) do
prefix = Map.get(opts, :prefix, "public")
p = prefix_str(prefix)
execute("DROP INDEX IF EXISTS #{p}phoenix_kit_projects_assigned_person_idx")
execute("DROP INDEX IF EXISTS #{p}phoenix_kit_projects_assigned_department_idx")
execute("DROP INDEX IF EXISTS #{p}phoenix_kit_projects_assigned_team_idx")
execute("""
ALTER TABLE #{p}phoenix_kit_projects
DROP CONSTRAINT IF EXISTS phoenix_kit_projects_single_assignee
""")
execute("ALTER TABLE #{p}phoenix_kit_projects DROP COLUMN IF EXISTS assigned_person_uuid")
execute("ALTER TABLE #{p}phoenix_kit_projects DROP COLUMN IF EXISTS assigned_department_uuid")
execute("ALTER TABLE #{p}phoenix_kit_projects DROP COLUMN IF EXISTS assigned_team_uuid")
execute("COMMENT ON TABLE #{p}phoenix_kit IS '127'")
end
defp add_assignee_column(p, schema, column, target_table) do
constraint = "phoenix_kit_projects_#{column}_fkey"
execute("""
DO $$
BEGIN
IF NOT EXISTS (
SELECT FROM information_schema.columns
WHERE table_schema = '#{schema}'
AND table_name = 'phoenix_kit_projects'
AND column_name = '#{column}'
) THEN
ALTER TABLE #{p}phoenix_kit_projects ADD COLUMN #{column} UUID;
END IF;
IF NOT EXISTS (
SELECT FROM information_schema.table_constraints
WHERE table_schema = '#{schema}'
AND table_name = 'phoenix_kit_projects'
AND constraint_name = '#{constraint}'
) THEN
ALTER TABLE #{p}phoenix_kit_projects
ADD CONSTRAINT #{constraint}
FOREIGN KEY (#{column})
REFERENCES #{p}#{target_table}(uuid)
ON DELETE SET NULL;
END IF;
END $$;
""")
end
# At most one of team/department/person set. Mirrors the assignments table's
# `phoenix_kit_project_assignments_single_assignee` check.
defp add_single_assignee_check(p, schema) do
execute("""
DO $$
BEGIN
IF NOT EXISTS (
SELECT FROM information_schema.table_constraints
WHERE table_schema = '#{schema}'
AND table_name = 'phoenix_kit_projects'
AND constraint_name = 'phoenix_kit_projects_single_assignee'
) THEN
ALTER TABLE #{p}phoenix_kit_projects
ADD CONSTRAINT phoenix_kit_projects_single_assignee
CHECK (num_nonnulls(assigned_team_uuid, assigned_department_uuid, assigned_person_uuid) <= 1);
END IF;
END $$;
""")
end
defp create_assignee_index(p, schema, column, short) do
index = "phoenix_kit_projects_assigned_#{short}_idx"
execute("""
DO $$
BEGIN
IF NOT EXISTS (
SELECT FROM pg_indexes
WHERE schemaname = '#{schema}'
AND tablename = 'phoenix_kit_projects'
AND indexname = '#{index}'
) THEN
CREATE INDEX #{index}
ON #{p}phoenix_kit_projects (#{column})
WHERE #{column} IS NOT NULL;
END IF;
END $$;
""")
end
defp schema_for("public"), do: "public"
defp schema_for(prefix), do: prefix
defp prefix_str("public"), do: "public."
defp prefix_str(prefix), do: "#{prefix}."
end