This commit is contained in:
341
lib/provider_service/aggregates/provider.ex
Normal file
341
lib/provider_service/aggregates/provider.ex
Normal file
@@ -0,0 +1,341 @@
|
||||
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
|
||||
existing = get_in(agg.templates, [cmd.policy_type, cmd.client_type]) || []
|
||||
version = length(existing) + 1
|
||||
|
||||
%ProviderTemplateAdded{
|
||||
provider_id: agg.provider_id,
|
||||
template_id: cmd.template_id,
|
||||
policy_type: cmd.policy_type,
|
||||
client_type: cmd.client_type,
|
||||
s3_key: cmd.s3_key,
|
||||
fields: cmd.fields,
|
||||
version: version,
|
||||
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,
|
||||
s3_key: e.s3_key,
|
||||
fields: e.fields,
|
||||
version: e.version,
|
||||
active: true
|
||||
}
|
||||
]
|
||||
)
|
||||
|
||||
%__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
|
||||
Reference in New Issue
Block a user