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