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
2 changes: 1 addition & 1 deletion lib/diffo/provider/assigner/assignable_value.ex
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defmodule Diffo.Provider.AssignableValue do
default: 1,
constraints: [min: 0]

field :type, :string, description: "the type of the thing"
field :type, :atom, description: "the type of the assignable thing"

field :algorithm, :atom,
description: "the assignment algorithm",
Expand Down
76 changes: 69 additions & 7 deletions lib/diffo/provider/assigner/assigner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ defmodule Diffo.Provider.Assigner do
end

:unassign ->
unrelate_is_assigned(result, things, assignment.id, assignee_id)
unrelate_is_assigned(result, things, thing, assignment.id, assignee_id)
end
end
end
Expand Down Expand Up @@ -80,12 +80,57 @@ defmodule Diffo.Provider.Assigner do
end
end

defp unrelate_is_assigned(result, things, value, assignee_id)
when is_struct(result) and is_atom(things) and is_integer(value) and
defp unrelate_is_assigned(result, things, thing, value, assignee_id)
when is_struct(result) and is_atom(things) and is_atom(thing) and is_integer(value) and
is_bitstring(assignee_id) do
# destroy characteristic
# destroy relationship
{:error, "not implemented"}
relationships =
Enum.filter(result.forward_relationships, fn %{
type: type,
target_id: target_id,
characteristics: characteristics
} ->
type == :assignedTo and target_id == assignee_id and
Enum.any?(characteristics, fn %{name: name, value: v} ->
name == thing and v == value
end)
end)

case length(relationships) do
0 ->
{:error, "#{thing} #{value} is not assigned to assignee #{assignee_id}"}

1 ->
relationship = hd(relationships)

characteristic =
Enum.find(relationship.characteristics, fn %{name: n} -> n == thing end)

# unrelate the relationship characterisitic
relationship = Diffo.Provider.unrelate_relationship_characteristics!(relationship, %{
characteristics: [characteristic.id]
})

# delete the relationship characteristic
Diffo.Provider.delete_characteristic(characteristic.id)

# delete the relationship
case Diffo.Provider.delete_relationship(relationship.id) do
:ok ->
case increment_free(result, things) do
:ok ->
{:ok, result}

{:error, error} ->
{:error, error}
end

{:error, error} ->
{:error, error}
end

_ ->
{:error, "multiple relationships found for #{thing} #{value} and assignee #{assignee_id}"}
end
end

defp assignments(instance, thing) when is_struct(instance) and is_atom(thing) do
Expand All @@ -103,7 +148,8 @@ defmodule Diffo.Provider.Assigner do
assignment =
struct(Diffo.Provider.Assignment, %{
id: characteristic.value,
instance_id: target_id
type: thing,
assignee_id: target_id
})

[assignment | acc]
Expand Down Expand Up @@ -165,6 +211,22 @@ defmodule Diffo.Provider.Assigner do
end
end

defp increment_free(instance, things) when is_struct(instance) and is_atom(things) do
characteristic =
Enum.find(instance.characteristics, fn %{name: name} -> name == things end)

{_free, assignable_value} =
Map.get_and_update(characteristic.value, :free, fn free -> {free + 1, free + 1} end)

case Diffo.Provider.update_characteristic(characteristic, %{value: assignable_value}) do
{:ok, _characteristic} ->
:ok

{:error, error} ->
{:error, error}
end
end

defp free(instance, thing, assignable_value)
when is_struct(instance) and is_atom(thing) and
is_struct(assignable_value, AssignableValue) do
Expand Down
8 changes: 5 additions & 3 deletions lib/diffo/provider/assigner/assignment.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ defmodule Diffo.Provider.Assignment do
typed_struct do
field :id, :integer,
constraints: [min: 0],
description: "the id of the partial resource"
description: "the id of the assigned thing"

field :type, :atom, description: "the type of the assigned thing"

field :assignee_id, :uuid, description: "the id of the assignee Ash resource"

