Skip to content

YeboNa Database Models

Complete schema documentation. YeboNa uses inline SQL with Neon Serverless Postgres.

Type Definitions

typescript
// Service categories
type ServiceCategory = 'exchange' | 'sourcing' | 'verification' | 'freight' | 'translation' | 'consulting';

// User types
type UserType = 'user' | 'provider' | 'both';

// Verification levels
type VerificationLevel = 'phone' | 'id' | 'business' | 'pro';

// Provider status
type ProviderStatus = 'pending' | 'active' | 'suspended';

// Request status
type RequestStatus = 'open' | 'quoted' | 'accepted' | 'completed' | 'cancelled';

// Quote status
type QuoteStatus = 'pending' | 'accepted' | 'declined' | 'expired';

// Transaction status
type TransactionStatus = 'pending_payment' | 'payment_received' | 'in_progress' | 'completed' | 'disputed' | 'refunded' | 'released';

// Review types
type ReviewType = 'user_to_provider' | 'provider_to_user';

// Message types
type MessageType = 'text' | 'image' | 'document' | 'voice' | 'system';

// Badge types
type BadgeType = 'verified' | 'top_rated' | 'pro' | 'fast_response';

// Price units
type PriceUnit = 'fixed' | 'hourly' | 'per_item' | 'percentage';

Users Table

