Skip to main content

ElastiCORE Insurance Domain Sample Model

An entity model design guide for the insurance industry based on ElastiCORE. Referencing the Salesforce Insurance data model, this guide presents models ready for real-world use.

📋 Domain Overview

Core Business Entities

  • Insurance Policy: Core information of insurance contracts
  • Insurance Product: Available insurance products for sale
  • Insurance Quote: Quotation and underwriting process
  • Insurance Claim: Insurance claim filing and payment
  • Coverage Type: Insurance coverage scope definitions
  • Policy Participant: Insured persons, beneficiaries, etc.

🏗️ Entity Model Definitions

1. Insurance Policy

entity:
InsurancePolicy:
meta: entity @expose(50) @audited @extend(AuditEntity) @table(name="INSURANCE_POLICY")
fields:
policyId: long @id @sequence @search(eq) -- Policy ID
policyNumber: string(50)! @search(like) @unique -- Policy number (user-facing)
policyType: string(30)! @search(eq) -- Insurance type (AUTO, HOME, LIFE, HEALTH)
policyStatus: string(20)! @search(eq) -- Policy status (ACTIVE, EXPIRED, CANCELLED, PENDING)
insuredName: string(100)! @search(like) -- Insured name
policyEffectiveDate: date! @search(between) -- Policy effective date
policyExpiryDate: date! @search(between) -- Policy expiry date
totalPremium: bigdecimal(12.2) @search(between) -- Total premium
currencyCode: string(3) @search(eq) @default('KRW') -- Currency code (KRW, USD)
producerId: long @search(eq) @ref(Producer.id) -- Assigned agent/producer ID
productId: long! @search(eq) @ref(InsuranceProduct.id) -- Insurance product ID
accountId: long! @search(eq) @ref(Account.id) -- Customer account ID
renewalCount: int @search(between) @default(0) -- Renewal count
riskScore: int @search(between) -- Risk score (1-100)
notes: text @search(like) -- Special notes

2. Insurance Product

entity:
InsuranceProduct:
meta: entity @expose(50) @audited @extend(AuditEntity) @table(name="INSURANCE_PRODUCT")
fields:
productId: long @id @sequence @search(eq) -- Product ID
productCode: string(20)! @search(eq) @unique -- Product code
productName: string(100)! @search(like) -- Product name
productType: string(30)! @search(eq) -- Product type (AUTO, HOME, LIFE, HEALTH, COMMERCIAL)
productCategory: string(50) @search(eq) -- Product category
isActive: boolean @search(eq) @default(true) -- Available for sale
minPremium: bigdecimal(12.2) @search(between) -- Minimum premium
maxPremium: bigdecimal(12.2) @search(between) -- Maximum premium
minCoverage: bigdecimal(15.2) @search(between) -- Minimum coverage limit
maxCoverage: bigdecimal(15.2) @search(between) -- Maximum coverage limit
salesStartDate: date @search(between) -- Sales start date
salesEndDate: date @search(between) -- Sales end date
description: text @search(like) -- Product description
terms: text -- Terms and conditions

3. Insurance Coverage

entity:
InsuranceCoverage:
meta: entity @expose(50) @table(name="INSURANCE_COVERAGE")
fields:
coverageId: long @id @sequence -- Coverage ID
policyId: long! @search(eq) @ref(InsurancePolicy.id) -- Policy ID
coverageTypeId: long! @search(eq) @ref(CoverageType.id) -- Coverage type ID
coverageAmount: bigdecimal(15.2)! @search(between) -- Coverage limit
deductibleAmount: bigdecimal(12.2) @search(between) @default(0) -- Deductible amount
premiumAmount: bigdecimal(12.2) @search(between) -- Coverage premium
isOptional: boolean @search(eq) @default(false) -- Optional coverage flag
effectiveDate: date! @search(between) -- Coverage start date
expiryDate: date! @search(between) -- Coverage end date

4. Insurance Claim

entity:
InsuranceClaim:
meta: entity @expose(50) @audited @pageable @extend(AuditEntity) @table(name="INSURANCE_CLAIM")
fields:
claimId: long @id @sequence @search(eq) -- Claim ID
claimNumber: string(50)! @search(like) @unique -- Claim number
policyId: long! @search(eq) @ref(InsurancePolicy.id) -- Policy ID
claimStatus: string(20)! @search(eq) -- Claim status (SUBMITTED, INVESTIGATING, APPROVED, DENIED, PAID)
claimType: string(30)! @search(eq) -- Claim type (ACCIDENT, THEFT, DAMAGE, MEDICAL, DEATH)
incidentDate: date! @search(between) -- Incident date
reportedDate: datetime! @search(between) -- Report date/time
claimedAmount: bigdecimal(15.2)! @search(between) -- Claimed amount
approvedAmount: bigdecimal(15.2) @search(between) -- Approved amount
paidAmount: bigdecimal(15.2) @search(between) -- Paid amount
deductibleApplied: bigdecimal(12.2) @search(between) @default(0) -- Applied deductible
claimantName: string(100)! @search(like) -- Claimant name
claimantPhone: string(20) @search(like) -- Claimant phone number
incidentLocation: string(200) @search(like) -- Incident location
description: text @search(like) -- Incident description
assessorId: long @search(eq) @ref(Assessor.id) -- Claims assessor ID
finalizedDate: datetime @search(between) -- Finalized date/time

5. Coverage Type

