Data Models
Complete data models and schemas for the Esto platform
Data Models
The Esto platform uses a comprehensive data model designed to capture all aspects of real estate operations, from client preferences to property details and AI-powered matching.
📊 Contact Model
The Contact model represents potential clients with detailed preferences and requirements.
Schema
interface Contact {
// Core Information
id: string; // Unique identifier
email: string; // Primary contact email
fullName: string; // Full name of the contact
phone: string; // Contact phone number
age: number; // Age of the contact
// Family Information
familySituation: string; // "single", "married", "divorced", "widowed"
children?: number; // Number of children (optional)
// Location Preferences
wilaya: string; // Administrative region (e.g., "Alger", "Oran")
baladiya?: string; // Municipality (optional)
// Budget Preferences (Arrays for multiple ranges)
minBudgets: number[]; // Minimum budget ranges in DZD
maxBudgets: number[]; // Maximum budget ranges in DZD
// Property Preferences
minSurface: number[]; // Minimum surface area in sq.m
maxSurface: number[]; // Maximum surface area in sq.m
preferedPropertyType: string; // "apartment", "villa", "studio", "office"
bedrooms: number; // Number of bedrooms required
// Additional Options
options: string[]; // ["parking", "elevator", "balcony", "garden"]
// Metadata
createdAt: string; // ISO 8601 timestamp
updatedAt: string; // ISO 8601 timestamp
}Example Contact
{
"id": "c_123456",
"email": "ahmed.benali@email.com",
"fullName": "Ahmed Benali",
"phone": "+213 123 456 789",
"age": 35,
"familySituation": "married",
"children": 2,
"wilaya": "Alger",
"baladiya": "Hydra",
"minBudgets": [50000000, 80000000],
"maxBudgets": [70000000, 100000000],
"minSurface": [80, 120],
"maxSurface": [100, 150],
"preferedPropertyType": "apartment",
"bedrooms": 3,
"options": ["parking", "elevator", "balcony", "internet"],
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}Field Descriptions
| Field | Type | Description | Example |
|---|---|---|---|
id | string | Unique identifier | "c_123456" |
email | string | Primary contact email | "ahmed@email.com" |
fullName | string | Full name | "Ahmed Benali" |
phone | string | Phone number | "+213 123 456 789" |
age | number | Age in years | 35 |
familySituation | string | Marital status | "married" |
children | number? | Number of children | 2 |
wilaya | string | Administrative region | "Alger" |
baladiya | string? | Municipality | "Hydra" |
minBudgets | number[] | Minimum budget ranges | [50000000, 80000000] |
maxBudgets | number[] | Maximum budget ranges | [70000000, 100000000] |
minSurface | number[] | Minimum surface areas | [80, 120] |
maxSurface | number[] | Maximum surface areas | [100, 150] |
preferedPropertyType | string | Property type preference | "apartment" |
bedrooms | number | Required bedrooms | 3 |
options | string[] | Additional preferences | ["parking", "elevator"] |
🏠 Property Model
The Property model represents real estate listings with comprehensive details.
Schema
interface Property {
// Core Information
id: string; // Unique identifier
title: string; // Property title
description: string; // Detailed description
// Financial Information
price: number; // Price in DZD
// Physical Characteristics
surface: number; // Surface area in sq.m
bedrooms: number; // Number of bedrooms
bathrooms: number; // Number of bathrooms
propertyType: string; // "apartment", "villa", "studio", "office"
// Location Information
wilaya: string; // Administrative region
baladiya: string; // Municipality
// Media
images: string[]; // Array of image URLs
// Metadata
createdAt: string; // ISO 8601 timestamp
updatedAt: string; // ISO 8601 timestamp
}Example Property
{
"id": "e_123456",
"title": "Modern Apartment in Hydra",
"description": "Beautiful 3-bedroom apartment with sea view, modern amenities, and parking space. Located in the prestigious Hydra neighborhood.",
"price": 75000000,
"surface": 120,
"bedrooms": 3,
"bathrooms": 2,
"propertyType": "apartment",
"wilaya": "Alger",
"baladiya": "Hydra",
"images": ["https://example.com/image1.jpg", "https://example.com/image2.jpg", "https://example.com/image3.jpg"],
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}Field Descriptions
| Field | Type | Description | Example |
|---|---|---|---|
id | string | Unique identifier | "e_123456" |
title | string | Property title | "Modern Apartment in Hydra" |
description | string | Detailed description | "Beautiful apartment..." |
price | number | Price in DZD | 75000000 |
surface | number | Surface area in sq.m | 120 |
bedrooms | number | Number of bedrooms | 3 |
bathrooms | number | Number of bathrooms | 2 |
propertyType | string | Type of property | "apartment" |
wilaya | string | Administrative region | "Alger" |
baladiya | string | Municipality | "Hydra" |
images | string[] | Image URLs | ["url1", "url2"] |
🤖 Matching Model
The Matching model represents AI-powered recommendations between properties and contacts.
Schema
interface ContactMatch {
// Core Information
contactId: string; // Contact identifier
propertyId: string; // Property identifier
// Matching Scores
score: number; // Similarity score (0.0 - 1.0)
// Detailed Analysis
explanation: string; // Human-readable explanation
criteria: {
// Detailed scoring criteria
budgetMatch: number; // Budget compatibility score
locationMatch: number; // Location compatibility score
propertyTypeMatch: number; // Property type compatibility
surfaceMatch: number; // Surface area compatibility
featuresMatch: number; // Features compatibility
};
// Metadata
createdAt: string; // ISO 8601 timestamp
}Example Match
{
"contactId": "c_123456",
"propertyId": "e_123456",
"score": 0.92,
"explanation": "Perfect match: Budget range 50M-70M matches property price 75M, location preference 'Alger' matches property location, property type 'apartment' matches preference, surface area 120sqm within preferred range 80-150sqm",
"criteria": {
"budgetMatch": 0.95,
"locationMatch": 1.0,
"propertyTypeMatch": 1.0,
"surfaceMatch": 0.9,
"featuresMatch": 0.85
},
"createdAt": "2024-01-15T10:30:00Z"
}📊 Marketing Strategy Model
The Marketing Strategy model represents AI-generated marketing recommendations.
Schema
interface MarketingStrategy {
// Core Information
propertyId: string; // Property identifier
// Target Audience
targetAudience: string; // Description of target audience
// Advertising Strategy
adFormat: string; // Recommended ad format
budgetRecommendation: string; // Budget recommendation
// Creative Recommendations
creativeRecommendations: string[]; // Creative suggestions
copySuggestions: string[]; // Copy suggestions
// Performance Metrics
expectedReach: number; // Expected reach
expectedEngagement: number; // Expected engagement rate
// Metadata
createdAt: string; // ISO 8601 timestamp
}Example Marketing Strategy
{
"propertyId": "e_123456",
"targetAudience": "Young professionals aged 25-35, families with children",
"adFormat": "Carousel ads with property images",
"budgetRecommendation": "5000-10000 DZD per day",
"creativeRecommendations": [
"Highlight sea view and modern amenities",
"Emphasize proximity to schools and shopping centers",
"Show floor plan and room dimensions"
],
"copySuggestions": [
"🏠 Beautiful 3-bedroom apartment in Hydra",
"🌊 Sea view from every room",
"🏫 Near schools and shopping centers",
"💰 Competitive price: 75M DZD"
],
"expectedReach": 50000,
"expectedEngagement": 0.08,
"createdAt": "2024-01-15T10:30:00Z"
}📄 Document Model
The Document model represents generated PDF documents and quotes.
Schema
interface Document {
// Core Information
id: string; // Unique identifier
type: string; // "quote", "comparison", "invoice"
// Content
propertyId: string; // Property identifier
contactId?: string; // Contact identifier (optional)
// Document Details
title: string; // Document title
content: string; // Document content
pdfUrl: string; // PDF file URL
// Quote Details (for quotes)
quoteDetails?: {
validUntil: string; // Quote validity date
specialConditions: string; // Special conditions
totalAmount: number; // Total amount
};
// Metadata
createdAt: string; // ISO 8601 timestamp
}🔄 Data Relationships
One-to-Many Relationships
- Property → Matches: One property can have multiple contact matches
- Contact → Matches: One contact can match multiple properties
- Property → Marketing Strategies: One property can have multiple marketing strategies
- Property → Documents: One property can have multiple documents
Many-to-Many Relationships
- Contacts ↔ Properties: Through the matching system
- Properties ↔ Marketing Strategies: Through AI recommendations
📈 Data Validation Rules
Contact Validation
- Email must be valid format
- Phone number must be Algerian format (+213)
- Age must be between 18 and 100
- Budget ranges must be positive numbers
- Surface areas must be positive numbers
- Property type must be from predefined list
Property Validation
- Price must be positive number
- Surface area must be positive number
- Bedrooms and bathrooms must be positive integers
- Property type must be from predefined list
- Images must be valid URLs
Matching Validation
- Score must be between 0.0 and 1.0
- Contact and property must exist
- Explanation must not be empty
🗄️ Database Schema
The platform uses PostgreSQL with the following main tables:
-- Contacts table
CREATE TABLE contacts (
id UUID PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
full_name VARCHAR(255) NOT NULL,
phone VARCHAR(20) NOT NULL,
age INTEGER NOT NULL,
family_situation VARCHAR(50) NOT NULL,
children INTEGER,
wilaya VARCHAR(100) NOT NULL,
baladiya VARCHAR(100),
min_budgets JSONB NOT NULL,
max_budgets JSONB NOT NULL,
min_surface JSONB NOT NULL,
max_surface JSONB NOT NULL,
prefered_property_type VARCHAR(50) NOT NULL,
bedrooms INTEGER NOT NULL,
options JSONB NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Properties table
CREATE TABLE properties (
id UUID PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
price DECIMAL(15,2) NOT NULL,
surface DECIMAL(10,2) NOT NULL,
bedrooms INTEGER NOT NULL,
bathrooms INTEGER NOT NULL,
property_type VARCHAR(50) NOT NULL,
wilaya VARCHAR(100) NOT NULL,
baladiya VARCHAR(100) NOT NULL,
images JSONB NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
-- Matches table
CREATE TABLE matches (
id UUID PRIMARY KEY,
contact_id UUID REFERENCES contacts(id),
property_id UUID REFERENCES properties(id),
score DECIMAL(3,2) NOT NULL,
explanation TEXT NOT NULL,
criteria JSONB NOT NULL,
created_at TIMESTAMP DEFAULT NOW(),
UNIQUE(contact_id, property_id)
);📚 Next Steps
- API Reference - Complete API documentation
- Recommendation Logic - AI matching algorithms
- Integration Guide - Implementation examples
- Testing - Testing strategies