sql
CREATE TABLE users (
  id                 TEXT PRIMARY KEY,
  phone_number       TEXT UNIQUE NOT NULL,
  password_hash      TEXT NOT NULL,
  email              TEXT UNIQUE,
  name               TEXT,
  avatar_url         TEXT,
  country            TEXT,
  country_code       TEXT,
  user_type          TEXT DEFAULT 'user',
  verification_level TEXT DEFAULT 'phone',
  language           TEXT DEFAULT 'en',
  currency           TEXT DEFAULT 'USD',
  verified           BOOLEAN DEFAULT false,
  created_at         TIMESTAMP DEFAULT NOW(),
  updated_at         TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_users_phone ON users(phone_number);
CREATE INDEX idx_users_email ON users(email);

Providers Table

sql
CREATE TABLE providers (
  id                   TEXT PRIMARY KEY,
  user_id              TEXT UNIQUE NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  business_name        TEXT,
  bio                  TEXT,
  city                 TEXT,
  country              TEXT,
  languages            TEXT[] DEFAULT '{}',
  response_time_mins   INTEGER DEFAULT 60,
  
  -- Ratings (calculated from reviews)
  rating               DECIMAL(2,1) DEFAULT 0,
  review_count         INTEGER DEFAULT 0,
  rating_communication DECIMAL(2,1) DEFAULT 0,
  rating_quality       DECIMAL(2,1) DEFAULT 0,
  rating_value         DECIMAL(2,1) DEFAULT 0,
  rating_timeliness    DECIMAL(2,1) DEFAULT 0,
  
  status               TEXT DEFAULT 'pending',
  verified_at          TIMESTAMP,
  created_at           TIMESTAMP DEFAULT NOW(),
  updated_at           TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_providers_user ON providers(user_id);
CREATE INDEX idx_providers_status ON providers(status);

Provider Services Table

sql
CREATE TABLE provider_services (
  id             TEXT PRIMARY KEY,
  provider_id    TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
  category       TEXT NOT NULL,
  description    TEXT NOT NULL,
  starting_price DECIMAL(12,2) NOT NULL,
  currency       TEXT DEFAULT 'USD',
  price_unit     TEXT DEFAULT 'fixed',
  created_at     TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_provider_services_provider ON provider_services(provider_id);
CREATE INDEX idx_provider_services_category ON provider_services(category);

Portfolio Items Table

sql
CREATE TABLE portfolio_items (
  id          TEXT PRIMARY KEY,
  provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
  title       TEXT NOT NULL,
  description TEXT,
  image_url   TEXT NOT NULL,
  created_at  TIMESTAMP DEFAULT NOW()
);

Badges Table

sql
CREATE TABLE badges (
  id          TEXT PRIMARY KEY,
  provider_id TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
  badge_type  TEXT NOT NULL,
  label       TEXT NOT NULL,
  earned_at   TIMESTAMP DEFAULT NOW()
);

Requests Table

sql
CREATE TABLE requests (
  id               TEXT PRIMARY KEY,
  user_id          TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  category         TEXT NOT NULL,
  title            TEXT NOT NULL,
  description      TEXT NOT NULL,
  attachments      TEXT[] DEFAULT '{}',
  budget_min       DECIMAL(12,2),
  budget_max       DECIMAL(12,2),
  budget_currency  TEXT DEFAULT 'USD',
  timeline         TEXT,
  target_providers TEXT[] DEFAULT '{}',
  status           TEXT DEFAULT 'open',
  expires_at       TIMESTAMP,
  created_at       TIMESTAMP DEFAULT NOW(),
  updated_at       TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_requests_user ON requests(user_id);
CREATE INDEX idx_requests_status ON requests(status);
CREATE INDEX idx_requests_category ON requests(category);

Quotes Table

sql
CREATE TABLE quotes (
  id           TEXT PRIMARY KEY,
  request_id   TEXT NOT NULL REFERENCES requests(id) ON DELETE CASCADE,
  provider_id  TEXT NOT NULL REFERENCES providers(id) ON DELETE CASCADE,
  amount       DECIMAL(12,2) NOT NULL,
  currency     TEXT DEFAULT 'USD',
  description  TEXT NOT NULL,
  deliverables TEXT[] DEFAULT '{}',
  timeline     TEXT,
  valid_until  TIMESTAMP,
  status       TEXT DEFAULT 'pending',
  created_at   TIMESTAMP DEFAULT NOW(),
  updated_at   TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_quotes_request ON quotes(request_id);
CREATE INDEX idx_quotes_provider ON quotes(provider_id);

Transactions Table

sql
CREATE TABLE transactions (
  id                   TEXT PRIMARY KEY,
  quote_id             TEXT NOT NULL REFERENCES quotes(id),
  request_id           TEXT NOT NULL REFERENCES requests(id),
  user_id              TEXT NOT NULL REFERENCES users(id),
  provider_id          TEXT NOT NULL REFERENCES providers(id),
  amount               DECIMAL(12,2) NOT NULL,
  currency             TEXT DEFAULT 'USD',
  fee                  DECIMAL(12,2) DEFAULT 0,
  provider_payout      DECIMAL(12,2) NOT NULL,
  status               TEXT DEFAULT 'pending_payment',
  payment_proof_url    TEXT,
  completion_proof_url TEXT,
  paid_at              TIMESTAMP,
  completed_at         TIMESTAMP,
  released_at          TIMESTAMP,
  created_at           TIMESTAMP DEFAULT NOW(),
  updated_at           TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_transactions_user ON transactions(user_id);
CREATE INDEX idx_transactions_provider ON transactions(provider_id);
CREATE INDEX idx_transactions_status ON transactions(status);

Reviews Table

sql
CREATE TABLE reviews (
  id                   TEXT PRIMARY KEY,
  transaction_id       TEXT NOT NULL REFERENCES transactions(id),
  reviewer_id          TEXT NOT NULL REFERENCES users(id),
  reviewee_id          TEXT NOT NULL REFERENCES users(id),
  review_type          TEXT NOT NULL,
  rating               DECIMAL(2,1) NOT NULL,
  rating_communication DECIMAL(2,1),
  rating_quality       DECIMAL(2,1),
  rating_value         DECIMAL(2,1),
  rating_timeliness    DECIMAL(2,1),
  text                 TEXT NOT NULL,
  photos               TEXT[] DEFAULT '{}',
  response             TEXT,
  created_at           TIMESTAMP DEFAULT NOW(),
  UNIQUE(transaction_id, reviewer_id)
);

CREATE INDEX idx_reviews_transaction ON reviews(transaction_id);
CREATE INDEX idx_reviews_reviewee ON reviews(reviewee_id);

Conversations Table

sql
CREATE TABLE conversations (
  id              TEXT PRIMARY KEY,
  participant_1_id TEXT NOT NULL REFERENCES users(id),
  participant_2_id TEXT NOT NULL REFERENCES users(id),
  request_id      TEXT REFERENCES requests(id),
  transaction_id  TEXT REFERENCES transactions(id),
  last_message_at TIMESTAMP,
  created_at      TIMESTAMP DEFAULT NOW(),
  updated_at      TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_conversations_participants ON conversations(participant_1_id, participant_2_id);

Messages Table

sql
CREATE TABLE messages (
  id              TEXT PRIMARY KEY,
  conversation_id TEXT NOT NULL REFERENCES conversations(id) ON DELETE CASCADE,
  sender_id       TEXT NOT NULL REFERENCES users(id),
  message_type    TEXT DEFAULT 'text',
  content         TEXT NOT NULL,
  metadata        JSONB,
  read_at         TIMESTAMP,
  created_at      TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_messages_conversation ON messages(conversation_id);
CREATE INDEX idx_messages_created ON messages(created_at);

OTPs Table

sql
CREATE TABLE otps (
  id           TEXT PRIMARY KEY,
  phone_number TEXT NOT NULL,
  code         TEXT NOT NULL,
  type         TEXT NOT NULL,
  expires_at   TIMESTAMP NOT NULL,
  verified     BOOLEAN DEFAULT false,
  created_at   TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_otps_phone_type ON otps(phone_number, type);

Refresh Tokens Table

sql
CREATE TABLE refresh_tokens (
  token        TEXT PRIMARY KEY,
  user_id      TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  phone_number TEXT NOT NULL,
  expires_at   TIMESTAMP NOT NULL,
  created_at   TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_refresh_tokens_user ON refresh_tokens(user_id);

Waitlist Table

sql
CREATE TABLE waitlist (
  id         TEXT PRIMARY KEY,
  name       TEXT NOT NULL,
  phone      TEXT NOT NULL,
  interest   TEXT,
  product    TEXT,
  source     TEXT,
  status     TEXT DEFAULT 'pending',
  notes      TEXT,
  country    TEXT,
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

Blog Posts Table

sql
CREATE TABLE blog_posts (
  id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  title          VARCHAR(500) NOT NULL,
  slug           VARCHAR(500) NOT NULL UNIQUE,
  content        TEXT NOT NULL,
  excerpt        TEXT,
  category       VARCHAR(100),
  tags           TEXT[] DEFAULT ARRAY[]::TEXT[],
  status         VARCHAR(20) DEFAULT 'published',
  author         VARCHAR(100) DEFAULT 'AI',
  featured_image TEXT,
  published_at   TIMESTAMP DEFAULT NOW(),
  created_at     TIMESTAMP DEFAULT NOW(),
  updated_at     TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_blog_posts_slug ON blog_posts(slug);
CREATE INDEX idx_blog_posts_status ON blog_posts(status);

Relationships Diagram

User 1──* RefreshToken

 ├──1 Provider 1──* ProviderService
 │      │
 │      ├──* Portfolio
 │      ├──* Badge
 │      └──* Quote

 ├──* Request ──* Quote
 │      │
 │      └──1 Transaction ──* Review

 └──* Conversation ──* Message

One chat. Everything done.