-- Создание таблицы для логирования всех платежных операций -- Содержит исчерпывающую информацию о клиенте, услуге, VIN и результате -- Создание последовательности для ID записей CREATE SEQUENCE payment_logs_seq START WITH 1 INCREMENT BY 1 CACHE 100; -- Создание основной таблицы логов CREATE TABLE payment_logs ( log_id NUMBER PRIMARY KEY, -- Информация о пользователе user_id NUMBER NOT NULL, user_first_name VARCHAR2(255), user_last_name VARCHAR2(255), user_username VARCHAR2(255), user_language_code VARCHAR2(10), user_is_premium NUMBER(1) DEFAULT 0, -- Информация об услуге service_type VARCHAR2(50) NOT NULL, -- 'decode_vin', 'check_salvage', 'get_photos' vin_number VARCHAR2(17) NOT NULL, -- Информация о платеже payment_amount NUMBER(10,2) NOT NULL, transaction_id VARCHAR2(255), payment_status VARCHAR2(50) DEFAULT 'completed', -- 'completed', 'pending', 'failed' payment_currency VARCHAR2(10) DEFAULT 'XTR', -- Результат предоставления услуги service_status VARCHAR2(50), -- 'success', 'failed', 'no_data', 'error' data_found_count NUMBER DEFAULT 0, -- количество найденных записей/фото refund_status VARCHAR2(50) DEFAULT 'no_refund', -- 'no_refund', 'auto_refund', 'manual_refund', 'admin_refund' refund_reason VARCHAR2(500), -- Информация об автомобиле vehicle_make VARCHAR2(100), vehicle_model VARCHAR2(100), vehicle_year VARCHAR2(10), -- Техническая информация error_message CLOB, created_date DATE DEFAULT SYSDATE, ip_address VARCHAR2(45), -- для будущего использования -- Индексы для быстрого поиска CONSTRAINT chk_service_type CHECK (service_type IN ('decode_vin', 'check_salvage', 'get_photos')), CONSTRAINT chk_payment_status CHECK (payment_status IN ('completed', 'pending', 'failed')), CONSTRAINT chk_service_status CHECK (service_status IN ('success', 'failed', 'no_data', 'error', 'pending')), CONSTRAINT chk_refund_status CHECK (refund_status IN ('no_refund', 'auto_refund', 'manual_refund', 'admin_refund')) ); -- Создание индексов для оптимизации запросов CREATE INDEX idx_payment_logs_user_id ON payment_logs(user_id); CREATE INDEX idx_payment_logs_vin ON payment_logs(vin_number); CREATE INDEX idx_payment_logs_service_type ON payment_logs(service_type); CREATE INDEX idx_payment_logs_date ON payment_logs(created_date); CREATE INDEX idx_payment_logs_transaction_id ON payment_logs(transaction_id); CREATE INDEX idx_payment_logs_status ON payment_logs(payment_status, service_status); -- Комментарии к таблице и полям COMMENT ON TABLE payment_logs IS 'Логирование всех платежных операций бота с детальной информацией'; COMMENT ON COLUMN payment_logs.log_id IS 'Уникальный идентификатор записи'; COMMENT ON COLUMN payment_logs.user_id IS 'ID пользователя Telegram'; COMMENT ON COLUMN payment_logs.service_type IS 'Тип услуги: decode_vin, check_salvage, get_photos'; COMMENT ON COLUMN payment_logs.vin_number IS 'VIN номер автомобиля'; COMMENT ON COLUMN payment_logs.payment_amount IS 'Сумма платежа в Telegram Stars'; COMMENT ON COLUMN payment_logs.transaction_id IS 'ID транзакции Telegram'; COMMENT ON COLUMN payment_logs.data_found_count IS 'Количество найденных данных (записей, фото и т.д.)'; COMMENT ON COLUMN payment_logs.refund_status IS 'Статус возврата средств'; COMMENT ON COLUMN payment_logs.created_date IS 'Дата и время создания записи'; -- Создание представления для аналитики CREATE OR REPLACE VIEW payment_analytics AS SELECT service_type, COUNT(*) as total_transactions, SUM(payment_amount) as total_revenue, AVG(payment_amount) as avg_payment, COUNT(CASE WHEN refund_status != 'no_refund' THEN 1 END) as refunds_count, COUNT(CASE WHEN service_status = 'success' THEN 1 END) as successful_services, ROUND(COUNT(CASE WHEN service_status = 'success' THEN 1 END) * 100.0 / COUNT(*), 2) as success_rate, TRUNC(created_date) as date_created FROM payment_logs GROUP BY service_type, TRUNC(created_date) ORDER BY date_created DESC, service_type; -- Создание триггера для автоматического заполнения created_date CREATE OR REPLACE TRIGGER trg_payment_logs_created_date BEFORE INSERT ON payment_logs FOR EACH ROW BEGIN IF :NEW.created_date IS NULL THEN :NEW.created_date := SYSDATE; END IF; END; /