init commit
Some checks failed
Build and Publish / build-release (push) Failing after 1s

This commit is contained in:
2026-04-15 16:20:22 -05:00
parent 072dbf6e66
commit b1b1c21e4e
28 changed files with 822 additions and 194 deletions

View File

@@ -0,0 +1,51 @@
defmodule CustomerService.Aggregates.CorporateCustomer do
defstruct [
:id,
:legal_name,
:commercial_name,
:ruc,
:legal_rep_name,
:legal_rep_document_id,
:email,
:phone,
:address
]
alias __MODULE__
alias Commanded.Aggregates.Aggregate
alias CustomerService.Commands
alias CustomerService.Events
@behaviour Aggregate
@impl Aggregate
def execute(%CorporateCustomer{id: nil}, %Commands.CreateCorporateCustomer{} = cmd) do
%Events.CorporateCustomerCreated{
id: cmd.id,
legal_name: cmd.legal_name,
commercial_name: cmd.commercial_name,
ruc: cmd.ruc,
legal_rep_name: cmd.legal_rep_name,
legal_rep_document_id: cmd.legal_rep_document_id,
email: cmd.email,
phone: cmd.phone,
address: cmd.address
}
end
@impl Aggregate
def apply(%CorporateCustomer{} = c, %Events.CorporateCustomerCreated{} = e) do
%CorporateCustomer{
c
| id: e.id,
legal_name: e.legal_name,
commercial_name: e.commercial_name,
ruc: e.ruc,
legal_rep_name: e.legal_rep_name,
legal_rep_document_id: e.legal_rep_document_id,
email: e.email,
phone: e.phone,
address: e.address
}
end
end

View File

@@ -6,7 +6,9 @@ defmodule CustomerService.Aggregates.Customer do
:birth_date,
:gender,
:email,
:phone
:phone,
:address,
:document_id
]
alias __MODULE__
@@ -24,13 +26,15 @@ defmodule CustomerService.Aggregates.Customer do
birth_date: cmd.birth_date,
gender: cmd.gender,
email: cmd.email,
phone: cmd.phone
phone: cmd.phone,
document_id: cmd.document_id,
address: cmd.address
}
end
@impl Aggregate
def apply(%Customer{} = c, %Events.CustomerCreated{} = e) do
%Customer{
%__MODULE__{
c
| id: e.id,
first_name: e.first_name,
@@ -38,7 +42,9 @@ defmodule CustomerService.Aggregates.Customer do
birth_date: e.birth_date,
gender: e.gender,
email: e.email,
phone: e.phone
phone: e.phone,
address: e.address,
document_id: e.document_id
}
end
end

View File

@@ -5,6 +5,11 @@ defmodule CustomerService.Router do
identify(Aggregates.Customer, by: :id)
dispatch([Commands.CreateCustomer], to: Aggregates.Customer)
dispatch(Commands.CreateCorporateCustomer,
to: Aggregates.CorporateCustomer,
identity: :id
)
end
defmodule CustomerService.CommandedApp do

View File

@@ -6,6 +6,22 @@ defmodule CustomerService.Commands.CreateCustomer do
:birth_date,
:gender,
:email,
:phone
:phone,
:address,
:document_id
]
end
defmodule CustomerService.Commands.CreateCorporateCustomer do
defstruct [
:id,
:legal_name,
:commercial_name,
:ruc,
:legal_rep_name,
:legal_rep_document_id,
:email,
:phone,
:address
]
end

View File

@@ -0,0 +1,19 @@
defmodule CustomerService.Customers.Filters do
import Ecto.Query
def search(query, %Flop.Filter{value: value}, _opts) do
term = "%#{value}%"
where(
query,
[c],
ilike(c.first_name, ^term) or
ilike(c.last_name, ^term) or
ilike(c.legal_name, ^term) or
ilike(c.email, ^term) or
ilike(c.phone, ^term) or
ilike(c.document_id, ^term) or
ilike(c.ruc, ^term)
)
end
end