field :operation, :atom,
description: "the operation the assignee is requesting",
default: :assign,
constraints: [one_of: [:assign, :unassign, :auto_assign]]
default: nil,
constraints: [one_of: [nil, :assign, :unassign, :auto_assign]]
end

defimpl String.Chars do
Expand Down
4 changes: 2 additions & 2 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
%{
"ash": {:hex, :ash, "3.10.0", "839d696ef8a4d1f5b980a469fb19ef1383f21ddfb0e602ef91fc9811b2be529a", [:mix], [{:crux, ">= 0.1.2 and < 1.0.0-0", [hex: :crux, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.29 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.11", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.3.14 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, ">= 0.2.6 and < 1.0.0-0", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "04b722edb6f8674fbe6ee7833e7e7ca43c404635e748bc4d17a6a1dba288dfc7"},
"ash": {:hex, :ash, "3.11.1", "9794620bffeb83d1803d92a64e7803f70b57372eb4addba5c12a24343cd04e1a", [:mix], [{:crux, ">= 0.1.2 and < 1.0.0-0", [hex: :crux, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.7", [hex: :ecto, repo: "hexpm", optional: false]}, {:ets, "~> 0.8", [hex: :ets, repo: "hexpm", optional: false]}, {:igniter, ">= 0.6.29 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: false]}, {:picosat_elixir, "~> 0.2", [hex: :picosat_elixir, repo: "hexpm", optional: true]}, {:plug, ">= 0.0.0", [hex: :plug, repo: "hexpm", optional: true]}, {:reactor, "~> 0.11", [hex: :reactor, repo: "hexpm", optional: false]}, {:simple_sat, ">= 0.1.1 and < 1.0.0-0", [hex: :simple_sat, repo: "hexpm", optional: true]}, {:spark, ">= 2.3.14 and < 3.0.0-0", [hex: :spark, repo: "hexpm", optional: false]}, {:splode, ">= 0.2.6 and < 1.0.0-0", [hex: :splode, repo: "hexpm", optional: false]}, {:stream_data, "~> 1.0", [hex: :stream_data, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.1", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e0074302bb88d667635fcbfdacbf8a641c53973a3902d0e744f567a49ec808fc"},
"ash_jason": {:hex, :ash_jason, "3.0.4", "50478b7a654584c9fcdb39dfca15a20f832f9183c393eb6aed7c9755e645550f", [:mix], [{:ash, ">= 3.6.2 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:spark, ">= 2.1.21 and < 3.0.0", [hex: :spark, repo: "hexpm", optional: false]}], "hexpm", "f6d33382fce7032d2f177663cf30c2d3eb887fcd1c5bb2c22bc65d72e0b95095"},
"ash_neo4j": {:hex, :ash_neo4j, "0.2.12", "cc662833f3d4eb10ff36b217a1693c6deff3a878a9aea3baaf66090d987bb54a", [:mix], [{:ash, ">= 3.6.2 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:boltx, ">= 0.0.6", [hex: :boltx, repo: "hexpm", optional: false]}], "hexpm", "fda719bfc002ce0840d62eabbf0502ab79dd1e249d852aa3eb0bee457bf96352"},
"ash_outstanding": {:hex, :ash_outstanding, "0.2.3", "dc8ec13028ea7bd1d74b46569b9db08f0d275d63700e2418d9e33fe4b21af2eb", [:mix], [{:ash, ">= 3.6.2 and < 4.0.0-0", [hex: :ash, repo: "hexpm", optional: false]}, {:outstanding, "~> 0.2.4", [hex: :outstanding, repo: "hexpm", optional: false]}], "hexpm", "05e2718b59937d9f7e77b7bc90f70e8f28c3f328de7cabf3ea55ca04a1abed52"},
Expand All @@ -11,7 +11,7 @@
"earmark_parser": {:hex, :earmark_parser, "1.4.44", "f20830dd6b5c77afe2b063777ddbbff09f9759396500cdbe7523efd58d7a339c", [:mix], [], "hexpm", "4778ac752b4701a5599215f7030989c989ffdc4f6df457c5f36938cc2d2a2750"},
"ecto": {:hex, :ecto, "3.13.5", "9d4a69700183f33bf97208294768e561f5c7f1ecf417e0fa1006e4a91713a834", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df9efebf70cf94142739ba357499661ef5dbb559ef902b68ea1f3c1fabce36de"},
"ets": {:hex, :ets, "0.9.0", "79c6a6c205436780486f72d84230c6cba2f8a9920456750ddd1e47389107d5fd", [:mix], [], "hexpm", "2861fdfb04bcaeff370f1a5904eec864f0a56dcfebe5921ea9aadf2a481c822b"},
"ex_doc": {:hex, :ex_doc, "0.39.1", "e19d356a1ba1e8f8cfc79ce1c3f83884b6abfcb79329d435d4bbb3e97ccc286e", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "8abf0ed3e3ca87c0847dfc4168ceab5bedfe881692f1b7c45f4a11b232806865"},
"ex_doc": {:hex, :ex_doc, "0.39.3", "519c6bc7e84a2918b737aec7ef48b96aa4698342927d080437f61395d361dcee", [:mix], [{:earmark_parser, "~> 1.4.44", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "0590955cf7ad3b625780ee1c1ea627c28a78948c6c0a9b0322bd976a079996e1"},
"finch": {:hex, :finch, "0.20.0", "5330aefb6b010f424dcbbc4615d914e9e3deae40095e73ab0c1bb0968933cadf", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.6.2 or ~> 1.7", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 1.1", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2658131a74d051aabfcba936093c903b8e89da9a1b63e430bee62045fa9b2ee2"},
"glob_ex": {:hex, :glob_ex, "0.1.11", "cb50d3f1ef53f6ca04d6252c7fde09fd7a1cf63387714fe96f340a1349e62c93", [:mix], [], "hexpm", "342729363056e3145e61766b416769984c329e4378f1d558b63e341020525de4"},
"hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"},
Expand Down
42 changes: 42 additions & 0 deletions test/assigner/assigner_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -166,5 +166,47 @@ defmodule Diffo.Test.AssignerTest do
assert encoding ==
~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceRelationship\":[{\"type\":\"assignedTo\",\"resource\":{\"id\":\"#{assignee.id}\",\"href\":\"resourceInventoryManagement/v4/resource/shelf/#{assignee.id}\"},\"resourceRelationshipCharacteristic\":[{\"name\":\"port\",\"value\":5}]}],\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":47,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]})
end

test "unassign an auto-assigned port from a resource" do
{:ok, assignee} = Domain.build_shelf()

{:ok, card} = Domain.build_card(%{})

updates = [
card: [family: :ISAM, model: "EBLT48", technology: :adsl2Plus],
ports: [first: 1, last: 48, free: 48, type: "ADSL2+"]
]

{:ok, card} = Domain.define_card(card, %{characteristic_value_updates: updates})

{:ok, card} =
Domain.assign_port(card, %{
assignment: %Assignment{assignee_id: assignee.id, operation: :auto_assign}
})

Characteristics.check_values([ports: [free: 47]], card)

assigned_port =
Enum.find(card.forward_relationships, fn rel -> rel.type == :assignedTo end)
|> Map.get(:characteristics)
|> Enum.find(fn char -> char.name == :port end)
|> Map.get(:value)

{:ok, card} =
Domain.assign_port(card, %{
assignment: %Assignment{
id: assigned_port,
assignee_id: assignee.id,
operation: :unassign
}
})

Characteristics.check_values([ports: [free: 48]], card)

encoding = Jason.encode!(card) |> Diffo.Util.summarise_dates()

assert encoding ==
~s({\"id\":\"#{card.id}",\"href\":\"resourceInventoryManagement/v4/resource/card/#{card.id}",\"category\":\"Network Resource\",\"resourceSpecification\":{\"id\":\"cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"href\":\"resourceCatalogManagement/v4/resourceSpecification/cd29956f-6c68-44cc-bf54-705eb8d2f754\",\"name\":\"card\",\"version\":\"v1.0.0\"},\"resourceCharacteristic\":[{\"name\":\"card\",\"value\":{\"family\":\"ISAM\",\"model\":\"EBLT48\",\"technology\":\"adsl2Plus\"}},{\"name\":\"ports\",\"value\":{\"first\":1,\"last\":48,\"free\":48,\"type\":\"ADSL2+\",\"algorithm\":\"lowest\"}}]})
end
end
end
2 changes: 1 addition & 1 deletion test/provider/characteristic_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ defmodule Diffo.Provider.CharacteristicTest do
end
end

describe "Diffo.Provider updated Characteristics" do
describe "Diffo.Provider update Characteristics" do
test "update characteristic value - success" do
parent_specification =
Diffo.Provider.create_specification!(%{name: "can", type: :resourceSpecification})
Expand Down
2 changes: 0 additions & 2 deletions test/provider/external_identifier_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,6 @@ defmodule Diffo.Provider.ExternalIdentifierTest do
|> Diffo.Provider.update_external_identifier(%{owner_id: "T4_VIRTUAL"})
end

@tag bugged: true
# update bug?
test "update instance_id - success" do
specification = Diffo.Provider.create_specification!(%{name: "nbnAccess"})
instance1 = Diffo.Provider.create_instance!(%{specified_by: specification.id})
Expand Down
26 changes: 24 additions & 2 deletions test/provider/feature_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ defmodule Diffo.Provider.FeatureTest do
end
end

describe "Diffo.Provider updated Features" do
describe "Diffo.Provider update Features" do
test "update feature isEnabled - success" do
feature =
Diffo.Provider.create_feature!(%{
Expand Down Expand Up @@ -125,6 +125,29 @@ defmodule Diffo.Provider.FeatureTest do
})
end

test "update feature remove characteristic - success" do
device_characteristic =
Diffo.Provider.create_characteristic!(%{
name: :device,
value: :epic1000a,
type: :feature
})

feature =
Diffo.Provider.create_feature!(%{
name: :management,
characteristics: [device_characteristic.id]
})

updated_feature =
feature
|> Diffo.Provider.unrelate_feature_characteristics!(%{
characteristics: [device_characteristic.id]
})

assert updated_feature.characteristics == []
end

test "update feature with duplicate characteristic - failure" do
first_characteristic =
Diffo.Provider.create_characteristic!(%{
Expand Down Expand Up @@ -267,7 +290,6 @@ defmodule Diffo.Provider.FeatureTest do

:ok = Diffo.Provider.delete_feature(feature)
{:error, _error} = Diffo.Provider.get_feature_by_id(feature.id)
Diffo.Provider.get_characteristic_by_id!(characteristic.id)
end

test "delete feature with related instance - failure, related instance" do
Expand Down
42 changes: 41 additions & 1 deletion test/provider/relationship_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,47 @@ defmodule Diffo.Provider.RelationshipTest do
end
end

describe "Diffo.Provider updated Relationships" do
describe "Diffo.Provider update Relationships" do
test "update relationship remove characteristics - success" do
specification = Diffo.Provider.create_specification!(%{name: "evc1"})

first_instance =
Diffo.Provider.create_instance!(%{specified_by: specification.id, name: "first"})

second_instance =
Diffo.Provider.create_instance!(%{specified_by: specification.id, name: "second"})

first_characteristic =
Diffo.Provider.create_characteristic!(%{
name: :role,
value: "worker",
type: :relationship
})

second_characteristic =
Diffo.Provider.create_characteristic!(%{
name: :type,
value: :evpl,
type: :relationship
})

relationship =
Diffo.Provider.create_relationship!(%{
type: :uses,
source_id: first_instance.id,
target_id: second_instance.id,
characteristics: [first_characteristic.id, second_characteristic.id]
})

updated_relationship =
relationship
|> Diffo.Provider.unrelate_relationship_characteristics!(%{
characteristics: [first_characteristic.id, second_characteristic.id]
})

assert updated_relationship.characteristics == []
end

test "add alias - success" do
parent_specification =
Diffo.Provider.create_specification!(%{name: "can", type: :resourceSpecification})
Expand Down