This commit is contained in:
207
lib/provider_service_web/controllers/provider_controller.ex
Normal file
207
lib/provider_service_web/controllers/provider_controller.ex
Normal file
@@ -0,0 +1,207 @@
|
||||
defmodule ProviderServiceWeb.ProviderController do
|
||||
use ProviderServiceWeb, :controller
|
||||
use OpenApiSpex.ControllerSpecs
|
||||
|
||||
alias ProviderService.CommandedApp
|
||||
alias ProviderService.Queries.ProviderQueries
|
||||
|
||||
alias ProviderService.Commands.{
|
||||
RegisterProvider,
|
||||
UpdateProvider,
|
||||
DeactivateProvider,
|
||||
ReactivateProvider
|
||||
}
|
||||
|
||||
alias ProviderServiceWeb.Schemas.Provider, as: PS
|
||||
|
||||
operation(:index,
|
||||
summary: "List providers",
|
||||
parameters: [
|
||||
"page[number]": [in: :query, type: :integer, required: false],
|
||||
"page[size]": [in: :query, type: :integer, required: false],
|
||||
"filters[0][field]": [in: :query, type: :string, required: false],
|
||||
"filters[0][op]": [in: :query, type: :string, required: false],
|
||||
"filters[0][value]": [in: :query, type: :string, required: false]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Provider list", "application/json", PS.ProviderListResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def index(conn, params) do
|
||||
case ProviderQueries.list_providers(params) do
|
||||
{:ok, {providers, meta}} ->
|
||||
conn
|
||||
|> put_status(:ok)
|
||||
|> json(%{
|
||||
data: Enum.map(providers, &provider_json/1),
|
||||
meta: meta_json(meta)
|
||||
})
|
||||
|
||||
{:error, _} ->
|
||||
conn |> put_status(:bad_request) |> json(%{error: "invalid parameters"})
|
||||
end
|
||||
end
|
||||
|
||||
operation(:show,
|
||||
summary: "Get provider",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Provider", "application/json", PS.ProviderResponse},
|
||||
not_found: {"Not found", "application/json", %OpenApiSpex.Schema{type: :object}}
|
||||
]
|
||||
)
|
||||
|
||||
def show(conn, %{"provider_id" => provider_id}) do
|
||||
case ProviderQueries.get_provider(provider_id) do
|
||||
{:ok, provider} ->
|
||||
conn |> put_status(:ok) |> json(%{data: provider_json(provider)})
|
||||
|
||||
{:error, :not_found} ->
|
||||
conn |> put_status(:not_found) |> json(%{error: "not found"})
|
||||
end
|
||||
end
|
||||
|
||||
operation(:create,
|
||||
summary: "Register provider",
|
||||
request_body: {"Provider data", "application/json", PS.RegisterProvider, required: true},
|
||||
responses: [
|
||||
created: {"Provider registered", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def create(conn, params) do
|
||||
provider_id = params["provider_id"]
|
||||
|
||||
command = %RegisterProvider{
|
||||
provider_id: provider_id,
|
||||
name: params["name"],
|
||||
email: params["email"],
|
||||
phone: params["phone"],
|
||||
contact_name: params["contact_name"],
|
||||
ruc: params["ruc"],
|
||||
address: params["address"]
|
||||
}
|
||||
|
||||
case CommandedApp.dispatch(command, consistency: :strong) do
|
||||
:ok ->
|
||||
{:ok, provider} = ProviderQueries.get_provider(provider_id)
|
||||
conn |> put_status(:created) |> json(%{data: provider_json(provider)})
|
||||
|
||||
{:error, reason} ->
|
||||
conn |> put_status(:unprocessable_entity) |> json(%{error: inspect(reason)})
|
||||
end
|
||||
end
|
||||
|
||||
operation(:update,
|
||||
summary: "Update provider",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
request_body: {"Provider data", "application/json", PS.UpdateProvider, required: true},
|
||||
responses: [
|
||||
ok: {"Provider updated", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def update(conn, %{"provider_id" => provider_id} = params) do
|
||||
command = %UpdateProvider{
|
||||
provider_id: provider_id,
|
||||
name: params["name"],
|
||||
email: params["email"],
|
||||
phone: params["phone"],
|
||||
contact_name: params["contact_name"],
|
||||
ruc: params["ruc"],
|
||||
address: params["address"]
|
||||
}
|
||||
|
||||
case CommandedApp.dispatch(command, consistency: :strong) do
|
||||
:ok ->
|
||||
{:ok, provider} = ProviderQueries.get_provider(provider_id)
|
||||
conn |> put_status(:ok) |> json(%{data: provider_json(provider)})
|
||||
|
||||
{:error, reason} ->
|
||||
conn |> put_status(:unprocessable_entity) |> json(%{error: inspect(reason)})
|
||||
end
|
||||
end
|
||||
|
||||
operation(:deactivate,
|
||||
summary: "Deactivate provider",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Provider deactivated", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def deactivate(conn, %{"provider_id" => provider_id}) do
|
||||
command = %DeactivateProvider{
|
||||
provider_id: provider_id,
|
||||
deactivated_by: "system"
|
||||
}
|
||||
|
||||
case CommandedApp.dispatch(command, consistency: :strong) do
|
||||
:ok ->
|
||||
{:ok, provider} = ProviderQueries.get_provider(provider_id)
|
||||
conn |> put_status(:ok) |> json(%{data: provider_json(provider)})
|
||||
|
||||
{:error, reason} ->
|
||||
conn |> put_status(:unprocessable_entity) |> json(%{error: inspect(reason)})
|
||||
end
|
||||
end
|
||||
|
||||
operation(:reactivate,
|
||||
summary: "Reactivate provider",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Provider reactivated", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def reactivate(conn, %{"provider_id" => provider_id}) do
|
||||
command = %ReactivateProvider{
|
||||
provider_id: provider_id,
|
||||
reactivated_by: "system"
|
||||
}
|
||||
|
||||
case CommandedApp.dispatch(command, consistency: :strong) do
|
||||
:ok ->
|
||||
{:ok, provider} = ProviderQueries.get_provider(provider_id)
|
||||
conn |> put_status(:ok) |> json(%{data: provider_json(provider)})
|
||||
|
||||
{:error, reason} ->
|
||||
conn |> put_status(:unprocessable_entity) |> json(%{error: inspect(reason)})
|
||||
end
|
||||
end
|
||||
|
||||
defp provider_json(p) do
|
||||
%{
|
||||
provider_id: p.provider_id,
|
||||
name: p.name,
|
||||
email: p.email,
|
||||
phone: p.phone,
|
||||
contact_name: p.contact_name,
|
||||
ruc: p.ruc,
|
||||
address: p.address,
|
||||
active: p.active,
|
||||
templates: p.templates,
|
||||
default_templates: p.default_templates
|
||||
}
|
||||
end
|
||||
|
||||
defp meta_json(meta) do
|
||||
%{
|
||||
total_count: meta.total_count,
|
||||
total_pages: meta.total_pages,
|
||||
current_page: meta.current_page,
|
||||
page_size: meta.page_size,
|
||||
has_next: meta.has_next_page?,
|
||||
has_prev: meta.has_previous_page?
|
||||
}
|
||||
end
|
||||
end
|
||||
215
lib/provider_service_web/controllers/template_controller.ex
Normal file
215
lib/provider_service_web/controllers/template_controller.ex
Normal file
@@ -0,0 +1,215 @@
|
||||
defmodule ProviderServiceWeb.TemplateController do
|
||||
use ProviderServiceWeb, :controller
|
||||
use OpenApiSpex.ControllerSpecs
|
||||
|
||||
alias ProviderService.CommandedApp
|
||||
alias ProviderService.Queries.ProviderQueries
|
||||
|
||||
alias ProviderService.Commands.{
|
||||
AddProviderTemplate,
|
||||
ActivateProviderTemplate,
|
||||
DeactivateProviderTemplate,
|
||||
SetDefaultProviderTemplate,
|
||||
RemoveProviderTemplate
|
||||
}
|
||||
|
||||
alias ProviderService.S3
|
||||
alias ProviderServiceWeb.Schemas.Provider, as: PS
|
||||
|
||||
operation(:index,
|
||||
summary: "List templates for provider",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Templates", "application/json", %OpenApiSpex.Schema{type: :object}}
|
||||
]
|
||||
)
|
||||
|
||||
def index(conn, %{"provider_id" => provider_id}) do
|
||||
case ProviderQueries.get_provider(provider_id) do
|
||||
{:ok, provider} ->
|
||||
conn |> put_status(:ok) |> json(%{data: provider.templates})
|
||||
|
||||
{:error, :not_found} ->
|
||||
conn |> put_status(:not_found) |> json(%{error: "provider not found"})
|
||||
end
|
||||
end
|
||||
|
||||
operation(:upload_template,
|
||||
summary: "Upload solicitation template",
|
||||
description: "Upload a fillable PDF. Fields are auto-discovered via solicitation_service.",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
request_body:
|
||||
{"Multipart PDF upload", "multipart/form-data", PS.UploadTemplateRequest, required: true},
|
||||
responses: [
|
||||
created: {"Template registered", "application/json", PS.UploadTemplateResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def upload_template(conn, %{"provider_id" => provider_id} = params) do
|
||||
# %Plug.Upload{}
|
||||
upload = params["file"]
|
||||
policy_type = params["policy_type"]
|
||||
client_type = params["client_type"]
|
||||
|
||||
template_id = Ecto.UUID.generate()
|
||||
s3_key = "templates/#{provider_id}/#{policy_type}/#{client_type}/#{template_id}.pdf"
|
||||
|
||||
# Upload to S3/MinIO
|
||||
case S3.upload(upload.path, s3_key) do
|
||||
:ok ->
|
||||
# Discover AcroForm fields via solicitation_service
|
||||
fields = discover_fields(s3_key)
|
||||
|
||||
cmd = %AddProviderTemplate{
|
||||
provider_id: provider_id,
|
||||
template_id: template_id,
|
||||
client_type: client_type,
|
||||
policy_type: policy_type,
|
||||
s3_key: s3_key,
|
||||
fields: fields
|
||||
}
|
||||
|
||||
case ProviderService.CommandedApp.dispatch(cmd) do
|
||||
:ok ->
|
||||
conn
|
||||
|> put_status(:created)
|
||||
|> json(%{template_id: template_id, s3_key: s3_key, fields: fields})
|
||||
|
||||
{:error, reason} ->
|
||||
conn |> put_status(:unprocessable_entity) |> json(%{error: reason})
|
||||
end
|
||||
|
||||
{:error, reason} ->
|
||||
conn
|
||||
|> put_status(:internal_server_error)
|
||||
|> json(%{error: "S3 upload failed: #{reason}"})
|
||||
end
|
||||
end
|
||||
|
||||
defp discover_fields(s3_key) do
|
||||
url = Application.get_env(:provider_service, :solicitation_service_url)
|
||||
|
||||
case Req.get("#{url}/api/solicitations/templates/fields", params: [s3_key: s3_key]) do
|
||||
{:ok, %{status: 200, body: %{"fields" => fields}}} -> fields
|
||||
_ -> []
|
||||
end
|
||||
end
|
||||
|
||||
operation(:activate,
|
||||
summary: "Activate a template",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true],
|
||||
template_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Template activated", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def activate(conn, %{"provider_id" => provider_id, "template_id" => template_id} = params) do
|
||||
command = %ActivateProviderTemplate{
|
||||
provider_id: provider_id,
|
||||
template_id: template_id,
|
||||
policy_type: params["policy_type"],
|
||||
client_type: params["client_type"]
|
||||
}
|
||||
|
||||
dispatch_and_respond(conn, command, provider_id)
|
||||
end
|
||||
|
||||
operation(:deactivate,
|
||||
summary: "Deactivate a template",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true],
|
||||
template_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Template deactivated", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def deactivate(conn, %{"provider_id" => provider_id, "template_id" => template_id} = params) do
|
||||
command = %DeactivateProviderTemplate{
|
||||
provider_id: provider_id,
|
||||
template_id: template_id,
|
||||
policy_type: params["policy_type"],
|
||||
client_type: params["client_type"]
|
||||
}
|
||||
|
||||
dispatch_and_respond(conn, command, provider_id)
|
||||
end
|
||||
|
||||
operation(:set_default,
|
||||
summary: "Set default template for a policy type",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true],
|
||||
template_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Default template set", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def set_default(conn, %{"provider_id" => provider_id, "template_id" => template_id} = params) do
|
||||
command = %SetDefaultProviderTemplate{
|
||||
provider_id: provider_id,
|
||||
template_id: template_id,
|
||||
policy_type: params["policy_type"],
|
||||
client_type: params["client_type"]
|
||||
}
|
||||
|
||||
dispatch_and_respond(conn, command, provider_id)
|
||||
end
|
||||
|
||||
operation(:remove,
|
||||
summary: "Remove a template",
|
||||
parameters: [
|
||||
provider_id: [in: :path, type: :string, required: true],
|
||||
template_id: [in: :path, type: :string, required: true]
|
||||
],
|
||||
responses: [
|
||||
ok: {"Template removed", "application/json", PS.ProviderResponse}
|
||||
]
|
||||
)
|
||||
|
||||
def remove(conn, %{"provider_id" => provider_id, "template_id" => template_id} = params) do
|
||||
command = %RemoveProviderTemplate{
|
||||
provider_id: provider_id,
|
||||
template_id: template_id,
|
||||
policy_type: params["policy_type"],
|
||||
client_type: params["client_type"]
|
||||
}
|
||||
|
||||
dispatch_and_respond(conn, command, provider_id)
|
||||
end
|
||||
|
||||
defp dispatch_and_respond(conn, command, provider_id) do
|
||||
case CommandedApp.dispatch(command, consistency: :strong) do
|
||||
:ok ->
|
||||
{:ok, provider} = ProviderQueries.get_provider(provider_id)
|
||||
conn |> put_status(:ok) |> json(%{data: provider_json(provider)})
|
||||
|
||||
{:error, reason} ->
|
||||
conn |> put_status(:unprocessable_entity) |> json(%{error: inspect(reason)})
|
||||
end
|
||||
end
|
||||
|
||||
defp provider_json(p) do
|
||||
%{
|
||||
provider_id: p.provider_id,
|
||||
name: p.name,
|
||||
email: p.email,
|
||||
phone: p.phone,
|
||||
contact_name: p.contact_name,
|
||||
ruc: p.ruc,
|
||||
address: p.address,
|
||||
active: p.active,
|
||||
templates: p.templates,
|
||||
default_templates: p.default_templates
|
||||
}
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user