View File

@@ -0,0 +1,15 @@
defmodule CustomerService.Customer.Queries do
alias CustomerService.Projections.Customer
alias CustomerService.Repo
def list_customers(params \\ %{}) do
Flop.validate_and_run(Customer, params, for: Customer)
end
def get_customer(id) do
case Repo.get(Customer, id) do
nil -> {:error, :not_found}
customer -> {:ok, customer}
end
end
end

View File

@@ -7,6 +7,23 @@ defmodule CustomerService.Events.CustomerCreated do
:birth_date,
:gender,
:email,
:phone
:phone,
:address,
:document_id
]
end
defmodule CustomerService.Events.CorporateCustomerCreated do
@derive Jason.Encoder
defstruct [
:id,
:legal_name,
:commercial_name,
:ruc,
:legal_rep_name,
:legal_rep_document_id,
:email,
:phone,
:address
]
end

View File

@@ -2,24 +2,66 @@ defmodule CustomerService.Projections.Customer do
use Ecto.Schema
@derive {Jason.Encoder,
only: [
:id,
:first_name,
:last_name,
:birth_date,
:gender,
:email,
:phone,
:inserted_at,
:updated_at
]}
only: [
:id,
:customer_type,
# individual
:first_name,
:last_name,
:birth_date,
:gender,
:document_id,
# corporate
:legal_name,
:commercial_name,
:ruc,
:legal_rep_name,
:legal_rep_document_id,
# shared
:address,
:email,
:phone,
:inserted_at,
:updated_at
]}
@derive {
Flop.Schema,
filterable: [:customer_type, :email, :phone, :document_id, :ruc, :search],
sortable: [:last_name, :legal_name, :inserted_at],
default_limit: 20,
max_limit: 100,
custom_fields: [
search: [
filter: {CustomerService.Customers.Filters, :search, []},
ecto_type: :string,
operators: [:==]
]
]
}
@primary_key {:id, :binary_id, autogenerate: false}
@timestamps_opts [type: :utc_datetime_usec]
schema "customers" do
field :customer_type, :string, default: "individual"
# individual fields
field :first_name, :string
field :last_name, :string
field :birth_date, :date
field :gender, :string
field :document_id, :string
# corporate fields
field :legal_name, :string
field :commercial_name, :string
field :ruc, :string
field :legal_rep_name, :string
field :legal_rep_document_id, :string
# shared
field :address, :string
field :email, :string
field :phone, :string

View File

@@ -11,21 +11,40 @@ defmodule CustomerService.Projectors.Customer do
project(%Events.CustomerCreated{} = event, fn multi ->
Ecto.Multi.insert(multi, :customer, %Customer{
id: event.id,
customer_type: "individual",
first_name: event.first_name,
last_name: event.last_name,
birth_date: event.birth_date,
birth_date: parse_date(event.birth_date),
gender: event.gender,
email: event.email,
phone: event.phone
phone: event.phone,
address: event.address,
document_id: event.document_id
})
end)
# project %Events.CustomerDeactivated{} = event, _metadata do
# Ecto.Multi.update_all(
# multi,
# :deactivate_customer,
# from(c in Customer, where: c.customer_id == ^event.customer_id),
# set: [active: false]
# )
# end
defp parse_date(nil), do: nil
defp parse_date(%Date{} = d), do: d
defp parse_date(str) when is_binary(str) do
case Date.from_iso8601(str) do
{:ok, d} -> d
_ -> nil
end
end
project(%Events.CorporateCustomerCreated{} = e, _meta, fn multi ->
Ecto.Multi.insert(multi, :customer, %Customer{
id: e.id,
customer_type: "corporate",
legal_name: e.legal_name,
commercial_name: e.commercial_name,
ruc: e.ruc,
legal_rep_name: e.legal_rep_name,
legal_rep_document_id: e.legal_rep_document_id,
email: e.email,
phone: e.phone,
address: e.address
})
end)
end