Files
provider-service/lib/provider_service/projections/provider_projection.ex
HaimKortovich f566d04a04
All checks were successful
Build and Publish / build-release (push) Successful in 4m46s
init commit
2026-04-15 15:31:56 -05:00

197 lines
5.9 KiB
Elixir

defmodule ProviderService.Projections.ProviderProjection do
use Commanded.Projections.Ecto,
application: ProviderService.CommandedApp,
repo: ProviderService.Repo,
name: "ProviderProjection",
consistency: :strong
alias ProviderService.Events.{
ProviderRegistered,
ProviderUpdated,
ProviderDeactivated,
ProviderReactivated,
ProviderTemplateAdded,
ProviderTemplateActivated,
ProviderTemplateDeactivated,
ProviderTemplateDefaultSet,
ProviderTemplateRemoved
}
alias ProviderService.Projections.Provider
import Ecto.Query
project(%ProviderRegistered{} = e, _meta, fn multi ->
Ecto.Multi.insert(multi, :provider, %Provider{
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,
templates: %{},
default_templates: %{}
})
end)
project(%ProviderUpdated{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
Ecto.Changeset.change(p,
name: e.name,
email: e.email,
phone: e.phone,
contact_name: e.contact_name,
ruc: e.ruc,
address: e.address
)
end)
end)
project(%ProviderDeactivated{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
Ecto.Changeset.change(p, active: false)
end)
end)
project(%ProviderReactivated{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
Ecto.Changeset.change(p, active: true)
end)
end)
# templates: %{ policy_type => %{ client_type => [template] } }
# default_templates: %{ policy_type => %{ client_type => template_id } }
project(%ProviderTemplateAdded{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
template = %{
"template_id" => e.template_id,
"client_type" => e.client_type,
"s3_key" => e.s3_key,
"fields" => e.fields || [],
"version" => e.version,
"active" => false
}
updated =
p.templates
|> Map.update(e.policy_type, %{e.client_type => [template]}, fn inner ->
Map.update(inner, e.client_type, [template], fn list -> list ++ [template] end)
end)
Ecto.Changeset.change(p, templates: updated)
end)
end)
project(%ProviderTemplateActivated{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
updated =
update_template_field(
p.templates,
e.policy_type,
e.client_type,
e.template_id,
"active",
true
)
Ecto.Changeset.change(p, templates: updated)
end)
end)
project(%ProviderTemplateDeactivated{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
updated =
update_template_field(
p.templates,
e.policy_type,
e.client_type,
e.template_id,
"active",
false
)
template_id = e.template_id
default_templates =
case get_in(p.default_templates, [e.policy_type, e.client_type]) do
^template_id ->
Map.update(p.default_templates, e.policy_type, %{}, &Map.delete(&1, e.client_type))
_ ->
p.default_templates
end
Ecto.Changeset.change(p, templates: updated, default_templates: default_templates)
end)
end)
project(%ProviderTemplateDefaultSet{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
default_templates =
p.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)
Ecto.Changeset.change(p, default_templates: default_templates)
end)
end)
project(%ProviderTemplateRemoved{} = e, _meta, fn multi ->
multi
|> Ecto.Multi.run(:fetch, fn repo, _ -> {:ok, repo.get!(Provider, e.provider_id)} end)
|> Ecto.Multi.update(:provider, fn %{fetch: p} ->
updated =
p.templates
|> Map.update(e.policy_type, %{}, fn inner ->
Map.update(inner, e.client_type, [], fn list ->
Enum.reject(list, &(&1["template_id"] == e.template_id))
end)
end)
template_id = e.template_id
default_templates =
case get_in(p.default_templates, [e.policy_type, e.client_type]) do
^template_id ->
Map.update(p.default_templates, e.policy_type, %{}, &Map.delete(&1, e.client_type))
_ ->
p.default_templates
end
Ecto.Changeset.change(p, templates: updated, default_templates: default_templates)
end)
end)
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
defp update_template_field(templates, policy_type, client_type, template_id, field, value) do
Map.update(templates, policy_type, %{}, fn inner ->
Map.update(inner, client_type, [], fn list ->
Enum.map(list, fn t ->
if t["template_id"] == template_id, do: Map.put(t, field, value), else: t
end)
end)
end)
end
end