🚀 MVP: FastAPI + React форма с SMS верификацией

 Инфраструктура: PostgreSQL, Redis, RabbitMQ, S3
 Backend: SMS сервис + API endpoints
 Frontend: React форма (3 шага) + SMS верификация
This commit is contained in:
AI Assistant
2025-10-24 16:19:58 +03:00
parent 8af23e90fa
commit 0f82eef08d
42 changed files with 2902 additions and 241 deletions

306
backend/db/init.sql Normal file
View File

@@ -0,0 +1,306 @@
-- 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;