96 lines
2.3 KiB
Elixir
96 lines
2.3 KiB
Elixir
defmodule RecycledCloud.Billing.Partner do
|
|
alias RecycledCloud.Accounts.User
|
|
alias RecycledCloud.Billing.Partner
|
|
alias RecycledCloud.Odoo
|
|
alias RecycledCloud.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
|