From 018c81849aa654cfd4c6e2a313c46ac915c33a93 Mon Sep 17 00:00:00 2001 From: AGorokhov Date: Sun, 21 Jun 2026 12:51:40 +0300 Subject: [PATCH] feat: implement admin services management, Docker deployment, and YooKassa webhook IP security checks --- .env.example | 45 + .gitignore | 5 + Dockerfile | 21 + config.py | 62 + database.py | 265 ++++ docker-compose.yml | 16 + ...r_oferty_kibersport_versia_izmenennaya.pdf | Bin 0 -> 115081 bytes form/fix_excel.py | 73 + form/index.html | 169 ++ form/script.js | 384 +++++ form/style.css | 538 +++++++ form/Политика ПД.pdf | Bin 0 -> 28493 bytes index.html | 10 +- requirements.txt | 3 + server.py | 1392 +++++++++++++++++ 15 files changed, 2978 insertions(+), 5 deletions(-) create mode 100644 .env.example create mode 100644 Dockerfile create mode 100644 config.py create mode 100644 database.py create mode 100644 docker-compose.yml create mode 100644 form/Dogovor_oferty_kibersport_versia_izmenennaya.pdf create mode 100644 form/fix_excel.py create mode 100644 form/index.html create mode 100644 form/script.js create mode 100644 form/style.css create mode 100644 form/Политика ПД.pdf create mode 100644 requirements.txt create mode 100644 server.py diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..dcdeb9d --- /dev/null +++ b/.env.example @@ -0,0 +1,45 @@ +# Настройки ВКонтакте (для отправки уведомлений оператору) +# Токен сообщества ВКонтакте (с правами на сообщения) +VK_TOKEN=your_vk_community_token_here +# Идентификатор (ID) сообщества (только цифры) +VK_GROUP_ID=0 +# ID оператора ВКонтакте для отправки лидов (только цифры) +OPERATOR_PEER_ID=12345678 +# Список ID администраторов через запятую +ADMIN_IDS=12345678 + +# Настройки ЮKassa (YooKassa) +# Идентификатор магазина (Shop ID) из личного кабинета +YOOKASSA_SHOP_ID= +# Секретный ключ (API Key) из личного кабинета +YOOKASSA_SECRET_KEY= + +# Настройки почты по SMTP (для отправки писем о заказах) +# Адрес SMTP-сервера (например: smtp.yandex.ru, smtp.gmail.com, smtp.mail.ru) +SMTP_SERVER=smtp.yandex.ru +# Порт SMTP (465 для SSL/TLS или 587 для STARTTLS) +SMTP_PORT=465 +# Имя пользователя (ваш email полностью) +SMTP_USER= +# Пароль приложения (специальный пароль для сторонних приложений) +SMTP_PASSWORD= +# Email отправителя (обычно совпадает с SMTP_USER) +SMTP_FROM= +# Email получателя уведомлений (куда слать сообщения о заказах) +SMTP_TO= + +# Пароль для входа в Личный Кабинет Администратора (на сайте /admin) +ADMIN_PASSWORD=admin123 + +# Настройки агентской схемы для 54-ФЗ (чеки ОФД) +# Система налогообложения агента (1 - ОСНО, 2 - УСН доход, 3 - УСН доход-расход, 6 - Патент) +TAX_SYSTEM_CODE=2 +# Данные реального продавца (поставщика услуг) +SUPPLIER_NAME=ИП Груздев Артём Сергеевич +SUPPLIER_INN=370306440114 +SUPPLIER_PHONE=+79611157051 + +# Безопасность +# Включение верификации IP отправителя для вебхуков ЮKassa (True/False) +VERIFY_WEBHOOK_IP=True + diff --git a/.gitignore b/.gitignore index 5dba771..0354433 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,8 @@ .idea/ Thumbs.db Desktop.ini +.env +.DS_Store +__pycache__/ +*.db +*.xlsx \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..9c85b83 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.11-slim + +# Установка рабочей директории +WORKDIR /app + +# Отключение кэширования pip и буферизации вывода Python +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +# Копирование требований и установка +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# Копирование остального исходного кода +COPY . . + +# Открытие порта +EXPOSE 8000 + +# Запуск сервера +CMD ["python", "server.py"] diff --git a/config.py b/config.py new file mode 100644 index 0000000..1d442bd --- /dev/null +++ b/config.py @@ -0,0 +1,62 @@ +import os + +# Load environment variables from .env in the project root +def _load_env(): + root_dir = os.path.dirname(os.path.abspath(__file__)) + dotenv_path = os.path.join(root_dir, ".env") + if os.path.exists(dotenv_path): + try: + with open(dotenv_path, "r", encoding="utf-8") as f: + for line in f: + line = line.strip() + if not line or line.startswith("#"): + continue + if "=" in line: + key, val = line.split("=", 1) + val = val.strip().strip('"').strip("'") + os.environ[key.strip()] = val + except Exception as e: + print(f"Warning: Failed to load .env file: {e}") + +_load_env() + +# VK API Configuration +VK_TOKEN = os.getenv("VK_TOKEN", "your_vk_community_token_here") +GROUP_ID = int(os.getenv("VK_GROUP_ID", "0")) + +# Operator / Admin configuration +OPERATOR_PEER_ID = int(os.getenv("OPERATOR_PEER_ID", "0")) + +admin_ids_raw = os.getenv("ADMIN_IDS") +if admin_ids_raw: + try: + ADMIN_IDS = [int(x.strip()) for x in admin_ids_raw.split(",") if x.strip().isdigit()] + except Exception: + ADMIN_IDS = [OPERATOR_PEER_ID] if OPERATOR_PEER_ID else [] +else: + ADMIN_IDS = [OPERATOR_PEER_ID] if OPERATOR_PEER_ID else [] + +# YooKassa Configuration +YOOKASSA_SHOP_ID = os.getenv("YOOKASSA_SHOP_ID", "") +YOOKASSA_SECRET_KEY = os.getenv("YOOKASSA_SECRET_KEY", "") + +# SMTP configuration for email notifications +SMTP_SERVER = os.getenv("SMTP_SERVER", "smtp.yandex.ru") +SMTP_PORT = int(os.getenv("SMTP_PORT", "465")) +SMTP_USER = os.getenv("SMTP_USER", "") +SMTP_PASSWORD = os.getenv("SMTP_PASSWORD", "") +SMTP_FROM = os.getenv("SMTP_FROM", "") +SMTP_TO = os.getenv("SMTP_TO", "") + +# Admin Dashboard Password +ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "admin123") + +# Supplier / Agent Configuration for 54-FZ receipts (Agent Scheme) +SUPPLIER_NAME = os.getenv("SUPPLIER_NAME", "ИП Груздев Артём Сергеевич") +SUPPLIER_INN = os.getenv("SUPPLIER_INN", "370306440114") +SUPPLIER_PHONE = os.getenv("SUPPLIER_PHONE", "+79611157051") +TAX_SYSTEM_CODE = int(os.getenv("TAX_SYSTEM_CODE", "2")) # Default: 2 (УСН Доход ООО "АЙТИГРУПП") + +# Security Configurations +VERIFY_WEBHOOK_IP = os.getenv("VERIFY_WEBHOOK_IP", "True").lower() == "true" + diff --git a/database.py b/database.py new file mode 100644 index 0000000..e2edd50 --- /dev/null +++ b/database.py @@ -0,0 +1,265 @@ +import sqlite3 +import os +from typing import Optional, Dict, Any + +class DatabaseManager: + def __init__(self, db_path: str = "bot_database.db"): + self.db_path = db_path + self._init_db() + + def _get_connection(self): + return sqlite3.connect(self.db_path) + + def _init_db(self): + with self._get_connection() as conn: + cursor = conn.cursor() + # Table for user states and collected form data (needed for VK bot sync) + cursor.execute(""" + CREATE TABLE IF NOT EXISTS user_states ( + user_id INTEGER PRIMARY KEY, + state TEXT NOT NULL DEFAULT 'FREE_CHAT', + name TEXT, + phone TEXT, + question TEXT, + consent_1 TEXT, + consent_2 TEXT, + consent_3 TEXT, + last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + + # Migration checks for existing databases (VK bot) + for col in ["consent_1", "consent_2", "consent_3"]: + try: + cursor.execute(f"ALTER TABLE user_states ADD COLUMN {col} TEXT") + except sqlite3.OperationalError: + pass + + # Table for logs / dialogue history if needed + cursor.execute(""" + CREATE TABLE IF NOT EXISTS dialogue_logs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + user_id INTEGER, + sender TEXT, -- 'user' or 'bot' + message TEXT, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + + # Table for dynamic services + cursor.execute(""" + CREATE TABLE IF NOT EXISTS services ( + id TEXT PRIMARY KEY, + name TEXT NOT NULL, + price TEXT NOT NULL, + description TEXT NOT NULL, + is_active INTEGER DEFAULT 1 + ) + """) + + # Migration check: add price_numeric to services table + try: + cursor.execute("ALTER TABLE services ADD COLUMN price_numeric REAL DEFAULT 0.0") + except sqlite3.OperationalError: + pass + + # Seed default bot services if empty (legacy) + cursor.execute("SELECT COUNT(*) FROM services") + if cursor.fetchone()[0] == 0: + default_services = { + "1": { + "name": "Тренировка по Dota 2 🎮", + "price": "1 500 ₽/час", + "description": "Индивидуальное занятие с опытным тренером, разбор реплеев, позиционка и микроконтроль." + }, + "2": { + "name": "Тренировка по CS2 🔫", + "price": "1 500 ₽/час", + "description": "Анализ ошибок, тренировка стрельбы (aim), раскидки гранат и командное взаимодействие." + }, + "3": { + "name": "Пакет услуг 'Стандарт' 📦", + "price": "7 500 ₽", + "description": "5 индивидуальных тренировок по выбранной дисциплине + базовый план развития." + }, + "4": { + "name": "Пакет услуг 'Pro' 🌟", + "price": "14 000 ₽", + "description": "10 индивидуальных тренировок + детальный разбор матчей + постоянная поддержка тренера." + } + } + for key, svc in default_services.items(): + cursor.execute( + "INSERT INTO services (id, name, price, price_numeric, description) VALUES (?, ?, ?, ?, ?)", + (key, svc["name"], svc["price"], float(svc["price"].replace(" ", "").replace("₽/час", "").replace("₽", "")), svc["description"]) + ) + + # Seed default web services if they don't exist + web_services = { + "web_1": {"name": "Разовая тренировка", "price": "870 ₽", "price_numeric": 870.0, "description": "counter-strike, dota, tanks"}, + "web_2": {"name": "Абонемент на 4 занятия (Групповой)", "price": "2 790 ₽", "price_numeric": 2790.0, "description": "counter-strike, dota, tanks"}, + "web_3": {"name": "Абонемент на 8 занятий (Групповой)", "price": "4 990 ₽", "price_numeric": 4990.0, "description": "counter-strike, dota, tanks"}, + "web_4": {"name": "Абонемент на 4 занятия (Индивидуальный)", "price": "3 290 ₽", "price_numeric": 3290.0, "description": "counter-strike, dota, tanks"}, + "web_5": {"name": "Абонемент на 8 занятий (Индивидуальный)", "price": "5 990 ₽", "price_numeric": 5990.0, "description": "counter-strike, dota, tanks"} + } + for sid, svc in web_services.items(): + cursor.execute("SELECT COUNT(*) FROM services WHERE id = ?", (sid,)) + if cursor.fetchone()[0] == 0: + cursor.execute( + "INSERT INTO services (id, name, price, price_numeric, description) VALUES (?, ?, ?, ?, ?)", + (sid, svc["name"], svc["price"], svc["price_numeric"], svc["description"]) + ) + + # Table for web registrations with payments support + cursor.execute(""" + CREATE TABLE IF NOT EXISTS web_registrations ( + id TEXT PRIMARY KEY, + name TEXT, + phone TEXT, + email TEXT, + vk_link TEXT, + agree_oferta INTEGER, + agree_policy INTEGER, + agree_newsletter INTEGER, + service_name TEXT, + amount REAL, + payment_status TEXT DEFAULT 'pending', + yookassa_payment_id TEXT, + paid_at TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) + """) + + # Run migration on web_registrations to add new columns if they don't exist + for col, col_type in [ + ("service_name", "TEXT"), + ("amount", "REAL"), + ("payment_status", "TEXT DEFAULT 'pending'"), + ("yookassa_payment_id", "TEXT"), + ("paid_at", "TIMESTAMP") + ]: + try: + cursor.execute(f"ALTER TABLE web_registrations ADD COLUMN {col} {col_type}") + except sqlite3.OperationalError: + pass + + conn.commit() + + def get_services(self) -> Dict[str, Dict[str, Any]]: + with self._get_connection() as conn: + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + cursor.execute("SELECT id, name, price, price_numeric, description FROM services WHERE is_active = 1") + rows = cursor.fetchall() + services = {} + for row in rows: + services[row["id"]] = { + "name": row["name"], + "price": row["price"], + "price_numeric": row["price_numeric"] if "price_numeric" in row.keys() else 0.0, + "description": row["description"] + } + return services + + def add_web_registration(self, reg_id: str, data: dict): + """Сохранить заявку с веб-формы в базу данных SQLite.""" + with self._get_connection() as conn: + cursor = conn.cursor() + cursor.execute(""" + INSERT INTO web_registrations ( + id, name, phone, email, vk_link, + agree_oferta, agree_policy, agree_newsletter, + service_name, amount, payment_status, yookassa_payment_id + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """, ( + reg_id, + data.get("name", "").strip(), + data.get("phone", "").strip(), + data.get("email", "").strip(), + data.get("vk", "").strip(), + 1 if data.get("agreeOferta") else 0, + 1 if data.get("agreePolicy") else 0, + 1 if data.get("agreeNewsletter") else 0, + data.get("serviceName", "Разовая тренировка").strip(), + float(data.get("servicePrice", 870)), + data.get("paymentStatus", "pending"), + data.get("yookassaPaymentId", None) + )) + conn.commit() + + def update_web_payment_status(self, reg_id: str, status: str, yookassa_payment_id: str = None, paid_at: str = None): + """Обновить статус оплаты и сопутствующие данные для заявки.""" + with self._get_connection() as conn: + cursor = conn.cursor() + if yookassa_payment_id and paid_at: + cursor.execute(""" + UPDATE web_registrations + SET payment_status = ?, yookassa_payment_id = ?, paid_at = ? + WHERE id = ? + """, (status, yookassa_payment_id, paid_at, reg_id)) + elif yookassa_payment_id: + cursor.execute(""" + UPDATE web_registrations + SET payment_status = ?, yookassa_payment_id = ? + WHERE id = ? + """, (status, yookassa_payment_id, reg_id)) + else: + cursor.execute(""" + UPDATE web_registrations + SET payment_status = ? + WHERE id = ? + """, (status, reg_id)) + conn.commit() + + def get_web_registration(self, reg_id: str) -> Optional[Dict[str, Any]]: + """Получить детали одной веб-регистрации.""" + with self._get_connection() as conn: + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + cursor.execute("SELECT * FROM web_registrations WHERE id = ?", (reg_id,)) + row = cursor.fetchone() + return dict(row) if row else None + + def get_all_web_registrations(self) -> list: + """Получить все веб-регистрации для админ-панели.""" + with self._get_connection() as conn: + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + cursor.execute("SELECT * FROM web_registrations ORDER BY created_at DESC") + rows = cursor.fetchall() + return [dict(row) for row in rows] + + def get_all_services_list(self) -> list: + """Получить полный список всех услуг (включая неактивные) для админ-панели.""" + with self._get_connection() as conn: + conn.row_factory = sqlite3.Row + cursor = conn.cursor() + cursor.execute("SELECT id, name, price, price_numeric, description, is_active FROM services") + rows = cursor.fetchall() + return [dict(row) for row in rows] + + def add_service(self, service_id: str, name: str, price: str, price_numeric: float, description: str) -> bool: + """Добавить новую услугу в базу данных.""" + with self._get_connection() as conn: + cursor = conn.cursor() + try: + cursor.execute(""" + INSERT INTO services (id, name, price, price_numeric, description, is_active) + VALUES (?, ?, ?, ?, ?, 1) + """, (service_id.strip(), name.strip(), price.strip(), float(price_numeric), description.strip())) + conn.commit() + return True + except sqlite3.IntegrityError: + return False + + def update_service(self, service_id: str, name: str, price: str, price_numeric: float, description: str, is_active: int) -> bool: + """Обновить поля существующей услуги по её ID.""" + with self._get_connection() as conn: + cursor = conn.cursor() + cursor.execute(""" + UPDATE services + SET name = ?, price = ?, price_numeric = ?, description = ?, is_active = ? + WHERE id = ? + """, (name.strip(), price.strip(), float(price_numeric), description.strip(), int(is_active), service_id.strip())) + conn.commit() + return cursor.rowcount > 0 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1896d7a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,16 @@ +version: '3.8' + +services: + ikp-web: + build: . + container_name: ikp-site-container + restart: unless-stopped + ports: + - "8000:8000" + env_file: + - .env + volumes: + # Постоянное сохранение БД SQLite на хосте + - ./bot_database.db:/app/bot_database.db + # Постоянное сохранение Excel-файла с заявками + - ./form/registration_for_training.xlsx:/app/form/registration_for_training.xlsx diff --git a/form/Dogovor_oferty_kibersport_versia_izmenennaya.pdf b/form/Dogovor_oferty_kibersport_versia_izmenennaya.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9d5fd84357172478403451e5b94eed2aae4379ce GIT binary patch literal 115081 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 U{c=G7+aC-<#Lh0GEKBr%0IMxaUH||9 literal 0 HcmV?d00001 diff --git a/form/fix_excel.py b/form/fix_excel.py new file mode 100644 index 0000000..4775fe3 --- /dev/null +++ b/form/fix_excel.py @@ -0,0 +1,73 @@ +import os +import openpyxl +from openpyxl.styles import Alignment + +SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +FILE_NAME = os.path.join(SCRIPT_DIR, "registration_for_training.xlsx") + +def fix_shifted_rows(): + if not os.path.exists(FILE_NAME): + print(f"Файл {FILE_NAME} не найден.") + return + + try: + wb = openpyxl.load_workbook(FILE_NAME) + ws = wb.active + except PermissionError: + print("\n[ОШИБКА] Доступ запрещен. Пожалуйста, ЗАКРОЙТЕ файл 'registration_for_training.xlsx' в Excel или других программах и запустите скрипт снова.\n") + return + except Exception as e: + print(f"Ошибка при загрузке файла: {e}") + return + + rows = list(ws.iter_rows(values_only=False)) + if len(rows) <= 1: + print("В таблице нет данных для исправления (только заголовки).") + return + + changed = False + for i in range(1, len(rows)): + row_num = i + 1 + id_val = ws.cell(row=row_num, column=1).value + + # If the first cell doesn't start with 'id_', it means this row was written + # by the old running server process and needs to be shifted to the right. + if id_val and not str(id_val).startswith("id_"): + print(f"Исправляем смещение в строке {row_num} для пользователя: '{id_val}'") + + # Read the 8 fields that were written by the old server + old_values = [ws.cell(row=row_num, column=c).value for c in range(1, 9)] + + # Re-format this row: Column 1 is id_001, columns 2-9 are the shifted fields + ws.cell(row=row_num, column=1, value="id_001") + for col_idx, val in enumerate(old_values, 2): + ws.cell(row=row_num, column=col_idx, value=val) + + # Clear column 10 in case there is any residue + ws.cell(row=row_num, column=10, value=None) + + # Re-apply styles and alignments + data_align_left = Alignment(horizontal="left", vertical="center") + data_align_center = Alignment(horizontal="center", vertical="center") + + for col_idx in range(1, 10): + cell = ws.cell(row=row_num, column=col_idx) + if col_idx in [2, 4, 5]: + cell.alignment = data_align_left + else: + cell.alignment = data_align_center + + changed = True + + if changed: + try: + wb.save(FILE_NAME) + print("\n[УСПЕХ] Все смещенные строки в Excel были автоматически исправлены!") + print(f"Файл успешно сохранен: {FILE_NAME}\n") + except PermissionError: + print("\n[ОШИБКА] Не удалось сохранить файл. Пожалуйста, убедитесь, что файл закрыт в Excel, и попробуйте снова.\n") + else: + print("Смещенных строк не обнаружено. Все данные соответствуют формату.") + +if __name__ == "__main__": + fix_shifted_rows() diff --git a/form/index.html b/form/index.html new file mode 100644 index 0000000..e0b76cd --- /dev/null +++ b/form/index.html @@ -0,0 +1,169 @@ + + + + + + + + ИКП. Онлайн тренировки по киберспорту | Заявка на бесплатный урок + + + + + + + + + + + + +

