✅ Инфраструктура: PostgreSQL, Redis, RabbitMQ, S3 ✅ Backend: SMS сервис + API endpoints ✅ Frontend: React форма (3 шага) + SMS верификация
307 lines
11 KiB
PL/PgSQL
307 lines
11 KiB
PL/PgSQL
-- ERV Platform Database Initialization Script
|
|
-- PostgreSQL 16+
|
|
|
|
-- Enable extensions
|
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
|
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: claims (Основные заявки)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS claims (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
claim_number VARCHAR(50) UNIQUE NOT NULL,
|
|
|
|
-- Тип страхования
|
|
insurance_type VARCHAR(50) NOT NULL DEFAULT 'erv_travel',
|
|
case_type VARCHAR(100), -- например: 'flight_delay', 'medical', 'baggage_loss'
|
|
|
|
-- Данные клиента
|
|
client_phone VARCHAR(20) NOT NULL,
|
|
client_email VARCHAR(255),
|
|
client_inn VARCHAR(12),
|
|
client_full_name VARCHAR(500),
|
|
|
|
-- Данные полиса
|
|
policy_number VARCHAR(100),
|
|
policy_series VARCHAR(50),
|
|
|
|
-- Статус обработки
|
|
status VARCHAR(50) NOT NULL DEFAULT 'draft', -- draft, processing, crm_sent, completed, error
|
|
crm_id VARCHAR(100), -- ID в Vtiger CRM
|
|
|
|
-- Данные для аналитики
|
|
source VARCHAR(100), -- откуда пришла заявка: 'web_form', 'api', 'mobile_app'
|
|
user_agent TEXT,
|
|
ip_address INET,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
submitted_at TIMESTAMP WITH TIME ZONE,
|
|
completed_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- JSON поля для гибкости
|
|
form_data JSONB, -- все данные формы
|
|
metadata JSONB -- дополнительные метаданные
|
|
);
|
|
|
|
-- Индексы для claims
|
|
CREATE INDEX idx_claims_claim_number ON claims(claim_number);
|
|
CREATE INDEX idx_claims_status ON claims(status);
|
|
CREATE INDEX idx_claims_created_at ON claims(created_at DESC);
|
|
CREATE INDEX idx_claims_client_phone ON claims(client_phone);
|
|
CREATE INDEX idx_claims_policy_number ON claims(policy_number);
|
|
CREATE INDEX idx_claims_insurance_type ON claims(insurance_type);
|
|
CREATE INDEX idx_claims_form_data_gin ON claims USING gin(form_data);
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: claim_files (Файлы к заявкам)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS claim_files (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
claim_id UUID NOT NULL REFERENCES claims(id) ON DELETE CASCADE,
|
|
|
|
-- Файл
|
|
file_name VARCHAR(255) NOT NULL,
|
|
file_path VARCHAR(500) NOT NULL,
|
|
file_size BIGINT,
|
|
mime_type VARCHAR(100),
|
|
file_type VARCHAR(50), -- 'passport', 'ticket', 'receipt', 'medical_doc', etc.
|
|
|
|
-- S3 данные (если используется)
|
|
s3_bucket VARCHAR(255),
|
|
s3_key VARCHAR(500),
|
|
s3_url TEXT,
|
|
|
|
-- OCR/AI обработка
|
|
ocr_status VARCHAR(50), -- 'pending', 'processing', 'completed', 'error'
|
|
ocr_text TEXT,
|
|
ai_extracted_data JSONB,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
processed_at TIMESTAMP WITH TIME ZONE
|
|
);
|
|
|
|
-- Индексы для claim_files
|
|
CREATE INDEX idx_claim_files_claim_id ON claim_files(claim_id);
|
|
CREATE INDEX idx_claim_files_file_type ON claim_files(file_type);
|
|
CREATE INDEX idx_claim_files_ocr_status ON claim_files(ocr_status);
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: processing_logs (Логи обработки)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS processing_logs (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
claim_id UUID REFERENCES claims(id) ON DELETE CASCADE,
|
|
|
|
-- Лог
|
|
level VARCHAR(20) NOT NULL, -- 'debug', 'info', 'warning', 'error', 'critical'
|
|
message TEXT NOT NULL,
|
|
context JSONB, -- дополнительный контекст
|
|
|
|
-- Источник
|
|
source VARCHAR(100), -- 'ocr_service', 'ai_service', 'flight_api', 'crm_integration', etc.
|
|
function_name VARCHAR(200),
|
|
|
|
-- Ошибки
|
|
error_type VARCHAR(100),
|
|
error_traceback TEXT,
|
|
|
|
-- Timestamp
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для processing_logs
|
|
CREATE INDEX idx_processing_logs_claim_id ON processing_logs(claim_id);
|
|
CREATE INDEX idx_processing_logs_level ON processing_logs(level);
|
|
CREATE INDEX idx_processing_logs_created_at ON processing_logs(created_at DESC);
|
|
CREATE INDEX idx_processing_logs_source ON processing_logs(source);
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: api_calls (Логи внешних API вызовов)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS api_calls (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
claim_id UUID REFERENCES claims(id) ON DELETE SET NULL,
|
|
|
|
-- API детали
|
|
api_name VARCHAR(100) NOT NULL, -- 'ocr_service', 'openrouter_ai', 'flightaware', 'nspk_banks', etc.
|
|
endpoint VARCHAR(500),
|
|
method VARCHAR(10), -- 'GET', 'POST', etc.
|
|
|
|
-- Запрос
|
|
request_headers JSONB,
|
|
request_body JSONB,
|
|
|
|
-- Ответ
|
|
response_status INTEGER,
|
|
response_headers JSONB,
|
|
response_body JSONB,
|
|
|
|
-- Производительность
|
|
duration_ms INTEGER, -- длительность запроса в миллисекундах
|
|
|
|
-- Результат
|
|
success BOOLEAN DEFAULT FALSE,
|
|
error_message TEXT,
|
|
|
|
-- Timestamp
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для api_calls
|
|
CREATE INDEX idx_api_calls_claim_id ON api_calls(claim_id);
|
|
CREATE INDEX idx_api_calls_api_name ON api_calls(api_name);
|
|
CREATE INDEX idx_api_calls_success ON api_calls(success);
|
|
CREATE INDEX idx_api_calls_created_at ON api_calls(created_at DESC);
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: queue_tasks (Задачи в очереди RabbitMQ)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS queue_tasks (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
claim_id UUID REFERENCES claims(id) ON DELETE CASCADE,
|
|
|
|
-- Задача
|
|
task_type VARCHAR(100) NOT NULL, -- 'ocr_processing', 'ai_extraction', 'flight_check', etc.
|
|
queue_name VARCHAR(100) NOT NULL,
|
|
priority INTEGER DEFAULT 5, -- 1-10, где 10 - максимальный приоритет
|
|
|
|
-- Данные
|
|
task_data JSONB,
|
|
|
|
-- Статус
|
|
status VARCHAR(50) NOT NULL DEFAULT 'pending', -- pending, processing, completed, failed, retry
|
|
attempts INTEGER DEFAULT 0,
|
|
max_attempts INTEGER DEFAULT 3,
|
|
|
|
-- Результат
|
|
result JSONB,
|
|
error_message TEXT,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
started_at TIMESTAMP WITH TIME ZONE,
|
|
completed_at TIMESTAMP WITH TIME ZONE,
|
|
next_retry_at TIMESTAMP WITH TIME ZONE
|
|
);
|
|
|
|
-- Индексы для queue_tasks
|
|
CREATE INDEX idx_queue_tasks_claim_id ON queue_tasks(claim_id);
|
|
CREATE INDEX idx_queue_tasks_status ON queue_tasks(status);
|
|
CREATE INDEX idx_queue_tasks_task_type ON queue_tasks(task_type);
|
|
CREATE INDEX idx_queue_tasks_created_at ON queue_tasks(created_at DESC);
|
|
CREATE INDEX idx_queue_tasks_next_retry ON queue_tasks(next_retry_at) WHERE status = 'retry';
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: metrics (Метрики системы)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS metrics (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
|
|
-- Метрика
|
|
metric_name VARCHAR(100) NOT NULL,
|
|
metric_value NUMERIC(20, 4),
|
|
metric_unit VARCHAR(50), -- 'ms', 'count', 'bytes', '%', etc.
|
|
|
|
-- Теги для группировки
|
|
tags JSONB,
|
|
|
|
-- Timestamp
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для metrics
|
|
CREATE INDEX idx_metrics_metric_name ON metrics(metric_name);
|
|
CREATE INDEX idx_metrics_created_at ON metrics(created_at DESC);
|
|
CREATE INDEX idx_metrics_tags_gin ON metrics USING gin(tags);
|
|
|
|
-- ============================================
|
|
-- ТАБЛИЦА: cache_entries (Кеш для редких запросов)
|
|
-- ============================================
|
|
CREATE TABLE IF NOT EXISTS cache_entries (
|
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
|
|
|
-- Ключ-значение
|
|
cache_key VARCHAR(255) UNIQUE NOT NULL,
|
|
cache_value JSONB,
|
|
|
|
-- TTL
|
|
expires_at TIMESTAMP WITH TIME ZONE,
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для cache_entries
|
|
CREATE INDEX idx_cache_entries_key ON cache_entries(cache_key);
|
|
CREATE INDEX idx_cache_entries_expires ON cache_entries(expires_at);
|
|
|
|
-- Автоматическая очистка устаревшего кеша
|
|
CREATE OR REPLACE FUNCTION cleanup_expired_cache()
|
|
RETURNS void AS $$
|
|
BEGIN
|
|
DELETE FROM cache_entries WHERE expires_at < CURRENT_TIMESTAMP;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- ============================================
|
|
-- ТРИГГЕРЫ
|
|
-- ============================================
|
|
|
|
-- Автоматическое обновление updated_at для claims
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
CREATE TRIGGER update_claims_updated_at
|
|
BEFORE UPDATE ON claims
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- ============================================
|
|
-- ПРЕДСТАВЛЕНИЯ (VIEWS)
|
|
-- ============================================
|
|
|
|
-- Статистика по заявкам
|
|
CREATE OR REPLACE VIEW claims_statistics AS
|
|
SELECT
|
|
DATE(created_at) as date,
|
|
insurance_type,
|
|
status,
|
|
COUNT(*) as count,
|
|
AVG(EXTRACT(EPOCH FROM (completed_at - created_at))) as avg_processing_time_seconds
|
|
FROM claims
|
|
GROUP BY DATE(created_at), insurance_type, status;
|
|
|
|
-- Статистика по API вызовам
|
|
CREATE OR REPLACE VIEW api_performance AS
|
|
SELECT
|
|
api_name,
|
|
DATE(created_at) as date,
|
|
COUNT(*) as total_calls,
|
|
SUM(CASE WHEN success THEN 1 ELSE 0 END) as successful_calls,
|
|
AVG(duration_ms) as avg_duration_ms,
|
|
MAX(duration_ms) as max_duration_ms
|
|
FROM api_calls
|
|
GROUP BY api_name, DATE(created_at);
|
|
|
|
-- ============================================
|
|
-- НАЧАЛЬНЫЕ ДАННЫЕ
|
|
-- ============================================
|
|
|
|
-- Можно добавить тестовые данные для разработки
|
|
-- INSERT INTO claims (claim_number, client_phone, insurance_type, status)
|
|
-- VALUES ('TEST-001', '+79001234567', 'erv_travel', 'draft');
|
|
|
|
-- Завершение
|
|
SELECT 'Database initialized successfully!' as message;
|
|
|