Feat: CRM v2, Richer synthetic data, Canvas JSON Components

This commit is contained in:
Sagnik
2026-04-23 22:00:44 +05:30
parent 6cdc366718
commit f04571bd7b
54 changed files with 89916 additions and 578 deletions

View File

@@ -220,9 +220,13 @@ CREATE TABLE IF NOT EXISTS crm_property_interests (
budget_max DECIMAL(15, 2),
priority INTEGER DEFAULT 1, -- 1 = primary, 2 = secondary
notes TEXT,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
ALTER TABLE crm_property_interests
ADD COLUMN IF NOT EXISTS metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb;
CREATE INDEX IF NOT EXISTS idx_crm_pi_person ON crm_property_interests (person_id);
CREATE INDEX IF NOT EXISTS idx_crm_pi_project ON crm_property_interests (project_id);
@@ -706,3 +710,186 @@ COMMENT ON TABLE intel_qd_scores IS 'Latest QD summary by score_type per client.
COMMENT ON TABLE inventory_projects IS 'Master project catalog. 14 canonical Kolkata projects seeded.';
COMMENT ON TABLE workflow_import_batches IS 'RawImportBatch contract. Immutable after upload.';
COMMENT ON TABLE workflow_writebacks IS 'AI-proposed canonical mutations. Never auto-execute without approval.';
-- -----------------------------------------------------------------------------
-- Synthetic CRM v2 enrichment columns and Oracle read models
-- -----------------------------------------------------------------------------
ALTER TABLE crm_people
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS engagement_score FLOAT,
ADD COLUMN IF NOT EXISTS communication_preference TEXT,
ADD COLUMN IF NOT EXISTS best_contact_time TEXT;
ALTER TABLE crm_households
ADD COLUMN IF NOT EXISTS size INTEGER,
ADD COLUMN IF NOT EXISTS combined_budget_band TEXT,
ADD COLUMN IF NOT EXISTS decision_maker_id UUID REFERENCES crm_people(person_id) ON DELETE SET NULL;
ALTER TABLE crm_leads
ADD COLUMN IF NOT EXISTS stage TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS broker_team TEXT,
ADD COLUMN IF NOT EXISTS engagement_score FLOAT,
ADD COLUMN IF NOT EXISTS last_activity_at TIMESTAMPTZ;
ALTER TABLE crm_opportunities
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS deal_velocity TEXT,
ADD COLUMN IF NOT EXISTS risk_factors JSONB NOT NULL DEFAULT '[]'::jsonb;
ALTER TABLE crm_property_interests
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS last_discussed_at TIMESTAMPTZ;
ALTER TABLE crm_stage_history
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS transition_duration_days INTEGER;
ALTER TABLE intel_interactions
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS broker_team TEXT,
ADD COLUMN IF NOT EXISTS sentiment TEXT,
ADD COLUMN IF NOT EXISTS sentiment_score FLOAT,
ADD COLUMN IF NOT EXISTS intent_label TEXT,
ADD COLUMN IF NOT EXISTS emotion_tags JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS client_engagement_level TEXT;
ALTER TABLE intel_calls
ADD COLUMN IF NOT EXISTS objection_tags JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS outcome_summary TEXT,
ADD COLUMN IF NOT EXISTS follow_up_actions JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS call_quality_score FLOAT;
ALTER TABLE intel_emails
ADD COLUMN IF NOT EXISTS sentiment TEXT,
ADD COLUMN IF NOT EXISTS intent_label TEXT,
ADD COLUMN IF NOT EXISTS engagement_score FLOAT,
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS response_expected BOOLEAN;
ALTER TABLE intel_reminders
ADD COLUMN IF NOT EXISTS interaction_id UUID REFERENCES intel_interactions(interaction_id) ON DELETE SET NULL,
ADD COLUMN IF NOT EXISTS context_snippet TEXT,
ADD COLUMN IF NOT EXISTS completion_percentage INTEGER,
ADD COLUMN IF NOT EXISTS overdue_days INTEGER,
ADD COLUMN IF NOT EXISTS outcome_notes TEXT;
ALTER TABLE intel_transcripts
ADD COLUMN IF NOT EXISTS call_outcome TEXT,
ADD COLUMN IF NOT EXISTS follow_up_required BOOLEAN,
ADD COLUMN IF NOT EXISTS emotion_tags JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS call_summary TEXT;
ALTER TABLE intel_visits
ADD COLUMN IF NOT EXISTS outcome_type TEXT,
ADD COLUMN IF NOT EXISTS visit_duration_minutes INTEGER,
ADD COLUMN IF NOT EXISTS interest_signals JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS interest_score FLOAT,
ADD COLUMN IF NOT EXISTS companion_type TEXT,
ADD COLUMN IF NOT EXISTS companion_count INTEGER,
ADD COLUMN IF NOT EXISTS objections_raised JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS follow_up_required BOOLEAN,
ADD COLUMN IF NOT EXISTS next_steps TEXT,
ADD COLUMN IF NOT EXISTS broker_notes TEXT,
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT;
ALTER TABLE intel_whatsapp_threads
ADD COLUMN IF NOT EXISTS broker_id TEXT,
ADD COLUMN IF NOT EXISTS broker_name TEXT,
ADD COLUMN IF NOT EXISTS topic_category TEXT,
ADD COLUMN IF NOT EXISTS sentiment_direction TEXT,
ADD COLUMN IF NOT EXISTS resolution_status TEXT;
ALTER TABLE intel_qd_scores
ADD COLUMN IF NOT EXISTS score_drivers JSONB NOT NULL DEFAULT '[]'::jsonb,
ADD COLUMN IF NOT EXISTS trend_direction TEXT,
ADD COLUMN IF NOT EXISTS explanation TEXT,
ADD COLUMN IF NOT EXISTS confidence FLOAT;
ALTER TABLE intel_qd_timeseries
ADD COLUMN IF NOT EXISTS broker_id TEXT;
CREATE TABLE IF NOT EXISTS intel_email_threads (
thread_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
subject TEXT,
first_email_at TIMESTAMPTZ,
last_email_at TIMESTAMPTZ,
email_count INTEGER DEFAULT 0,
participants JSONB NOT NULL DEFAULT '[]'::jsonb,
status TEXT,
broker_id TEXT,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE TABLE IF NOT EXISTS intel_call_objections (
objection_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
call_id UUID REFERENCES intel_calls(call_id) ON DELETE CASCADE,
objection_type TEXT,
category TEXT,
severity TEXT,
status TEXT,
client_quote TEXT,
agent_response TEXT,
resolution_strategy TEXT,
extracted_at TIMESTAMPTZ,
confidence_score FLOAT,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE TABLE IF NOT EXISTS intel_extracted_facts (
fact_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
interaction_id UUID REFERENCES intel_interactions(interaction_id) ON DELETE SET NULL,
person_id UUID REFERENCES crm_people(person_id) ON DELETE CASCADE,
fact_type TEXT NOT NULL,
fact_value TEXT,
confidence FLOAT,
extracted_from TEXT,
source_context TEXT,
extracted_at TIMESTAMPTZ,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE TABLE IF NOT EXISTS read_last_contacted (
person_id UUID PRIMARY KEY REFERENCES crm_people(person_id) ON DELETE CASCADE,
last_contact_at TIMESTAMPTZ,
last_channel TEXT,
last_interaction_type TEXT,
days_since_contact INTEGER,
interactions_last_7d INTEGER,
interactions_last_30d INTEGER,
interactions_last_90d INTEGER,
total_interactions INTEGER,
current_stage TEXT,
broker_id TEXT,
broker_name TEXT,
computed_at TIMESTAMPTZ,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE TABLE IF NOT EXISTS read_next_best_action (
person_id UUID PRIMARY KEY REFERENCES crm_people(person_id) ON DELETE CASCADE,
recommended_action TEXT,
priority TEXT,
rationale TEXT,
suggested_channel TEXT,
due_within_days INTEGER,
broker_id TEXT,
broker_name TEXT,
opportunity_context TEXT,
computed_at TIMESTAMPTZ,
metadata_json JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE INDEX IF NOT EXISTS idx_read_last_contacted_at ON read_last_contacted (last_contact_at DESC);
CREATE INDEX IF NOT EXISTS idx_read_next_best_priority ON read_next_best_action (priority);
CREATE INDEX IF NOT EXISTS idx_intel_facts_person ON intel_extracted_facts (person_id, extracted_at DESC);
CREATE INDEX IF NOT EXISTS idx_intel_objections_call ON intel_call_objections (call_id);