Skip to content

Commit f2cedd9

Browse files
committed
field from assignment calculation
1 parent 1124574 commit f2cedd9

3 files changed

Lines changed: 165 additions & 0 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
defmodule Diffo.Provider.Calculations.FieldFromAssignment do
6+
@moduledoc false
7+
use Ash.Resource.Calculation
8+
9+
@impl true
10+
def load(_query, _opts, _context), do: []
11+
12+
@impl true
13+
def calculate(records, opts, _context) do
14+
alias_name = opts[:alias]
15+
field = opts[:field]
16+
17+
Enum.map(records, fn record ->
18+
record.id
19+
|> assignments(alias_name)
20+
|> Enum.map(&Map.get(&1, field))
21+
end)
22+
end
23+
24+
defp assignments(id, nil) do
25+
Diffo.Provider.AssignmentRelationship
26+
|> Ash.Query.filter_input(target_id: id)
27+
|> Ash.read!(domain: Diffo.Provider)
28+
end
29+
30+
defp assignments(id, alias_name) do
31+
Diffo.Provider.AssignmentRelationship
32+
|> Ash.Query.filter_input(target_id: id, alias: alias_name)
33+
|> Ash.read!(domain: Diffo.Provider)
34+
end
35+
end
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# SPDX-FileCopyrightText: 2025 diffo contributors <https://github.com/diffo-dev/diffo/graphs.contributors>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
defmodule Diffo.Provider.Extension.FieldFromAssignmentTest do
6+
@moduledoc false
7+
use ExUnit.Case, async: true
8+
@moduletag :domain_extended
9+
10+
alias Diffo.Provider.Assignment
11+
alias Diffo.Test.Servo
12+
13+
setup do
14+
AshNeo4j.Sandbox.checkout()
15+
on_exit(&AshNeo4j.Sandbox.rollback/0)
16+
end
17+
18+
defp setup_card do
19+
updates = [
20+
card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus],
21+
ports: [first: 1, last: 48, assignable_type: "ADSL2+"]
22+
]
23+
24+
{:ok, card} = Servo.build_card(%{})
25+
{:ok, card} = Servo.define_card(card, %{characteristic_value_updates: updates})
26+
{:ok, card} = Servo.lifecycle_card(card, %{resource_state: :operating})
27+
card
28+
end
29+
30+
describe "FieldFromAssignment — aliased" do
31+
test "returns field value from the aliased assignment record" do
32+
card = setup_card()
33+
{:ok, service} = Servo.build_access_service(%{})
34+
35+
{:ok, _card} =
36+
Servo.assign_port(card, %{
37+
assignment: %Assignment{
38+
assignee_id: service.id,
39+
operation: :auto_assign,
40+
alias: :primary
41+
}
42+
})
43+
44+
service = Ash.load!(service, [:assigned_port], domain: Servo)
45+
46+
assert length(service.assigned_port) == 1
47+
assert hd(service.assigned_port) == 1
48+
end
49+
50+
test "returns empty list when no assignment exists" do
51+
{:ok, service} = Servo.build_access_service(%{})
52+
53+
service = Ash.load!(service, [:assigned_port], domain: Servo)
54+
55+
assert service.assigned_port == []
56+
end
57+
58+
test "alias filters to only the matching assignment record" do
59+
card_a = setup_card()
60+
card_b = setup_card()
61+
{:ok, service} = Servo.build_access_service(%{})
62+
63+
{:ok, _card_a} =
64+
Servo.assign_port(card_a, %{
65+
assignment: %Assignment{
66+
assignee_id: service.id,
67+
operation: :auto_assign,
68+
alias: :primary
69+
}
70+
})
71+
72+
{:ok, _card_b} =
73+
Servo.assign_port(card_b, %{
74+
assignment: %Assignment{
75+
assignee_id: service.id,
76+
operation: :auto_assign,
77+
alias: :secondary
78+
}
79+
})
80+
81+
service = Ash.load!(service, [:assigned_port], domain: Servo)
82+
83+
assert length(service.assigned_port) == 1
84+
end
85+
end
86+
87+
describe "FieldFromAssignment — unaliased (all assignments)" do
88+
test "returns field values from all assignment records" do
89+
card_a = setup_card()
90+
card_b = setup_card()
91+
{:ok, service} = Servo.build_access_service(%{})
92+
93+
{:ok, _card_a} =
94+
Servo.assign_port(card_a, %{
95+
assignment: %Assignment{
96+
assignee_id: service.id,
97+
operation: :auto_assign,
98+
alias: :primary
99+
}
100+
})
101+
102+
{:ok, _card_b} =
103+
Servo.assign_port(card_b, %{
104+
assignment: %Assignment{
105+
assignee_id: service.id,
106+
operation: :auto_assign,
107+
alias: :secondary
108+
}
109+
})
110+
111+
service = Ash.load!(service, [:all_assignment_values], domain: Servo)
112+
113+
assert length(service.all_assignment_values) == 2
114+
end
115+
116+
test "returns empty list when no assignments exist" do
117+
{:ok, service} = Servo.build_access_service(%{})
118+
119+
service = Ash.load!(service, [:all_assignment_values], domain: Servo)
120+
121+
assert service.all_assignment_values == []
122+
end
123+
end
124+
end

test/support/resource/instance/access_service.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ defmodule Diffo.Test.Instance.AccessService do
4545

4646
calculate :assigner_names, {:array, :string},
4747
{Diffo.Provider.Calculations.FieldViaAssignedRelationship, [field: :name]}
48+
49+
calculate :assigned_port, {:array, :integer},
50+
{Diffo.Provider.Calculations.FieldFromAssignment, [alias: :primary, field: :value]}
51+
52+
calculate :all_assignment_values, {:array, :integer},
53+
{Diffo.Provider.Calculations.FieldFromAssignment, [field: :value]}
4854
end
4955

5056
actions do

0 commit comments

Comments
 (0)