+
+ +
+
+ ИКП Киберспорт +
+ +

ИКП. Онлайн тренировки по киберспорту

+

Оставить заявку на бесплатный урок и доступ к тестовым материалам ИКП

+ +
+ + + + + + + +
+ +
+ + 👤 +
+
+ ⚠️ Пожалуйста, введите ваше имя +
+
+ + +
+ +
+ + 📞 +
+
+ ⚠️ Введите корректный номер телефона: +7 (999) 999-99-99 +
+
+ + +
+ +
+ + ✉️ +
+
+ ⚠️ Введите корректный e-mail (например, name@mail.ru) +
+
+ + +
+ +
+ + 🌐 +
+
+ ⚠️ Ссылка должна вести на vk.com или vkontakte.ru +
+
+ +
+ +
+ ⚠️ Вы должны согласиться с офертой +
+
+ +
+ +
+ ⚠️ Вы должны согласиться с политикой обработки данных +
+
+ +
+ +
+ + + + + + +
+
+ + + +
+
+ + + + + + \ No newline at end of file diff --git a/form/script.js b/form/script.js new file mode 100644 index 0000000..9625892 --- /dev/null +++ b/form/script.js @@ -0,0 +1,384 @@ +document.addEventListener('DOMContentLoaded', () => { + const nameInput = document.getElementById('name'); + const phoneInput = document.getElementById('phone'); + const emailInput = document.getElementById('email'); + const vkInput = document.getElementById('vk'); + const agreeOfertaInput = document.getElementById('agreeOferta'); + const agreePolicyInput = document.getElementById('agreePolicy'); + const agreeNewsletterInput = document.getElementById('agreeNewsletter'); + + const form = document.getElementById('ikpForm'); + const formContainer = document.getElementById('formContainer'); + const successContainer = document.getElementById('successContainer'); + const resetBtn = document.getElementById('resetBtn'); + + // Service display elements + const serviceDisplay = document.getElementById('serviceDisplay'); + const serviceNameDisplay = document.getElementById('serviceNameDisplay'); + const servicePriceDisplay = document.getElementById('servicePriceDisplay'); + const serviceIdInput = document.getElementById('serviceId'); + + // Parse URL query parameters + const urlParams = new URLSearchParams(window.location.search); + const serviceIdParam = urlParams.get('service_id'); + const successParam = urlParams.get('success'); + + // If redirected back from payment successfully + if (successParam === 'true') { + formContainer.style.display = 'none'; + successContainer.style.display = 'flex'; + successContainer.style.opacity = '1'; + } + + let services = {}; + + const servicesUrl = window.location.protocol === 'file:' ? 'http://localhost:8000/api/services' : '/api/services'; + + fetch(servicesUrl) + .then(response => { + if (!response.ok) { + throw new Error('Не удалось загрузить список услуг'); + } + return response.json(); + }) + .then(data => { + if (data.status === 'success') { + services = data.services; + initializeServiceDisplay(); + } else { + console.error('Error loading services:', data.message); + fallbackServiceDisplay(); + } + }) + .catch(err => { + console.error('Error fetching services:', err); + fallbackServiceDisplay(); + }); + + function initializeServiceDisplay() { + if (serviceIdParam && services[serviceIdParam]) { + const selectedService = services[serviceIdParam]; + serviceNameDisplay.textContent = selectedService.name; + const price = selectedService.price_numeric || parseFloat(selectedService.price) || 0; + servicePriceDisplay.textContent = price.toLocaleString('ru-RU') + ' ₽'; + serviceIdInput.value = serviceIdParam; + serviceDisplay.style.display = 'block'; + } else { + // Default to web_1 + serviceIdInput.value = "web_1"; + if (services["web_1"]) { + const selectedService = services["web_1"]; + serviceNameDisplay.textContent = selectedService.name; + const price = selectedService.price_numeric || parseFloat(selectedService.price) || 0; + servicePriceDisplay.textContent = price.toLocaleString('ru-RU') + ' ₽'; + serviceDisplay.style.display = 'block'; + } + } + } + + function fallbackServiceDisplay() { + services = { + "web_1": { name: "Разовая тренировка", price_numeric: 870 }, + "web_2": { name: "Абонемент на 4 занятия (Групповой)", price_numeric: 2790 }, + "web_3": { name: "Абонемент на 8 занятий (Групповой)", price_numeric: 4990 }, + "web_4": { name: "Абонемент на 4 занятия (Индивидуальный)", price_numeric: 3290 }, + "web_5": { name: "Абонемент на 8 занятий (Индивидуальный)", price_numeric: 5990 } + }; + initializeServiceDisplay(); + } + + // List of fields to manage focus and validation state + const fields = [ + { input: nameInput, check: checkName, dirty: false }, + { input: phoneInput, check: checkPhone, dirty: false }, + { input: emailInput, check: checkEmail, dirty: false }, + { input: vkInput, check: checkVK, dirty: false }, + { input: agreeOfertaInput, check: checkOferta, dirty: false }, + { input: agreePolicyInput, check: checkPolicy, dirty: false } + ]; + + /* ==================================================== + Validation Functions + ==================================================== */ + function showError(input, show) { + const group = input.closest('.form-group') || input.closest('.checkbox-group'); + if (show) { + group.classList.add('has-error'); + } else { + group.classList.remove('has-error'); + } + } + + function checkName() { + const val = nameInput.value.trim(); + const isValid = val.length >= 2; + showError(nameInput, !isValid); + return isValid; + } + + function checkPhone() { + const val = phoneInput.value; + const digits = val.replace(/\D/g, ''); + const isValid = digits.length === 11 && val.startsWith('+7') && val.length === 18; + showError(phoneInput, !isValid); + return isValid; + } + + function checkEmail() { + const val = emailInput.value.trim(); + const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/; + const isValid = emailRegex.test(val); + showError(emailInput, !isValid); + return isValid; + } + + function checkVK() { + const val = vkInput.value.trim().toLowerCase(); + const isValid = val.length > 0; + showError(vkInput, !isValid); + return isValid; + } + + if (agreeOfertaInput) { + agreeOfertaInput.addEventListener('change', checkOferta); + } + if (agreePolicyInput) { + agreePolicyInput.addEventListener('change', checkPolicy); + } + + function checkOferta() { + const isValid = agreeOfertaInput.checked; + showError(agreeOfertaInput, !isValid); + return isValid; + } + + function checkPolicy() { + const isValid = agreePolicyInput.checked; + showError(agreePolicyInput, !isValid); + return isValid; + } + + /* ==================================================== + Interaction Listeners (UX enhancements) + ==================================================== */ + fields.forEach(field => { + field.input.addEventListener('blur', () => { + field.dirty = true; + field.check(); + }); + + const eventType = field.input.type === 'checkbox' ? 'change' : 'input'; + field.input.addEventListener(eventType, () => { + if (field.dirty) { + field.check(); + } + }); + }); + + /* ==================================================== + Phone Input Mask Implementation + ==================================================== */ + phoneInput.addEventListener('input', (e) => { + let value = e.target.value; + let digits = value.replace(/\D/g, ''); + + if (digits.startsWith('7') || digits.startsWith('8')) { + digits = digits.substring(1); + } + + digits = digits.substring(0, 10); + + let formatted = ''; + if (digits.length > 0) { + formatted = '+7 (' + digits.substring(0, 3); + } + if (digits.length >= 3) { + formatted += ') '; + } + if (digits.length > 3) { + formatted += digits.substring(3, 6); + } + if (digits.length > 6) { + formatted += '-' + digits.substring(6, 8); + } + if (digits.length > 8) { + formatted += '-' + digits.substring(8, 10); + } + + e.target.value = formatted; + + const phoneField = fields.find(item => item.input === phoneInput); + if (phoneField && phoneField.dirty) { + checkPhone(); + } + }); + + phoneInput.addEventListener('keydown', (e) => { + if (e.key === 'Backspace') { + const val = e.target.value; + if (val === '+7 ' || val === '+7' || val === '+') { + e.target.value = ''; + } + } + }); + + phoneInput.addEventListener('focus', (e) => { + if (!e.target.value) { + e.target.value = '+7 '; + } + }); + + phoneInput.addEventListener('blur', (e) => { + if (e.target.value === '+7 ' || e.target.value === '+7') { + e.target.value = ''; + } + const phoneField = fields.find(item => item.input === phoneInput); + if (phoneField) { + phoneField.dirty = true; + checkPhone(); + } + }); + + /* ==================================================== + Form Submission + ==================================================== */ + form.addEventListener('submit', (e) => { + e.preventDefault(); + + fields.forEach(field => { + field.dirty = true; + }); + + const isNameValid = checkName(); + const isPhoneValid = checkPhone(); + const isEmailValid = checkEmail(); + const isVKValid = checkVK(); + const isOfertaValid = checkOferta(); + const isPolicyValid = checkPolicy(); + + if (isNameValid && isPhoneValid && isEmailValid && isVKValid && isOfertaValid && isPolicyValid) { + const formData = { + name: nameInput.value.trim(), + phone: phoneInput.value, + email: emailInput.value.trim(), + vk: vkInput.value.trim(), + agreeOferta: agreeOfertaInput.checked, + agreePolicy: agreePolicyInput.checked, + agreeNewsletter: agreeNewsletterInput.checked, + serviceId: serviceIdInput.value || "web_1" + }; + + const submitBtn = document.getElementById('submitBtn'); + const originalBtnText = submitBtn.textContent; + submitBtn.disabled = true; + submitBtn.textContent = 'Отправка...'; + + const submitUrl = window.location.protocol === 'file:' ? 'http://localhost:8000/submit' : '/submit'; + + fetch(submitUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData) + }) + .then(response => { + return response.json().then(data => { + if (!response.ok) { + throw new Error(data.message || 'Ошибка сервера'); + } + return data; + }).catch(err => { + if (!response.ok) { + throw new Error('Ошибка сети или сервера'); + } + throw err; + }); + }) + .then(data => { + if (data.payment_url) { + // Redirect directly to YooKassa payment gateway + window.location.href = data.payment_url; + return; + } + + // Fallback success UI container (if YooKassa keys not configured in server) + formContainer.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; + formContainer.style.opacity = '0'; + formContainer.style.transform = 'translateY(-10px)'; + + setTimeout(() => { + formContainer.style.display = 'none'; + successContainer.style.display = 'flex'; + successContainer.style.opacity = '0'; + successContainer.style.transform = 'translateY(10px)'; + + successContainer.offsetHeight; + + successContainer.style.transition = 'opacity 0.4s ease, transform 0.4s ease'; + successContainer.style.opacity = '1'; + successContainer.style.transform = 'translateY(0)'; + }, 300); + + form.reset(); + fields.forEach(field => { + field.dirty = false; + }); + + serviceDisplay.style.display = 'none'; + }) + .catch(error => { + console.error('Error submitting form:', error); + alert('Произошла ошибка при отправке заявки: ' + error.message + '. Пожалуйста, убедитесь, что сервер server.py запущен.'); + }) + .finally(() => { + submitBtn.disabled = false; + submitBtn.textContent = originalBtnText; + }); + } else { + const firstInvalid = fields.find(field => { + if (field.input === nameInput) return !isNameValid; + if (field.input === phoneInput) return !isPhoneValid; + if (field.input === emailInput) return !isEmailValid; + if (field.input === vkInput) return !isVKValid; + if (field.input === agreeOfertaInput) return !isOfertaValid; + if (field.input === agreePolicyInput) return !isPolicyValid; + return false; + }); + + if (firstInvalid) { + firstInvalid.input.focus(); + } + } + }); + + /* ==================================================== + Reset / Back to Form Handler + ==================================================== */ + resetBtn.addEventListener('click', () => { + successContainer.style.transition = 'opacity 0.3s ease, transform 0.3s ease'; + successContainer.style.opacity = '0'; + successContainer.style.transform = 'translateY(10px)'; + + // Remove parameters from URL to prevent showing success container on reload + const newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname + "?service_id=" + serviceIdInput.value; + window.history.replaceState({ path: newUrl }, '', newUrl); + + setTimeout(() => { + successContainer.style.display = 'none'; + formContainer.style.display = 'block'; + formContainer.style.opacity = '0'; + formContainer.style.transform = 'translateY(-10px)'; + + formContainer.offsetHeight; + + formContainer.style.transition = 'opacity 0.4s ease, transform 0.4s ease'; + formContainer.style.opacity = '1'; + formContainer.style.transform = 'translateY(0)'; + + if (serviceIdInput.value && services[serviceIdInput.value]) { + serviceDisplay.style.display = 'block'; + } + }, 300); + }); +}); diff --git a/form/style.css b/form/style.css new file mode 100644 index 0000000..cb613fb --- /dev/null +++ b/form/style.css @@ -0,0 +1,538 @@ +/* ---------------------------------------------------- + 1. DESIGN SYSTEM & RESET + ---------------------------------------------------- */ +:root { + --bg-color: #0A0F1F; + --card-bg: rgba(16, 22, 42, 0.85); + --primary-orange: #ff7a00; + --primary-orange-hover: #ff9233; + --cyan-accent: #00d2ff; + --text-white: #ffffff; + --text-gray: #8f9cae; + --text-dark: #0A0F1F; + --error-red: #ff4a4a; + --input-border: rgba(255, 255, 255, 0.12); + --font-headings: 'Montserrat', sans-serif; + --font-body: 'Inter', sans-serif; +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + background-color: var(--bg-color); + /* Dark gradient overlay + brand background image from help_img */ + background-image: + radial-gradient(circle at center, rgba(13, 25, 47, 0.93) 0%, rgba(10, 15, 31, 0.99) 100%), + url('../help_img/bg.jpg'); + background-repeat: no-repeat; + background-position: center center; + background-attachment: fixed; + background-size: cover; + color: var(--text-white); + font-family: var(--font-body); + min-height: 100vh; + display: flex; + justify-content: center; + align-items: center; + padding: 24px 16px; + overflow-x: hidden; +} + +/* ---------------------------------------------------- + 2. LAYOUT & CARD CONTAINER + ---------------------------------------------------- */ +main { + width: 100%; + display: flex; + justify-content: center; + align-items: center; +} + +.card { + background: var(--card-bg); + backdrop-filter: blur(16px); + -webkit-backdrop-filter: blur(16px); + border: 1px solid rgba(255, 255, 255, 0.08); + border-radius: 24px; + padding: 40px; + width: 100%; + max-width: 480px; + box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6), + inset 0 1px 1px rgba(255, 255, 255, 0.1); + position: relative; + overflow: hidden; + transition: all 0.3s ease; +} + +/* Premium Esports Accent Line at the top of the card */ +.card::before { + content: ''; + position: absolute; + top: 0; + left: 0; + right: 0; + height: 4px; + background: linear-gradient(90deg, var(--cyan-accent) 0%, var(--primary-orange) 100%); +} + +/* ---------------------------------------------------- + 3. BRANDING & HEADER + ---------------------------------------------------- */ +.logo-container { + display: flex; + justify-content: center; + margin-bottom: 24px; +} + +.logo-img { + height: 110px; + width: auto; + object-fit: contain; + border: 2px solid rgba(255, 122, 0, 0.25); + border-radius: 16px; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5); + transition: transform 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease; +} + +.logo-img:hover { + transform: scale(1.04); + border-color: var(--primary-orange); + box-shadow: 0 8px 28px rgba(255, 122, 0, 0.4); +} + +.form-title { + font-family: var(--font-headings); + font-weight: 800; + font-size: 1.6rem; + text-transform: uppercase; + text-align: center; + margin: 0 0 10px 0; + background: linear-gradient(90deg, #ffffff 50%, var(--text-gray) 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + letter-spacing: 0.5px; + line-height: 1.3; +} + +.form-subtitle { + font-size: 0.92rem; + color: var(--text-gray); + text-align: center; + margin: 0 0 32px 0; + line-height: 1.5; +} + +/* ---------------------------------------------------- + 4. FORM INPUTS & ELEMENTS + ---------------------------------------------------- */ +.form-group { + margin-bottom: 22px; + position: relative; +} + +.form-label { + display: block; + font-size: 0.75rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 1.2px; + color: var(--cyan-accent); + margin-bottom: 8px; +} + +.required-star { + color: var(--primary-orange); +} + +.input-wrapper { + position: relative; + display: flex; + align-items: center; +} + +.form-input { + width: 100%; + height: 52px; + padding: 0 16px 0 44px; + background: rgba(10, 15, 31, 0.7); + border: 1.5px solid var(--input-border); + border-radius: 12px; + color: var(--text-white); + font-family: var(--font-body); + font-size: 0.95rem; + transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); + box-sizing: border-box; +} + +.form-input::placeholder { + color: #4a5c73; +} + +.form-input:focus { + outline: none; + border-color: var(--primary-orange); + background: rgba(10, 15, 31, 0.85); + box-shadow: 0 0 14px rgba(255, 122, 0, 0.2); +} + +.input-icon { + position: absolute; + left: 16px; + font-size: 1.1rem; + color: #4a5c73; + pointer-events: none; + transition: color 0.25s ease; +} + +.form-input:focus + .input-icon { + color: var(--primary-orange); +} + +/* ---------------------------------------------------- + 5. ERROR HANDLING + ---------------------------------------------------- */ +.error-message { + color: var(--error-red); + font-size: 0.8rem; + margin-top: 6px; + display: none; + align-items: center; + gap: 6px; + font-weight: 500; + animation: slideDown 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards; +} + +@keyframes slideDown { + from { opacity: 0; transform: translateY(-4px); } + to { opacity: 1; transform: translateY(0); } +} + +/* Error States for Inputs */ +.form-group.has-error .form-input { + border-color: var(--error-red); + box-shadow: 0 0 8px rgba(255, 74, 74, 0.15); +} + +.form-group.has-error .input-icon { + color: var(--error-red); +} + +.form-group.has-error .error-message { + display: flex; +} + +/* ---------------------------------------------------- + 6. BUTTONS & ACTIONS + ---------------------------------------------------- */ +.submit-btn { + width: 100%; + height: 54px; + background: var(--primary-orange); + border: none; + border-radius: 12px; + color: var(--text-dark); + font-family: var(--font-headings); + font-weight: 800; + font-size: 1.05rem; + text-transform: uppercase; + letter-spacing: 1px; + cursor: pointer; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + box-shadow: 0 4px 12px rgba(255, 122, 0, 0.2); + margin-top: 10px; + display: flex; + justify-content: center; + align-items: center; +} + +.submit-btn:hover { + background: var(--primary-orange-hover); + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(255, 122, 0, 0.4); +} + +.submit-btn:active { + transform: translateY(0); + box-shadow: 0 4px 12px rgba(255, 122, 0, 0.2); +} + +.submit-btn:focus-visible { + outline: 2px solid var(--text-white); + outline-offset: 2px; +} + +/* ---------------------------------------------------- + 7. LEGAL CONSENT + ---------------------------------------------------- */ +.consent-text { + font-size: 0.72rem; + color: var(--text-gray); + text-align: center; + margin-top: 22px; + line-height: 1.5; +} + +.consent-link { + color: var(--cyan-accent); + text-decoration: none; + border-bottom: 1px dashed rgba(0, 210, 255, 0.3); + transition: all 0.2s ease; +} + +.consent-link:hover { + color: var(--primary-orange); + border-bottom-color: rgba(255, 122, 0, 0.5); +} + +/* ---------------------------------------------------- + 8. SUCCESS STATE WINDOW + ---------------------------------------------------- */ +.success-card { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 10px 0; + animation: scaleIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1) forwards; +} + +@keyframes scaleIn { + from { opacity: 0; transform: scale(0.9); } + to { opacity: 1; transform: scale(1); } +} + +.success-icon-wrapper { + width: 80px; + height: 80px; + border-radius: 50%; + background: rgba(0, 210, 255, 0.1); + border: 3px solid var(--cyan-accent); + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 24px; + box-shadow: 0 0 20px rgba(0, 210, 255, 0.25); +} + +.success-icon { + font-size: 2.5rem; + color: var(--cyan-accent); + font-weight: bold; +} + +.success-title { + font-family: var(--font-headings); + font-size: 1.7rem; + font-weight: 800; + text-transform: uppercase; + color: var(--primary-orange); + margin: 0 0 16px 0; + letter-spacing: 0.5px; +} + +.success-text { + font-size: 0.95rem; + color: #b8c7db; + line-height: 1.6; + margin: 0 0 32px 0; +} + +.reset-btn { + width: 100%; + height: 52px; + background: transparent; + border: 2px solid rgba(255, 255, 255, 0.15); + border-radius: 12px; + color: var(--text-white); + font-family: var(--font-headings); + font-weight: 700; + font-size: 0.95rem; + text-transform: uppercase; + letter-spacing: 1px; + cursor: pointer; + transition: all 0.25s ease; +} + +.reset-btn:hover { + border-color: var(--cyan-accent); + color: var(--cyan-accent); + background: rgba(0, 210, 255, 0.05); + box-shadow: 0 0 12px rgba(0, 210, 255, 0.15); +} + +/* ---------------------------------------------------- + 10. CUSTOM CHECKBOXES + ---------------------------------------------------- */ +.checkbox-group { + margin-bottom: 18px; + position: relative; +} + +.checkbox-label { + display: flex; + align-items: flex-start; + cursor: pointer; + user-select: none; + font-size: 0.85rem; + color: var(--text-gray); + line-height: 1.4; +} + +/* Hide default checkbox */ +.checkbox-label input[type="checkbox"] { + position: absolute; + opacity: 0; + cursor: pointer; + height: 0; + width: 0; +} + +/* Custom checkbox indicator */ +.checkbox-custom { + flex-shrink: 0; + height: 20px; + width: 20px; + background: rgba(10, 15, 31, 0.7); + border: 1.5px solid var(--input-border); + border-radius: 6px; + margin-right: 12px; + position: relative; + transition: all 0.2s ease; + margin-top: 1px; +} + +/* On hover */ +.checkbox-label:hover .checkbox-custom { + border-color: var(--cyan-accent); + box-shadow: 0 0 8px rgba(0, 210, 255, 0.2); +} + +/* Checked state background */ +.checkbox-label input[type="checkbox"]:checked ~ .checkbox-custom { + background: var(--primary-orange); + border-color: var(--primary-orange); + box-shadow: 0 0 10px rgba(255, 122, 0, 0.3); +} + +/* Custom checkmark symbol */ +.checkbox-custom::after { + content: ''; + position: absolute; + display: none; + left: 6px; + top: 2px; + width: 5px; + height: 10px; + border: solid var(--text-dark); + border-width: 0 2px 2px 0; + transform: rotate(45deg); +} + +/* Show checkmark when checked */ +.checkbox-label input[type="checkbox"]:checked ~ .checkbox-custom::after { + display: block; +} + +/* Focus outline for accessibility */ +.checkbox-label input[type="checkbox"]:focus-visible ~ .checkbox-custom { + outline: 2px solid var(--text-white); + outline-offset: 2px; +} + +/* Error States for Checkboxes */ +.checkbox-group.has-error .checkbox-custom { + border-color: var(--error-red); + box-shadow: 0 0 8px rgba(255, 74, 74, 0.2); +} +.checkbox-group.has-error .error-message { + display: flex; + margin-left: 32px; /* Aligns error text with checkbox text label */ +} + +/* ---------------------------------------------------- + 9. RESPONSIVE DESIGN + ---------------------------------------------------- */ +@media (max-width: 480px) { + body { + padding: 16px 8px; + } + .card { + padding: 30px 20px; + border-radius: 20px; + } + .form-title { + font-size: 1.35rem; + } + .form-subtitle { + font-size: 0.85rem; + margin-bottom: 24px; + } + .logo-img { + height: 90px; + } + .form-input { + height: 48px; + font-size: 0.9rem; + } + .submit-btn { + height: 50px; + font-size: 0.95rem; + } +} + +/* ---------------------------------------------------- + 11. SELECTED SERVICE DISPLAY + ---------------------------------------------------- */ +.service-display-badge { + padding: 14px 16px; + background: rgba(0, 210, 255, 0.05); + border: 1.5px dashed rgba(0, 210, 255, 0.3); + border-radius: 12px; + box-shadow: 0 4px 15px rgba(0, 210, 255, 0.05); + animation: slideDown 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards; +} + +.service-badge-content { + display: flex; + align-items: center; + gap: 12px; +} + +.service-icon { + font-size: 1.6rem; + line-height: 1; +} + +.service-details { + display: flex; + flex-direction: column; + gap: 2px; +} + +.service-label { + font-size: 0.65rem; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 1px; + color: var(--text-gray); +} + +.service-value { + font-family: var(--font-headings); + font-weight: 800; + font-size: 0.95rem; + color: var(--text-white); +} + +#serviceNameDisplay { + color: var(--cyan-accent); +} + +#servicePriceDisplay { + color: var(--primary-orange); +} + diff --git a/form/Политика ПД.pdf b/form/Политика ПД.pdf new file mode 100644 index 0000000000000000000000000000000000000000..309ea58494daf025e7b7cd6bfd5ce32004e6ef3a GIT binary patch literal 28493 zcma&O1ymhP*ENWHaEHLfgS)%CySuvtch}$$T!Om=g1fuBySv-KBlEs9-#6yLV5*jMBiZDBL; z8)|!$PdEYszSGN_V0v>q!uchIsxZm;)wbF$h3(coZ(kuJ$8`(S<)fDsHY=30xx{R} zH42VbT-yZPQ>? z`6cmj6q)wb6YYJGuM6EjR$ANG#fFm^RIKTkKvv0W7NSgClJRUJXsCnoCDh_>M{+=2 zB)R*wjoACETrMA#UwRkAE}B|~V6RGs8e6ymej6U%Wed`$EC;8pAL!6&Tev{_<>Rbd z{*fi<4w;+W=^oV|Wg(P*&bHFt6*)9S33z0at4A4mL}q=;i~6K{RxgrQ#QUz3e!sWTTi;UHF%Pd$ljhIcX>RNGXh1j$N$HC;lihzsh7 z9{%0nk4RrdU%6ReU4^D|Y1vy)EfTyXO8W{dYmQXjtc8bObj*OnujRZpOJ4i!vq^Jl zDh)#enIvIH{-5A43NuQbuDxWXdB0&hsZRt{Od4#|$&~K7pk~i~IbZT4`{Ta{rP_+` zDvAm>?8&W@J12&mFg7G$6zpxFEbsqNP>HyA4=%#j9@^o!CQQ;#hplZ`LGUCS@A+2n zDi^V8lT0&>Rd2sq4GJ3!OOPfRren?uJW~55t4Z7D9w^gK z`i^^lg7DD^`&JmQ=3pI6NnsN#7rPj)N>BB`StVVK9;q$UrP-$cFwjPUAbJJfu15xP zYGF?Xn`D&lh+rqgvC%J`^8VNj$= z#)c?w=(L$YzNt`(J%E!ig(RP6tcQl9-UczapEN18j7we88xBHtQ1yEb%xc|bB$q*B zN_O97g7On1hAt$emmNTl1j4eaOIVS#4-s6c@x*_LkjRSdQOkGn`5Cz}-d8ocO%nAN zDkYM&thm@0Ep1g06g+;_uhh?tG)r>OF;j|aAa`)doj$H`Z`}q@>xtc*SfJNk9+=P{ z#S8qifOk5lmt-AGRPSNev{5zOWxJ?x7kP4MXq_QDq$ugc3z&k%aWoDbAsVLv5C$O^jlgH2Wz*~^7r`u2%Hcf5gBL`@z@ z7NV!zuC2D{4zCVyjB8{XELKxUa+T?ThcuNd8<;Qp@)KZ`Se8y651=OAbeW4 z+dDV$u~t)3cE03F;wzHDDkH3$wmZG!5SDG+KEh<3MQ%xKwM=(dr8$5Rn= z9{c$MZku*kX^HA==A8QDLF_n) z);}W(4i8@WuI-Z)IsoV>liY|d6t0P@&#s|?3s#N%v{ZgvnoQ5ExO_(2D2~9qeE^J~ zJ)7Q)6*8qSbGPEZCN7PALraAS^_3h1u<3JfR7mUlcAqqj@JfFnwOVv^60$~7gkxSo zYnw|mVLu;$Aw8MZK~4oH=wG$NZci?zd?%f=PLN#FQ{xXaOrQDX1SN!A@GXe$8x|>- zF|9ks+W}Ho;&IGw631F^UZNsuQ365 z3712KbC?)-C5K5YC&v5WpqdfrsGvx0V_!-jimy!KpfPo_9ZJhioZ0!W`uTpz=S$ z8j3a+wvS-eJc{CSMu5)-FXM4})PW7QLx9y1-&+4P_#}2ds@AdslogYQ>LBEpx6Qw( zL^XIIl}d1rXS@SBx1t%Cnii_DvvvIn@mj(Oxa`EwfQAnfFXDtLM2PLEk#*+;uHIPr zX0FVz0PP;I$fAkZxWwkC!&%4Ma*al}mWCC3Tmu;@#I~Izg%GsLmU~pt!GC^yN#a~?quk7gt#WTg6!tY8ez^usJE05bVwsTMPNZoQi||X{?{tD+#Pc3Q zo$--0PY0X7QF@H=$&X{Bg&gW!qv^(=Ca1pHk+QPnf$gW`Zi+s^<>3zm>U;P)S9g~w zr!EH2{7%IcpW=Bbp@Wr*4ZD$V&jh2h#Ki10f5VKsY5#7p6KjmvOc+QC-!zY=ilQ(g zBv!p8Pl{KWrnQloEQ4}C+eP0ku;O3<+YO%O{bs*Kagmy@{)Gm1sKj?(4_2R}4x+`s z2=8edXqJ>#V8|}@T;Sq}qfll0i(e{?T?qE~{aKb^=oYR&VYswmi(yZr3D69`Ss0%Z z63=`5<$lkk)GXMBb;?|{H`wkYID~9^!;4d^A{Wghg7EusHYOu}xrd(_ueI}BT>!Dy zk&1((@hHd{&+2DTnJ#%^>b8kR;1NA=MsTLJV@l)6)ju%t+&4qUo{mu1f(VHT=QS}t z>kNckFf~M#DY5D%@%6YXUcSsuRvc*NRXun1a_=G$i#(2lh2P?53Aw>qf4@g3R|)Th zjoZR3%x^IcZ2@aVcJm%fIdk$ZPZXBiCkdFwyWP3LmN|y)IV4&9^Kf}D7%`UQHe3zY z4I(0Dh5ssz0!ss*yN=-E=H-U$>N1OulJ1nU!nO6yRBYF2+6-JP^uF`X`rsuiXS3Se z#O&c?g6~Hi1LvmRjp|>}4m)*%8L&Na;E{A<%++;TJj(_31$)scMeegveW0Rr$S9hf z3{53kXG2$iG-MaS)$IXieW$OtTlEfz@gzT(nK(iv{%w#?m9rhl)mz z8Hxy@Oz7iW~AWGv6<_IB!Q5-Q5eOmB3wX?yzACr;2o zDU_IP(D(9?veD1zRlFgIC+$@3(3<3^Wz0@32-5R(`6+p~RirSCqa416F|l0jl`lN4 z=es>FrHtNtK94^8w7l$Nn`T({Z5R|(jQBrH;a8lSmZgN9TPo&28yGFnlS;3ho0!qe^H(zAy8 znjelUVuMvEQX($qLjPgrNMCEi`gAkU7~MYmy=NGWbz8QD7^*TH#SvjJ`a!KmgdgsQ zAg2xrnb`QieyUmU&!X!U)df-1G?qe72F$tTcaX&K#xNLT8>4?9_Q%mDFsJ`7fUe|b z_kqae^iBWz?_g}>1Yr26Rshf{7(3d2cQ7<|1Tg(=5VW;%`lxpVd;_SyJfHX!FDxp3?7~j>hKZvFSC*o1Az6@3`47=!~|gf%j4sa1wj8f zBZUtx@kuBCo#f{<{tYbiF=kr+Pby;b!9xJFLdMSKhQnY8VaMr z2KXDyLti1v^>xY%3Gc2(T0)i5TcWj!NfQdc`fy}(La;KyeiS^aqozeIjH7`@O%aJDAx93F}#Bf-6WDT1k*F1=RoI{5pMTXTHO`yQ8o|$OeWpQ z!B!u`YGKNZY?fO~CE5HH36`VvlVrp6mnWogtCDys(C+=W>FI}bDIhx36y1@1(j2QW z24PgJv#=`=AgF{M_7(^Dh(~s_Od!_+)17dzFmZzdr1_uby9Wa%PnWfdj|TLV3Ek40 zp{`QnH+677=rDXMZIgt7Nz|=V%wkW=aZgXx=l0AV+ZWgIycJ)$2i%{PFG)|vGx;Mk z)z_^~%4l2Bf$oSk(!SQVB`O2eSwrycZkEZO1Awl;f$G-MuknJdbmDrp;K*PjPEM>G zfwL@WC=Xblv;1v`+Jo8eQ-;r;RX7VUc>RdP(HM<|cMA#&B!xys;NX+Tjb85&-?uy1 z%|{2jsnWALFfM}*l;sZ+paa9qnuECf)M99iU;=$+H+?W!$RM%2Gb~ZfzUu;c1+mNh z5r-VG}zSo#rppP1-4dsOtI^)#!Jt3em^PdIVm`#Z3lbTM;WEVngjiy#^w6G0FQC$vP1RBf9ly8IV{1Sm19F$0e1CM->ky#!w(8PpR`$ z61O1KCgmn=C5Rv7FcNjZROi!?tsu?<=#n7B@yaE9BSn>!z!er)lwp@>t-24vY{zQd|1l6(Se zf$4m=sXuknbsS5^OLSjFS@WK!;}3gp@DEyVpp8k4HFv-5;_hPa)($B^bkXTOFe+f> zN5)4sM@C;W?KO^Xk1w-Sn(Mr`kS9J;*id*T5+<4?0w+e7NGaRSqRwWNSeMAo&{>dL z=vypWJkQdUMvWJayJU`M=rXwynxs`>8RBu`QG?Qo3o~mIg?A=@gp1<7E9w}kDBh(@?&{xrQsZOaBsgJ4f)ydVt)vW7|s-C)+ zdQvU54ZZqWewP=!H?#s$Ux;ue8oBi==r*w(6X3#+dUId+kxS*Ngw9%d%F=?on%1BS#{wTY8ySji; z8wd*t_B4w{4@?b+Mns`YqPvI;iuMZ6ib@N62qz0mCaY1Y*Y1c!YD5AGxY6-(&^(Bp z9g6R#RwYBWPqtvT&uAF6l4?(u9DeT>506*G=ys~xQ{ds?e_cm>4@2oH-j%Aj(QS0u z1)Gm=4tb8-@1xw0y3~F!eu)K34y*~B6iV*V4l@+55JwZ=29f3ez45(9_sValI3XtC z7dd0`WbvqZVBJIAv;c{Icon5KBR5$qZ8y^|I>DwP^Vu_Hlw7{aSgCK0>L$%Uf4oWE zibWEqkp!s2)>_o8nTi@`4atun?cMC8?$``}9lRcV_GUI=cKL4F=KL1?(#d>g311#G zSE04sDC45t*|d4vb{uUDuohdq7#10hGR9fA316F$&z7%h(=)3*-|G`-6p-I+r5@9S zx9YV*vpQWhsV%oyPA1fuyfql!3g40?S&2JdSNBqVTphU!JZ;Ut%YSy+aE5YOSv_pJ zR!cEZ*IAsX*w8ND9l6TAYG_tHX;abHwAVv0k2Z>~V<@U=m8i53oh>}dJMzPhPTgxg z@@P2CSn6M%Z(q0enFfvm?SmEPOJ!)z<_0jbaIu*N& z9TyD}&F}Au{yxh&GtXMYn!wT(71vk2ZQpPEx^XM$fl_)X$M~!90gR1+{c@}S0slM` zj%(2^+^gh}>^1AIenKN$BWG@9F04L}#oR;6WBt%~I^*luS8Cq0ch8&1yOh-0Aydim z*fF&9H1;eP?<;}6pv#Cbj1Uf0C!VIdovDn9s*1H?zvN1t%SMOd<<{pH<>XS+3U+Ny zuMDr&)8N;rIlSh~B;6Bl^TXfg)~$zjwXaFr#T4edab=qLKY+F@Q%2%y_&rmo^0om!N^i%mhhIp&OXeW6t~`-WY6o3*M^!# z2mcYIeNTL>l-Py-VSOff2+SwoGi`qc6n|! zH5lx5n};k$sR&%!=Z5 z@q~W4awWAk*;~I4yng{~Hhg_ig#V`xMl7(zmiT{Tu!}{)7Af zgP=dL_P+r7?*@NCaazUi22Ovm1|^5@#(!6Q&f@P%{?9)_NK>7!F-R;CYM`VUg_pY!n7;Ql=k z|2(^3WMTh5vjy$AVT*1$MB)2480ux=Dk^q!7y&s25S<(TRc~MFsDPZLs1vG}`_^B1 zd=5@QInj%ZK9JLmRJ%+$HZ0ntp+`v+omPDg?&-!?rOw5ZD)b5d$>M{hZ3 znUr#Hg6LBaA0ajNNGi6@2BWE0ua`7$P@nCPU35b@%4hb?p9=iC2#rk2FJ?CXB%8Qf zLm<0ZtSaH%daJV@JS|@~$`I2bafA2vKCV%lRA)(8$bk?Md zHuudqiYj8vM8y1?@0q&fH{bd)&2PTQ$M7)OoO6)hd~MY4<$!L>qU8Yjab;f;$Z1-s zy+O!-Zq_0#t&zTViUkzf1VOr6sA^q^1>H?y z?xJTaF%o8jFud3`3pA9QEraUMW>rR#aqOt+i23uh&bg<$QMr59bcRcW$Ks`MIQmHa z%-2w9gH6T*xCC{VYzX+DOYN^j`}dRkPYVAh75`368GY*yPWZoPu9d#&CjtJ8g$jI- zT^LPjW_or2H6s)I$Esyv_((NI_KyW9{;`zI4f$wgQ+wo%o$i|H}7|L}&R}^!l!Um*^Q8 z*!~{M$8$B~kJv1KT{iwJRX+{?PWbOsr3cWn($Rec_$PDOS?KL*2JcVK*~cBn9LL;>X^!y^ zNGNK8FNoVs?OpJZc-60gP&{bVO}hUS$005@J$k{S8*<$O2*Uq>V^sW%zARgZ61UJ= zSROs99w(293yJ~sK~aO4P-(STvG*~qL+bc!#$}3mC*f~JMKmXiX3Fve|2fS)>uptQ z>w_IRIzErunRXV4%raQ>xsoQ31;LYY9#k2W4&#mMsoTFF&&kI|xVdVCH^30n4M66J9w#vF8QK>)*l`3go{M}%Y{fUi zfWqei3KKBt)}fCvu*972R*hq5^M81t?{Lt=szOx*p@KjM=H>(b2`>e@6dKLuMtgGr zayJ^?%N453rvahMx5URruY?-*6;eWsD@*){j|X%!XFf#^LNN*02f=}HKtE<1;Bes1 zQKtqbn-KAy^YiK2sE#NiQs@=NGUf@ne z2a)MO^aLu;6>tZ(W#3~MdKxMUN)9f!gVfWlc23X}5DJNSPjn`@5;1$uZzZ@A^#`^Z z&7O?K3v$c3tPR{AXG^8Wq=#DV+@y!JN2EtO6bA_hkyUT{xcccf^cXQ9)Dr2qs!OAX zIkXh1T~sURLAyf>%)Jr08loE89^3$J%b~|OG%*w{bT?EIDH#BPIE*NX^cot0x2&V{B&q6eM~#f&!Nn;|+v{2hwj!xo4kA5|m} zDXc_DfoO=h3#`Z#+_h#(gzme#)zI38BR-Y^$7He^7U4T(L}N(h}0 zWs`3KGz@J*4MG5lxF#qQPYf4StXl}DD_l%i4Urs*kq|33kd6QuNkj;QhX5}NF(j-S z3REC^f}jrSi$IhdK>`$bJ-KL)UM?Jguoxnjzn~l#5`T9nq5+saj6JeF$fZkCEFHRPjqNI!4Cp&KF?@O5zmkZ^vf?>mOZMWw3lwWV3GdJV!WcB=yY8} zIX=QKBzjZ<3x%P-fDNg8c%U(lfqX=8`8{#z<^;Dyfek@71bZMu@2d~*5zh?_&-DyL zkbDGMqM}-ZZr6lb{9M1Du)K=)3@p)>zW}8A*ci~^~j~iBI zb@zSb7g44#SHMDuEA}NSODjeiyuq}r!Sr7lcESIdVu(C*(F=aAAZgyXmzV~eTk<_b zeqa|*H=BH2Y#oB3kf6}<1b2J@eVC0mzAmK>FTX(aj#fV~+6_FanlBM6QNm|kgqrl{ zGE{DmeK!4ZnurbhL7GTupwQFVqncGuqoLBFQ49HLRXb5?4xn4Xd;*L!n$aYcqFN!C za6JuzYrp*-;5(Z5UZ^^j_&murQu$tlI%fSIQhe79*Ob++T-0_X&f&kgOR3tv@-Lfl zmt-1v;q9=;fC8SC_tilGf&lNBuK-zJF8C|V0p}P|emr0|%pHOlNPaw^M*JO~7!Uq4 z;6(@r)&cFIpt)uKdfycY2g(7H7)?GKh()j(q#e>295mQ+96lQ$bp!|Q0XA@#a8CX) zB9${@JA&$|SwA+rl$&rqDox*y%m;;Fv3y3tAbLWSM8qIKC!!J3@@2!94=aK?P&fQY z&`<^;@?0?a$ZrC!h(W+|b}{IHE2RHBucUz@k@GA9VRD4NAvy?2@pVg4Uyp%#BQU^S zeH~~3towR?*?R%o83%~+@jyI6?FhyobWoiKv_M`_4KMskb8h~(d7f&F+(m0OOTX9tJ!wIgt!QQ=+lm0Yjs$*zN=>j41X1c z_rKukY|{!h6E1Dg8&5@=MpQ&nM2ts@N0bf?3xy69>2VbT&Bc=s5fjbR-?xUMBt+Ba z&jXBv8VMnH1$IjbVYa$-*opGV_@#rf17ErP1a0?wfw_Vm7zgz8dxMm|L0z%N(DJtd zJ>u>##piuClq{mR59xfpS1Daf%$)KMBKcfzWMg&HLM);fnOGwj5 z`vjh$EP*(i0?PXY4oEUW@Ps(AK?6c;h|YD=5CVK+NXTH(8;Gc?#FuNZA}|4gd~G1T zZLnAHA72-|el1_F&%|mV70a ztIDd^8=O4aWv6s!#+7l;3q_yFlh(L$BXE)* zp6Y2YrL}8}29HQwXcyasn%oD2Nmk&Y?AJ(Oq`QTqBD}Jw3XJeENZn&Vwb(i+letEN zHdgx)v<7erFnmGAAcd(Ms4u8j+B#U*naAgwy)rBNndj$EkFG}TzdxDSp5Kf*j9!ec z@N~~_THH&ATw)2f5)WE$n_({QS0E{&k<1D@uEqV0TYKR}-mmay)}%yIC!>WRWxf+5L|1$+ z?~Aw#*{N9EQ4dh%S%fyq@GaIH<{!_1`HO;kfHRv__^-UmtfKb;G-dH8 z6O&(;UYA(wUX)I8Pm!rBr)$_M?=7^!zi>n;Z+|_XyGXQ={%ukcyq=w-6IEK(Svoji zRiq-TJT8CjQd+EfI$-m_kEP03+rG^i{4f(eFn70bnV6^84D zN%Rzscv>wvCW?*u)o|hH&GdI~56b5|mhp?>xyLZuzL7fu3EKnATrKM~-nL>lh`vgl z_DnU4)R&~WJD_&!wETi!gYCgVtvd9$Ci)=49O<>m@KoAOBaJiAx`5hbfuS1U2Q>ao zoG#FdUIDOhw)ftUL|>_I)aV)a=wdzrdJh|{JSbCW>%%dsPZRbB4BVr~B7~XAWX9G& z8-yYEA12sYxjwAaO%%w{-84xF-xz3f-&52%N5Y55+Re%-;?wBc+fc(s$a0`Ns+x%& zoYg{1h&~MhsmrLuBsOTFXl0C`|f*%-0%b;kJF}d)w5ZH7YG)#--{`6;%DV_j}Kzxn*4NL$M}AKiM3>?@dn2hvXj#jGS%corLL!8XL#}=Irc^Wiu=*;g~}VB$OqKt3WXj1 zQWvm`+2iedUaL4R{h0V7;Z5X2M%Lk9I52=!&Dc$48W`BoXV;O9yDNU+bl^lWoP$h} z&v0SxP?9ZCQh;5O&%svFlOF#IdzAh~aO_Z{@EX;CvzqBgUqHK59%-u7=msk_Q=*1B zwsc|Pb)1N!RSeMtoJI5uV>olX$g##IW+J9}P~vF8U^^^@~_ z5gN!45jsMxMrlqgjeJWOZ$Ski@1$Sx-((yJU%pa9;gd;tN|Yr!QvI znv5No-T(ew&m^11VSJTW5Qc)?&pIl&yt`|{eu5>?G>d9G zam+-KFMvlBFX8$lZpA$(XL!%W>5&9Jr4W?|XH1@bpnL;nt7Fzuz#csh0_PZ&I{OafZ0*T)pIE_ng^h zuLIpyYnNUpZ4Fqb?keqa7W+$^diB%`iLx9VIW_`deR^ zf@EL>w+HBC#ZG+{k6pawMM)YAW-B4(J^c|3ee=Z~YFkp$(5sQ=fW(ntOLuzZhdoY; zB|Ku~^5W)xliHY{nT&t*Zduq~q{=xmU+t}cm+H=aToCDdYGZwiR#n-9<-O!djP3RH zkBUZaSgd9b$RG|(f`hoa-_Nbz5iguY6V!PV&V#R3wdq2IrM`@wdN)k$M`KvXEyn;w zEgWO~u8&Zr`@M#*drYRy9joE(!aWm2uE0A0*Ud4ogq*s3k1YFeAQwB@GA$S`26-H^ zt_CY&KZ8&|o_5~goU-5fl5T6sTKL%dHMl8_+?pF3%Dfw3C2)lk7vf&muF`C`W>I>3KQluK-hK7^Lce*ts`1 zUiN~BP=;(+2a_=omf#jG_%4=#q-S=_!k;~5W;Kt4Oq$ITlul4|AuZEODfT}rgr8Y{ z!cAifbrpdN6?`uQ>YzDArLjmSW=5_KE(A+BcF7HCcw(6;M0| zc>F;$k6F+I_p>+p0lhk(*o)q2U=1Wn&g2Bk(ps)x#fhoI=wdf;{Pm>tT!RfFsWY2S ze=U1rNe8+fb^ev&TH@|NZAvI@$>PeP^L_>n+DZF5Cb_~gW3mlnY^wgd^(ioX#ep{S zS3#_p`L=nHP*tg2H3~^1VJoUG4GX_eEh^i!V-lmNpOi=_J+87b$n;-e`LRj3`QfK; zCLM6|#OX#U3%++is{Ax3_zCo4*J_Q&IKKN87P6URVT(|Nj^ssw7p){T3#DYE*I(*X z6{eNhJ5jECs#M*bxnNk$JyLGFPy}WO+Fus?1i3@DGr^L~WC^%daNLB~v;n+(v;MA5 zaBuSmlNxd@pGn;_n#=-Z-d&iS4Ocvk7~Z+=^z`Txzh~9V;!yg;G_WPX5&$)2LzNFU zTntt&m%psLfJo^Gc-a@Y_sJ6Qk?@=6b~PdOvhbLN-w^f9ON3uI0K*ZofvVn{=|i8<7b86?##@CFue zIE~mhW6R6_n<0T{BcMXOZjB(zxC=eRd#!ZU;{6+q&~GVYEn1I_#n|+2c5)Su`)G2y z4x`_4& zADZ;a?6MOi1`!RI@0Ec}?D8VV5{WSox4kSx)&uTDXtZ7Y%{LQN*3nt3n3iT=dAGEBPqdLfGPDDsfU<8??x?a$N!np(zKUQD)*4 zlYHEFewuXFx$E|-7b0)Id2&~QO4O@Vt&-SrgGOjI*(ZD>h7PqaJdfhwm2%{yl%C-- z!j%TqTa?C$SLC~#6e&j}x33p_F@Z@}_?^^QWb}FIQlyGv%RIR`nmLAs2c^wNM>}rx z;{pjpEKd|K+&KA~t@g+=hAgVEy*0;=Cf$KYKaU$(6u7VUiDH z8VuYCD}2k5ej%~&`9FYBST7Cf$h+%*t6w{%XOUUi80xP{AXi)72PO1Dqu>3Df~m{ zRNq1eff6H{#-S9NRdZ}<7^*ulz|EaIaHb)er0|?o5IFf`yLV@}wGQxtAF(vyucx_g z&VR@0PVjI4Mkb(MmACpvahcaCC9UVkl~^cDBZCNM<=>wHFCl^ZJHxBAFc42>cv$k+ zZ8DFYeg2^GG1Y0=I1IPRP!`?Yk@W6&x4xwrdPeMX&-%LJ83`ZVbr&6F6)lqrBYhha zmFr#Wv$-b1)*8E`$D8<(5-Y<2TW8hi7j9cmZ-;}vo)(Qg^Mc^^#G-tVvO`OG4?ol` z&m<4%^w2QpfOvZ$r(LM23O=n;Fd8jc^!*5!VT7qh;L0tof-0o_%}t9t@FxyWMAYBs z>tzV3HT{bZ2&86e5^}nqe%?e{@B`G@6n-rH9-EqO+)8JHmdFXY*5U*QUYy4`M>Y zzE6&@67fBPqKp`$kf|;)RDj|UDp7J(N}u+x35t9LIo+a|3grVewL+-!Y}?uk5W854 zblsu65hc5Xk_mog!ap*ixeRsU#zUyL;BPj}51g#*sM@h-7n2zr9E*5DT`;KIB~Xb- z$Qv}@$ch413iu3yVSs+n(if5lD(Uo1*FnOATG*vrS`8k}s4y2o6uKtipuT3sm+K$# zaA|!jL0unAYYq2lC@$hy39X5T42GD;GQo9p_^{8vu~z$Wx#}5Gaa3)zaUr;)Sg5tepa^q>-#H^33J$TD0y@f#+$D-duB=bFETjOK-{nK=@D`dX>NH~xJNozmFm zC^G+>bgJ|Gyr#{olOxK-opjb32m4Ki^;K%c*}Al3t+dAU=zw(_8Pg2=?HbB*L*~tR zro(xq#~!cK;U8$q^E9_NqTx~;S|6akKX`jz5RR#WjN&N?DX9hTm>QtRxX{noEB!G~ zwuxFRHpDdtt z@0(5Mw4jnq?vyc%CP7q>Yb2K)1iK%<#MeI46yGK0U8vG}yP6vpky(fh-rBfG8O)~7 zIvy`MD&;^Q8hUN$&TOK*u+p75O<`j($AUMexun9?EF3@?1~~1}RPNqD!4^Mn3=q^4 zy_yE)3bGq^6;xx56i{4)Txiv|eB2ElEHF3ALQZavYmcRN9c)cHA-)~loCNMEj<2CE zW*4VWR)E($HrK1=urH_WZ#ySCTp6`f8{H^yORNxT7zX17o4aoDmCuKBXmI@^w2KC& z>>QEJpr!%$t1$WM%7U%Rb!CwBHCF!t?UlguurriS=A5^@Gimow5R%t@FWc@)&jT_U z6Qh3&Uk*Zt-n6eoYS#D+xm4w8I+~&UH&bO1m(EvFNdZwq<}l^mGlevfyLlo8wO?*Q zhLIG42WHVRh6&=R?#!=>-(<^G#fSt2R$2q><5wb!dPH?ZVBQ%5ZK*RjJ_2HXnmg=#N2#AL^dX z24S@-3c>0PgEI~FIht7H8&6NmPo&IjVz1*4V84k@r3Aya>hPuA> z#EcGG9W`1R1vZHBn_ncaXg{(zxa6n9yt_>&F$xTq$Y7YkR%gX7?4S;fPF{&m&B)_; z{AyJFDnh;(7q1PKsu+wHTXUU(Ge$Q0ERN-Z!xjQ!L-P_MvAfd8EmIiNm8LZAU{xva z_&D(kWT~xx5|^_#MFD~=G2@8k5EVq5f(rGS8LpN>K3&dAB8;1BKC8A_B$2ot)kIb! zhaPy$xDPC~Ah9n`Try#>QJ`tMjN^OOP=;zLvABfoN#mVxi3bBMC+B{`V%*5O{c^Ib7JX^o z$e!HJ2rx%TGsc0Z)I*>ZbXjfbVDIyQ(HXpgB)Xl8Ya&K+Wy>FQZ!wV=5AqEOKeRgq zU#DJ(#$DO^e60nAwwh9Ev3=KVxY?v)^f3eR^vS7(xKl}^VfZsRJIik_F7Cmwi${(g zA~2oCHIERYv6K0b`}C9VrdKq0G9|w>@s~jjdPqX>@=;YZ%&Q~DN1WJ%5Qu2nmDaYg zR5-_)VF}oZbk1wvn5n>;nMJVwfIo zrp9U{#4G)cQ7tovoDax zzZo(uo}!qAhCRt4iu<<=w=#Q)>Abgbt)-rJ*l)r0WZ6O4Y~9du{zEwjgUuZU3q(sw zCyJ=tBSeg2KGBG@!sUGQP@rB%;D#XuH$Baa{2y&GHupjUSZ5n4UyIMK;b%^BSO!6@W;v=^OnP{MXE zrxL5Gnwm_fUGm#K-OfspLTOt1u@?a6hzsN!5yrTa=hKqyFO??K{=( zSk*no8rG~jwuRlC6La7XQ%!#Sp^N*t#EtQEVjo(zvPMou2B|6oR)|pXFL+Ebi&lQT z1uIxCnSa>yK|{@e)0LG#?H&^Bkt8F2Rc?u9BpT&&IE=t~#WNI`Sezf3WXKc6`{tDG z_JZ3qh$j))B^w+4SW-fMcRQHeb{UgO#;GkEGl*a?-(tp}3`gMFi2sSv70=~Lfc5e! z!sZSWSNX^en^bl;c6{c03bj!QdDkUl51xQoK4!wSIYlD0}x+@b=o zt)X*a-J#}$4?N>Lc`EeEp1R`g4M*h3k}375qqEgv^VSqqoduIhwDwHb$W-T2a!ZlPEeHi>4gd5(RMBkSG1 zEQR=&+a*fu#gxF)!&^EF=Q$coWaP!4vvxyk$N&q)n7uO@*<>t@4RG-@#1-XDDh3Xz zJ&!k7qPUr4ox3f=9MiFr_cLkPvLgN0EcWgC^4gsDn@jZuTJDD0ZSHFp8tR`)2AyLL zJ+SC1T~yZ{vz0cqSlz2_{W1;?3N1s0jZu2tYG=EA;o9K)1sSum3a(MxE2lO;+)*y! zde^o(q!If7ZN2QRNn>kW5)zyF2E`H4xY1G2Q6@GJ#*>rnz!{qZ7k^ZGC0kXNLrEuv%5^Kc@9A@O#5v7G4Xs>*hj%BJu zm5Mqwfglvhnwj9KV%U~boV`SoJsMe>qVd6s`#j$UHMF-d95m!nqp9A? z9y$hP_C^Dk7^XV~*oLy)3CC@7I;s1i2->oV;%->}u=P@k8ZRoYX>gEnyST(KRI$zK zrUCaeBzF%@!A=i*I@YcF{BE1+orl(}Bed5})Fw#}9c!DBXMnK;`;cthcP{%-MWOJ zM1Y2~9|@;AiR=j4)QU5~rdszD`!vH8g+si;smk|oPVUK6GrC3ac+*-&C*MAgk zA3C!CqbO6DlHb8x-%48PZw1+ZL~t_6;`EX**>AIGd8T07=K z82yn(hZ=Ox6_h;P`wha1frub)Qi;fT5})}L6p;=|K@gE3qQ$G-alcR*V|~l6^3(%< zWAys$+6G&-;jt~f*-K-UPUba^X8(AK#6_&%e(0*}*07KXbMr#OA&c|0r``O)shM}x@VD>1 z`mUDL|5syQ0oK-&evMP0NO5#uuXmp>U*2Gr`0?Fz% z@c}k!E98)t#0W#etYq-kOz~qz_3COi zcAJw zl*$&i9T_%UlRPZA@fJ2XJUweul4&@tVbWlN?5g>U83S`$tP}cpM4ELqQWC0D`uPP) zJ#G<_V2-VnpA|cq8P{e?&A})5W6XIlY8{Bj49IvV^tdWlr-n)#5gOT*T3671uwMsz z80e%kVSk>{CukoLo-)LHA-(E`s>qY!-%F*m<{1$s#8HYADsr z2#tN|!vGqV__efkAwFgxbOSE^TmEpo@@6;j+8faUb-fXBTHJf#uZN_U8fy;o# zM4r&94NlA6?Ji^tONRlzx}ml4>&ofgE6|E%^J$`Yd7nCACHTZ&F(T$KR#4 z&v$eFDYXT68DJUhpHf>nQ$rI=J9BWS@R#iNS=9TN?3SG!ET#WbcKfUHUkc!V%5ML0 z>*?QQw}0=I|B&4RIa&Ww-Ey$9{ST_!8ck0fRY_3phihs`Ofn&K9W)Wr{BkuBbR6sj z7;zXK&E;3(Cdy*Un9K9R%OyYFI>3r!ZbHeZy=fwEwwh8ev8bwr*d#4wTf`b+i$-|m=hcB%k;M*eKLI4u(u5DV`yz2?N(#O|!YV=LP?Bz~URP~p&K zi*SEkBL#vp+W8Q&TLFPCimiQT>V@INHmsxWgqC94la`E)1dcDvMSTCy`DE_F%TB_* zWsirao0vd#+(@{UP;xkd)IAKb<0(P7+C7dZv(coAAT_qvd}|pOKo&mwr`{65P74Hk zEcZ7DyKl*pUZiLG%_H5zteOy>wTcnV5{)tnYxNKMclF&kMB%~Ngcit@qTlw}^XE86 zDe=Bk#7zKr^`^s6U`o8^t7CgFiR1xN;$ucnIcJ!1djw#@pR;-hgo@G<`bqY_2;2y( zD-gluuCImIaend}@L%SjTsA?$?O-D;s|C}$MH4=_JVOOm^Are1{3gfOR!M~&x) z6rjPS9kHFv+>L2c%9>ng^aUCAENPObtu+?@4C1NTfjKQs>D6H~JR81mu#)?LB(EWp zc(22!-iJpE0DkNY?a=zPvQ&gmJjt2lRy-%75Jdv~nK&Xl)CV$V%*fFE_p~su4L!pD>Z*O!rzp`?q4 zu!j?Hhm}w%Mcm-bqt+`0rMANQl=&88yTtvCG_s?kPVEK*GkPdl57H${gON?s8nJA6 z%_lxMuj=4m(}9LMzaeAm1`t``Ti{#qOtbg0&$54ZsoAHPE-U3><7F#Z@MtVCyB}l9 z>^!0te~Bzh>?5QKiK|SD#nX=iC;FXmKB_%|uUH&qS={Pa=8WizFk?Q83N02nL06A> ziAtUwLYxyxsgd?u?AnyDtLPjk2H#VyNrrdiq0K7vXQp=>jb#eT_?IVY5bWy+CCY1G zze2ey?<$S~R&~8JLa=Z(Y$&JrJ-c1zdm7z_&=_w>+GI>c1oZP^N)aWhPCI!Wm#*_( z@33|@9>&41q(fRmigH0#A4SDCO3`cd%cRKclcjOvo2a!#30rkRJaPvrj7w!-AN%;4 zNSa;Q>6kx&jz0Rsk=VV?TWqZy0kQqq9ATK)Olmn~YU#Q>imKcjIfq9y4pTxV=k?zn z=;=pxQH}b9=uQD0c-Q~UTQ507=;fN!4sG1bd>VC4C6j&uuC?*3?bO200Z%F*{(jUJ z9%tgFxw$>%#If%80qz!FL!t~0<(&{T3Rjy+^e+_|id@>86YNaC70*&kAfV5{= zxvxMf5ll;JWO233MywbRN+6uKLb!>7TU%8PU2XI2``lY~f9lun)8aM_9xEiEOOIyL z(?y1Fyw-g_17r4|hY~BcCze3KS-#S*@1Rg$&3{HIBsL6OhOJg)tcCinKJ$}RlCtSd zzg)EK<9m|4*||j&+#Jk(UQ6sPZ@*fJ?u)8rn(h7E!d*36FW31yM@#q-wlobV3@=I) z6r#h2gQB*KZ9(@){h9$XE+h>dp0DNBS?YMsZpT;Ot-hCO)+eUBr!R&Nl9Igl36wK6 zEr~T%Oo`VZqmSYN-rK$cDXXc-REJ+3_S64_(qEEyEr*7>&0bE&m_sXj9nBN21}rTR zcgHnK6-JT@$xi_x(qh0)Nz5jWrVy*YVUBp)dnOJvdiU|IX~~5_wn;1@MZ^0|OcVtx z*u05h!kla!gXTp<=@sq>O%qE%dlcd8LWgU!mt;%98<9Svn!2B9YqhGjiLHrx`W^GN2#&3L&Q{SxQ)krBdR|@<7qy7RzZOA-V;6I5L#xU> zEib}%y6a<9@!#fY`S^r(t#@@^$~^451EZA3Oe1M81^4xJPh;(ZQ5xM zv8}&>!_|R3TNFttK>w&Z192E1PBq8sh6c?|iP2|EkuE)&zRAFuw$?`QoyXE zM-n+Xl&{y+GcR_jCGX|VY?!Wo%YAN6<8+%#0~+cuBi^EXzM?tScT-`6TlTKcE&{uE z4y#JTGsngn`@+46e#yk_rjQsNc;Tk;!Y~D|6NbtBy#kmk7z|$>aDQZaf9Eqq!0j66M(EOBWO!ZT! z;7?Y#RAubB^Wv3*Ez}|ZuYOFGUMBi0&a>NnBhVir4jgm0#~5wG#$yf5JJ zk2%a#A0#2axz)GEOVqqUD1I8&EfBF7>Z@(^34F|7hn>!@EI;7X(Ka0g zre%BFm^~i3?xvAso}V;M=pS-5ksnCSo<&nkb&_YVm@BI1X-4rcwHWI(_%<`0)@kEO zE$Q1)*k?UqhFS9nqC#E?hNSEDdxswr>g{=usy;B>jM|gLT`yy+2|HDTwqxOO zNmR7%2f1BASe!Oht`Tk#5uo#q`4weV7$kqR23nj?LVf<&gVJWA?G=OlVNG?4JlKb; zG9s7XZQMaYkH>DXdhhQ0v=@$<;#u@Y3H-%UdS-O=NlwW4N@i zr`OV0gM%!a{8RC|co_F>%lDocrEBo5hjNcUG1ta9FL#BPAWo{0CRxH_(a?mE3q^X_ zLv}t7B6BIZT#{j%cj+uC=*`YzZi8laux0>r^QI5zXJTt-tOVDeb~v-_SGyK{g1z1c zjBOPQfku=v*0iAj0R;v7mOk zGCZxvG>gr~VF%5JfvF7RHRGH=rgcW3f$}}VH*qD9xt5v1y5}REySH)~KaO@ejoRh) z74%vF9yf+*q@i` zk18Ciepzy!T1sTtC3m00=J=4Oe$y2@nbhhvwghwlWlkq0{WxZMn z#3pv{N~%xYpMh@ZaMS#It4oxq zF=7k}ak=#z-GsbW)}A#SR;UD-+?QzmgbMmEtXiR*Qq&#ZVPz|lGQ+3<6xHog6m(PE z5-Vut{jr@Pl)lyI#ZgF8^>5l82KbTfUdYDldBd9#agCzT z-pc8^5Q=!O_KFR}%*9qO*mZx`nELJt=M0~RPVwy)kr0LIIs#QFeTbKh$4vjCo@H8^*_&U;2@5Q$F$jesPkIFuw*Fy*uE2+<=r}0fO*f_h; zuZ?{X2H39WzcStop2OJ^?(WP|O@G;R$*`-p(8eCb9dz0gsQumeNM|vEQO_TsDo9*C zJ-Zv=TD?v=ciUAI%q>PudhZe6kpP03HPV=ci@@gmKgoJ<$OkmH5j z8L+g8f|kO#{lPw!Aj$=o$NMx6D!!T7YH8$aJl|!M8l84?T4^ZgeR+MqMU;B{m16o} z_H!42&5}pUcO_(Ga<(Ag<+^`(7+pXIWCxJTUlh|w8Z}fMraz+)Dd1alyqg96oWtUQ z6*BPX0O&Q9aCJt?wC=KKYooSY-@Tzge*sf#zLLRDATw(1e1>|ym|h&wl7L*|yc17z z{M~=NHb{gp6xFEgNBfDWzMz1H`#1P{s5d-U$YR~F27)sT2dMIynlLPk&A@zEKo~Bp z`_v{C!@#{;GWG3E$UufJw`6fs+-{3WD8ggREtB7bflTPcdvDNQzXcZII>i9xiQj5kDc zfKRtc&E4-HdIGeR44~lpU?*_e3q7pMMFh~S0zH1(t0?){j#baTPS=<7_T)+~pBIyw z{bapJDO^WDjEKEBv>Zd^$iQ@tzM1eXo~R~$jH%koa7%pdk+sjhQi*Hv1_TLN)hNk7&60+q9~X&=zI zkv*VmP>WF&WU~O&K$nl8DThNnPfJse8;xD5{S(CDb~@G6m>3<4NRqn#)Q#MtBCC6Y z);o@c0y|Gt;EaKP+0D#{jaAiNxzI14zy^3DJ5b1eOXXxcF$Ra;HvUJ@b6VH&i@0}$ zSIEb&jqB+<%pHaO@f}`dI=WHJ*&WMD!H0wLZ)-!0DI`@B~#r?ifJiLpk>Dbe4&nOVOq@vPqdTRDH1`X1&}G`5_vL9u&SqvmpN@ z>@o+V*fkWA*qrw#G<;*`lnDOL^|z}rrOXF;?7E#^y9!7tZB^C~5jiitu%U^?o<!W|mP8YAW0zm#S@3DRb7 z9nY8>riYMYuzQrj9akRZ3%?I&k61C`f~}@-zr`@* zms-U_b?Foyx%N&?bqn|$6Xb`MT97`G6PUA7p-6_^vo~otvKJ*2ZtPW<@L@A-VpYKE zA<`qk{X9XE5RC#Q@5ps>tOF-E&~ zYA+3<~uNHp5o-2n>B4csf;|3kdt75 zZP#)pJk86SIqQpPYuFLY=C`pv&5hvy$p#4A4xc_bt_`f=TNHPe6Ek3|TCC@wj z#rq!g8X(8Seb;{Q{NJAC1mY$vW63$B*T9gnBfU{E$Dun#q|@j{(#Sg zz6s(^enI^Y%Niy6#y@-Ue4%=ip`whteu#cn0pteME0%B;S_Eupmy6 zt8Wvtjc>|}mnKW@(7_b7f70RwM0+>bCcmZ-W3YPM$87RBRU57r`yjs}%J>$ME3QuM z6WVC7s~@Bty94^aU&vo){g3nXKk@N@UBCap#y`(zF|u-Ufc+M^o{cY90J{H`jen-Q z|1!P+r~i$O2R{3`{K>}u)A$0B9qi-s7X$xn!txgb4|dvkrq97`>K_a|c;@Z7@%+WW z{|fx^N&jHrIoO`(DgW6%*jPCK2L?VyQ`-g;geSn}eY*HDv{`=4^d;Nqsa?Q(7P55% z(V@-D#d!q-+d9L+(E6>*n1Eo%wi2NOA*snX(iGxW``-#G?<7dRBvv+@Pf{oBWtDWi zITEds@vWe5_AQ@@B2V1E&cn-+O)BS2bABAXeL8>IeR^^>V;tG*NzDma*bZLYv2| zp&wlXjr;EPQ<$R~r{EKoF-Hdci2oy`myo9IOtrgJT3Pqc=(0SUERbSTXI)&g=iQ!y zVyipTfqGOKiT&k;an0ym`2PNj^d-)joa&D*B&V zDv}I&c=->`+-H_u_K%Nx**BJ57xVMybyc}LD^A#6UewMs_|bmbUjQqeVU4u}Ej;ed z2k-A7i{#h3P4$kKH}{F!%Z{gUE_Q(v2S-`_zQ;SJzKYWgk2XnV$9C;if{oUCYYS%` ztBb64$McU3xuLZ?@{5BQKGy1M_=`=aVph}V?T!#czN1ZDruU(P7+D~1FV&(lYi~}s zSX&GGL&BwGMkRm#%e=+5Zb!4Gf+D}-S_*Czdzz!g*a4|xQ6hvb>3QoVQ1k$=l|&^^ zA%*oJKCczq$94)JIuwUlm0RMwhK2Bk;*QUeJ3U4zVA~<1cPs_V*!zZF=J1l@7cB-9 zMaJsl%B#)xo#!Y^%N(Su1T8<_;kLVpt2qa&QxSTBei%`+$@4u@eT1~h9HGDw&9ieD zMTrrSjFq6cuL?lLh>G(cf*XUw-Y<-r_3l1>B)ns&G9J6XA36Vo+R-gO*XTuJ2AU_Z z!3LQE1EcQN44enn9ewB2>vp>R`U$CSJTH&;`upJmTU~Z;Ms8*{Z5(fjDsvtm3(!jY zb6gB&7(9|>T*t+xkpJ4oYObwULutEs#elUFAE(yzVjn$+qsvweV`TV_Sc+I=QE8xf zvkJ7RdY86riA_wIn0m;xr&l&YYllcZ8B`Gfn;b6mwr9QEbbBR{5LWJ#WvJ|!A|es{ zA|#XHZQ*AaJr$oejXr~m-hRdSd-b7ZwCeSC3@mIJQ91Q0+6Iha-=$D0AkG%GqN6o> zAw5f~6qYRa1v&%&r@eP@#w^2wr^#{W;#7MvZ~JKF7s7hSXPV-#Pso=>>uw$r0VAPg zg_Z((^~=dhGCD}>WJtuSgyZt3$%ac&tDofu##Q4>8fp`>JkMvgX=t?42by*^s3 zsA6$wh*Yu%n=#@=n^IwCsD3A>e2)uL4+#tY^$;WNXG=FaA5sm(Z_GUAL(RXKucDpk+}0V$&qyW7)*kHMmt+dRUG6_A>I^{AH44e%;MT;bi zaFPAZi_D&&1m%NZm|!2U1QqAut@at#W%w{j=w<#p*fEV{3NwTPeh5JF7lIeo2}CX7 zt;J+Jsx2!kiy~8|nm#I9Zl)_d?o9g9)Xva$D1ot>Ns#J}g&B$aZ-Yc)p<-xwU$qpt z=x1Cf_w*$I+wKGCN!VnJI!p?!DZO>#V;V%4tKS!fe#N57R!3&2&6dhmkO%M<$d^8n^eKCezZD~8=MyhS{fugTNwkkvmr@=ZHD(MW% zZ6L%JI=r{Y%r%N%KVI1(+H#J_>PN^3cX!pVwb4TawL?7L(7Dc9OzdoX zF_-z=qY*Gs(~%~Sofiouq-7mvoG>tag8KUxst#%Y%_thmvRHjwrdhh86MR>u5K^_t=i-$4) zp4LQDcrK>SBq&^s8rquv-N)evOiq|UCNhXNU6uzfu13VGfM|mkW$t(H$@}mk`5375 zrUtaKHb0p=4)nEc;7hL#?^A76A^N_$GIT8OiI=a#5utU~w!Nq8VgaJE~h?5V=nb5cQD|WAmL^&t?0-79mdQ z8_Gua`O2XED=)hsZr*m~peY>g;M6!2yU2>|MD$Zt4;vGtpGqc$N05 z?U*l~s^tgQfl^4tFAMzg=?w~oJQG|+O+lcx@fL;-fzld6WYu`(Lsr0ByFwJQ%GET|~L!!eK5L7m=qr z0bvl8;lfCY(ND7+Lc{xK?npB3nxs6(nuc-;{TuHYgWPKQ{K=2szQVK!*vy=;E|n4G z7oq)w1n+O>!*KUr6=e>V9FGWe8do>TYrW3pZ`!$xk#{dDFkyS93G`<%Do(w_I?=Z}baDejV6D}-c z`gP(i3m0JhN*De~Bscmz;59~Y$W+^CX^b8!Kb6DfB!-C!-_X|q3^hTt<2uXBEwL{8 zXrNaYeL{X@VviwLwRk>@G37?B!Uq>TO{n>!YFf370LWJvAsIQf1iO!^eHA~MHy}o~ zHxd`hzr;}txW4W@7_{onM)ywaR!7O-{!9<5ZK0%+3d_t6-`)Ee1dBQQCd|#qw{ES> zLG;bg)&Rv)ftWJAK)bXZ>0193E>v7z(x+%#jh{d&)kU0Z$`%XVF!Zw-UoHwd%%%jn zNa7eB8e_0M`In3q|Lt~#_l}~aGsx2bg{|xqRfoksiHNR1D~KPO64=~0@VV0{EoL)h zmAqGQ*(ITSF44>ox$Mc%hXGGo0}tT@gT!bG+VD*%1Z!APtNNMcdc7ReH)JZCj2qW%lm`aTUQes zg%9N4Q@B3W6%S!;;`$SXy(7d4b%dgNHMB~-mRmI^ke|pB1ys$ei=ja6Zf9p_p)})(o%NXn=VMa$s_yk`Ju}^hyI9?c z>^j-m67aP64@-YH_bt_f!h|=vGQ&-Rpw%vS#ZdbgflnH=YEu?!dyhB-S?)(xcB`HD zQKALGr~=B={rA`IEvQ5cxtaIF1e|`FL;S5Ag!@m2IQ}-)c6LR(k{gP|KdtxVtYz)* zAB)sC?vAX@5iz{S0z27V8{P}lt1Nni`*rRVd_daOGd}FLBKD2?4}-P88+3x5@=aWg z!7FFcK0fJywNJLsVE7Ei&!G4Ws?R_Q26i0)E9>)Lj%N^h2H|JmdWK)A&shMLXLwEl zFg*k3pQT^1Unx4Y;NYK!lYQP0dakHD48XB6hv4NWzixJQW+~7=%jR0I6>_!{_6K-Px#Q!_xA1s!$i=mUtuhs^Z PFmtdYQc;O3N+A9}@+;k5 literal 0 HcmV?d00001 diff --git a/index.html b/index.html index 4641178..b7d0127 100644 --- a/index.html +++ b/index.html @@ -287,7 +287,7 @@ class="text-[9px] font-mono text-gray-500 block uppercase tracking-widest">Цена: 870 ₽ - Записаться Цена: 2 790 ₽ - Записаться Цена: 4 990 ₽ - Записаться Цена: 3 290 ₽ - Записаться Цена: 5 990 ₽ - Записаться =3.0.0 +requests>=2.31.0 +openpyxl>=3.1.2 diff --git a/server.py b/server.py new file mode 100644 index 0000000..c6546d0 --- /dev/null +++ b/server.py @@ -0,0 +1,1392 @@ +import sys +import subprocess +import os + +# Auto-install dependencies if missing +for package in ["flask", "requests", "openpyxl"]: + try: + __import__(package) + except ImportError: + print(f"Пакет '{package}' не найден. Устанавливаем...") + try: + subprocess.check_call([sys.executable, "-m", "pip", "install", package]) + print(f"Пакет '{package}' успешно установлен!") + except Exception as e: + print(f"Ошибка при автоматической установке '{package}': {e}") + sys.exit(1) + +import json +import uuid +import smtplib +import requests +from requests.auth import HTTPBasicAuth +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from datetime import datetime +import ipaddress + +# YooKassa official IP address ranges for webhook callbacks +YOOKASSA_ALLOWED_NETWORKS = [ + ipaddress.ip_network("185.71.76.0/27"), + ipaddress.ip_network("185.71.77.0/27"), + ipaddress.ip_network("77.75.153.0/25"), + ipaddress.ip_network("77.75.154.128/25"), + ipaddress.ip_network("77.75.156.11/32"), + ipaddress.ip_network("77.75.156.35/32"), + ipaddress.ip_network("2a02:5180::/32"), + ipaddress.ip_network("2a02:5180:0:1509::/64"), + ipaddress.ip_network("2a02:5180:0:2655::/64"), + ipaddress.ip_network("2a02:5180:0:1533::/64"), + ipaddress.ip_network("2a02:5180:0:2669::/64"), +] + +def is_yookassa_ip(ip_str: str) -> bool: + """Check if the provided IP address belongs to YooKassa's official subnets.""" + try: + ip = ipaddress.ip_address(ip_str) + return any(ip in net for net in YOOKASSA_ALLOWED_NETWORKS) + except ValueError: + return False + +import openpyxl +from openpyxl import Workbook, load_workbook +from openpyxl.styles import Font, Alignment, PatternFill +from flask import Flask, request, jsonify, redirect, url_for, session, render_template_string + +# Import local modules +import config +from database import DatabaseManager + +# Get root directory +ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) + +# Initialize SQLite database +db_path = os.path.join(ROOT_DIR, "bot_database.db") +db = DatabaseManager(db_path=db_path) + +# Initialize Flask +# static_folder points to the root directory to serve the whole site! +app = Flask(__name__, static_folder=ROOT_DIR, static_url_path='') +app.secret_key = os.getenv("FLASK_SECRET_KEY", "ikp_stable_admin_session_key_secret_2026") + +# Path to the Excel spreadsheet in the form directory +FILE_NAME = os.path.join(ROOT_DIR, "form", "registration_for_training.xlsx") + +def init_excel(): + """Create the Excel file with styled headers if it doesn't exist.""" + recreate = False + if os.path.exists(FILE_NAME): + try: + wb = load_workbook(FILE_NAME) + ws = wb.active + # Recreate if it does not have the 'id_user' column as the first header + if ws.cell(row=1, column=1).value != "id_user": + recreate = True + except Exception: + recreate = True + + if recreate: + try: + os.remove(FILE_NAME) + print("Обнаружена старая структура Excel файла. Пересоздаём с новыми колонками...") + except Exception as e: + print(f"Не удалось удалить старый Excel файл: {e}") + + if not os.path.exists(FILE_NAME): + # Ensure form directory exists + os.makedirs(os.path.dirname(FILE_NAME), exist_ok=True) + + wb = Workbook() + ws = wb.active + ws.title = "Заявки на обучение" + + headers = [ + "id_user", + "Имя", + "Номер телефона", + "E-mail", + "Ссылка на профиль ВКонтакте", + "Согласие с офертой", + "Согласие с политикой", + "Согласие на рассылку", + "Услуга", + "Сумма", + "Статус оплаты", + "ID платежа YooKassa", + "Дата регистрации", + "Дата оплаты" + ] + + ws.append(headers) + + # Style header cells + header_font = Font(name="Calibri", size=11, bold=True, color="FFFFFF") + header_fill = PatternFill(start_color="1F4E78", end_color="1F4E78", fill_type="solid") + header_align = Alignment(horizontal="center", vertical="center") + + for col_num, header in enumerate(headers, 1): + cell = ws.cell(row=1, column=col_num) + cell.font = header_font + cell.fill = header_fill + cell.alignment = header_align + + column_widths = [15, 20, 25, 25, 30, 15, 15, 15, 25, 15, 15, 30, 22, 22] + for i, width in enumerate(column_widths, 1): + ws.column_dimensions[openpyxl.utils.get_column_letter(i)].width = width + + wb.save(FILE_NAME) + print(f"Создан новый файл Excel с поддержкой платежей: {FILE_NAME}") + +def get_next_user_id(ws): + """Generate the next unique user ID in the format id_001, id_002...""" + max_row = ws.max_row + if max_row <= 1: + return "id_001" + + last_id_val = ws.cell(row=max_row, column=1).value + if not last_id_val or not str(last_id_val).startswith("id_"): + return f"id_{(max_row - 1):03d}" + + try: + numeric_part = int(str(last_id_val).split("_")[1]) + next_num = numeric_part + 1 + return f"id_{next_num:03d}" + except (IndexError, ValueError): + return f"id_{max_row:03d}" + +def add_registration_to_excel(reg_id, data): + """Append a new form submission row into the Excel sheet.""" + init_excel() + + try: + wb = load_workbook(FILE_NAME) + ws = wb.active + except Exception as e: + print(f"Ошибка загрузки Excel файла, пересоздаём: {e}") + init_excel() + wb = load_workbook(FILE_NAME) + ws = wb.active + + current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + row = [ + reg_id, + data.get("name", "").strip(), + data.get("phone", "").strip(), + data.get("email", "").strip(), + data.get("vk", "").strip(), + "Да" if data.get("agreeOferta") else "Нет", + "Да" if data.get("agreePolicy") else "Нет", + "Да" if data.get("agreeNewsletter") else "Нет", + data.get("serviceName", "Разовая тренировка").strip(), + float(data.get("servicePrice", 870)), + "Не оплачено", + data.get("yookassaPaymentId", ""), + current_time, + "" + ] + + ws.append(row) + + new_row_index = ws.max_row + data_align_left = Alignment(horizontal="left", vertical="center") + data_align_center = Alignment(horizontal="center", vertical="center") + + for col_idx in range(1, len(row) + 1): + cell = ws.cell(row=new_row_index, column=col_idx) + if col_idx in [2, 4, 5, 9]: + cell.alignment = data_align_left + else: + cell.alignment = data_align_center + + wb.save(FILE_NAME) + +def update_excel_payment_status(reg_id, status="Оплачено", paid_at=""): + """Update payment status in the Excel file for a specific registration ID.""" + init_excel() + if not os.path.exists(FILE_NAME): + return + + try: + wb = load_workbook(FILE_NAME) + ws = wb.active + + found = False + for r in range(2, ws.max_row + 1): + if str(ws.cell(row=r, column=1).value) == str(reg_id): + ws.cell(row=r, column=11).value = status # Col 11: Статус оплаты + ws.cell(row=r, column=14).value = paid_at # Col 14: Дата оплаты + found = True + break + + if found: + wb.save(FILE_NAME) + print(f"Статус оплаты заказа {reg_id} успешно обновлен в Excel на '{status}'") + except Exception as e: + print(f"Ошибка при обновлении статуса оплаты в Excel: {e}") + +# ==================================================== +# YooKassa REST API Functions +# ==================================================== +def create_yookassa_payment(reg_id, amount, description, return_url, customer_email=None, customer_phone=None, customer_name=None): + shop_id = config.YOOKASSA_SHOP_ID + secret_key = config.YOOKASSA_SECRET_KEY + + if not shop_id or not secret_key: + print("[YOOKASSA] Создание платежа пропущено: логин/пароль ЮKassa не настроены в .env") + return None + + url = "https://api.yookassa.ru/v3/payments" + headers = { + "Idempotence-Key": str(uuid.uuid4()), + "Content-Type": "application/json" + } + payload = { + "amount": { + "value": f"{amount:.2f}", + "currency": "RUB" + }, + "capture": True, + "confirmation": { + "type": "redirect", + "return_url": return_url + }, + "description": description[:128], + "metadata": { + "registration_id": reg_id + } + } + + # Add 54-FZ compliant receipt if customer contact is available + if customer_email or customer_phone: + clean_phone = None + if customer_phone: + clean_phone = "".join(filter(str.isdigit, customer_phone)) + if clean_phone.startswith("8") and len(clean_phone) == 11: + clean_phone = "7" + clean_phone[1:] + + customer = {} + if customer_name: + customer["full_name"] = customer_name[:256] + if customer_email: + customer["email"] = customer_email + if clean_phone: + customer["phone"] = clean_phone + + payload["receipt"] = { + "customer": customer, + "tax_system_code": config.TAX_SYSTEM_CODE, + "items": [ + { + "description": description[:128], + "quantity": "1.00", + "amount": { + "value": f"{amount:.2f}", + "currency": "RUB" + }, + "vat_code": 1, # "Без НДС" (no VAT) + "payment_mode": "full_payment", + "payment_subject": "service", + "agent_type": "bank_paying_agent", + "supplier_info": { + "phone": config.SUPPLIER_PHONE, + "name": config.SUPPLIER_NAME, + "inn": config.SUPPLIER_INN + } + } + ] + } + + try: + response = requests.post(url, json=payload, headers=headers, auth=HTTPBasicAuth(shop_id, secret_key), timeout=15) + if response.status_code == 200: + res_data = response.json() + payment_id = res_data.get("id") + confirmation_url = res_data.get("confirmation", {}).get("confirmation_url") + return {"payment_id": payment_id, "confirmation_url": confirmation_url} + else: + print(f"[YOOKASSA] Ошибка API ({response.status_code}): {response.text}") + return None + except Exception as e: + print(f"[YOOKASSA] Исключение при вызове API ЮKassa: {e}") + return None + +def check_yookassa_payment_status(payment_id): + """Retrieve payment status directly from YooKassa API.""" + shop_id = config.YOOKASSA_SHOP_ID + secret_key = config.YOOKASSA_SECRET_KEY + + if not shop_id or not secret_key or not payment_id: + return None + + url = f"https://api.yookassa.ru/v3/payments/{payment_id}" + try: + response = requests.get(url, auth=HTTPBasicAuth(shop_id, secret_key), timeout=15) + if response.status_code == 200: + res_data = response.json() + return res_data.get("status") # succeeded, pending, canceled + else: + print(f"[YOOKASSA] Ошибка проверки платежа {payment_id}: {response.text}") + return None + except Exception as e: + print(f"[YOOKASSA] Исключение при проверке платежа: {e}") + return None + +# ==================================================== +# Notifications Logic +# ==================================================== +try: + import vk_api + from vk_api.utils import get_random_id +except ImportError: + vk_api = None + +def send_vk_operator_notification(reg_id, data, paid=False): + """Send VK chat alert to operators about registrations.""" + if not vk_api: + return + + token = getattr(config, "VK_TOKEN", "") + operator_id = getattr(config, "OPERATOR_PEER_ID", 0) + + if not token or token == "your_vk_community_token_here" or not operator_id: + return + + try: + vk_session = vk_api.VkApi(token=token) + vk = vk_session.get_api() + + status_emoji = "✅ [ОПЛАЧЕНО]" if paid else "⏳ [ОЖИДАЕТ ОПЛАТЫ]" + + message = ( + f"🌐 **Новая активность на сайте ИКП!**\n\n" + f"Статус: {status_emoji}\n" + f"🆔 ID заявки: {reg_id}\n" + f"👤 Имя: {data.get('name', '').strip()}\n" + f"📞 Телефон: {data.get('phone', '').strip()}\n" + f"✉️ E-mail: {data.get('email', '').strip()}\n" + f"🌐 Профиль VK: {data.get('vk', '').strip()}\n" + f"🏆 Услуга: {data.get('serviceName', '').strip()}\n" + f"💰 Сумма: {data.get('servicePrice', '')} ₽\n\n" + f"⚖️ Согласия пользователя:\n" + f"• Оферта: {'Да' if data.get('agreeOferta') else 'Нет'}\n" + f"• Политика ПД: {'Да' if data.get('agreePolicy') else 'Нет'}\n" + f"• Рассылка: {'Да' if data.get('agreeNewsletter') else 'Нет'}\n" + ) + + vk.messages.send( + peer_id=operator_id, + message=message, + random_id=get_random_id() + ) + print(f"[VK NOTIFICATION] Отправлено уведомление оператору (ID: {operator_id}) для {reg_id}.") + except Exception as e: + print(f"[VK NOTIFICATION] Ошибка при отправке уведомления в VK: {e}") + +def send_email_notification(reg_id, data, paid=False): + """Send SMTP email notification.""" + smtp_server = config.SMTP_SERVER + smtp_port = config.SMTP_PORT + smtp_user = config.SMTP_USER + smtp_password = config.SMTP_PASSWORD + smtp_from = config.SMTP_FROM or smtp_user + smtp_to = config.SMTP_TO or smtp_user + + if not smtp_server or not smtp_user or not smtp_password: + print("[SMTP] Пропущено: параметры SMTP не заполнены в .env") + return False + + status_str = "УСПЕШНО ОПЛАЧЕН" if paid else "СОЗДАН (ОЖИДАЕТ ОПЛАТЫ)" + subject = f"Новый заказ на сайте ИКП #{reg_id} - {status_str}" + + html_content = f""" + + +
+
+

ИКП — Детали заказа

+
+ +

Здравствуйте!

+

На сайте зарегистрирована заявка с новым статусом:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID заявки:{reg_id}
Статус заказа: + + {status_str} + +
Выбранная услуга:{data.get('serviceName')}
Сумма платежа:{data.get('servicePrice')} ₽
Имя клиента:{data.get('name')}
Номер телефона:{data.get('phone')}
E-mail:{data.get('email')}
Профиль VK:{data.get('vk')}
Дата регистрации:{datetime.now().strftime("%d.%m.%Y %H:%M:%S")}
+ +
+ Это автоматическое системное уведомление от ИКП. +
+
+ + + """ + + try: + msg = MIMEMultipart('alternative') + msg['Subject'] = subject + msg['From'] = smtp_from + msg['To'] = smtp_to + msg.attach(MIMEText(html_content, 'html', 'utf-8')) + + if smtp_port == 465: + server = smtplib.SMTP_SSL(smtp_server, smtp_port) + else: + server = smtplib.SMTP(smtp_server, smtp_port) + server.starttls() + + server.login(smtp_user, smtp_password) + server.sendmail(smtp_from, [smtp_to], msg.as_string()) + server.quit() + print(f"[SMTP] Письмо о заказе {reg_id} отправлено на {smtp_to}") + return True + except Exception as e: + print(f"[SMTP] Ошибка отправки письма: {e}") + return False + +# ==================================================== +# Flask Web App Routes +# ==================================================== + +# Template filters +@app.template_filter('numberformat') +def numberformat_filter(value): + try: + return f"{int(value):,}".replace(",", " ") + except (ValueError, TypeError): + return value + +# Serve static files logic +@app.route('/') +def root_index(): + return app.send_static_file('index.html') + +@app.route('/form/') +@app.route('/form/index.html') +def form_index(): + return app.send_static_file('form/index.html') + +@app.after_request +def add_cors_headers(response): + response.headers['Access-Control-Allow-Origin'] = '*' + response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' + response.headers['Access-Control-Allow-Headers'] = 'Content-Type' + return response + +@app.route('/api/services', methods=['GET']) +def get_api_services(): + try: + services = db.get_services() + return jsonify({"status": "success", "services": services}) + except Exception as e: + return jsonify({"status": "error", "message": str(e)}), 500 + +@app.route('/submit', methods=['POST', 'OPTIONS']) +def submit(): + if request.method == 'OPTIONS': + return '', 204 + + try: + data = request.json + if not data: + return jsonify({"status": "error", "message": "Отсутствуют данные запроса"}), 400 + + # Validate mandatory data + name = data.get("name", "").strip() + phone = data.get("phone", "").strip() + email = data.get("email", "").strip() + + if not name or not phone or not email: + return jsonify({"status": "error", "message": "Заполните обязательные поля: Имя, Телефон, E-mail"}), 400 + + init_excel() + + # Load excel to generate sequential user ID + try: + wb = load_workbook(FILE_NAME) + ws = wb.active + except Exception: + init_excel() + wb = load_workbook(FILE_NAME) + ws = wb.active + + reg_id = get_next_user_id(ws) + + # Secure price lookup based on serviceId from SQLite database + service_id = str(data.get("serviceId", "web_1")).strip() + db_services = db.get_services() + service_info = db_services.get(service_id) + + if not service_info: + return jsonify({"status": "error", "message": f"Выбранная услуга '{service_id}' не найдена в базе данных"}), 400 + + service_name = service_info["name"] + amount = service_info["price_numeric"] + + # 1. YooKassa checkout generation + return_url = f"{request.host_url}form/index.html?success=true®_id={reg_id}&service_id={service_id}" + payment_info = create_yookassa_payment( + reg_id=reg_id, + amount=amount, + description=f"Оплата: {service_name} (ИКП)", + return_url=return_url, + customer_email=email, + customer_phone=phone, + customer_name=name + ) + + payment_id = None + payment_url = None + if payment_info: + payment_id = payment_info.get("payment_id") + payment_url = payment_info.get("confirmation_url") + + # Update payload dict with secure details + data_to_save = data.copy() + data_to_save["yookassaPaymentId"] = payment_id or "" + data_to_save["serviceName"] = service_name + data_to_save["servicePrice"] = amount + + # 2. Save registration in SQLite database as pending + db.add_web_registration(reg_id, { + "name": name, + "phone": phone, + "email": email, + "vk": data.get("vk", "").strip(), + "agreeOferta": data.get("agreeOferta"), + "agreePolicy": data.get("agreePolicy"), + "agreeNewsletter": data.get("agreeNewsletter"), + "serviceName": service_name, + "servicePrice": amount, + "paymentStatus": "pending", + "yookassaPaymentId": payment_id + }) + + # 3. Save initial registration in Excel + add_registration_to_excel(reg_id, data_to_save) + + # 4. Trigger operator alerts (unpaid yet) + send_vk_operator_notification(reg_id, data_to_save, paid=False) + send_email_notification(reg_id, data_to_save, paid=False) + + res = {"status": "success", "message": "Заявка зарегистрирована!"} + if payment_url: + res["payment_url"] = payment_url + + return jsonify(res) + + except PermissionError: + return jsonify({ + "status": "error", + "message": "Файл таблицы Excel заблокирован. Пожалуйста, закройте Excel на сервере и попробуйте отправить форму заново." + }), 500 + except Exception as e: + import traceback + traceback.print_exc() + return jsonify({"status": "error", "message": str(e)}), 500 + +# ==================================================== +# YooKassa Webhook Listener +# ==================================================== +@app.route('/webhook/yookassa', methods=['POST']) +def yookassa_webhook(): + try: + # Enforce YooKassa IP filtering if enabled + if config.VERIFY_WEBHOOK_IP: + # Handle proxy and Docker headers + x_forwarded_for = request.headers.get("X-Forwarded-For") + if x_forwarded_for: + client_ip = x_forwarded_for.split(',')[0].strip() + else: + client_ip = request.remote_addr + + if not is_yookassa_ip(client_ip): + print(f"[SECURITY WARNING] Заблокирован запрос к вебхуку от недоверенного IP: {client_ip}") + return jsonify({"status": "error", "message": "Access Denied: Untrusted IP"}), 403 + + event_data = request.json + if not event_data: + return 'Empty body', 400 + + event_type = event_data.get("event") + if event_type == "payment.succeeded": + payment_obj = event_data.get("object", {}) + payment_id = payment_obj.get("id") + metadata = payment_obj.get("metadata", {}) + reg_id = metadata.get("registration_id") + + if reg_id: + # Retrieve existing record + reg = db.get_web_registration(reg_id) + if reg: + # Only process if status is not already paid + if reg.get("payment_status") != "paid": + paid_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + # 1. Update SQLite Status + db.update_web_payment_status(reg_id, "paid", payment_id, paid_at) + + # 2. Update Excel file Status + update_excel_payment_status(reg_id, "Оплачено", paid_at) + + # Rebuild data dict for notification helpers + notify_data = { + "name": reg.get("name"), + "phone": reg.get("phone"), + "email": reg.get("email"), + "vk": reg.get("vk_link"), + "agreeOferta": reg.get("agree_oferta"), + "agreePolicy": reg.get("agree_policy"), + "agreeNewsletter": reg.get("agree_newsletter"), + "serviceName": reg.get("service_name"), + "servicePrice": reg.get("amount") + } + + # 3. Send paid success notifications + send_vk_operator_notification(reg_id, notify_data, paid=True) + send_email_notification(reg_id, notify_data, paid=True) + + print(f"[WEBHOOK] Заявка {reg_id} успешно переведена в статус ОПЛАЧЕНО.") + else: + print(f"[WEBHOOK] Заявка {reg_id} не найдена в базе данных.") + else: + print("[WEBHOOK] Отсутствует registration_id в метаданных платежа.") + + return 'OK', 200 + + except Exception as e: + print(f"[WEBHOOK] Исключение при обработке вебхука: {e}") + return 'Internal Server Error', 500 + +# ==================================================== +# Admin Cabinet Views (ЛК Администратора) +# ==================================================== +LOGIN_TEMPLATE = """ + + + + + + ИКП Панель | Авторизация + + + + + +
+
+ +
+
+

ИКП Админ

+

Панель управления оплатами

+
+ + {% if error %} +
+ ⚠️ {{ error }} +
+ {% endif %} + +
+
+ + +
+ + +
+
+ + +""" + +DASHBOARD_TEMPLATE = """ + + + + + + ИКП Админ | Реестр оплат + + + + + +
+ +
+ +
+ +
+ + +
+ + +
+ +
+
+

Всего заявок

+

{{ stats.total }}

+
+
+

Оплачено заказов

+

{{ stats.paid_count }}

+
+
+

Ожидает оплаты

+

{{ stats.pending_count }}

+
+
+

Сумма сборов

+

{{ stats.total_revenue | int | numberformat }} ₽

+
+
+ + +
+
+ + + +
+ +
+ + 🔍 +
+
+ + +
+
+ + + + + + + + + + + + + + + {% for reg in registrations %} + + + + + + + + + + + {% endfor %} + +
IDКлиентКонтактыУслугаСуммаСтатусРегистрацияДействие
{{ reg.id }} + {{ reg.name }} + +
+ 📞 {{ reg.phone }} +
+
+ ✉️ {{ reg.email }} +
+ {% if reg.vk_link %} + + {% endif %} +
+ {{ reg.service_name }} + {{ reg.amount | int }} ₽ + {% if reg.payment_status == 'paid' %} + + Оплачено + + {% else %} + + Ожидает + + {% endif %} + +
Рег: {{ reg.created_at }}
+ {% if reg.paid_at %} +
Опл: {{ reg.paid_at }}
+ {% endif %} +
+ {% if reg.payment_status != 'paid' and reg.yookassa_payment_id %} + + {% else %} + - + {% endif %} +
+
+
+
+ + + +
+ + + + + + + + + + + + +""" + +@app.route('/admin', methods=['GET']) +def admin_dashboard(): + if not session.get('logged_in'): + return render_template_string(LOGIN_TEMPLATE) + + # Fetch registrations and services + registrations = db.get_all_web_registrations() + services = db.get_all_services_list() + + # Calculate stats + stats = { + "total": len(registrations), + "paid_count": sum(1 for r in registrations if r["payment_status"] == "paid"), + "pending_count": sum(1 for r in registrations if r["payment_status"] != "paid"), + "total_revenue": sum(r["amount"] for r in registrations if r["payment_status"] == "paid") + } + + return render_template_string(DASHBOARD_TEMPLATE, registrations=registrations, stats=stats, services=services) + +@app.route('/admin/services/add', methods=['POST']) +def admin_add_service(): + if not session.get('logged_in'): + return jsonify({"status": "error", "message": "Не авторизован"}), 403 + + try: + data = request.json + if not data: + return jsonify({"status": "error", "message": "Отсутствуют данные запроса"}), 400 + + service_id = data.get("id", "").strip() + name = data.get("name", "").strip() + price = data.get("price", "").strip() + price_numeric = data.get("price_numeric") + description = data.get("description", "").strip() + + if not service_id or not name or not price or price_numeric is None: + return jsonify({"status": "error", "message": "Заполните все обязательные поля"}), 400 + + try: + price_numeric = float(price_numeric) + except ValueError: + return jsonify({"status": "error", "message": "Числовая цена должна быть числом"}), 400 + + success = db.add_service(service_id, name, price, price_numeric, description) + if success: + return jsonify({"status": "success", "message": "Услуга успешно добавлена"}) + else: + return jsonify({"status": "error", "message": "Услуга с таким ID уже существует"}), 400 + except Exception as e: + return jsonify({"status": "error", "message": str(e)}), 500 + +@app.route('/admin/services/edit/', methods=['POST']) +def admin_edit_service(service_id): + if not session.get('logged_in'): + return jsonify({"status": "error", "message": "Не авторизован"}), 403 + + try: + data = request.json + if not data: + return jsonify({"status": "error", "message": "Отсутствуют данные запроса"}), 400 + + name = data.get("name", "").strip() + price = data.get("price", "").strip() + price_numeric = data.get("price_numeric") + description = data.get("description", "").strip() + is_active = data.get("is_active", 1) + + if not name or not price or price_numeric is None: + return jsonify({"status": "error", "message": "Заполните все обязательные поля"}), 400 + + try: + price_numeric = float(price_numeric) + except ValueError: + return jsonify({"status": "error", "message": "Числовая цена должна быть числом"}), 400 + + success = db.update_service(service_id, name, price, price_numeric, description, int(is_active)) + if success: + return jsonify({"status": "success", "message": "Услуга успешно сохранена"}) + else: + return jsonify({"status": "error", "message": "Не удалось обновить услугу"}), 400 + except Exception as e: + return jsonify({"status": "error", "message": str(e)}), 500 + +@app.route('/admin/login', methods=['POST']) +def admin_login(): + password = request.form.get("password") + if password == config.ADMIN_PASSWORD: + session['logged_in'] = True + return redirect(url_for('admin_dashboard')) + else: + return render_template_string(LOGIN_TEMPLATE, error="Неверный пароль администратора") + +@app.route('/admin/logout', methods=['GET']) +def admin_logout(): + session.pop('logged_in', None) + return redirect(url_for('admin_dashboard')) + +@app.route('/admin/check-payment/', methods=['POST']) +def admin_check_payment(reg_id): + if not session.get('logged_in'): + return jsonify({"status": "error", "message": "Не авторизован"}), 403 + + try: + reg = db.get_web_registration(reg_id) + if not reg: + return jsonify({"status": "error", "message": "Заявка не найдена"}), 404 + + payment_id = reg.get("yookassa_payment_id") + if not payment_id: + return jsonify({"status": "error", "message": "У этой заявки нет ID платежа ЮKassa"}), 400 + + yoo_status = check_yookassa_payment_status(payment_id) + if not yoo_status: + return jsonify({"status": "error", "message": "Не удалось связаться с ЮKassa API"}), 500 + + # Update if paid + if yoo_status == "succeeded" and reg.get("payment_status") != "paid": + paid_at = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + db.update_web_payment_status(reg_id, "paid", payment_id, paid_at) + update_excel_payment_status(reg_id, "Оплачено", paid_at) + + # Send paid notifications + notify_data = { + "name": reg.get("name"), + "phone": reg.get("phone"), + "email": reg.get("email"), + "vk": reg.get("vk_link"), + "agreeOferta": reg.get("agree_oferta"), + "agreePolicy": reg.get("agree_policy"), + "agreeNewsletter": reg.get("agree_newsletter"), + "serviceName": reg.get("service_name"), + "servicePrice": reg.get("amount") + } + send_vk_operator_notification(reg_id, notify_data, paid=True) + send_email_notification(reg_id, notify_data, paid=True) + + return jsonify({"status": "success", "payment_status": "paid"}) + + return jsonify({"status": "success", "payment_status": reg.get("payment_status")}) + + except Exception as e: + return jsonify({"status": "error", "message": str(e)}), 500 + +def run_server(port=8000): + init_excel() + print(f"\n=======================================================") + print(f"Flask-сервер ИКП запущен на http://localhost:{port}/") + print(f"Главная страница: http://localhost:{port}/") + print(f"Форма регистрации: http://localhost:{port}/form/index.html") + print(f"Панель администратора: http://localhost:{port}/admin") + print(f"Данные пишутся в SQLite и Excel: {FILE_NAME}") + print(f"Нажмите Ctrl+C для остановки сервера.") + print(f"=======================================================\n") + app.run(host='0.0.0.0', port=port, debug=True) + +if __name__ == '__main__': + run_server()