All checks were successful
Build and Publish / build-release (push) Successful in 1m30s
335 lines
9.5 KiB
Elixir
335 lines
9.5 KiB
Elixir
defmodule ProviderService.Aggregates.Provider do
|
|
defstruct [
|
|
:provider_id,
|
|
:name,
|
|
:email,
|
|
:phone,
|
|
:contact_name,
|
|
:ruc,
|
|
:address,
|
|
:active,
|
|
templates: %{},
|
|
default_templates: %{}
|
|
]
|
|
|
|
alias ProviderService.Commands.{
|
|
RegisterProvider,
|
|
UpdateProvider,
|
|
DeactivateProvider,
|
|
ReactivateProvider,
|
|
AddProviderTemplate,
|
|
ActivateProviderTemplate,
|
|
DeactivateProviderTemplate,
|
|
SetDefaultProviderTemplate,
|
|
RemoveProviderTemplate
|
|
}
|
|
|
|
alias ProviderService.Events.{
|
|
ProviderRegistered,
|
|
ProviderUpdated,
|
|
ProviderDeactivated,
|
|
ProviderReactivated,
|
|
ProviderTemplateAdded,
|
|
ProviderTemplateActivated,
|
|
ProviderTemplateDeactivated,
|
|
ProviderTemplateDefaultSet,
|
|
ProviderTemplateRemoved
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Execute — Provider
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def execute(%__MODULE__{provider_id: nil}, %RegisterProvider{} = cmd) do
|
|
%ProviderRegistered{
|
|
provider_id: cmd.provider_id,
|
|
name: cmd.name,
|
|
email: cmd.email,
|
|
phone: cmd.phone,
|
|
contact_name: cmd.contact_name,
|
|
ruc: cmd.ruc,
|
|
address: cmd.address,
|
|
registered_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
|
|
def execute(%__MODULE__{active: false}, %UpdateProvider{}),
|
|
do: {:error, :provider_inactive}
|
|
|
|
def execute(%__MODULE__{} = agg, %UpdateProvider{} = cmd) do
|
|
%ProviderUpdated{
|
|
provider_id: agg.provider_id,
|
|
name: cmd.name,
|
|
email: cmd.email,
|
|
phone: cmd.phone,
|
|
contact_name: cmd.contact_name,
|
|
ruc: cmd.ruc,
|
|
address: cmd.address,
|
|
updated_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
|
|
def execute(%__MODULE__{active: false}, %DeactivateProvider{}),
|
|
do: {:error, :already_inactive}
|
|
|
|
def execute(%__MODULE__{} = agg, %DeactivateProvider{} = cmd) do
|
|
%ProviderDeactivated{
|
|
provider_id: agg.provider_id,
|
|
deactivated_by: cmd.deactivated_by,
|
|
deactivated_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
|
|
def execute(%__MODULE__{active: true}, %ReactivateProvider{}),
|
|
do: {:error, :already_active}
|
|
|
|
def execute(%__MODULE__{} = agg, %ReactivateProvider{} = cmd) do
|
|
%ProviderReactivated{
|
|
provider_id: agg.provider_id,
|
|
reactivated_by: cmd.reactivated_by,
|
|
reactivated_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Execute — Templates
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def execute(%__MODULE__{active: false}, %AddProviderTemplate{}),
|
|
do: {:error, :provider_inactive}
|
|
|
|
def execute(%__MODULE__{} = agg, %AddProviderTemplate{} = cmd) do
|
|
%ProviderTemplateAdded{
|
|
provider_id: agg.provider_id,
|
|
template_id: cmd.template_id,
|
|
policy_type: cmd.policy_type,
|
|
client_type: cmd.client_type,
|
|
document_url: cmd.document_url,
|
|
added_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
|
|
def execute(%__MODULE__{} = agg, %ActivateProviderTemplate{} = cmd) do
|
|
case find_template(agg, cmd.policy_type, cmd.client_type, cmd.template_id) do
|
|
nil ->
|
|
{:error, :template_not_found}
|
|
|
|
_ ->
|
|
%ProviderTemplateActivated{
|
|
provider_id: agg.provider_id,
|
|
template_id: cmd.template_id,
|
|
policy_type: cmd.policy_type,
|
|
client_type: cmd.client_type,
|
|
activated_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
end
|
|
|
|
def execute(%__MODULE__{} = agg, %DeactivateProviderTemplate{} = cmd) do
|
|
case find_template(agg, cmd.policy_type, cmd.client_type, cmd.template_id) do
|
|
nil ->
|
|
{:error, :template_not_found}
|
|
|
|
_ ->
|
|
%ProviderTemplateDeactivated{
|
|
provider_id: agg.provider_id,
|
|
template_id: cmd.template_id,
|
|
policy_type: cmd.policy_type,
|
|
client_type: cmd.client_type,
|
|
deactivated_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
end
|
|
|
|
def execute(%__MODULE__{} = agg, %SetDefaultProviderTemplate{} = cmd) do
|
|
case find_template(agg, cmd.policy_type, cmd.client_type, cmd.template_id) do
|
|
nil ->
|
|
{:error, :template_not_found}
|
|
|
|
%{active: false} ->
|
|
{:error, :template_not_active}
|
|
|
|
_ ->
|
|
%ProviderTemplateDefaultSet{
|
|
provider_id: agg.provider_id,
|
|
template_id: cmd.template_id,
|
|
policy_type: cmd.policy_type,
|
|
client_type: cmd.client_type,
|
|
set_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
end
|
|
|
|
def execute(%__MODULE__{} = agg, %RemoveProviderTemplate{} = cmd) do
|
|
case find_template(agg, cmd.policy_type, cmd.client_type, cmd.template_id) do
|
|
nil ->
|
|
{:error, :template_not_found}
|
|
|
|
_ ->
|
|
%ProviderTemplateRemoved{
|
|
provider_id: agg.provider_id,
|
|
template_id: cmd.template_id,
|
|
policy_type: cmd.policy_type,
|
|
client_type: cmd.client_type,
|
|
removed_at: DateTime.utc_now()
|
|
}
|
|
end
|
|
end
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Apply — Provider
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderRegistered{} = e) do
|
|
%__MODULE__{
|
|
agg
|
|
| provider_id: e.provider_id,
|
|
name: e.name,
|
|
email: e.email,
|
|
phone: e.phone,
|
|
contact_name: e.contact_name,
|
|
ruc: e.ruc,
|
|
address: e.address,
|
|
active: true
|
|
}
|
|
end
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderUpdated{} = e) do
|
|
%__MODULE__{
|
|
agg
|
|
| name: e.name,
|
|
email: e.email,
|
|
phone: e.phone,
|
|
contact_name: e.contact_name,
|
|
ruc: e.ruc,
|
|
address: e.address
|
|
}
|
|
end
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderDeactivated{}),
|
|
do: %__MODULE__{agg | active: false}
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderReactivated{}),
|
|
do: %__MODULE__{agg | active: true}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Apply — Templates
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderTemplateAdded{} = e) do
|
|
existing = get_in(agg.templates, [e.policy_type, e.client_type]) || []
|
|
|
|
templates =
|
|
agg.templates
|
|
|> Map.update(e.policy_type, %{e.client_type => []}, fn inner ->
|
|
Map.update(inner, e.client_type, [], fn list -> list end)
|
|
end)
|
|
|> put_in(
|
|
[e.policy_type, e.client_type],
|
|
existing ++
|
|
[
|
|
%{
|
|
template_id: e.template_id,
|
|
document_url: e.document_url,
|
|
active: false
|
|
}
|
|
]
|
|
)
|
|
|
|
%__MODULE__{agg | templates: templates}
|
|
end
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderTemplateActivated{} = e) do
|
|
templates =
|
|
update_template(
|
|
agg.templates,
|
|
e.policy_type,
|
|
e.client_type,
|
|
e.template_id,
|
|
&Map.put(&1, :active, true)
|
|
)
|
|
|
|
%__MODULE__{agg | templates: templates}
|
|
end
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderTemplateDeactivated{} = e) do
|
|
templates =
|
|
update_template(
|
|
agg.templates,
|
|
e.policy_type,
|
|
e.client_type,
|
|
e.template_id,
|
|
&Map.put(&1, :active, false)
|
|
)
|
|
|
|
template_id = e.template_id
|
|
# Clear default if the deactivated template was the default
|
|
default_templates =
|
|
case get_in(agg.default_templates, [e.policy_type, e.client_type]) do
|
|
^template_id ->
|
|
update_in(agg.default_templates, [e.policy_type], &Map.delete(&1, e.client_type))
|
|
|
|
_ ->
|
|
agg.default_templates
|
|
end
|
|
|
|
%__MODULE__{agg | templates: templates, default_templates: default_templates}
|
|
end
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderTemplateDefaultSet{} = e) do
|
|
default_templates =
|
|
agg.default_templates
|
|
|> Map.update(e.policy_type, %{e.client_type => e.template_id}, fn inner ->
|
|
Map.put(inner, e.client_type, e.template_id)
|
|
end)
|
|
|
|
%__MODULE__{agg | default_templates: default_templates}
|
|
end
|
|
|
|
def apply(%__MODULE__{} = agg, %ProviderTemplateRemoved{} = e) do
|
|
templates =
|
|
agg.templates
|
|
|> update_in([e.policy_type, e.client_type], fn list ->
|
|
Enum.reject(list || [], &(&1.template_id == e.template_id))
|
|
end)
|
|
|
|
template_id = e.template_id
|
|
# Clear default if the removed template was the default
|
|
default_templates =
|
|
case get_in(agg.default_templates, [e.policy_type, e.client_type]) do
|
|
^template_id ->
|
|
update_in(agg.default_templates, [e.policy_type], &Map.delete(&1, e.client_type))
|
|
|
|
_ ->
|
|
agg.default_templates
|
|
end
|
|
|
|
%__MODULE__{agg | templates: templates, default_templates: default_templates}
|
|
end
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Helpers
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# templates structure: %{ policy_type => %{ client_type => [%{template_id, ...}] } }
|
|
# default_templates: %{ policy_type => %{ client_type => template_id } }
|
|
|
|
defp find_template(agg, policy_type, client_type, template_id) do
|
|
agg.templates
|
|
|> get_in([policy_type, client_type])
|
|
|> List.wrap()
|
|
|> Enum.find(&(&1.template_id == template_id))
|
|
end
|
|
|
|
defp update_template(templates, policy_type, client_type, template_id, fun) do
|
|
templates
|
|
|> Map.update(policy_type, %{}, fn inner ->
|
|
Map.update(inner, client_type, [], fn list ->
|
|
Enum.map(list, fn t ->
|
|
if t.template_id == template_id, do: fun.(t), else: t
|
|
end)
|
|
end)
|
|
end)
|
|
end
|
|
end
|