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 defmodule InsuredIndividual do require OpenApiSpex OpenApiSpex.schema(%{ title: "InsuredIndividual", type: :object, required: [:type, :name, :date_of_birth, :document_id, :gender], properties: %{ type: %Schema{type: :string, enum: ["individual"]}, 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"}, gender: %Schema{type: :string, enum: ["male", "female"], example: "male"}, email: %Schema{type: :string, format: :email, example: "juan@example.com"}, phone: %Schema{type: :string, example: "+507-1234-5678"}, address: %Schema{type: :string, example: "Calle 50, Panama City"} } }) end defmodule InsuredCorporate do require OpenApiSpex OpenApiSpex.schema(%{ title: "InsuredCorporate", type: :object, required: [:type, :company_name, :ruc, :legal_rep_name, :legal_rep_document], properties: %{ type: %Schema{type: :string, enum: ["corporate"]}, 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"}, email: %Schema{type: :string, format: :email, example: "contact@empresa-abc.com"}, phone: %Schema{type: :string, example: "+507-1234-5678"}, address: %Schema{type: :string, example: "Calle 50, Panama City"} } }) end defmodule Insured do require OpenApiSpex OpenApiSpex.schema(%{ title: "Insured", oneOf: [InsuredIndividual, InsuredCorporate] }) end defmodule BuyerIndividual do require OpenApiSpex OpenApiSpex.schema(%{ title: "BuyerIndividual", type: :object, required: [:type, :name, :date_of_birth, :document_id], properties: %{ type: %Schema{type: :string, enum: ["individual"]}, name: %Schema{type: :string, example: "María García"}, date_of_birth: %Schema{type: :string, format: :date, example: "1980-03-20"}, document_id: %Schema{type: :string, example: "8-456-789"}, email: %Schema{type: :string, format: :email, example: "maria@example.com"}, phone: %Schema{type: :string, example: "+507-8765-4321"}, address: %Schema{type: :string, example: "Calle 75, Panama City"} } }) end defmodule BuyerCorporate do require OpenApiSpex OpenApiSpex.schema(%{ title: "BuyerCorporate", type: :object, required: [:type, :company_name, :ruc, :legal_rep_name, :legal_rep_document], properties: %{ type: %Schema{type: :string, enum: ["corporate"]}, company_name: %Schema{type: :string, example: "Empresa XYZ S.A."}, ruc: %Schema{type: :string, example: "987654-1-987654"}, legal_rep_name: %Schema{type: :string, example: "Carlos López"}, legal_rep_document: %Schema{type: :string, example: "8-789-012"}, email: %Schema{type: :string, format: :email, example: "carlos@empresa-xyz.com"}, phone: %Schema{type: :string, example: "+507-8765-4321"}, address: %Schema{type: :string, example: "Calle 100, Panama City"} } }) end defmodule Buyer do require OpenApiSpex OpenApiSpex.schema(%{ title: "Buyer", oneOf: [BuyerIndividual, BuyerCorporate] }) end # --------------------------------------------------------------------------- # Policy details — one per policy type # --------------------------------------------------------------------------- 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, :use_type, :car_type, :rc_limits, :market_value, :requested_value ], 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}, 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"}, rc_limits: %Schema{ type: :object, properties: %{ bodily_injury: %Schema{type: :number, example: 50000}, property_damage: %Schema{type: :number, example: 25000} } }, market_value: %Schema{type: :number, example: 18000}, requested_value: %Schema{type: :number, example: 20000} } }) end defmodule LifePolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "LifePolicyDetails", type: :object, required: [:coverage_type, :coverage_amount, :coverage_years, :smoker], properties: %{ coverage_type: %Schema{ type: :string, enum: ["banking", "protection"] }, coverage_amount: %Schema{type: :number, example: 100_000}, coverage_years: %Schema{type: :integer, example: 10}, smoker: %Schema{type: :boolean, example: false}, medications: %Schema{type: :array, items: %Schema{type: :string}, example: ["Aspirin", "Lisinopril"]}, surgeries: %Schema{type: :array, items: %Schema{type: :string}, example: ["Appendectomy, 2015"]}, weight: %Schema{type: :number, example: 70}, height: %Schema{type: :number, example: 175} } }) end defmodule FireStructurePolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "FireStructurePolicyDetails", type: :object, required: [:location, :property_value, :property_use, :security_measures, :market_value], properties: %{ location: %Schema{type: :string, example: "Calle 50, Panama City"}, property_value: %Schema{type: :number, example: 250_000}, property_use: %Schema{type: :string, example: "residential"}, security_measures: %Schema{type: :array, items: %Schema{type: :string}}, market_value: %Schema{type: :number, example: 260_000} } }) end defmodule FireContentsPolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "FireContentsPolicyDetails", type: :object, required: [:location, :contents_value, :property_use, :security_measures], properties: %{ location: %Schema{type: :string, example: "Calle 50, Panama City"}, contents_value: %Schema{type: :number, example: 50_000}, property_use: %Schema{type: :string, example: "residential"}, security_measures: %Schema{type: :array, items: %Schema{type: :string}}, high_value_items: %Schema{ type: :array, items: %Schema{ type: :object, properties: %{ description: %Schema{type: :string}, value: %Schema{type: :number}, type: %Schema{type: :string, enum: ["electronic", "other"]} } } } } }) end defmodule PolicyDetails do require OpenApiSpex OpenApiSpex.schema(%{ title: "PolicyDetails", oneOf: [ CarPolicyDetails, LifePolicyDetails, FireStructurePolicyDetails, FireContentsPolicyDetails ] }) 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, :insured, :buyer, :policy_details, :selected_providers], properties: %{ policy_type: %Schema{ type: :string, enum: ["car", "life", "fire_structure", "fire_contents"], description: "Determines the shape of policy_details" }, insured: Insured, buyer: Buyer, 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: [:accepted_plan_id], properties: %{ accepted_plan_id: %Schema{ type: :string, description: "Plan ID to accept" } } }) 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 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_structure", "fire_contents"] }, status: %Schema{ type: :string, enum: ["quote_requested", "quotes_received", "awaiting_policy", "issued"] }, insured: Insured, buyer: Buyer, policy_details: PolicyDetails, provider_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_structure", "fire_contents"] }, status: %Schema{ type: :string, enum: ["quote_requested", "quotes_received", "awaiting_policy", "issued"] }, insured: Insured, buyer: Buyer, policy_details: PolicyDetails, selected_providers: %Schema{type: :array, items: %Schema{type: :string}}, quotes: %Schema{type: :object, additionalProperties: QuoteData}, accepted_plan_id: %Schema{type: :string, nullable: true}, accepted_by: %Schema{type: :string, nullable: true}, provider_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