entity:
CoverageType:
meta: entity @expose(50) @table(name="COVERAGE_TYPE")
fields:
coverageTypeId: long @id @sequence @search(eq) -- Coverage type ID
coverageCode: string(20)! @search(eq) @unique -- Coverage code
coverageName: string(100)! @search(like) -- Coverage name
insuranceType: string(30)! @search(eq) -- Insurance type (AUTO, HOME, LIFE, HEALTH)
isBasic: boolean @search(eq) @default(false) -- Basic coverage flag
defaultAmount: bigdecimal(15.2) @search(between) -- Default coverage amount
minAmount: bigdecimal(15.2) @search(between) -- Minimum coverage amount
maxAmount: bigdecimal(15.2) @search(between) -- Maximum coverage amount
description: text @search(like) -- Coverage description

6. Policy Participant

entity:
PolicyParticipant:
meta: entity @expose(50) @table(name="POLICY_PARTICIPANT")
fields:
participantId: long @id @sequence -- Participant ID
policyId: long! @search(eq) @ref(InsurancePolicy.id) -- Policy ID
participantType: string(20)! @search(eq) -- Participant type (INSURED, BENEFICIARY, OWNER, GUARDIAN)
contactId: long! @search(eq) @ref(Contact.id) -- Contact ID
relationshipType: string(30) @search(eq) -- Relationship (SELF, SPOUSE, CHILD, PARENT, SIBLING, OTHER)
beneficiaryPercentage: bigdecimal(5.2) @search(between) -- Beneficiary allocation (0-100%)
isPrimary: boolean @search(eq) @default(false) -- Primary participant flag
effectiveDate: date! @search(between) -- Participation start date
expiryDate: date @search(between) -- Participation end date

7. Insurance Quote

entity:
InsuranceQuote:
meta: entity @expose(50) @pageable @extend(AuditEntity) @table(name="INSURANCE_QUOTE")
fields:
quoteId: long @id @sequence @search(eq) -- Quote ID
quoteNumber: string(50)! @search(like) @unique -- Quote number
quoteStatus: string(20)! @search(eq) -- Quote status (DRAFT, SUBMITTED, APPROVED, REJECTED, CONVERTED)
productId: long! @search(eq) @ref(InsuranceProduct.id) -- Insurance product ID
accountId: long! @search(eq) @ref(Account.id) -- Customer account ID
producerId: long @search(eq) @ref(Producer.id) -- Agent/producer ID
quotedPremium: bigdecimal(12.2)! @search(between) -- Quoted premium
totalCoverage: bigdecimal(15.2) @search(between) -- Total coverage amount
validUntil: date! @search(between) -- Quote validity period
riskScore: int @search(between) -- Risk score
underwritingNotes: text @search(like) -- Underwriting notes
convertedPolicyId: long @search(eq) @ref(InsurancePolicy.id) -- Converted policy ID

🔗 Relational Design Patterns

1:N Relationships

  • InsurancePolicy (1) ↔ (N) InsuranceCoverage
  • InsurancePolicy (1) ↔ (N) InsuranceClaim
  • InsurancePolicy (1) ↔ (N) PolicyParticipant
  • InsuranceProduct (1) ↔ (N) InsurancePolicy

N:M Relationships (Using Junction Tables)

  • InsuranceProductCoverageType (ProductCoverage junction table)

📊 DTO Design Examples

PolicySearchDTO

dto:
PolicySearchDTO:
meta: dto @searchable @template('SEARCH')
fields:
policyNumber: string @search(like) -- Policy number
insuredName: string @search(like) -- Insured name
policyStatus: string @search(eq) -- Policy status
effectiveDateFrom: date @search(gte) @param('policyEffectiveDate') -- Effective date (from)
effectiveDateTo: date @search(lte) @param('policyEffectiveDate') -- Effective date (to)

ClaimSummaryDTO

dto:
ClaimSummaryDTO:
meta: dto
fields:
claimNumber: string -- Claim number
policyNumber: string -- Policy number
claimStatus: string -- Claim status
claimedAmount: bigdecimal(15.2) -- Claimed amount
approvedAmount: bigdecimal(15.2) -- Approved amount
incidentDate: date -- Incident date

📚 Repository Design Patterns

Complex Search Queries

repository:
InsurancePolicy:
methods:
- id: findPoliciesByStatusAndDateRange
params:
status: string
startDate: date
endDate: date
return: List<InsurancePolicy>
nativeQuery: true
query: |
SELECT p.* FROM INSURANCE_POLICY p
WHERE p.policy_status = :status
AND p.policy_effective_date BETWEEN :startDate AND :endDate
ORDER BY p.policy_effective_date DESC

- id: getClaimStatsByPolicy
params:
policyId: long
return: ClaimStatsDTO
nativeQuery: true
query: |
SELECT
COUNT(*) as claim_count,
SUM(claimed_amount) as total_claimed,
SUM(approved_amount) as total_approved
FROM INSURANCE_CLAIM
WHERE policy_id = :policyId

🎯 Best Practice Guidelines

1. Data Integrity

  • Apply @nullable(false) to required fields
  • Ensure referential integrity with the @ref annotation on foreign keys
  • Manage status values with a restricted set of enum-style values

2. Search Optimization

  • Apply appropriate @search annotations to frequently searched fields
  • Use @search(between) for date range searches
  • Use @search(like) for text searches

3. Audit Tracking

  • Apply @audited annotation to critical entities
  • Include creation and modification timestamp fields

4. Performance Considerations

  • Use @pageable for large dataset queries
  • Consider @Index annotation for fields that need indexing
  • Handle computed fields in DTOs

5. Business Logic

  • Use decimal types for monetary fields to ensure precision
  • Manage status changes through workflow-based processes
  • Date validation logic is essential

These models provide a foundation for building a stable system that can effectively handle various business requirements in the insurance industry.