Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.spn.wtf/llms.txt

Use this file to discover all available pages before exploring further.

Overview

The application uses PostgreSQL with two main tables:
  • leads: incoming lead queue and retry state
  • calls: one record per outbound call attempt
db.py creates and migrates the schema at startup. It is safe to call init_db() repeatedly.

leads Table

CREATE TABLE IF NOT EXISTS leads (
    id            SERIAL PRIMARY KEY,
    name          TEXT NOT NULL,
    phone         TEXT NOT NULL,
    source        TEXT NOT NULL,
    email         TEXT,
    product_name  TEXT,
    city          TEXT,
    state         TEXT,
    query_message TEXT,
    status        TEXT NOT NULL DEFAULT 'new',
    retry_after   TIMESTAMPTZ,
    retry_count   INT NOT NULL DEFAULT 0,
    created_at    TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at    TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Lead statuses:
StatusMeaning
newReady to be called, unless retry_after is in the future
dispatchedA call attempt was successfully started
failedInvalid lead or retry limit reached

calls Table

CREATE TABLE IF NOT EXISTS calls (
    id                SERIAL PRIMARY KEY,
    lead_id           INT REFERENCES leads(id) ON DELETE SET NULL,
    name              TEXT,
    phone             TEXT NOT NULL,
    source            TEXT,
    qualification     JSONB,
    status            TEXT NOT NULL DEFAULT 'calling',
    failure_reason    TEXT,
    call_room         TEXT,
    call_started_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    call_ended_at     TIMESTAMPTZ,
    duration_seconds  INT,
    created_at        TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at        TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
Call statuses:
StatusMeaning
callingSIP call has been initiated or is active
calledAgent saved qualification JSON
pushedTalking Shops accepted the CRM task
failedThe call attempt did not produce a successful CRM-ready result

Qualification JSON

The exact JSON differs by agent mode. Sarvam mode stores broader machinery qualification:
{
  "machine_interest": "paper plate machine",
  "location": "Kolkata",
  "budget": "Rs. 10 lakhs",
  "first_product": "paper plates",
  "units_per_day": "5000",
  "local_demand": "yes",
  "new_or_expand": "new business",
  "partnership": "with partner",
  "operators_needed": "2",
  "own_brand": "yes",
  "seriousness": "ready to start soon",
  "factory_visit": "interested",
  "video_demo": "yes"
}
OpenAI Realtime mode stores a tighter Ignitech schema:
{
  "product_interest": "carbon cleaning",
  "location": "Kolkata",
  "budget": "10-25 lakhs"
}
Only non-null values are stored.

Important Helpers

FunctionPurpose
insert_lead()Adds an incoming lead
get_new_leads()Gets retry-ready new leads
set_lead_dispatched()Marks lead as dispatched after SIP trigger succeeds
schedule_lead_retry()Sets retry time and retry count
create_call()Creates a call attempt row
save_qualification()Saves JSON and marks call called
set_call_failed()Marks call failed with reason and duration
fail_stale_call_records()Recovers stuck calling rows
set_call_pushed()Marks CRM-pushed calls

Duration Tracking

For called, pushed, and failed terminal records, duration is calculated from:
call_ended_at - call_started_at
The minutes dashboard uses LEGACY_SUCCESS_CALL_ESTIMATE_MINUTES for older successful calls that do not have complete duration fields.