meta/lib/meta/billing/partner.ex

96 lines
2.3 KiB
Elixir

defmodule Meta.Billing.Partner do
alias Meta.Accounts.User
alias Meta.Billing.Partner
alias Meta.Odoo
alias Meta.Repo
import Ecto.Changeset
use Ecto.Schema
@address_fields [:display_name, :street, :city, :zip]
# Note: Odoo stores partner's country under 'country_id'. We do not support
# editing it at the moment.
embedded_schema do
field :name, :string
field :display_name, :string
field :email, :string
field :street, :string
field :city, :string
field :zip, :string
field :country, :string
end
def changeset(%Partner{} = partner, attrs) do
partner |> cast(attrs, @address_fields)
end
def apply(changeset) do
# Check if changeset is valid.
state = changeset |> Ecto.Changeset.apply_action(:update)
case state do
{:ok, partner} ->
changes = partner
|> Map.from_struct
|> Enum.filter(fn {k,_v} -> k in @address_fields end)
|> Enum.map(fn {k, v} -> {to_string(k), v} end)
|> Enum.into(%{})
# Propagate to Odoo
Odoo.query([
"res.partner",
"write",
[[partner.id], changes]
])
{:error, _} -> state
end
end
def get(id) do
fields = ["id", "name", "email", "country_id", "display_name"] ++ @address_fields
result = Odoo.query([
"res.partner",
"search_read",
[[["id", "=", id]]],
%{"fields" => fields}
])
format_fields = fn p ->
case p do
{k, false} when k in @address_fields -> {k, ""}
{:country_id, false} -> {:country, ""}
{:country_id, [_id, str]} -> {:country, str}
_ -> p
end
end
case result do
{:ok, [raw]} ->
args = raw
|> Enum.map(fn {k, v} -> {String.to_atom(k), v} end)
|> Enum.map(format_fields)
struct(Partner, args)
_ -> nil
end
end
def create(name, email) do
Odoo.query([
"res.partner",
"create",
[%{"name" => name, "email" => email}]
])
end
def get_or_create(%User{} = user) do
case user.partner_id do
nil ->
{:ok, id} = create(user.username, user.email)
{:ok, updated} = user |> change(%{partner_id: id}) |> Repo.update()
get_or_create(updated)
id -> get(id)
end
end
end