-
Notifications
You must be signed in to change notification settings - Fork 2
/
brazilian_document.ex
70 lines (55 loc) · 2.02 KB
/
brazilian_document.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
if Code.ensure_loaded?(Ecto.Type) do
defmodule BrazilianDocuments.Types.BrazilianDocument do
@moduledoc """
A polymorphic `Ecto.Type` for brazilian documents.
"""
use Ecto.Type
alias BrazilianDocuments.Types.CNPJ
alias BrazilianDocuments.Types.CPF
import BrazilianDocuments, only: [valid_cnpj?: 1, valid_cpf?: 1]
defstruct [:number, :kind]
def type, do: :string
def cast(value) when is_binary(value) do
raw_value = String.replace(value, ~r/\D/, "")
cond do
valid_cnpj?(raw_value) -> {:ok, %__MODULE__{number: raw_value, kind: :cnpj}}
valid_cpf?(raw_value) -> {:ok, %__MODULE__{number: raw_value, kind: :cpf}}
true -> :error
end
end
def cast(%__MODULE__{number: value}), do: cast(value)
def cast(%CPF{number: value}), do: cast(value)
def cast(%CNPJ{number: value}), do: cast(value)
def cast(_invalid), do: :error
def load(value), do: cast(value)
def dump(%__MODULE__{number: number}), do: {:ok, number}
def dump(%CPF{number: number}), do: {:ok, number}
def dump(%CNPJ{number: number}), do: {:ok, number}
def dump(value) when is_binary(value) do
case cast(value) do
{:ok, document} -> dump(document)
:error -> :error
end
end
def dump(_invalid), do: :error
end
defimpl Inspect, for: BrazilianDocuments.Types.BrazilianDocument do
def inspect(%{number: cnpj_number, kind: :cnpj}, _opts) do
case BrazilianDocuments.format_cnpj(cnpj_number) do
{:ok, formatted_cnpj} -> "#CNPJ<#{formatted_cnpj}>"
:error -> "#Invalid CNPJ<#{cnpj_number}>"
end
end
def inspect(%{number: cpf_number, kind: :cpf}, _opts) do
case BrazilianDocuments.format_cpf(cpf_number) do
{:ok, formatted_cpf} -> "#CPF<#{formatted_cpf}>"
:error -> "#Invalid CPF<#{cpf_number}>"
end
end
end
defimpl String.Chars, for: BrazilianDocuments.Types.BrazilianDocument do
def to_string(%{number: number}) when is_binary(number) do
number
end
end
end