We’re using a macro calling fragment
to build out a CASE statement that calculates the discount amount, a virtual field. Is there a clean way to reuse this CASE statement / fragment / macro in an order_by
call?
defmacro calc_discount_amount(account) do
quote do
fragment(
"CASE
WHEN ? = 'buyers_club' THEN
round(? * 0.95 * (? / 100), 0)::integer
WHEN ? = 'employee' AND ? >= 80 THEN
?
ELSE
round(? * (? / 100), 0)::integer
END",
unquote(account).account_type,
unquote(account).amount,
unquote(account).discount_percentage,
unquote(account).account_type,
unquote(account).discount_percentage,
unquote(account).amount,
unquote(account).amount,
unquote(account).discount_percentage
)
end
end
def with_discount_amount(query \\ base()) do
from e in query, select_merge: %{discount_amount: type(calc_discount_amount(e), Money.Ecto.Type)}
end
We’re currently duplicating the case statement which returns results in the expected order.
order = :asc
...
order_by(query, [a], [
{^order,
fragment(
"CASE
WHEN ? = 'buyers_club' THEN
round(? * 0.95 * (? / 100), 0)::integer
WHEN ? = 'employee' AND ? >= 80 THEN
?
ELSE
round(? * (? / 100), 0)::integer
END",
a.account_type,
a.amount,
a.discount_percentage,
a.account_type,
a.discount_percentage,
a.amount,
a.amount,
a.discount_percentage
)}
])
...
I would love to remove this duplication. Any ideas? Would dynamic
help?