defmodule PolicyServiceWeb.Schemas.Policy do alias OpenApiSpex.Schema defmodule PaginationMeta do require OpenApiSpex OpenApiSpex.schema(%{ title: "PaginationMeta", type: :object, properties: %{ total_count: %Schema{type: :integer}, total_pages: %Schema{type: :integer}, current_page: %Schema{type: :integer}, page_size: %Schema{type: :integer}, has_next: %Schema{type: :boolean}, has_prev: %Schema{type: :boolean} } }) end # --------------------------------------------------------------------------- # Applicant — discriminated by presence of keys # --------------------------------------------------------------------------- defmodule ApplicantIndividual do require OpenApiSpex OpenApiSpex.schema(%{ title: "ApplicantIndividual", type: :object, required: [:name, :date_of_birth, :document_id], properties: %{ name: %Schema{type: :string, example: "Juan Pérez"}, date_of_birth: %Schema{type: :string, format: :date, example: "1985-06-15"}, document_id: %Schema{type: :string, example: "8-123-456"} } }) end defmodule ApplicantCorporate do require OpenApiSpex OpenApiSpex.schema(%{ title: "ApplicantCorporate", type: :object, required: [:company_name, :ruc, :legal_rep_name, :legal_rep_document], properties: %{ company_name: %Schema{type: :string, example: "Empresa ABC S.A."}, ruc: %Schema{type: :string, example: "123456-1-123456"}, legal_rep_name: %Schema{type: :string, example: "María García"}, legal_rep_document: %Schema{type: :string, example: "8-456-789"} } }) end defmodule ApplicantInfo do require OpenApiSpex OpenApiSpex.schema(%{ title: "ApplicantInfo", oneOf: [ApplicantIndividual, ApplicantCorporate] }) end # --------------------------------------------------------------------------- # Policy details — one per policy type # --------------------------------------------------------------------------- defmodule CarPolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "CarPolicyDetails", type: :object, required: [ :plate, :make, :model, :year, :car_value, :use_type, :car_type, :chassis_number, :engine_number ], properties: %{ plate: %Schema{type: :string, example: "ABC-1234"}, make: %Schema{type: :string, example: "Toyota"}, model: %Schema{type: :string, example: "Corolla"}, year: %Schema{type: :integer, example: 2022}, car_value: %Schema{type: :number, example: 18000}, use_type: %Schema{type: :string, enum: ["private", "commercial", "bus", "taxi", "school"]}, car_type: %Schema{ type: :string, enum: [ "sedan", "suv", "hatchback", "coupe", "convertible", "pickup", "van", "minivan", "truck" ] }, chassis_number: %Schema{type: :string, example: "9BWZZZ377VT004251"}, engine_number: %Schema{type: :string, example: "1NZ-FE-1234567"} } }) end defmodule LifePolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "LifePolicyDetails", type: :object, required: [:coverage_amount, :beneficiary], properties: %{ coverage_amount: %Schema{type: :number, example: 100_000}, beneficiary: %Schema{type: :string, example: "María Pérez"} } }) end defmodule FirePolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "FirePolicyDetails", type: :object, required: [:property_address, :property_value], properties: %{ property_address: %Schema{type: :string, example: "Calle 50, Panama City"}, property_value: %Schema{type: :number, example: 250_000} } }) end defmodule PolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "PolicyDetails", oneOf: [CarPolicyDetails, LifePolicyDetails, FirePolicyDetails] }) end # --------------------------------------------------------------------------- # Shared # --------------------------------------------------------------------------- defmodule SelectedProvider do require OpenApiSpex OpenApiSpex.schema(%{ title: "SelectedProvider", type: :object, required: [:provider_id, :email], properties: %{ provider_id: %Schema{type: :string, format: :uuid}, email: %Schema{type: :string, format: :email} } }) end defmodule Plan do require OpenApiSpex OpenApiSpex.schema(%{ title: "Plan", type: :object, properties: %{ plan_id: %Schema{type: :string}, name: %Schema{type: :string}, premium: %Schema{type: :number}, coverage_details: %Schema{type: :string}, deductible: %Schema{type: :number, nullable: true}, coverage_limit: %Schema{type: :number, nullable: true} } }) end defmodule QuoteData do require OpenApiSpex OpenApiSpex.schema(%{ title: "QuoteData", type: :object, properties: %{ quote_id: %Schema{type: :string}, valid_until: %Schema{type: :string, format: :date}, received_at: %Schema{type: :string, format: :"date-time"}, plans: %Schema{type: :array, items: Plan} } }) end # --------------------------------------------------------------------------- # Requests # --------------------------------------------------------------------------- defmodule CreatePolicyRequest do require OpenApiSpex OpenApiSpex.schema(%{ title: "CreatePolicyRequest", type: :object, required: [:policy_type, :applicant_info, :policy_details, :selected_providers], properties: %{ policy_type: %Schema{ type: :string, enum: ["car", "life", "fire"], description: "Determines the shape of policy_details" }, applicant_info: ApplicantInfo, policy_details: PolicyDetails, selected_providers: %Schema{type: :array, items: SelectedProvider, minItems: 1} } }) end defmodule AcceptQuoteRequest do require OpenApiSpex OpenApiSpex.schema(%{ title: "AcceptQuoteRequest", type: :object, required: [:quote_id, :plan_id], properties: %{ quote_id: %Schema{type: :string}, plan_id: %Schema{type: :string}, solicitation_fields: %Schema{ type: :object, additionalProperties: %Schema{type: :string}, description: "Optional flat map of AcroForm field names to values", nullable: true } } }) end # --------------------------------------------------------------------------- # Responses # --------------------------------------------------------------------------- defmodule QuoteResponse do require OpenApiSpex OpenApiSpex.schema(%{ title: "QuoteResponse", type: :object, properties: %{ application_id: %Schema{type: :string}, status: %Schema{type: :string} } }) end defmodule SolicitationUrlResponse do require OpenApiSpex OpenApiSpex.schema(%{ title: "SolicitationUrlResponse", type: :object, properties: %{ download_url: %Schema{type: :string}, s3_key: %Schema{type: :string}, version: %Schema{type: :integer} } }) end defmodule PolicySummary do require OpenApiSpex OpenApiSpex.schema(%{ title: "PolicySummary", type: :object, properties: %{ application_id: %Schema{type: :string}, policy_type: %Schema{type: :string, enum: ["car", "life", "fire"]}, status: %Schema{ type: :string, enum: ["quote_requested", "quotes_received", "solicitation_sent", "issued"] }, applicant_info: ApplicantInfo, policy_details: PolicyDetails, policy_number: %Schema{type: :string, nullable: true}, submitted_at: %Schema{type: :string, format: :"date-time"} } }) end defmodule PolicyDetail do require OpenApiSpex OpenApiSpex.schema(%{ title: "PolicyDetail", type: :object, properties: %{ application_id: %Schema{type: :string}, org_id: %Schema{type: :string}, submitted_by: %Schema{type: :string}, policy_type: %Schema{type: :string, enum: ["car", "life", "fire"]}, status: %Schema{ type: :string, enum: ["quote_requested", "quotes_received", "solicitation_sent", "issued"] }, applicant_info: ApplicantInfo, policy_details: PolicyDetails, selected_providers: %Schema{type: :array, items: %Schema{type: :string}}, quotes: %Schema{type: :object, additionalProperties: QuoteData}, accepted_quote_id: %Schema{type: :string, nullable: true}, accepted_plan_id: %Schema{type: :string, nullable: true}, accepted_provider_id: %Schema{type: :string, nullable: true}, accepted_at: %Schema{type: :string, format: :"date-time", nullable: true}, solicitation_id: %Schema{type: :string, nullable: true}, solicitation_s3_key: %Schema{type: :string, nullable: true}, policy_number: %Schema{type: :string, nullable: true}, premium: %Schema{type: :number, nullable: true}, effective_date: %Schema{type: :string, format: :date, nullable: true}, expiry_date: %Schema{type: :string, format: :date, nullable: true}, submitted_at: %Schema{type: :string, format: :"date-time"}, solicitation_sent_at: %Schema{type: :string, format: :"date-time", nullable: true}, issued_at: %Schema{type: :string, format: :"date-time", nullable: true} } }) end defmodule PolicyListResponse do require OpenApiSpex OpenApiSpex.schema(%{ title: "PolicyListResponse", type: :object, properties: %{ data: %Schema{type: :array, items: PolicySummary}, meta: PaginationMeta } }) end defmodule PolicyDetailResponse do require OpenApiSpex OpenApiSpex.schema(%{ title: "PolicyDetailResponse", type: :object, properties: %{ data: PolicyDetail } }) end defmodule ErrorResponse do require OpenApiSpex OpenApiSpex.schema(%{ title: "ErrorResponse", type: :object, properties: %{ error: %Schema{type: :string} } }) end end