Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
#
# SPDX-License-Identifier: MIT

defmodule Diffo.Provider.Calculations.FieldFromAssignment do
@moduledoc false
use Ash.Resource.Calculation

@impl true
def load(_query, _opts, _context), do: []

@impl true
def calculate(records, opts, _context) do
alias_name = opts[:alias]
field = opts[:field]

Enum.map(records, fn record ->
record.id
|> assignments(alias_name)
|> Enum.map(&Map.get(&1, field))
end)
end

defp assignments(id, nil) do
Diffo.Provider.AssignmentRelationship
|> Ash.Query.filter_input(target_id: id)
|> Ash.read!(domain: Diffo.Provider)
end

defp assignments(id, alias_name) do
Diffo.Provider.AssignmentRelationship
|> Ash.Query.filter_input(target_id: id, alias: alias_name)
|> Ash.read!(domain: Diffo.Provider)
end
end
124 changes: 124 additions & 0 deletions test/provider/extension/field_from_assignment_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
#
# SPDX-License-Identifier: MIT

defmodule Diffo.Provider.Extension.FieldFromAssignmentTest do
@moduledoc false
use ExUnit.Case, async: true
@moduletag :domain_extended

alias Diffo.Provider.Assignment
alias Diffo.Test.Servo

setup do
AshNeo4j.Sandbox.checkout()
on_exit(&AshNeo4j.Sandbox.rollback/0)
end

defp setup_card do
updates = [
card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus],
ports: [first: 1, last: 48, assignable_type: "ADSL2+"]
]

{:ok, card} = Servo.build_card(%{})
{:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates})
{:ok, card} = Servo.lifecycle_card(card, %{resource_state: :operating})
card
end

describe "FieldFromAssignment — aliased" do
test "returns field value from the aliased assignment record" do
card = setup_card()
{:ok, service} = Servo.build_access_service(%{})

{:ok, _card} =
Servo.assign_port(card, %{
assignment: %Assignment{
assignee_id: service.id,
operation: :auto_assign,
alias: :primary
}
})

service = Ash.load!(service, [:assigned_port], domain: Servo)

assert length(service.assigned_port) == 1
assert hd(service.assigned_port) == 1
end

test "returns empty list when no assignment exists" do
{:ok, service} = Servo.build_access_service(%{})

service = Ash.load!(service, [:assigned_port], domain: Servo)

assert service.assigned_port == []
end

test "alias filters to only the matching assignment record" do
card_a = setup_card()
card_b = setup_card()
{:ok, service} = Servo.build_access_service(%{})

{:ok, _card_a} =
Servo.assign_port(card_a, %{
assignment: %Assignment{
assignee_id: service.id,
operation: :auto_assign,
alias: :primary
}
})

{:ok, _card_b} =
Servo.assign_port(card_b, %{
assignment: %Assignment{
assignee_id: service.id,
operation: :auto_assign,
alias: :secondary
}
})

service = Ash.load!(service, [:assigned_port], domain: Servo)

assert length(service.assigned_port) == 1
end
end

describe "FieldFromAssignment — unaliased (all assignments)" do
test "returns field values from all assignment records" do
card_a = setup_card()
card_b = setup_card()
{:ok, service} = Servo.build_access_service(%{})

{:ok, _card_a} =
Servo.assign_port(card_a, %{
assignment: %Assignment{
assignee_id: service.id,
operation: :auto_assign,
alias: :primary
}
})

{:ok, _card_b} =
Servo.assign_port(card_b, %{
assignment: %Assignment{
assignee_id: service.id,
operation: :auto_assign,
alias: :secondary
}
})

service = Ash.load!(service, [:all_assignment_values], domain: Servo)

assert length(service.all_assignment_values) == 2
end

test "returns empty list when no assignments exist" do
{:ok, service} = Servo.build_access_service(%{})

service = Ash.load!(service, [:all_assignment_values], domain: Servo)

assert service.all_assignment_values == []
end
end
end
6 changes: 6 additions & 0 deletions test/support/resource/instance/access_service.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ defmodule Diffo.Test.Instance.AccessService do

calculate :assigner_names, {:array, :string},
{Diffo.Provider.Calculations.FieldViaAssignedRelationship, [field: :name]}

calculate :assigned_port, {:array, :integer},
{Diffo.Provider.Calculations.FieldFromAssignment, [alias: :primary, field: :value]}

calculate :all_assignment_values, {:array, :integer},
{Diffo.Provider.Calculations.FieldFromAssignment, [field: :value]}
end

actions do
Expand Down
Loading