44
55defmodule Diffo.Provider.Assigner do
66 @ moduledoc """
7- Helper to perform Assignment using `Diffo.Provider.DefinedSimpleRelationship `.
7+ Helper to perform Assignment using `Diffo.Provider.AssignmentRelationship `.
88
9- Each assignment is stored as a `DefinedSimpleRelationship` with `type: :assignedTo`
10- and a single `NameValuePrimitive` characteristic carrying the thing name and assigned value.
9+ Each assignment is stored as an `AssignmentRelationship` with top-level `pool`,
10+ `thing`, and `value` attributes. This makes them filterable at the Cypher level
11+ and usable in aggregate expressions.
1112 """
1213 alias Diffo.Provider.AssignableCharacteristic
13- alias Diffo.Provider.DefinedSimpleRelationship
14- alias Diffo.Type.NameValuePrimitive
15- alias Diffo.Type.Primitive
14+ alias Diffo.Provider.AssignmentRelationship
1615
1716 @ doc """
1817 Assign a thing using the pool declared via `pools do` on the instance module.
@@ -42,96 +41,76 @@ defmodule Diffo.Provider.Assigner do
4241 _ ->
4342 case Map . get ( assignment , :operation , :auto_assign ) do
4443 :auto_assign ->
45- case next ( result , pool , thing ) do
46- { :ok , assigned } ->
47- relate_is_assigned ( result , pool , thing , assigned , assignee_id )
48-
49- { :error , error } ->
50- { :error , error }
44+ with { :ok , value } <- next ( result , pool , thing ) do
45+ create_assignment ( result , pool , thing , value , assignee_id )
5146 end
5247
5348 :assign ->
54- case assignable? ( result , pool , thing , assignment . id ) do
55- true ->
56- relate_is_assigned ( result , pool , thing , assignment . id , assignee_id )
57-
58- false ->
59- { :error , "#{ thing } #{ assignment . id } is not assignable" }
49+ if assignable? ( result , pool , thing , assignment . id ) do
50+ create_assignment ( result , pool , thing , assignment . id , assignee_id )
51+ else
52+ { :error , "#{ thing } #{ assignment . id } is not assignable" }
6053 end
6154
6255 :unassign ->
63- unrelate_is_assigned ( result , pool , thing , assignment . id , assignee_id )
56+ destroy_assignment ( result , pool , thing , assignment . id , assignee_id )
6457 end
6558 end
6659 end
6760
68- defp relate_is_assigned ( result , _pool , thing , value , assignee_id )
69- when is_struct ( result ) and is_atom ( thing ) and is_integer ( value ) and
61+ defp create_assignment ( result , pool , thing , value , assignee_id )
62+ when is_struct ( result ) and is_atom ( pool ) and is_atom ( thing ) and is_integer ( value ) and
7063 is_bitstring ( assignee_id ) do
71- case Diffo.Provider . create_defined_simple_relationship ( % {
72- type: :assignedTo ,
73- characteristic: % NameValuePrimitive {
74- name: thing ,
75- value: Primitive . wrap ( "integer" , value )
76- } ,
77- source_id: result . id ,
78- target_id: assignee_id
79- } ) do
80- { :ok , _relationship } ->
81- { :ok , result }
82-
83- { :error , error } ->
84- { :error , error }
64+ with { :ok , _ } <-
65+ Diffo.Provider . create_assignment_relationship ( % {
66+ pool: pool ,
67+ thing: thing ,
68+ value: value ,
69+ source_id: result . id ,
70+ target_id: assignee_id
71+ } ) do
72+ { :ok , result }
8573 end
8674 end
8775
88- defp unrelate_is_assigned ( result , pool , thing , value , assignee_id )
76+ defp destroy_assignment ( result , pool , thing , value , assignee_id )
8977 when is_struct ( result ) and is_atom ( pool ) and is_atom ( thing ) and is_integer ( value ) and
9078 is_bitstring ( assignee_id ) do
9179 case find_assignment ( result . id , assignee_id , pool , thing , value ) do
9280 { :ok , nil } ->
9381 { :error , "#{ thing } #{ value } is not assigned to assignee #{ assignee_id } " }
9482
95- { :ok , relationship } ->
96- case Ash . destroy ( relationship , domain: Diffo.Provider ) do
97- :ok ->
98- { :ok , result }
99-
100- { :error , error } ->
101- { :error , error }
83+ { :ok , assignment } ->
84+ with :ok <- Ash . destroy ( assignment , domain: Diffo.Provider ) do
85+ { :ok , result }
10286 end
10387
10488 { :error , error } ->
10589 { :error , error }
10690 end
10791 end
10892
109- defp find_assignment ( source_id , target_id , _pool , thing , value ) do
110- case DefinedSimpleRelationship
111- |> Ash.Query . new ( )
112- |> Ash.Query . filter_input ( source_id: source_id , target_id: target_id , type: :assignedTo )
113- |> Ash . read ( domain: Diffo.Provider ) do
114- { :ok , rels } ->
115- { :ok ,
116- Enum . find ( rels , fn rel ->
117- rel . characteristic &&
118- rel . characteristic . name == thing &&
119- Diffo.Unwrap . unwrap ( rel . characteristic . value ) == value
120- end ) }
121-
122- { :error , error } ->
123- { :error , error }
124- end
93+ defp find_assignment ( source_id , target_id , pool , thing , value ) do
94+ AssignmentRelationship
95+ |> Ash.Query . filter_input (
96+ source_id: source_id ,
97+ target_id: target_id ,
98+ pool: pool ,
99+ thing: thing ,
100+ value: value
101+ )
102+ |> Ash . read_one ( domain: Diffo.Provider )
125103 end
126104
127105 defp next ( instance , pool , thing )
128106 when is_struct ( instance ) and is_atom ( pool ) and is_atom ( thing ) do
129- case pool_characteristic ( instance . id , pool , thing ) do
107+ case pool_characteristic ( instance . id , pool ) do
130108 { :ok , nil } ->
131109 { :error , "pool #{ pool } not found on instance #{ instance . id } " }
132110
133111 { :ok , char } ->
134- free = Enum . to_list ( char . first .. char . last ) -- char . assigned_values
112+ assigned = assigned_values_for ( instance . id , thing )
113+ free = Enum . to_list ( char . first .. char . last ) -- assigned
135114
136115 case free do
137116 [ ] ->
@@ -152,18 +131,30 @@ defmodule Diffo.Provider.Assigner do
152131
153132 defp assignable? ( instance , pool , thing , value )
154133 when is_struct ( instance ) and is_atom ( pool ) and is_atom ( thing ) and is_integer ( value ) do
155- case pool_characteristic ( instance . id , pool , thing ) do
156- { :ok , nil } -> false
157- { :ok , char } -> value in ( Enum . to_list ( char . first .. char . last ) -- char . assigned_values )
158- { :error , _ } -> false
134+ case pool_characteristic ( instance . id , pool ) do
135+ { :ok , nil } ->
136+ false
137+
138+ { :ok , char } ->
139+ assigned = assigned_values_for ( instance . id , thing )
140+ value in ( Enum . to_list ( char . first .. char . last ) -- assigned )
141+
142+ { :error , _ } ->
143+ false
159144 end
160145 end
161146
162- defp pool_characteristic ( instance_id , pool , thing ) do
147+ defp assigned_values_for ( instance_id , thing ) do
148+ AssignmentRelationship
149+ |> Ash.Query . filter_input ( source_id: instance_id , thing: thing )
150+ |> Ash . read! ( domain: Diffo.Provider )
151+ |> Enum . map ( & & 1 . value )
152+ end
153+
154+ defp pool_characteristic ( instance_id , pool ) do
163155 AssignableCharacteristic
164156 |> Ash.Query . new ( )
165157 |> Ash.Query . filter_input ( instance_id: instance_id , name: pool )
166- |> Ash.Query . load ( assigned_values: [ thing: thing ] )
167158 |> Ash . read_one ( domain: Diffo.Provider )
168159 end
169160end
0 commit comments