commit 352d65b1fafad3fe14276c18648f8e1ccab23e26
parent 92d7f2f45932a28159f80e9ece95b2f6d6272002
Author: srfsh <dev@srf.sh>
Date: Fri, 23 Sep 2022 16:56:34 +0300
Zenflows.VF.EconomicResource.{Domain,Filter}: improve filtering
Diffstat:
2 files changed, 75 insertions(+), 14 deletions(-)
diff --git a/src/zenflows/vf/economic_resource/domain.ex b/src/zenflows/vf/economic_resource/domain.ex
@@ -18,13 +18,12 @@
defmodule Zenflows.VF.EconomicResource.Domain do
@moduledoc "Domain logic of EconomicResources."
-import Ecto.Query
-
alias Ecto.Multi
alias Zenflows.DB.{Paging, Repo}
alias Zenflows.VF.{
Action,
EconomicResource,
+ EconomicResource.Filter,
Measure,
}
@@ -44,20 +43,13 @@ def one(repo, clauses) do
end
end
-@spec all(Paging.params()) :: Paging.result()
-def all(params) do
- Paging.page(filter(params[:filter]), params)
-end
-
-defp filter(params) do
- Enum.reduce(params || %{}, EconomicResource, &filt(&2, &1))
+@spec all(Paging.params()) :: Filter.error() | Paging.result()
+def all(params \\ %{}) do
+ with {:ok, q} <- Filter.filter(params[:filter] || %{}) do
+ Paging.page(q, params)
+ end
end
-defp filt(q, {:classified_as, v}), do: where(q, [x], fragment("? @> ?", x.classified_as, ^v))
-defp filt(q, {:primary_accountable, v}), do: where(q, [x], x.primary_accountable_id in ^v)
-defp filt(q, {:custodian, v}), do: where(q, [x], x.custodian_id in ^v)
-defp filt(q, {:conforms_to, v}), do: where(q, [x], x.conforms_to_id in ^v)
-
@spec update(id(), params()) :: {:ok, EconomicResource.t()} | {:error, error()}
def update(id, params) do
Multi.new()
diff --git a/src/zenflows/vf/economic_resource/filter.ex b/src/zenflows/vf/economic_resource/filter.ex
@@ -0,0 +1,69 @@
+# Zenflows is designed to implement the Valueflows vocabulary,
+# written and maintained by srfsh <info@dyne.org>.
+# Copyright (C) 2021-2022 Dyne.org foundation <foundation@dyne.org>.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+defmodule Zenflows.VF.EconomicResource.Filter do
+@moduledoc "Filtering logic of EconomicResources."
+
+use Zenflows.DB.Schema
+
+import Ecto.Query
+
+alias Ecto.Query
+alias Zenflows.DB.{Filter, ID}
+alias Zenflows.VF.{EconomicResource, Validate}
+
+@type error() :: Filter.error()
+
+@spec filter(Filter.params()) :: Filter.result()
+def filter(params) do
+ case chgset(params) do
+ %{valid?: true, changes: c} ->
+ {:ok, Enum.reduce(c, EconomicResource, &f(&2, &1))}
+ %{valid?: false} = cset ->
+ {:error, cset}
+ end
+end
+
+@spec f(Query.t(), {atom(), term()}) :: Query.t()
+defp f(q, {:classified_as, v}),
+ do: where(q, [x], fragment("? @> ?", x.classified_as, ^v))
+defp f(q, {:primary_accountable, v}),
+ do: where(q, [x], x.primary_accountable_id in ^v)
+defp f(q, {:custodian, v}),
+ do: where(q, [x], x.custodian_id in ^v)
+defp f(q, {:conforms_to, v}),
+ do: where(q, [x], x.conforms_to_id in ^v)
+
+embedded_schema do
+ field :classified_as, {:array, :string}
+ field :primary_accountable, {:array, ID}
+ field :custodian, {:array, ID}
+ field :conforms_to, {:array, ID}
+end
+
+@cast ~w[classified_as primary_accountable custodian conforms_to]a
+
+@spec chgset(params()) :: Changeset.t()
+defp chgset(params) do
+ %__MODULE__{}
+ |> Changeset.cast(params, @cast)
+ |> Validate.class(:classified_as)
+ |> Validate.class(:primary_accountable)
+ |> Validate.class(:custodian)
+ |> Validate.class(:conforms_to)
+end
+end