-- 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;