Files
call-center/migrations/sql/0023_sales_postgres.sql
T
2026-05-09 09:16:06 +05:00

346 lines
11 KiB
SQL

CREATE TABLE IF NOT EXISTS sales_leads (
id BIGSERIAL PRIMARY KEY,
lead_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
source_type TEXT NOT NULL,
source_channel TEXT NOT NULL,
source_campaign_id TEXT,
full_name TEXT NOT NULL,
company_name TEXT,
phone TEXT,
email TEXT,
messenger_handles_json TEXT NOT NULL DEFAULT '{}',
lead_temperature TEXT NOT NULL,
lead_score DOUBLE PRECISION NOT NULL DEFAULT 50,
customer_type TEXT,
segment_type TEXT,
initial_need_summary TEXT,
preferred_channel TEXT NOT NULL,
assigned_agent_type TEXT NOT NULL,
status TEXT NOT NULL,
crm_customer_id TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_leads_tenant_status_score ON sales_leads(tenant_id, status, lead_score);
CREATE INDEX IF NOT EXISTS idx_sales_leads_phone_email ON sales_leads(phone, email);
CREATE TABLE IF NOT EXISTS sales_deals (
id BIGSERIAL PRIMARY KEY,
deal_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
lead_id TEXT,
customer_id TEXT,
pipeline_id TEXT NOT NULL DEFAULT 'sales_default',
stage_id TEXT NOT NULL,
scenario_type TEXT NOT NULL,
priority INTEGER NOT NULL DEFAULT 3,
title TEXT NOT NULL,
need_summary TEXT,
product_context_json TEXT NOT NULL DEFAULT '{}',
estimated_amount DOUBLE PRECISION,
final_amount DOUBLE PRECISION,
currency TEXT NOT NULL DEFAULT 'KZT',
payment_model TEXT,
document_required BOOLEAN NOT NULL DEFAULT TRUE,
payment_required BOOLEAN NOT NULL DEFAULT TRUE,
assigned_human_user_id TEXT,
assigned_ai_orchestrator_id TEXT,
preferred_channel TEXT NOT NULL,
current_channel TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
won_reason TEXT,
lost_reason TEXT,
close_reason TEXT,
next_action_type TEXT,
next_action_at TEXT,
last_contact_at TEXT,
closed_at TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_deals_tenant_stage_status ON sales_deals(tenant_id, stage_id, status);
CREATE INDEX IF NOT EXISTS idx_sales_deals_customer_channel ON sales_deals(customer_id, current_channel);
CREATE INDEX IF NOT EXISTS idx_sales_deals_next_action ON sales_deals(next_action_at, status);
CREATE TABLE IF NOT EXISTS sales_communication_sessions (
id BIGSERIAL PRIMARY KEY,
communication_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
lead_id TEXT,
customer_id TEXT,
channel_type TEXT NOT NULL,
direction TEXT NOT NULL,
agent_type TEXT NOT NULL,
started_at TEXT NOT NULL,
ended_at TEXT,
duration_sec INTEGER,
subject TEXT,
status TEXT NOT NULL DEFAULT 'active',
summary TEXT,
transcript_id TEXT,
next_action_type TEXT,
next_action_at TEXT,
sentiment TEXT,
result_code TEXT,
metadata_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_comm_deal_started ON sales_communication_sessions(deal_id, started_at);
CREATE INDEX IF NOT EXISTS idx_sales_comm_channel_status ON sales_communication_sessions(channel_type, status);
CREATE TABLE IF NOT EXISTS sales_messages (
id BIGSERIAL PRIMARY KEY,
message_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
communication_id TEXT NOT NULL,
sender_type TEXT NOT NULL,
sender_id TEXT,
channel_provider TEXT NOT NULL,
external_message_id TEXT,
body TEXT NOT NULL,
attachments_json TEXT NOT NULL DEFAULT '[]',
delivery_status TEXT,
read_status TEXT,
message_metadata_json TEXT NOT NULL DEFAULT '{}',
sent_at TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_messages_deal_sent ON sales_messages(deal_id, sent_at);
CREATE INDEX IF NOT EXISTS idx_sales_messages_ext_id ON sales_messages(channel_provider, external_message_id);
CREATE TABLE IF NOT EXISTS sales_calls (
id BIGSERIAL PRIMARY KEY,
call_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
communication_id TEXT NOT NULL,
phone_number TEXT NOT NULL,
direction TEXT NOT NULL,
provider TEXT NOT NULL,
external_call_id TEXT,
recording_url TEXT,
transcript_status TEXT NOT NULL DEFAULT 'pending',
transcript_id TEXT,
call_status TEXT NOT NULL DEFAULT 'started',
summary TEXT,
started_at TEXT NOT NULL,
ended_at TEXT,
duration_sec INTEGER,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_calls_deal_started ON sales_calls(deal_id, started_at);
CREATE INDEX IF NOT EXISTS idx_sales_calls_ext_provider ON sales_calls(provider, external_call_id);
CREATE TABLE IF NOT EXISTS sales_transcripts (
id BIGSERIAL PRIMARY KEY,
transcript_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
call_id TEXT NOT NULL,
language TEXT NOT NULL DEFAULT 'ru',
transcript_text TEXT NOT NULL,
diarization_json TEXT NOT NULL DEFAULT '{}',
extracted_entities_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS sales_notes (
id BIGSERIAL PRIMARY KEY,
note_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
author_type TEXT NOT NULL,
author_id TEXT,
note_type TEXT NOT NULL,
content TEXT NOT NULL,
created_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS sales_offers (
id BIGSERIAL PRIMARY KEY,
offer_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
offer_type TEXT NOT NULL,
title TEXT NOT NULL,
description TEXT,
line_items_json TEXT NOT NULL DEFAULT '[]',
pricing_json TEXT NOT NULL DEFAULT '{}',
total_amount DOUBLE PRECISION NOT NULL DEFAULT 0,
currency TEXT NOT NULL DEFAULT 'KZT',
validity_until TEXT,
status TEXT NOT NULL DEFAULT 'draft',
rendered_document_url TEXT,
created_by_type TEXT NOT NULL DEFAULT 'text_ai',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_offers_deal_status ON sales_offers(deal_id, status);
CREATE TABLE IF NOT EXISTS sales_conditions (
id BIGSERIAL PRIMARY KEY,
condition_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
product_name TEXT,
service_name TEXT,
quantity DOUBLE PRECISION,
unit TEXT,
delivery_mode TEXT,
execution_date TEXT,
start_date TEXT,
end_date TEXT,
payment_terms TEXT,
custom_terms_json TEXT NOT NULL DEFAULT '{}',
agreed_price DOUBLE PRECISION,
currency TEXT NOT NULL DEFAULT 'KZT',
confirmed_at TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS sales_counterparties (
id BIGSERIAL PRIMARY KEY,
counterparty_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL UNIQUE,
customer_id TEXT,
company_name TEXT,
full_name TEXT,
bin_iin TEXT,
address TEXT,
bank_details_json TEXT NOT NULL DEFAULT '{}',
signer_name TEXT,
signer_role TEXT,
signer_basis TEXT,
email_for_docs TEXT,
phone_for_docs TEXT,
completeness_status TEXT NOT NULL DEFAULT 'draft',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS sales_documents (
id BIGSERIAL PRIMARY KEY,
document_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
customer_id TEXT,
document_type TEXT NOT NULL,
template_id TEXT,
version INTEGER NOT NULL DEFAULT 1,
status TEXT NOT NULL DEFAULT 'draft',
file_url TEXT,
rendered_payload_json TEXT NOT NULL DEFAULT '{}',
external_sign_provider_id TEXT,
signed_at TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_documents_deal_status ON sales_documents(deal_id, status);
CREATE TABLE IF NOT EXISTS sales_invoices (
id BIGSERIAL PRIMARY KEY,
invoice_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
customer_id TEXT,
invoice_number TEXT NOT NULL UNIQUE,
basis_document_id TEXT,
amount DOUBLE PRECISION NOT NULL DEFAULT 0,
currency TEXT NOT NULL DEFAULT 'KZT',
due_date TEXT,
status TEXT NOT NULL DEFAULT 'draft',
payment_link TEXT,
line_items_json TEXT NOT NULL DEFAULT '[]',
metadata_json TEXT NOT NULL DEFAULT '{}',
issued_at TEXT,
paid_at TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_invoices_deal_status_due ON sales_invoices(deal_id, status, due_date);
CREATE TABLE IF NOT EXISTS sales_payments (
id BIGSERIAL PRIMARY KEY,
payment_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
invoice_id TEXT,
payment_provider TEXT,
external_payment_id TEXT,
amount DOUBLE PRECISION NOT NULL DEFAULT 0,
currency TEXT NOT NULL DEFAULT 'KZT',
status TEXT NOT NULL DEFAULT 'pending',
paid_at TEXT,
payment_method TEXT,
failure_reason TEXT,
metadata_json TEXT NOT NULL DEFAULT '{}',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_payments_deal_status ON sales_payments(deal_id, status);
CREATE TABLE IF NOT EXISTS sales_stage_history (
id BIGSERIAL PRIMARY KEY,
history_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
from_stage_id TEXT,
to_stage_id TEXT NOT NULL,
changed_by_type TEXT NOT NULL,
changed_by_id TEXT,
reason TEXT,
changed_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_stage_history_deal_changed ON sales_stage_history(deal_id, changed_at);
CREATE TABLE IF NOT EXISTS sales_escalations (
id BIGSERIAL PRIMARY KEY,
escalation_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
escalation_type TEXT NOT NULL,
reason TEXT NOT NULL,
severity TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'open',
assigned_to_user_id TEXT,
created_at TEXT NOT NULL,
resolved_at TEXT
);
CREATE INDEX IF NOT EXISTS idx_sales_escalations_deal_status ON sales_escalations(deal_id, status);
CREATE TABLE IF NOT EXISTS sales_automation_tasks (
id BIGSERIAL PRIMARY KEY,
task_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
task_type TEXT NOT NULL,
payload_json TEXT NOT NULL DEFAULT '{}',
run_at TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
retry_count INTEGER NOT NULL DEFAULT 0,
last_error TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_tasks_run_status ON sales_automation_tasks(run_at, status);
CREATE TABLE IF NOT EXISTS sales_channel_switches (
id BIGSERIAL PRIMARY KEY,
switch_id TEXT NOT NULL UNIQUE,
tenant_id TEXT NOT NULL,
deal_id TEXT NOT NULL,
communication_id TEXT,
from_channel TEXT NOT NULL,
to_channel TEXT NOT NULL,
reason_for_channel_switch TEXT NOT NULL,
switched_at TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sales_channel_switches_deal_switched ON sales_channel_switches(deal_id, switched_at);