Commit 4dc23f7f authored by Antonis Kalou's avatar Antonis Kalou

Add support for claims relationships

parent d1eea29c
......@@ -15,7 +15,6 @@ defmodule ValueFlows.Claim do
alias ValueFlows.Knowledge.Action
alias ValueFlows.Knowledge.ResourceSpecification
alias ValueFlows.Observation.EconomicEvent
alias ValueFlows.Observation.EconomicResource
@type t :: %__MODULE__{}
......@@ -52,28 +51,39 @@ defmodule ValueFlows.Claim do
@required ~w(action_id)a
@cast @required ++
~w(note finished agreed_in created due resource_classified_as is_disabled)a
~w(note finished agreed_in created due resource_classified_as is_disabled)a ++
~w(context_id resource_conforms_to_id triggered_by_id)a
def create_changeset(%User{} = creator, %{id: _} = provider, %{id: _} = receiver, attrs) do
%__MODULE__{}
|> Changeset.cast(attrs, @cast)
|> Changeset.validate_required(@required)
|> Changeset.change(
creator_id: creator.id,
provider_id: provider.id,
receiver_id: receiver.id,
is_public: true,
# preload
provider: provider,
receiver: receiver,
creator: creator
is_public: true
)
|> change_measures(attrs)
|> common_changeset()
end
def validate_required(changeset) do
Changeset.validate_required(changeset, @required)
end
def change_measures(changeset, %{} = attrs) do
measures = Map.take(attrs, measure_fields())
Enum.reduce(measures, changeset, fn {field_name, measure}, c ->
Changeset.put_assoc(c, field_name, measure)
end)
end
defp common_changeset(changeset) do
changeset
|> change_public()
|> change_disabled()
end
def measure_fields, do: [:resource_quantity, :effort_quantity]
end
......@@ -8,17 +8,36 @@ defmodule ValueFlows.Claim.Claims do
alias CommonsPub.Meta.Pointers
import CommonsPub.Common, only: [maybe_put: 3]
def one(filters), do: Repo.single(Queries.query(Claim, filters))
def many(filters \\ []), do: {:ok, Repo.all(Queries.query(Claim, filters))}
def preload_all(%Claim{} = claim) do
Repo.preload(claim, [
:creator,
:provider,
:receiver,
:context,
:resource_conforms_to,
:resource_quantity,
:effort_quantity,
:triggered_by,
])
end
# TODO: change attributes and then pass to changeset, use preload for rest
def create(%User{} = creator, %{id: _} = provider, %{id: _} = receiver, %{} = attrs) do
Repo.transact_with(fn ->
attrs = prepare_attrs(attrs)
with {:ok, provider_ptr} <- Pointers.one(id: provider.id),
{:ok, receiver_ptr} <- Pointers.one(id: receiver.id) do
Repo.insert(Claim.create_changeset(creator, provider_ptr, receiver_ptr, attrs))
Claim.create_changeset(creator, provider_ptr, receiver_ptr, attrs)
|> Claim.validate_required()
|> Repo.insert()
|> CommonsPub.Common.maybe_ok_error(&preload_all/1)
end
end)
end
......@@ -31,8 +50,13 @@ defmodule ValueFlows.Claim.Claims do
{:ok, claim}
end
def prepare_attrs(attrs) do
defp prepare_attrs(attrs) do
attrs
|> CommonsPub.Common.maybe_put(:action_id, Map.get(attrs, :action))
|> maybe_put(:action_id, Map.get(attrs, :action))
|> maybe_put(:context_id,
attrs |> Map.get(:in_scope_of) |> CommonsPub.Common.maybe(&List.first/1)
)
|> maybe_put(:resource_conforms_to_id, Map.get(attrs, :resource_conforms_to))
|> maybe_put(:triggered_by_id, Map.get(attrs, :triggered_by))
end
end
......@@ -22,8 +22,10 @@ defmodule ValueFlows.Claim.Migrations do
add(:receiver_id, weak_pointer(), null: true)
add(:resource_conforms_to_id, weak_pointer(ResourceSpecification), null: true)
add(:triggered_by_id, weak_pointer(EconomicEvent), null: true)
add(:creator_id, references("mn_user", on_delete: :nilify_all))
add(:resource_quantity_id, weak_pointer(Measurement.Measure), null: true)
add(:effort_quantity_id, weak_pointer(Measurement.Measure), null: true)
add(:creator_id, references("mn_user", on_delete: :nilify_all))
add(:context_id, weak_pointer(), null: true)
add(:published_at, :timestamptz)
......
......@@ -15,6 +15,18 @@ defmodule CommonsPub.Common do
def maybe_put(map, _key, ""), do: map
def maybe_put(map, key, value), do: Map.put(map, key, value)
@doc "Applies change_fn if the first parameter is not nil."
def maybe(nil, _change_fn), do: nil
def maybe(val, change_fn) do
change_fn.(val)
end
@doc "Applies change_fn if the first parameter is an {:ok, val} tuple, else returns the value"
def maybe_ok_error({:ok, val}, change_fn) do
{:ok, change_fn.(val)}
end
def maybe_ok_error(other, _change_fn), do: other
@doc "Append an item to a list if it is not nil"
@spec maybe_append([any()], any()) :: [any()]
def maybe_append(list, nil), do: list
......@@ -23,7 +35,7 @@ defmodule CommonsPub.Common do
@doc "Replace a key in a map"
def map_key_replace(%{} = map, key, new_key) do
map
|> Map.put(new_key, map[key])
|> Map.put(new_key, Map.get(map, key))
|> Map.delete(key)
end
......
......@@ -2,10 +2,10 @@ defmodule ValueFlows.Claim.ClaimsTest do
use CommonsPub.Web.ConnCase, async: true
import CommonsPub.Test.Faking
import Measurement.Simulate
import ValueFlows.Simulate
import ValueFlows.Test.Faking
alias ValueFlows.Claim
alias ValueFlows.Claim.Claims
describe "create" do
......@@ -36,15 +36,48 @@ defmodule ValueFlows.Claim.ClaimsTest do
end
test "with measure quantities" do
user = fake_user!()
provider = fake_user!()
receiver = fake_user!()
unit = fake_unit!(user)
attrs = %{
resource_quantity: measure(%{unit_id: unit.id}),
effort_quantity: measure(%{unit_id: unit.id}),
}
assert {:ok, claim} = Claims.create(user, provider, receiver, claim(attrs))
assert_claim(claim)
assert claim.resource_quantity.id
assert claim.effort_quantity.id
end
test "with a resource specification" do
user = fake_user!()
provider = fake_user!()
receiver = fake_user!()
attrs = %{
resource_conforms_to: fake_resource_specification!(user).id
}
assert {:ok, claim} = Claims.create(user, provider, receiver, claim(attrs))
assert_claim(claim)
assert claim.resource_conforms_to.id == attrs.resource_conforms_to
end
test "with a triggered by event" do
user = fake_user!()
provider = fake_user!()
receiver = fake_user!()
attrs = %{
triggered_by: fake_economic_event!(user).id
}
assert {:ok, claim} = Claims.create(user, provider, receiver, claim(attrs))
assert_claim(claim)
assert claim.triggered_by.id == attrs.triggered_by
end
end
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment