query.ex (5696B)
1 # Zenflows is designed to implement the Valueflows vocabulary, 2 # written and maintained by srfsh <info@dyne.org>. 3 # Copyright (C) 2021-2023 Dyne.org foundation <foundation@dyne.org>. 4 # 5 # This program is free software: you can redistribute it and/or modify 6 # it under the terms of the GNU Affero General Public License as published by 7 # the Free Software Foundation, either version 3 of the License, or 8 # (at your option) any later version. 9 # 10 # This program is distributed in the hope that it will be useful, 11 # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 # GNU Affero General Public License for more details. 14 # 15 # You should have received a copy of the GNU Affero General Public License 16 # along with this program. If not, see <https://www.gnu.org/licenses/>. 17 18 defmodule Zenflows.VF.EconomicResource.Query do 19 @moduledoc false 20 21 import Ecto.Query 22 23 alias Ecto.{Changeset, Queryable} 24 alias Zenflows.DB.{ID, Page, Schema, Validate} 25 alias Zenflows.VF.{EconomicEvent, EconomicResource} 26 27 @spec all(Page.t()) :: {:ok, Queryable.t()} | {:error, Changeset.t()} 28 def all(%{filter: nil}), do: {:ok, EconomicResource} 29 def all(%{filter: params}) do 30 with {:ok, filters} <- all_validate(params) do 31 {:ok, Enum.reduce(filters, EconomicResource, &all_f(&2, &1))} 32 end 33 end 34 35 @spec all_f(Queryable.t(), {atom(), term()}) :: Queryable.t() 36 defp all_f(q, {:id, v}), 37 do: where(q, [x], x.id in ^v) 38 defp all_f(q, {:or_id, v}), 39 do: or_where(q, [x], x.id in ^v) 40 defp all_f(q, {:classified_as, v}), 41 do: where(q, [x], fragment("? @> ?", x.classified_as, ^v)) 42 defp all_f(q, {:or_classified_as, v}), 43 do: or_where(q, [x], fragment("? @> ?", x.classified_as, ^v)) 44 defp all_f(q, {:primary_accountable, v}), 45 do: where(q, [x], x.primary_accountable_id in ^v) 46 defp all_f(q, {:or_primary_accountable, v}), 47 do: or_where(q, [x], x.primary_accountable_id in ^v) 48 defp all_f(q, {:not_primary_accountable, v}), 49 do: where(q, [x], x.primary_accountable_id not in ^v) 50 defp all_f(q, {:custodian, v}), 51 do: where(q, [x], x.custodian_id in ^v) 52 defp all_f(q, {:or_custodian, v}), 53 do: or_where(q, [x], x.custodian_id in ^v) 54 defp all_f(q, {:not_custodian, v}), 55 do: where(q, [x], x.custodian_id not in ^v) 56 defp all_f(q, {:conforms_to, v}), 57 do: where(q, [x], x.conforms_to_id in ^v) 58 defp all_f(q, {:or_conforms_to, v}), 59 do: or_where(q, [x], x.conforms_to_id in ^v) 60 defp all_f(q, {:gt_onhand_quantity_has_numerical_value, v}), 61 do: where(q, [x], x.onhand_quantity_has_numerical_value > ^v) 62 defp all_f(q, {:or_gt_onhand_quantity_has_numerical_value, v}), 63 do: or_where(q, [x], x.onhand_quantity_has_numerical_value > ^v) 64 defp all_f(q, {:name, v}), 65 do: where(q, [x], ilike(x.name, ^"%#{v}%")) 66 defp all_f(q, {:or_name, v}), 67 do: or_where(q, [x], ilike(x.name, ^"%#{v}%")) 68 defp all_f(q, {:note, v}), 69 do: where(q, [x], ilike(x.note, ^"%#{v}%")) 70 defp all_f(q, {:or_note, v}), 71 do: or_where(q, [x], ilike(x.note, ^"%#{v}%")) 72 73 @spec all_validate(Schema.params()) :: 74 {:ok, Changeset.data()} | {:error, Changeset.t()} 75 defp all_validate(params) do 76 {%{}, %{ 77 id: {:array, ID}, 78 or_id: {:array, ID}, 79 classified_as: {:array, :string}, 80 or_classified_as: {:array, :string}, 81 primary_accountable: {:array, ID}, 82 or_primary_accountable: {:array, ID}, 83 not_primary_accountable: {:array, ID}, 84 custodian: {:array, ID}, 85 or_custodian: {:array, ID}, 86 not_custodian: {:array, ID}, 87 conforms_to: {:array, ID}, 88 or_conforms_to: {:array, ID}, 89 gt_onhand_quantity_has_numerical_value: :decimal, 90 or_gt_onhand_quantity_has_numerical_value: :decimal, 91 name: :string, 92 or_name: :string, 93 note: :string, 94 or_note: :string, 95 }} 96 |> Changeset.cast(params, ~w[ 97 id or_id 98 classified_as or_classified_as 99 primary_accountable or_primary_accountable not_primary_accountable 100 custodian or_custodian not_custodian 101 conforms_to or_conforms_to 102 gt_onhand_quantity_has_numerical_value 103 or_gt_onhand_quantity_has_numerical_value 104 name or_name note or_note 105 ]a) 106 |> Validate.class(:id) 107 |> Validate.class(:or_id) 108 |> Validate.exist_nand([:id, :or_id]) 109 |> Validate.class(:classified_as) 110 |> Validate.class(:or_classified_as) 111 |> Validate.exist_nand([:classified_as, :or_classified_as]) 112 |> Validate.class(:primary_accountable) 113 |> Validate.class(:or_primary_accountable) 114 |> Validate.class(:not_primary_accountable) 115 |> Validate.exist_nand([:primary_accountable, :or_primary_accountable]) 116 |> Validate.class(:custodian) 117 |> Validate.class(:or_custodian) 118 |> Validate.class(:not_custodian) 119 |> Validate.exist_nand([:custodian, :or_custodian]) 120 |> Validate.class(:conforms_to) 121 |> Validate.class(:or_conforms_to) 122 |> Validate.exist_nand([:conforms_to, :or_conforms_to]) 123 |> Changeset.validate_number(:gt_onhand_quantity_has_numerical_value, 124 greater_than_or_equal_to: 0) 125 |> Changeset.validate_number(:or_gt_onhand_quantity_has_numerical_value, 126 greater_than_or_equal_to: 0) 127 |> Validate.exist_nand([ 128 :gt_onhand_quantity_has_numerical_value, 129 :or_gt_onhand_quantity_has_numerical_value, 130 ]) 131 |> Validate.name(:name) 132 |> Validate.name(:or_name) 133 |> Validate.note(:note) 134 |> Validate.note(:or_note) 135 |> Validate.exist_nand([:name, :or_name]) 136 |> Validate.exist_nand([:note, :or_note]) 137 |> Validate.escape_like(:name) 138 |> Validate.escape_like(:or_name) 139 |> Validate.escape_like(:note) 140 |> Validate.escape_like(:or_note) 141 |> Changeset.apply_action(nil) 142 end 143 144 @spec previous(Schema.id()) :: Queryable.t() 145 def previous(id) do 146 from e in EconomicEvent, 147 or_where: not is_nil(e.output_of_id) and e.resource_inventoried_as_id == ^id, 148 or_where: e.to_resource_inventoried_as_id == ^id, 149 or_where: e.action_id in ["raise", "lower"] and e.resource_inventoried_as_id == ^id 150 end 151 end