🏗️ Архитектура системы DEXA

Назад к списку Редактировать
Информация
Slug:
architecture.html
Обновлено:
30.05.2026 15:03
Размер:
57.75 KB
Путь:
/resources/docs/developer/architecture.html
Ссылки
Публичная ссылка:
Ссылка в админке:
🏗️ Архитектура системы DEXA
👨‍💻 Целевая аудитория: Разработчики, DevOps инженеры, Технические руководители
📊 Уровень сложности: Средний
🎯 Цель документа: Полное описание архитектуры, компонентов, связей и бизнес-логики системы обмена валют DEXA

🎯 Обзор системы

DEXA - это высоконагруженная система обмена криптовалют и фиатных денег с микросервисной архитектурой. Система предназначена для автоматизации процесса обмена между клиентами и партнерами (точками обмена).

Ключевые возможности:

  • Обмен криптовалют - BTC, ETH, USDT, TRX и другие
  • Обмен фиатных валют - RUB, USD, EUR
  • Автоматическое обновление курсов из внешних API (Binance, Rapira.net)
  • Гибкая система наценок для разных типов транзакций
  • Партнерская программа с индивидуальными курсами для каждой точки обмена
  • Административная панель с ролевой моделью и 2FA
  • API для внешних интеграций
  • Автоматические уведомления по Email и Telegram

⚙️ Технологический стек

Laravel 10 PHP 8.1+ MySQL 8.0+ MariaDB 10.4+ Redis 6.0+ Nginx/Apache Bootstrap 5 jQuery 3.6 Font Awesome 6 CKEditor 5 Chart.js Google2FA

🏗️ Высокоуровневая архитектура

┌─────────────────────────────────────────────────────────────────────────────┐
│                           КЛИЕНТСКИЙ СЛОЙ                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐               │
│  │   Web    │    │  Mobile  │    │  Admin   │    │   API    │               │
│  │  Client  │    │   App    │    │  Panel   │    │  Client  │               │
│  └────┬─────┘    └────┬─────┘    └────┬─────┘    └────┬─────┘               │
│       │               │               │               │                     │
│       └───────────────┴───────────────┴───────────────┘                     │
│                                   │                                         │
│                                   ▼                                         │
│                          ┌─────────────────┐                               │
│                          │   API Gateway   │                               │
│                          │    (Laravel)    │                               │
│                          └────────┬────────┘                               │
└───────────────────────────────────┼─────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          СЕРВИСНЫЙ СЛОЙ                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │    Auth      │  │   Exchange   │  │    Rate      │  │  Notification│    │
│  │   Service    │  │   Service    │  │   Service    │  │   Service    │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
│                                                                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │   Partner    │  │   Currency   │  │     API      │  │  Analytics   │    │
│  │   Service    │  │   Service    │  │   Service    │  │   Service    │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           СЛОЙ ДАННЫХ                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │   Primary    │  │    Redis     │  │   External   │  │    File      │    │
│  │      DB      │  │    Cache     │  │    APIs      │  │   Storage    │    │
│  │   (MySQL)    │  │  (Session)   │  │  (Binance)   │  │   (Logos)    │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘
    

📂 Структура директорий проекта

dexa/
├── app/
│   ├── Console/
│   │   └── Commands/
│   │       ├── CheckRatesStale.php              # Проверка устаревших курсов
│   │       ├── ForceUpdateRates.php             # Принудительное обновление
│   │       ├── SyncCurrenciesCommand.php        # Синхронизация валют
│   │       ├── TestSmtpConnection.php           # Тест SMTP
│   │       ├── UpdateExchangeRates.php          # Обновление курсов
│   │       └── UpdateRatesFromConfiguredApis.php # Обновление из API (крон)
│   │
│   ├── Exports/
│   │   └── OrdersExport.php                     # Экспорт заявок в Excel
│   │
│   ├── Helpers/
│   │   └── ColorHelper.php                      # Утилиты для работы с цветами
│   │
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Admin/
│   │   │   │   ├── AdminController.php          # Управление администраторами
│   │   │   │   ├── ApiConfigController.php      # API конфигурации
│   │   │   │   ├── AuthController.php           # Аутентификация админов
│   │   │   │   ├── CityController.php           # Управление городами
│   │   │   │   ├── CurrencyController.php       # Управление валютами
│   │   │   │   ├── DashboardController.php      # Дашборд и отчеты
│   │   │   │   ├── DocumentationController.php  # Управление документацией
│   │   │   │   ├── ExchangeRateController.php   # Управление курсами
│   │   │   │   ├── OrderController.php          # Управление заявками
│   │   │   │   ├── PageController.php           # Управление страницами
│   │   │   │   ├── PartnerController.php        # Управление партнерами
│   │   │   │   ├── SettingController.php        # Настройки системы
│   │   │   │   ├── TwoFactorController.php      # 2FA для админов
│   │   │   │   └── UserController.php           # Управление пользователями
│   │   │   │
│   │   │   ├── Api/
│   │   │   │   └── ApiController.php            # Публичное API
│   │   │   │
│   │   │   ├── AuthController.php               # Аутентификация пользователей
│   │   │   ├── ContactController.php            # Контактная форма
│   │   │   ├── ExchangeController.php           # Обмен валют
│   │   │   ├── HomeController.php               # Главная страница
│   │   │   ├── PageController.php               # Динамические страницы
│   │   │   ├── ProfileController.php            # Личный кабинет
│   │   │   └── TwoFactorController.php          # 2FA для пользователей
│   │   │
│   │   └── Middleware/
│   │       ├── AdminAuthMiddleware.php          # Аутентификация админа
│   │       ├── AdminTwoFactorMiddleware.php     # 2FA для админа
│   │       ├── CheckAdminPermission.php         # Проверка прав админа
│   │       ├── CheckEmailVerified.php           # Проверка email
│   │       ├── CheckProfileAccess.php           # Доступ к профилю
│   │       ├── RateLimitMiddleware.php          # Ограничение запросов
│   │       ├── SetAdminSessionCookie.php        # Установка админ-сессии
│   │       ├── StartAdminSession.php            # Запуск админ-сессии
│   │       └── TwoFactorMiddleware.php          # 2FA для пользователей
│   │
│   ├── Mail/
│   │   ├── AdminOrderCreated.php                # Уведомление админу о заявке
│   │   ├── ApiStaleRatesNotification.php        # Уведомление о устаревших курсах
│   │   ├── BaseMailable.php                     # Базовый класс для писем
│   │   ├── ContactMessage.php                   # Контактная форма
│   │   ├── EmailVerification.php                # Подтверждение email
│   │   ├── NewExchangeOrder.php                 # Новая заявка на обмен
│   │   ├── OrderConfirmation.php                # Подтверждение заявки
│   │   ├── OrderStatusUpdated.php               # Обновление статуса
│   │   ├── OrderVerification.php                # Верификация заявки
│   │   └── PasswordReset.php                    # Сброс пароля
│   │
│   ├── Models/
│   │   ├── Admin.php                            # Администратор
│   │   ├── City.php                             # Город
│   │   ├── Currency.php                         # Валюта (с настройками 6 типов)
│   │   ├── Documentation.php                    # Управление документацией
│   │   ├── ExchangeApi.php                      # API конфигурация
│   │   ├── ExchangeOrder.php                    # Заявка на обмен
│   │   ├── ExchangeRate.php                     # Курс обмена
│   │   ├── ExternalRate.php                     # Внешний курс
│   │   ├── Page.php                             # Статическая страница
│   │   ├── Partner.php                          # Партнер
│   │   ├── Setting.php                          # Настройки системы
│   │   ├── User.php                             # Пользователь
│   │   └── UserWallet.php                       # Кошелек пользователя
│   │
│   ├── Providers/
│   │   ├── AppServiceProvider.php               # Регистрация команд
│   │   ├── DynamicMailConfigProvider.php        # Динамическая конфигурация почты
│   │   └── ExternalRateServiceProvider.php      # Регистрация сервисов
│   │
│   └── Services/
│       ├── RateCalculation/                     # КАЛЬКУЛЯТОРЫ КУРСОВ (новая архитектура)
│       │   ├── RateCalculatorInterface.php      # Интерфейс калькулятора
│       │   ├── RateCalculatorManager.php        # Менеджер калькуляторов
│       │   ├── PartnerManualRateCalculator.php  # Ручной курс партнера
│       │   ├── PartnerExternalRateCalculator.php # Внешний курс партнера
│       │   ├── GeneralManualRateCalculator.php  # Ручной общий курс
│       │   ├── GeneralExternalRateCalculator.php # Внешний общий курс
│       │   └── USDTCalculationCalculator.php    # Расчет через USDT
│       │
│       ├── ExchangeCalculationService.php       # Основная логика расчета
│       ├── ExternalRateService.php              # Обновление внешних курсов
│       ├── MailLoggerService.php                # Логирование почты
│       ├── RateUpdateService.php                # Обновление курсов
│       ├── TelegramService.php                  # Telegram уведомления
│       └── UniversalApiService.php              # Универсальный API клиент
│
├── bootstrap/
│   └── app.php                                   # Конфигурация приложения
│
├── config/
│   ├── admin_session.php                         # Настройки админ-сессии
│   ├── app.php                                   # Основные настройки
│   ├── auth.php                                  # Аутентификация (guards)
│   ├── beget.php                                 # Настройки для Beget хостинга
│   ├── cache.php                                 # Кэширование
│   ├── database.php                              # База данных
│   ├── filesystems.php                           # Файловая система
│   ├── google2fa.php                             # 2FA настройки
│   ├── logging.php                               # Логирование
│   ├── mail.php                                  # Почта
│   ├── queue.php                                 # Очереди
│   └── services.php                              # Сторонние сервисы
│
├── database/
│   ├── migrations/
│   │   ├── 0001_01_01_000000_create_users_table.php
│   │   ├── 0001_01_01_000001_create_cache_table.php
│   │   ├── 0001_01_01_000002_create_jobs_table.php
│   │   ├── 2026_01_18_000000_create_dexa_database.php  # Основная миграция
│   │   ├── 2026_02_21_000000_add_menu_settings_to_pages_table.php
│   │   ├── 2026_03_04_000000_add_2fa_fields_to_users_table.php
│   │   └── 2026_03_05_000000_add_2fa_fields_to_admins_table.php
│   │
│   └── seeders/
│       └── DatabaseSeeder.php                    # Начальные данные
│
├── public/
│   ├── css/
│   │   └── exchange-common.css                   # Общие стили
│   ├── js/
│   │   └── exchange-common.js                    # Общие JS функции
│   └── index.php
│
├── resources/
│   ├── docs/                                     # Файлы документации
│   │   ├── user/                                 # Документация для пользователей
│   │   └── developer/                            # Документация для разработчиков
│   │
│   └── views/                                    # Blade шаблоны
│       ├── admin/                                # Админ-панель
│       ├── auth/                                 # Аутентификация
│       ├── emails/                               # Email шаблоны
│       ├── errors/                               # Страницы ошибок
│       ├── layouts/                              # Базовые шаблоны
│       ├── pages/                                # Публичные страницы
│       ├── profile/                              # Личный кабинет
│       └── tracking.blade.php                    # Отслеживание заявок
│
├── routes/
│   ├── api.php                                   # API маршруты
│   ├── console.php                               # Cron задачи
│   └── web.php                                   # Веб-маршруты
│
└── storage/                                      # Логи, кэш, сессии

🏗️ Компоненты системы

🔐

Сервис аутентификации (Auth Service)

Назначение: Управление пользователями, сессиями, ролями и правами доступа.

Основные функции:

  • Раздельные гарды: web (пользователи) и admin (администраторы)
  • Раздельные сессии: через отдельные таблицы sessions и admin_sessions
  • Двухфакторная аутентификация (2FA): для пользователей и админов через Google Authenticator
  • Ролевая модель (RBAC): 4 уровня доступа (superadmin, admin, manager, moderator)
  • Granular permissions: детальные права на каждый модуль (view, create, edit, delete)
  • Управление сессиями: отдельные cookie для админ-панели (dexaSuperUser)
  • Email верификация: обязательное подтверждение email для пользователей
  • Сброс пароля: через email ссылку (действительна 24 часа)

Технологии:

Laravel Session bcrypt Google2FA CSRF Tokens Custom Middleware

API endpoints:

POST /login # Вход пользователя
POST /register # Регистрация
POST /logout # Выход
POST /forgot-password # Запрос сброса пароля
POST /reset-password # Сброс пароля
GET /verify-email/{token} # Подтверждение email
GET /2fa/verify # Форма 2FA
POST /2fa/verify # Проверка 2FA кода

POST /dexaSuperUser/login # Вход админа
POST /dexaSuperUser/logout # Выход админа
GET /dexaSuperUser/2fa/verify # Форма 2FA админа
POST /dexaSuperUser/2fa/verify # Проверка 2FA кода админа
💱

Сервис обмена (Exchange Service)

Назначение: Обработка операций обмена валют, расчет курсов с учетом наценок, управление заявками.

Основные функции:

  • Создание заявок: клиентские и административные
  • Расчет курсов: по 6 типам транзакций с учетом наценок/скидок
  • Стаканы (Order Book): использование bid/ask цен из внешних API
  • Система приоритетов курсов:
    1. Ручной курс партнера
    2. Внешний курс партнера
    3. Ручной общий курс
    4. Общий внешний курс
    5. Расчет через USDT (резерв)
  • Автоматическая верификация: по email ссылке или коду
  • Управление статусами: pending, confirmed, processing, completed, cancelled, rejected
  • Лимиты: минимальные и максимальные суммы для каждой пары
  • Комиссии: процентная комиссия (может быть отрицательной для скидки)

Архитектура калькуляторов курсов (новое):

1
RateCalculatorManager - координатор, вызывает все калькуляторы по приоритету
2
PartnerManualRateCalculator - проверяет ручные курсы партнера
3
PartnerExternalRateCalculator - проверяет внешние курсы партнера
4
GeneralManualRateCalculator - проверяет общие ручные курсы
5
GeneralExternalRateCalculator - проверяет общие внешние курсы
6
USDTCalculationCalculator - резервный расчет через USDT

Основные методы ExchangeCalculationService:

array getBestRate(int $fromCurrencyId, int $toCurrencyId, int|null $partnerId = null)
array calculateExchange(int $fromCurrencyId, int $toCurrencyId, float $amount, int|null $partnerId = null)
bool isRateStale(int $fromCurrencyId, int|null $staleThresholdMinutes = null)
array prepareFormulaInfo(Currency $fromCurrency, Currency $toCurrency, float $baseRate, float $finalRate, float $margin, string $transactionType, float $bidPrice = 0, float $askPrice = 0, string $usedStakan = '', float $manualMargin = 0, bool $useExternal = true)
📊

Сервис курсов (Rate Service)

Назначение: Получение, обработка и хранение курсов валют из внешних API.

Архитектура получения курсов:

1
ExternalRateService::updateRatesFromApi() - запускает обновление
2
Выбирает активные API из таблицы exchange_apis
3
Для каждого API вызывает UniversalApiService::fetchFromApi()
4
UniversalApiService отправляет HTTP запрос (GET/POST) с учетом аутентификации
5
Парсит ответ согласно field_mapping (JSON/XML/CSV)
6
Форматирует пары валют согласно pair_format
7
Сохраняет в таблицу external_rates (или обновляет существующие)
8
Создает обратные курсы (reverse_rates) для всех пар

Ключевые методы ExternalRateService:

int updateRatesFromApi()
array updateRatesFromSpecificApi(ExchangeApi $api)
int updatePartnerExternalRatesFromApi(int $partnerId, ExchangeApi|null $api = null)
array checkSpecificApi(ExchangeApi $api)
int createReverseRates()

UniversalApiService - универсальный клиент:

array fetchFromApi(ExchangeApi $api, bool $testMode = false)
array testApi(ExchangeApi $api, bool $useTestData = false, bool $showAllRates = false)
array|null fetchOrderBookData(string $symbol, array|null $mapping = null, ExchangeApi|null $api = null)
🤖

Сервис уведомлений (TelegramService)

Назначение: Отправка уведомлений о важных событиях в Telegram чат администраторов.

Основные функции:

  • Новые заявки: уведомление администраторов о создании заявки
  • Контактная форма: уведомление о новом сообщении
  • Админские заявки: уведомление о заявках, созданных через админ-панель
  • Тестовые уведомления: для проверки настроек

Ключевые методы:

bool sendExchangeOrderNotification(ExchangeOrder $order)
bool sendContactFormNotification(array $data)
bool sendAdminOrderNotification(array $orderData)
array checkBotStatus()
array sendTestNotification()

Настройки в .env:

TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here

🗄️ Структура базы данных

Основные таблицы и связи:


-- =====================================================
-- ЯДРО СИСТЕМЫ (АУТЕНТИФИКАЦИЯ)
-- =====================================================
users (
    id, name, email, password, phone, telegram,
    role, is_active,
    email_verified_at, email_verification_token, verification_sent_at,
    google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)

admins (
    id, name, email, password, role, permissions, is_active,
    google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)

sessions (id, user_id, ip_address, user_agent, payload, last_activity)
admin_sessions (id, admin_id, ip_address, user_agent, payload, last_activity)
password_reset_tokens (email, token, created_at)

-- =====================================================
-- ВАЛЮТЫ И КУРСЫ
-- =====================================================
currencies (
    id, code, name, symbol, type, icon, is_active, sort_order,
    our_wallet, wallet_for_other_currencies,

    -- НАСТРОЙКИ ДЛЯ USDT
    usdt_to_other_crypto_margin, usdt_to_other_crypto_min_amount,
    usdt_to_rub_margin, usdt_to_rub_min_amount,

    -- НАСТРОЙКИ ДЛЯ RUB
    rub_to_usdt_margin, rub_to_usdt_min_amount,
    rub_to_other_crypto_margin, rub_to_other_crypto_min_amount,

    -- НАСТРОЙКИ ДЛЯ ДРУГИХ КРИПТО
    other_crypto_to_rub_margin, other_crypto_to_rub_min_amount,
    other_crypto_to_other_crypto_margin, other_crypto_to_other_crypto_min_amount
)

exchange_apis (
    id, name, base_url, endpoint, method,
    request_format, response_format,
    field_mapping (JSON), pair_format (JSON),
    authentication_type, api_key (encrypted), secret_key (encrypted),
    is_active, priority, timeout, retry_count,
    success_count, error_count, last_success_at, last_error_at
)

external_rates (
    id, partner_id, from_currency_id, to_currency_id,
    external_rate, source, last_updated,
    order_book_buy (JSON), order_book_sell (JSON),
    bid_price, ask_price, bid_volume, ask_volume, spread,
    volume_24h, change_24h
)

exchange_rates (
    id, partner_id, from_currency_id, to_currency_id,
    rate, external_rate_id,
    use_external_rate, use_partner_external,
    manual_margin_percentage,
    override_margin, override_min_amount,
    min_amount, max_amount,
    is_active, is_hidden, priority, last_updated
)

-- =====================================================
-- ГЕОГРАФИЯ И ПАРТНЕРЫ
-- =====================================================
cities (
    id, name, country, latitude, longitude, is_active, sort_order
)

partners (
    id, city_id, name, address, phone, email,
    latitude, longitude, working_hours, description,
    accepted_currencies (JSON), api_id,
    rating, total_reviews, is_active
)

-- =====================================================
-- ОПЕРАЦИИ (ЗАЯВКИ)
-- =====================================================
exchange_orders (
    id, order_number, user_id,
    from_currency_id, to_currency_id,
    partner_id, city_id,
    amount, rate, fee_percentage, fee_amount, total_receive,
    full_name, email, phone, wallet_address,
    status, transaction_type,
    admin_notes, user_notes,
    verification_code, verification_token,
    verified_at, expires_at,
    ip_address, user_agent
)

-- =====================================================
-- КЛИЕНТСКИЕ ДАННЫЕ
-- =====================================================
user_wallets (
    id, user_id, currency_id,
    wallet_address, network, wallet_name,
    is_default, is_active, notes
)

-- =====================================================
-- НАСТРОЙКИ
-- =====================================================
settings (
    id, key, value, type, group, options,
    default_cron_api_id, default_cron_api_name,
    update_interval_minutes, auto_update_enabled,
    primary_api_id, fallback_api_id,
    order_expire_minutes, auto_confirm_orders, require_verification,
    site_timezone, date_format,
    recaptcha_site_key, recaptcha_secret_key
)

pages (
    id, slug, title, content,
    meta_title, meta_description, meta_keywords,
    is_active, is_homepage, show_in_menu,
    show_logistics_in_menu, show_home_in_menu,
    page_type, sort_order
)
    

Связи между таблицами:

  • currencies → exchange_rates: одна валюта может участвовать во многих курсах (как from или to)
  • currencies → external_rates: одна валюта может участвовать во многих внешних курсах
  • cities → partners: один город может иметь много партнеров
  • partners → exchange_rates: один партнер может иметь много индивидуальных курсов
  • partners → external_rates: один партнер может иметь много своих внешних курсов
  • users → exchange_orders: один пользователь может иметь много заявок
  • users → user_wallets: один пользователь может иметь много кошельков
  • exchange_apis → external_rates: один API может быть источником для многих курсов
  • exchange_apis → partners: один API может быть назначен многим партнерам
  • external_rates → exchange_rates: внешний курс может использоваться во многих курсах обмена

🔌 Интеграции и API

Интеграция Тип Назначение Статус
Binance API REST (GET) Получение курсов криптовалют (USDT, BTC, ETH) ✅ Активна
Rapira.net API REST (GET/POST) Получение курсов и стаканов заявок ✅ Активна
Telegram Bot API REST Уведомления администраторов ✅ Активна
SMTP сервер SMTP Отправка email уведомлений ✅ Активна (настраивается)

🛡️ Безопасность

Многоуровневая защита:

1. Сетевой уровень:

  • HTTPS с HSTS
  • Защита от DDoS (Cloudflare)
  • Ограничение доступа к админ-панели через middleware

2. Уровень приложения:

  • CSRF защита для всех форм (кроме API)
  • XSS фильтрация входных данных
  • SQL injection protection через Eloquent ORM и подготовленные запросы
  • Rate limiting для API endpoints (60 запросов в минуту)
  • Валидация всех входных данных через Form Requests
  • Раздельные сессии для пользователей и админов
  • Отдельная таблица сессий для админов (admin_sessions)

3. Уровень данных:

  • Шифрование API ключей в таблице exchange_apis (AES-256)
  • Хеширование паролей (bcrypt, cost 12)
  • Резервное копирование базы данных (настраивается через крон)

4. Аутентификация и авторизация:

  • Двухфакторная аутентификация (2FA) для пользователей и админов
  • Ролевая модель (RBAC) с 4 уровнями доступа
  • Granular permissions для каждого модуля (view, create, edit, delete)
  • Email верификация при регистрации
  • Токены для сброса пароля (действительны 24 часа)
  • Токены для подтверждения заявок (действительны 24 часа)

5. Middleware защита:

admin.auth # Проверка аутентификации админа
admin.permission # Проверка прав доступа
admin.2fa # Проверка 2FA для админа
profile.access # Доступ к личному кабинету
email.verified # Проверка подтверждения email
rate.limit # Ограничение запросов (60/мин)
2fa # Проверка 2FA для пользователей

🚀 Deploy и DevOps

Требования к серверу:

  • PHP: 8.1+ с расширениями (bcmath, ctype, fileinfo, json, mbstring, openssl, pdo, tokenizer, xml, zip, gd, redis)
  • База данных: MySQL 8.0+ или MariaDB 10.4+
  • Redis: 6.0+ (для кэширования и сессий)
  • Веб-сервер: Nginx 1.18+ или Apache 2.4+
  • Supervisor: для управления очередями (если используются)

Cron задачи (настроены в routes/console.php):

# Обновление курсов из API по умолчанию (каждый час)
* * * * * cd /path/to/dexa && php artisan schedule:run >> /dev/null 2>&1

# Фактические задачи внутри schedule:
$schedule->command('rates:update-from-apis')->hourly()
$schedule->command('rates:check-stale --threshold=30 --send-email')->everyFifteenMinutes()
$schedule->command('rates:force-update')->hourly()
$schedule->command('currencies:sync')->dailyAt('03:00')

Переменные окружения (.env):

APP_NAME="DEXA"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
APP_TIMEZONE=UTC

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dexa
DB_USERNAME=dexa_user
DB_PASSWORD=your_password

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379

SESSION_DRIVER=redis
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis

MAIL_MAILER=smtp
MAIL_HOST=smtp.mail.ru
MAIL_PORT=465
MAIL_USERNAME=your-email@mail.ru
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=your-email@mail.ru
MAIL_FROM_NAME="DEXA Exchange"

TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id

📊 Система приоритетов курсов (подробно)

1 Ручной курс партнера - самый высокий приоритет
  • Находится в таблице exchange_rates с заполненным partner_id
  • Поле rate заполнено, use_external_rate = false
  • Полностью игнорирует внешние API
2 Внешний курс партнера
  • Находится в таблице external_rates с заполненным partner_id
  • ИЛИ exchange_rates с use_partner_external = true
  • Использует API партнера (если настроен) или общий API
3 Ручной общий курс
  • В таблице exchange_rates с partner_id = NULL
  • Поле rate заполнено, use_external_rate = false
  • Применяется для всех партнеров, у которых нет своих курсов
4 Общий внешний курс
  • В таблице external_rates с partner_id = NULL
  • ИЛИ exchange_rates с use_external_rate = true
  • Использует API по умолчанию
5 Расчет через USDT (резервный вариант)
  • Вычисляется как BTC → USDT → RUB если нет прямого курса
  • Использует курсы USDT для расчета кросс-курса
  • Работает для любых пар, где есть через USDT

🧪 Тестирование

В проекте используются следующие типы тестов:

  • Unit тесты - для сервисов и моделей (PHPUnit)
  • Feature тесты - для контроллеров и API
  • Ручное тестирование через административную панель

Команды для тестирования:

# Тест SMTP подключения
php artisan smtp:test admin@example.com

# Проверка устаревших курсов
php artisan rates:check-stale --threshold=30 --send-email

# Принудительное обновление курсов
php artisan rates:force-update

# Синхронизация валют
php artisan currencies:sync

🔧 Устранение неисправностей

Проблема Причина Решение
502 Bad Gateway PHP-FPM не запущен sudo systemctl restart php8.1-fpm
Ошибки миграции Нет прав на базу данных Проверить пользователя MySQL, выполнить php artisan migrate:fresh
Медленная загрузка Нет OPCache или Redis Включить OPCache, настроить Redis для сессий и кэша
Не отправляются email Неправильные SMTP настройки Проверить в админ-панели Настройки → Email, выполнить php artisan smtp:test
Не обновляются курсы Не настроен API по умолчанию или проблемы с API В админ-панели Курсы обмена → Установить API по умолчанию → Обновить курсы
Курсы на сайте не отображаются Нет записей в external_rates или exchange_rates Запустить php artisan rates:update-from-apis, проверить настройки валют
📝 Примечание: Все логи хранятся в storage/logs/laravel.log. Для мониторинга используйте tail -f storage/logs/laravel.log.
⚠️ Важно: Супер-администратор только один: odeveloper@internet.ru. Его нельзя удалить или изменить роль. Все остальные администраторы создаются с правами, которые задает супер-админ.
Последнее обновление: 30.05.2026 в 15:03
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Архитектура системы DEXA - Полная документация</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            line-height: 1.6;
            color: #333;
            padding: 20px;
            max-width: 1400px;
            margin: 0 auto;
            background-color: #f8fafc;
        }
        h1 {
            color: #2c3e50;
            border-bottom: 3px solid #3498db;
            padding-bottom: 15px;
            margin-bottom: 30px;
        }
        h2 {
            color: #34495e;
            border-bottom: 2px solid #e0e6ed;
            padding-bottom: 10px;
            margin-top: 40px;
        }
        h3 {
            color: #2c3e50;
            margin-top: 25px;
        }
        h4 {
            color: #4a5568;
            margin-top: 20px;
        }
        .architecture-diagram {
            background: white;
            border: 2px solid #e2e8f0;
            border-radius: 10px;
            padding: 25px;
            margin: 20px 0;
            text-align: center;
            overflow-x: auto;
        }
        .component {
            background: white;
            border: 1px solid #e2e8f0;
            border-radius: 8px;
            padding: 20px;
            margin: 15px 0;
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
        }
        .component-header {
            display: flex;
            align-items: center;
            margin-bottom: 15px;
        }
        .component-icon {
            font-size: 24px;
            margin-right: 10px;
        }
        .tech-stack {
            display: flex;
            flex-wrap: wrap;
            gap: 10px;
            margin: 15px 0;
        }
        .tech-item {
            background: #e3f2fd;
            padding: 5px 12px;
            border-radius: 20px;
            font-size: 12px;
            font-weight: 500;
        }
        .flow-diagram {
            background: #f8f9fa;
            padding: 20px;
            border-radius: 8px;
            margin: 20px 0;
            border-left: 4px solid #3498db;
        }
        .flow-step {
            display: flex;
            align-items: center;
            margin: 10px 0;
        }
        .flow-number {
            background: #3498db;
            color: white;
            width: 30px;
            height: 30px;
            border-radius: 50%;
            text-align: center;
            line-height: 30px;
            margin-right: 15px;
            flex-shrink: 0;
        }
        .note {
            background: #e3f2fd;
            border-left: 4px solid #2196f3;
            padding: 15px;
            margin: 20px 0;
            border-radius: 4px;
        }
        .warning {
            background: #fff3cd;
            border-left: 4px solid #ffc107;
            padding: 15px;
            margin: 20px 0;
            border-radius: 4px;
        }
        table {
            border-collapse: collapse;
            width: 100%;
            margin: 20px 0;
            background: white;
            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
            border-radius: 8px;
            overflow: hidden;
        }
        th, td {
            padding: 12px 15px;
            border: 1px solid #e2e8f0;
            text-align: left;
        }
        th {
            background-color: #f7fafc;
            font-weight: 600;
            color: #4a5568;
        }
        code {
            background-color: #f1f3f4;
            padding: 2px 6px;
            border-radius: 4px;
            font-family: 'Consolas', 'Monaco', monospace;
            color: #e74c3c;
            font-size: 0.9em;
        }
        pre {
            background-color: #2d3436;
            color: #dfe6e9;
            padding: 20px;
            border-radius: 8px;
            overflow-x: auto;
            margin: 15px 0;
            border-left: 4px solid #3498db;
            font-family: 'Consolas', 'Monaco', monospace;
            font-size: 14px;
        }
        .method-signature {
            background: #2d3436;
            color: #dfe6e9;
            padding: 15px;
            border-radius: 8px;
            margin: 15px 0;
            overflow-x: auto;
            font-family: 'Consolas', 'Monaco', monospace;
        }
        .method-param {
            color: #74b9ff;
        }
        .method-return {
            color: #55efc4;
        }
        .mermaid {
            background: white;
            padding: 20px;
            border-radius: 8px;
            margin: 20px 0;
        }
        .database-schema {
            background: #2d3436;
            color: white;
            padding: 20px;
            border-radius: 8px;
            margin: 20px 0;
            overflow-x: auto;
        }
        .rate-priority {
            background: #e8f5e9;
            border-left: 4px solid #4caf50;
            padding: 15px;
            margin: 20px 0;
            border-radius: 4px;
        }
        .priority-item {
            margin: 10px 0;
            padding-left: 15px;
            border-left: 3px solid #4caf50;
        }
        .priority-number {
            display: inline-block;
            background: #4caf50;
            color: white;
            width: 24px;
            height: 24px;
            border-radius: 50%;
            text-align: center;
            line-height: 24px;
            font-size: 12px;
            margin-right: 10px;
        }
        @media (max-width: 768px) {
            body { padding: 10px; }
            th, td { padding: 8px; font-size: 12px; }
            pre { font-size: 11px; }
        }
    </style>
</head>
<body>

<h1>🏗️ Архитектура системы DEXA</h1>

<div class="note">
    <strong>👨‍💻 Целевая аудитория:</strong> Разработчики, DevOps инженеры, Технические руководители<br>
    <strong>📊 Уровень сложности:</strong> Средний<br>
    <strong>🎯 Цель документа:</strong> Полное описание архитектуры, компонентов, связей и бизнес-логики системы обмена валют DEXA
</div>

<h2>🎯 Обзор системы</h2>
<p>DEXA - это высоконагруженная система обмена криптовалют и фиатных денег с микросервисной архитектурой.
    Система предназначена для автоматизации процесса обмена между клиентами и партнерами (точками обмена).</p>

<h3>Ключевые возможности:</h3>
<ul>
    <li><strong>Обмен криптовалют</strong> - BTC, ETH, USDT, TRX и другие</li>
    <li><strong>Обмен фиатных валют</strong> - RUB, USD, EUR</li>
    <li><strong>Автоматическое обновление курсов</strong> из внешних API (Binance, Rapira.net)</li>
    <li><strong>Гибкая система наценок</strong> для разных типов транзакций</li>
    <li><strong>Партнерская программа</strong> с индивидуальными курсами для каждой точки обмена</li>
    <li><strong>Административная панель</strong> с ролевой моделью и 2FA</li>
    <li><strong>API для внешних интеграций</strong></li>
    <li><strong>Автоматические уведомления</strong> по Email и Telegram</li>
</ul>

<h2>⚙️ Технологический стек</h2>

<div class="tech-stack">
    <span class="tech-item">Laravel 10</span>
    <span class="tech-item">PHP 8.1+</span>
    <span class="tech-item">MySQL 8.0+</span>
    <span class="tech-item">MariaDB 10.4+</span>
    <span class="tech-item">Redis 6.0+</span>
    <span class="tech-item">Nginx/Apache</span>
    <span class="tech-item">Bootstrap 5</span>
    <span class="tech-item">jQuery 3.6</span>
    <span class="tech-item">Font Awesome 6</span>
    <span class="tech-item">CKEditor 5</span>
    <span class="tech-item">Chart.js</span>
    <span class="tech-item">Google2FA</span>
</div>

<h2>🏗️ Высокоуровневая архитектура</h2>

<div class="architecture-diagram">
    <pre style="background: white; color: #333; text-align: left; border: none; padding: 0;">
┌─────────────────────────────────────────────────────────────────────────────┐
│                           КЛИЕНТСКИЙ СЛОЙ                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│  ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐               │
│  │   Web    │    │  Mobile  │    │  Admin   │    │   API    │               │
│  │  Client  │    │   App    │    │  Panel   │    │  Client  │               │
│  └────┬─────┘    └────┬─────┘    └────┬─────┘    └────┬─────┘               │
│       │               │               │               │                     │
│       └───────────────┴───────────────┴───────────────┘                     │
│                                   │                                         │
│                                   ▼                                         │
│                          ┌─────────────────┐                               │
│                          │   API Gateway   │                               │
│                          │    (Laravel)    │                               │
│                          └────────┬────────┘                               │
└───────────────────────────────────┼─────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                          СЕРВИСНЫЙ СЛОЙ                                      │
├─────────────────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │    Auth      │  │   Exchange   │  │    Rate      │  │  Notification│    │
│  │   Service    │  │   Service    │  │   Service    │  │   Service    │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
│                                                                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │   Partner    │  │   Currency   │  │     API      │  │  Analytics   │    │
│  │   Service    │  │   Service    │  │   Service    │  │   Service    │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                           СЛОЙ ДАННЫХ                                        │
├─────────────────────────────────────────────────────────────────────────────┤
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐    │
│  │   Primary    │  │    Redis     │  │   External   │  │    File      │    │
│  │      DB      │  │    Cache     │  │    APIs      │  │   Storage    │    │
│  │   (MySQL)    │  │  (Session)   │  │  (Binance)   │  │   (Logos)    │    │
│  └──────────────┘  └──────────────┘  └──────────────┘  └──────────────┘    │
└─────────────────────────────────────────────────────────────────────────────┘
    </pre>
</div>

<h2>📂 Структура директорий проекта</h2>

<pre><code>dexa/
├── app/
│   ├── Console/
│   │   └── Commands/
│   │       ├── CheckRatesStale.php              # Проверка устаревших курсов
│   │       ├── ForceUpdateRates.php             # Принудительное обновление
│   │       ├── SyncCurrenciesCommand.php        # Синхронизация валют
│   │       ├── TestSmtpConnection.php           # Тест SMTP
│   │       ├── UpdateExchangeRates.php          # Обновление курсов
│   │       └── UpdateRatesFromConfiguredApis.php # Обновление из API (крон)
│   │
│   ├── Exports/
│   │   └── OrdersExport.php                     # Экспорт заявок в Excel
│   │
│   ├── Helpers/
│   │   └── ColorHelper.php                      # Утилиты для работы с цветами
│   │
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Admin/
│   │   │   │   ├── AdminController.php          # Управление администраторами
│   │   │   │   ├── ApiConfigController.php      # API конфигурации
│   │   │   │   ├── AuthController.php           # Аутентификация админов
│   │   │   │   ├── CityController.php           # Управление городами
│   │   │   │   ├── CurrencyController.php       # Управление валютами
│   │   │   │   ├── DashboardController.php      # Дашборд и отчеты
│   │   │   │   ├── DocumentationController.php  # Управление документацией
│   │   │   │   ├── ExchangeRateController.php   # Управление курсами
│   │   │   │   ├── OrderController.php          # Управление заявками
│   │   │   │   ├── PageController.php           # Управление страницами
│   │   │   │   ├── PartnerController.php        # Управление партнерами
│   │   │   │   ├── SettingController.php        # Настройки системы
│   │   │   │   ├── TwoFactorController.php      # 2FA для админов
│   │   │   │   └── UserController.php           # Управление пользователями
│   │   │   │
│   │   │   ├── Api/
│   │   │   │   └── ApiController.php            # Публичное API
│   │   │   │
│   │   │   ├── AuthController.php               # Аутентификация пользователей
│   │   │   ├── ContactController.php            # Контактная форма
│   │   │   ├── ExchangeController.php           # Обмен валют
│   │   │   ├── HomeController.php               # Главная страница
│   │   │   ├── PageController.php               # Динамические страницы
│   │   │   ├── ProfileController.php            # Личный кабинет
│   │   │   └── TwoFactorController.php          # 2FA для пользователей
│   │   │
│   │   └── Middleware/
│   │       ├── AdminAuthMiddleware.php          # Аутентификация админа
│   │       ├── AdminTwoFactorMiddleware.php     # 2FA для админа
│   │       ├── CheckAdminPermission.php         # Проверка прав админа
│   │       ├── CheckEmailVerified.php           # Проверка email
│   │       ├── CheckProfileAccess.php           # Доступ к профилю
│   │       ├── RateLimitMiddleware.php          # Ограничение запросов
│   │       ├── SetAdminSessionCookie.php        # Установка админ-сессии
│   │       ├── StartAdminSession.php            # Запуск админ-сессии
│   │       └── TwoFactorMiddleware.php          # 2FA для пользователей
│   │
│   ├── Mail/
│   │   ├── AdminOrderCreated.php                # Уведомление админу о заявке
│   │   ├── ApiStaleRatesNotification.php        # Уведомление о устаревших курсах
│   │   ├── BaseMailable.php                     # Базовый класс для писем
│   │   ├── ContactMessage.php                   # Контактная форма
│   │   ├── EmailVerification.php                # Подтверждение email
│   │   ├── NewExchangeOrder.php                 # Новая заявка на обмен
│   │   ├── OrderConfirmation.php                # Подтверждение заявки
│   │   ├── OrderStatusUpdated.php               # Обновление статуса
│   │   ├── OrderVerification.php                # Верификация заявки
│   │   └── PasswordReset.php                    # Сброс пароля
│   │
│   ├── Models/
│   │   ├── Admin.php                            # Администратор
│   │   ├── City.php                             # Город
│   │   ├── Currency.php                         # Валюта (с настройками 6 типов)
│   │   ├── Documentation.php                    # Управление документацией
│   │   ├── ExchangeApi.php                      # API конфигурация
│   │   ├── ExchangeOrder.php                    # Заявка на обмен
│   │   ├── ExchangeRate.php                     # Курс обмена
│   │   ├── ExternalRate.php                     # Внешний курс
│   │   ├── Page.php                             # Статическая страница
│   │   ├── Partner.php                          # Партнер
│   │   ├── Setting.php                          # Настройки системы
│   │   ├── User.php                             # Пользователь
│   │   └── UserWallet.php                       # Кошелек пользователя
│   │
│   ├── Providers/
│   │   ├── AppServiceProvider.php               # Регистрация команд
│   │   ├── DynamicMailConfigProvider.php        # Динамическая конфигурация почты
│   │   └── ExternalRateServiceProvider.php      # Регистрация сервисов
│   │
│   └── Services/
│       ├── RateCalculation/                     # КАЛЬКУЛЯТОРЫ КУРСОВ (новая архитектура)
│       │   ├── RateCalculatorInterface.php      # Интерфейс калькулятора
│       │   ├── RateCalculatorManager.php        # Менеджер калькуляторов
│       │   ├── PartnerManualRateCalculator.php  # Ручной курс партнера
│       │   ├── PartnerExternalRateCalculator.php # Внешний курс партнера
│       │   ├── GeneralManualRateCalculator.php  # Ручной общий курс
│       │   ├── GeneralExternalRateCalculator.php # Внешний общий курс
│       │   └── USDTCalculationCalculator.php    # Расчет через USDT
│       │
│       ├── ExchangeCalculationService.php       # Основная логика расчета
│       ├── ExternalRateService.php              # Обновление внешних курсов
│       ├── MailLoggerService.php                # Логирование почты
│       ├── RateUpdateService.php                # Обновление курсов
│       ├── TelegramService.php                  # Telegram уведомления
│       └── UniversalApiService.php              # Универсальный API клиент
│
├── bootstrap/
│   └── app.php                                   # Конфигурация приложения
│
├── config/
│   ├── admin_session.php                         # Настройки админ-сессии
│   ├── app.php                                   # Основные настройки
│   ├── auth.php                                  # Аутентификация (guards)
│   ├── beget.php                                 # Настройки для Beget хостинга
│   ├── cache.php                                 # Кэширование
│   ├── database.php                              # База данных
│   ├── filesystems.php                           # Файловая система
│   ├── google2fa.php                             # 2FA настройки
│   ├── logging.php                               # Логирование
│   ├── mail.php                                  # Почта
│   ├── queue.php                                 # Очереди
│   └── services.php                              # Сторонние сервисы
│
├── database/
│   ├── migrations/
│   │   ├── 0001_01_01_000000_create_users_table.php
│   │   ├── 0001_01_01_000001_create_cache_table.php
│   │   ├── 0001_01_01_000002_create_jobs_table.php
│   │   ├── 2026_01_18_000000_create_dexa_database.php  # Основная миграция
│   │   ├── 2026_02_21_000000_add_menu_settings_to_pages_table.php
│   │   ├── 2026_03_04_000000_add_2fa_fields_to_users_table.php
│   │   └── 2026_03_05_000000_add_2fa_fields_to_admins_table.php
│   │
│   └── seeders/
│       └── DatabaseSeeder.php                    # Начальные данные
│
├── public/
│   ├── css/
│   │   └── exchange-common.css                   # Общие стили
│   ├── js/
│   │   └── exchange-common.js                    # Общие JS функции
│   └── index.php
│
├── resources/
│   ├── docs/                                     # Файлы документации
│   │   ├── user/                                 # Документация для пользователей
│   │   └── developer/                            # Документация для разработчиков
│   │
│   └── views/                                    # Blade шаблоны
│       ├── admin/                                # Админ-панель
│       ├── auth/                                 # Аутентификация
│       ├── emails/                               # Email шаблоны
│       ├── errors/                               # Страницы ошибок
│       ├── layouts/                              # Базовые шаблоны
│       ├── pages/                                # Публичные страницы
│       ├── profile/                              # Личный кабинет
│       └── tracking.blade.php                    # Отслеживание заявок
│
├── routes/
│   ├── api.php                                   # API маршруты
│   ├── console.php                               # Cron задачи
│   └── web.php                                   # Веб-маршруты
│
└── storage/                                      # Логи, кэш, сессии
</code></pre>

<h2>🏗️ Компоненты системы</h2>

<div class="component">
    <div class="component-header">
        <div class="component-icon">🔐</div>
        <h3>Сервис аутентификации (Auth Service)</h3>
    </div>
    <p><strong>Назначение:</strong> Управление пользователями, сессиями, ролями и правами доступа.</p>

    <h4>Основные функции:</h4>
    <ul>
        <li><strong>Раздельные гарды:</strong> <code>web</code> (пользователи) и <code>admin</code> (администраторы)</li>
        <li><strong>Раздельные сессии:</strong> через отдельные таблицы <code>sessions</code> и <code>admin_sessions</code></li>
        <li><strong>Двухфакторная аутентификация (2FA):</strong> для пользователей и админов через Google Authenticator</li>
        <li><strong>Ролевая модель (RBAC):</strong> 4 уровня доступа (superadmin, admin, manager, moderator)</li>
        <li><strong>Granular permissions:</strong> детальные права на каждый модуль (view, create, edit, delete)</li>
        <li><strong>Управление сессиями:</strong> отдельные cookie для админ-панели (<code>dexaSuperUser</code>)</li>
        <li><strong>Email верификация:</strong> обязательное подтверждение email для пользователей</li>
        <li><strong>Сброс пароля:</strong> через email ссылку (действительна 24 часа)</li>
    </ul>

    <h4>Технологии:</h4>
    <div class="tech-stack">
        <span class="tech-item">Laravel Session</span>
        <span class="tech-item">bcrypt</span>
        <span class="tech-item">Google2FA</span>
        <span class="tech-item">CSRF Tokens</span>
        <span class="tech-item">Custom Middleware</span>
    </div>

    <h4>API endpoints:</h4>
    <div class="method-signature">
        POST   /login                          # Вход пользователя<br>
        POST   /register                       # Регистрация<br>
        POST   /logout                         # Выход<br>
        POST   /forgot-password                # Запрос сброса пароля<br>
        POST   /reset-password                 # Сброс пароля<br>
        GET    /verify-email/{token}           # Подтверждение email<br>
        GET    /2fa/verify                     # Форма 2FA<br>
        POST   /2fa/verify                     # Проверка 2FA кода<br>
        <br>
        POST   /dexaSuperUser/login            # Вход админа<br>
        POST   /dexaSuperUser/logout           # Выход админа<br>
        GET    /dexaSuperUser/2fa/verify       # Форма 2FA админа<br>
        POST   /dexaSuperUser/2fa/verify       # Проверка 2FA кода админа
    </div>
</div>

<div class="component">
    <div class="component-header">
        <div class="component-icon">💱</div>
        <h3>Сервис обмена (Exchange Service)</h3>
    </div>
    <p><strong>Назначение:</strong> Обработка операций обмена валют, расчет курсов с учетом наценок, управление заявками.</p>

    <h4>Основные функции:</h4>
    <ul>
        <li><strong>Создание заявок:</strong> клиентские и административные</li>
        <li><strong>Расчет курсов:</strong> по 6 типам транзакций с учетом наценок/скидок</li>
        <li><strong>Стаканы (Order Book):</strong> использование bid/ask цен из внешних API</li>
        <li><strong>Система приоритетов курсов:</strong>
            <ol>
                <li>Ручной курс партнера</li>
                <li>Внешний курс партнера</li>
                <li>Ручной общий курс</li>
                <li>Общий внешний курс</li>
                <li>Расчет через USDT (резерв)</li>
            </ol>
        </li>
        <li><strong>Автоматическая верификация:</strong> по email ссылке или коду</li>
        <li><strong>Управление статусами:</strong> pending, confirmed, processing, completed, cancelled, rejected</li>
        <li><strong>Лимиты:</strong> минимальные и максимальные суммы для каждой пары</li>
        <li><strong>Комиссии:</strong> процентная комиссия (может быть отрицательной для скидки)</li>
    </ul>

    <h4>Архитектура калькуляторов курсов (новое):</h4>
    <div class="flow-diagram">
        <div class="flow-step">
            <div class="flow-number">1</div>
            <div><strong>RateCalculatorManager</strong> - координатор, вызывает все калькуляторы по приоритету</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">2</div>
            <div><strong>PartnerManualRateCalculator</strong> - проверяет ручные курсы партнера</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">3</div>
            <div><strong>PartnerExternalRateCalculator</strong> - проверяет внешние курсы партнера</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">4</div>
            <div><strong>GeneralManualRateCalculator</strong> - проверяет общие ручные курсы</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">5</div>
            <div><strong>GeneralExternalRateCalculator</strong> - проверяет общие внешние курсы</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">6</div>
            <div><strong>USDTCalculationCalculator</strong> - резервный расчет через USDT</div>
        </div>
    </div>

    <h4>Основные методы ExchangeCalculationService:</h4>
    <div class="method-signature">
        <span class="method-return">array</span> getBestRate(<span class="method-param">int $fromCurrencyId</span>, <span class="method-param">int $toCurrencyId</span>, <span class="method-param">int|null $partnerId = null</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> calculateExchange(<span class="method-param">int $fromCurrencyId</span>, <span class="method-param">int $toCurrencyId</span>, <span class="method-param">float $amount</span>, <span class="method-param">int|null $partnerId = null</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">bool</span> isRateStale(<span class="method-param">int $fromCurrencyId</span>, <span class="method-param">int|null $staleThresholdMinutes = null</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> prepareFormulaInfo(<span class="method-param">Currency $fromCurrency</span>, <span class="method-param">Currency $toCurrency</span>, <span class="method-param">float $baseRate</span>, <span class="method-param">float $finalRate</span>, <span class="method-param">float $margin</span>, <span class="method-param">string $transactionType</span>, <span class="method-param">float $bidPrice = 0</span>, <span class="method-param">float $askPrice = 0</span>, <span class="method-param">string $usedStakan = ''</span>, <span class="method-param">float $manualMargin = 0</span>, <span class="method-param">bool $useExternal = true</span>)
    </div>
</div>

<div class="component">
    <div class="component-header">
        <div class="component-icon">📊</div>
        <h3>Сервис курсов (Rate Service)</h3>
    </div>
    <p><strong>Назначение:</strong> Получение, обработка и хранение курсов валют из внешних API.</p>

    <h4>Архитектура получения курсов:</h4>
    <div class="flow-diagram">
        <div class="flow-step">
            <div class="flow-number">1</div>
            <div><strong>ExternalRateService::updateRatesFromApi()</strong> - запускает обновление</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">2</div>
            <div>Выбирает активные API из таблицы <code>exchange_apis</code></div>
        </div>
        <div class="flow-step">
            <div class="flow-number">3</div>
            <div>Для каждого API вызывает <code>UniversalApiService::fetchFromApi()</code></div>
        </div>
        <div class="flow-step">
            <div class="flow-number">4</div>
            <div>UniversalApiService отправляет HTTP запрос (GET/POST) с учетом аутентификации</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">5</div>
            <div>Парсит ответ согласно <code>field_mapping</code> (JSON/XML/CSV)</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">6</div>
            <div>Форматирует пары валют согласно <code>pair_format</code></div>
        </div>
        <div class="flow-step">
            <div class="flow-number">7</div>
            <div>Сохраняет в таблицу <code>external_rates</code> (или обновляет существующие)</div>
        </div>
        <div class="flow-step">
            <div class="flow-number">8</div>
            <div>Создает обратные курсы (reverse_rates) для всех пар</div>
        </div>
    </div>

    <h4>Ключевые методы ExternalRateService:</h4>
    <div class="method-signature">
        <span class="method-return">int</span> updateRatesFromApi()
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> updateRatesFromSpecificApi(<span class="method-param">ExchangeApi $api</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">int</span> updatePartnerExternalRatesFromApi(<span class="method-param">int $partnerId</span>, <span class="method-param">ExchangeApi|null $api = null</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> checkSpecificApi(<span class="method-param">ExchangeApi $api</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">int</span> createReverseRates()
    </div>

    <h4>UniversalApiService - универсальный клиент:</h4>
    <div class="method-signature">
        <span class="method-return">array</span> fetchFromApi(<span class="method-param">ExchangeApi $api</span>, <span class="method-param">bool $testMode = false</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> testApi(<span class="method-param">ExchangeApi $api</span>, <span class="method-param">bool $useTestData = false</span>, <span class="method-param">bool $showAllRates = false</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">array|null</span> fetchOrderBookData(<span class="method-param">string $symbol</span>, <span class="method-param">array|null $mapping = null</span>, <span class="method-param">ExchangeApi|null $api = null</span>)
    </div>
</div>

<div class="component">
    <div class="component-header">
        <div class="component-icon">🤖</div>
        <h3>Сервис уведомлений (TelegramService)</h3>
    </div>
    <p><strong>Назначение:</strong> Отправка уведомлений о важных событиях в Telegram чат администраторов.</p>

    <h4>Основные функции:</h4>
    <ul>
        <li><strong>Новые заявки:</strong> уведомление администраторов о создании заявки</li>
        <li><strong>Контактная форма:</strong> уведомление о новом сообщении</li>
        <li><strong>Админские заявки:</strong> уведомление о заявках, созданных через админ-панель</li>
        <li><strong>Тестовые уведомления:</strong> для проверки настроек</li>
    </ul>

    <h4>Ключевые методы:</h4>
    <div class="method-signature">
        <span class="method-return">bool</span> sendExchangeOrderNotification(<span class="method-param">ExchangeOrder $order</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">bool</span> sendContactFormNotification(<span class="method-param">array $data</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">bool</span> sendAdminOrderNotification(<span class="method-param">array $orderData</span>)
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> checkBotStatus()
    </div>
    <div class="method-signature">
        <span class="method-return">array</span> sendTestNotification()
    </div>

    <h4>Настройки в .env:</h4>
    <pre><code>TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here</code></pre>
</div>

<h2>🗄️ Структура базы данных</h2>

<div class="database-schema">
    <h3 style="color: white;">Основные таблицы и связи:</h3>
    <pre><code style="color: #dfe6e9; font-size: 12px;">
-- =====================================================
-- ЯДРО СИСТЕМЫ (АУТЕНТИФИКАЦИЯ)
-- =====================================================
users (
    id, name, email, password, phone, telegram,
    role, is_active,
    email_verified_at, email_verification_token, verification_sent_at,
    google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)

admins (
    id, name, email, password, role, permissions, is_active,
    google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)

sessions (id, user_id, ip_address, user_agent, payload, last_activity)
admin_sessions (id, admin_id, ip_address, user_agent, payload, last_activity)
password_reset_tokens (email, token, created_at)

-- =====================================================
-- ВАЛЮТЫ И КУРСЫ
-- =====================================================
currencies (
    id, code, name, symbol, type, icon, is_active, sort_order,
    our_wallet, wallet_for_other_currencies,

    -- НАСТРОЙКИ ДЛЯ USDT
    usdt_to_other_crypto_margin, usdt_to_other_crypto_min_amount,
    usdt_to_rub_margin, usdt_to_rub_min_amount,

    -- НАСТРОЙКИ ДЛЯ RUB
    rub_to_usdt_margin, rub_to_usdt_min_amount,
    rub_to_other_crypto_margin, rub_to_other_crypto_min_amount,

    -- НАСТРОЙКИ ДЛЯ ДРУГИХ КРИПТО
    other_crypto_to_rub_margin, other_crypto_to_rub_min_amount,
    other_crypto_to_other_crypto_margin, other_crypto_to_other_crypto_min_amount
)

exchange_apis (
    id, name, base_url, endpoint, method,
    request_format, response_format,
    field_mapping (JSON), pair_format (JSON),
    authentication_type, api_key (encrypted), secret_key (encrypted),
    is_active, priority, timeout, retry_count,
    success_count, error_count, last_success_at, last_error_at
)

external_rates (
    id, partner_id, from_currency_id, to_currency_id,
    external_rate, source, last_updated,
    order_book_buy (JSON), order_book_sell (JSON),
    bid_price, ask_price, bid_volume, ask_volume, spread,
    volume_24h, change_24h
)

exchange_rates (
    id, partner_id, from_currency_id, to_currency_id,
    rate, external_rate_id,
    use_external_rate, use_partner_external,
    manual_margin_percentage,
    override_margin, override_min_amount,
    min_amount, max_amount,
    is_active, is_hidden, priority, last_updated
)

-- =====================================================
-- ГЕОГРАФИЯ И ПАРТНЕРЫ
-- =====================================================
cities (
    id, name, country, latitude, longitude, is_active, sort_order
)

partners (
    id, city_id, name, address, phone, email,
    latitude, longitude, working_hours, description,
    accepted_currencies (JSON), api_id,
    rating, total_reviews, is_active
)

-- =====================================================
-- ОПЕРАЦИИ (ЗАЯВКИ)
-- =====================================================
exchange_orders (
    id, order_number, user_id,
    from_currency_id, to_currency_id,
    partner_id, city_id,
    amount, rate, fee_percentage, fee_amount, total_receive,
    full_name, email, phone, wallet_address,
    status, transaction_type,
    admin_notes, user_notes,
    verification_code, verification_token,
    verified_at, expires_at,
    ip_address, user_agent
)

-- =====================================================
-- КЛИЕНТСКИЕ ДАННЫЕ
-- =====================================================
user_wallets (
    id, user_id, currency_id,
    wallet_address, network, wallet_name,
    is_default, is_active, notes
)

-- =====================================================
-- НАСТРОЙКИ
-- =====================================================
settings (
    id, key, value, type, group, options,
    default_cron_api_id, default_cron_api_name,
    update_interval_minutes, auto_update_enabled,
    primary_api_id, fallback_api_id,
    order_expire_minutes, auto_confirm_orders, require_verification,
    site_timezone, date_format,
    recaptcha_site_key, recaptcha_secret_key
)

pages (
    id, slug, title, content,
    meta_title, meta_description, meta_keywords,
    is_active, is_homepage, show_in_menu,
    show_logistics_in_menu, show_home_in_menu,
    page_type, sort_order
)
    </code></pre>
</div>

<h3>Связи между таблицами:</h3>
<ul>
    <li><strong>currencies → exchange_rates:</strong> одна валюта может участвовать во многих курсах (как from или to)</li>
    <li><strong>currencies → external_rates:</strong> одна валюта может участвовать во многих внешних курсах</li>
    <li><strong>cities → partners:</strong> один город может иметь много партнеров</li>
    <li><strong>partners → exchange_rates:</strong> один партнер может иметь много индивидуальных курсов</li>
    <li><strong>partners → external_rates:</strong> один партнер может иметь много своих внешних курсов</li>
    <li><strong>users → exchange_orders:</strong> один пользователь может иметь много заявок</li>
    <li><strong>users → user_wallets:</strong> один пользователь может иметь много кошельков</li>
    <li><strong>exchange_apis → external_rates:</strong> один API может быть источником для многих курсов</li>
    <li><strong>exchange_apis → partners:</strong> один API может быть назначен многим партнерам</li>
    <li><strong>external_rates → exchange_rates:</strong> внешний курс может использоваться во многих курсах обмена</li>
</ul>

<h2>🔌 Интеграции и API</h2>

<table>
    <thead>
    <tr>
        <th>Интеграция</th>
        <th>Тип</th>
        <th>Назначение</th>
        <th>Статус</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>Binance API</td>
        <td>REST (GET)</td>
        <td>Получение курсов криптовалют (USDT, BTC, ETH)</td>
        <td>✅ Активна</td>
    </tr>
    <tr>
        <td>Rapira.net API</td>
        <td>REST (GET/POST)</td>
        <td>Получение курсов и стаканов заявок</td>
        <td>✅ Активна</td>
    </tr>
    <table>
        <td>Telegram Bot API</td>
        <td>REST</td>
        <td>Уведомления администраторов</td>
        <td>✅ Активна</td>
        </tr>
        <tr>
            <td>SMTP сервер</td>
            <td>SMTP</td>
            <td>Отправка email уведомлений</td>
            <td>✅ Активна (настраивается)</td>
        </tr>
    </tbody>
</table>

<h2>🛡️ Безопасность</h2>

<h3>Многоуровневая защита:</h3>

<h4>1. Сетевой уровень:</h4>
<ul>
    <li>HTTPS с HSTS</li>
    <li>Защита от DDoS (Cloudflare)</li>
    <li>Ограничение доступа к админ-панели через middleware</li>
</ul>

<h4>2. Уровень приложения:</h4>
<ul>
    <li><strong>CSRF защита</strong> для всех форм (кроме API)</li>
    <li><strong>XSS фильтрация</strong> входных данных</li>
    <li><strong>SQL injection protection</strong> через Eloquent ORM и подготовленные запросы</li>
    <li><strong>Rate limiting</strong> для API endpoints (60 запросов в минуту)</li>
    <li><strong>Валидация</strong> всех входных данных через Form Requests</li>
    <li><strong>Раздельные сессии</strong> для пользователей и админов</li>
    <li><strong>Отдельная таблица сессий</strong> для админов (<code>admin_sessions</code>)</li>
</ul>

<h4>3. Уровень данных:</h4>
<ul>
    <li><strong>Шифрование</strong> API ключей в таблице <code>exchange_apis</code> (AES-256)</li>
    <li><strong>Хеширование паролей</strong> (bcrypt, cost 12)</li>
    <li><strong>Резервное копирование</strong> базы данных (настраивается через крон)</li>
</ul>

<h4>4. Аутентификация и авторизация:</h4>
<ul>
    <li><strong>Двухфакторная аутентификация (2FA)</strong> для пользователей и админов</li>
    <li><strong>Ролевая модель (RBAC)</strong> с 4 уровнями доступа</li>
    <li><strong>Granular permissions</strong> для каждого модуля (view, create, edit, delete)</li>
    <li><strong>Email верификация</strong> при регистрации</li>
    <li><strong>Токены для сброса пароля</strong> (действительны 24 часа)</li>
    <li><strong>Токены для подтверждения заявок</strong> (действительны 24 часа)</li>
</ul>

<h4>5. Middleware защита:</h4>
<div class="method-signature">
    <span class="method-return">admin.auth</span>          # Проверка аутентификации админа<br>
    <span class="method-return">admin.permission</span>    # Проверка прав доступа<br>
    <span class="method-return">admin.2fa</span>           # Проверка 2FA для админа<br>
    <span class="method-return">profile.access</span>      # Доступ к личному кабинету<br>
    <span class="method-return">email.verified</span>      # Проверка подтверждения email<br>
    <span class="method-return">rate.limit</span>          # Ограничение запросов (60/мин)<br>
    <span class="method-return">2fa</span>                 # Проверка 2FA для пользователей
</div>

<h2>🚀 Deploy и DevOps</h2>

<h3>Требования к серверу:</h3>
<ul>
    <li><strong>PHP:</strong> 8.1+ с расширениями (bcmath, ctype, fileinfo, json, mbstring, openssl, pdo, tokenizer, xml, zip, gd, redis)</li>
    <li><strong>База данных:</strong> MySQL 8.0+ или MariaDB 10.4+</li>
    <li><strong>Redis:</strong> 6.0+ (для кэширования и сессий)</li>
    <li><strong>Веб-сервер:</strong> Nginx 1.18+ или Apache 2.4+</li>
    <li><strong>Supervisor:</strong> для управления очередями (если используются)</li>
</ul>

<h3>Cron задачи (настроены в routes/console.php):</h3>
<pre><code># Обновление курсов из API по умолчанию (каждый час)
* * * * * cd /path/to/dexa && php artisan schedule:run >> /dev/null 2>&1

# Фактические задачи внутри schedule:
$schedule->command('rates:update-from-apis')->hourly()
$schedule->command('rates:check-stale --threshold=30 --send-email')->everyFifteenMinutes()
$schedule->command('rates:force-update')->hourly()
$schedule->command('currencies:sync')->dailyAt('03:00')</code></pre>

<h3>Переменные окружения (.env):</h3>
<pre><code>APP_NAME="DEXA"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
APP_TIMEZONE=UTC

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dexa
DB_USERNAME=dexa_user
DB_PASSWORD=your_password

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379

SESSION_DRIVER=redis
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis

MAIL_MAILER=smtp
MAIL_HOST=smtp.mail.ru
MAIL_PORT=465
MAIL_USERNAME=your-email@mail.ru
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=your-email@mail.ru
MAIL_FROM_NAME="DEXA Exchange"

TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id
</code></pre>

<h2>📊 Система приоритетов курсов (подробно)</h2>

<div class="rate-priority">
    <div class="priority-item">
        <span class="priority-number">1</span>
        <strong>Ручной курс партнера</strong> - самый высокий приоритет
        <ul>
            <li>Находится в таблице <code>exchange_rates</code> с заполненным <code>partner_id</code></li>
            <li>Поле <code>rate</code> заполнено, <code>use_external_rate = false</code></li>
            <li>Полностью игнорирует внешние API</li>
        </ul>
    </div>
    <div class="priority-item">
        <span class="priority-number">2</span>
        <strong>Внешний курс партнера</strong>
        <ul>
            <li>Находится в таблице <code>external_rates</code> с заполненным <code>partner_id</code></li>
            <li>ИЛИ <code>exchange_rates</code> с <code>use_partner_external = true</code></li>
            <li>Использует API партнера (если настроен) или общий API</li>
        </ul>
    </div>
    <div class="priority-item">
        <span class="priority-number">3</span>
        <strong>Ручной общий курс</strong>
        <ul>
            <li>В таблице <code>exchange_rates</code> с <code>partner_id = NULL</code></li>
            <li>Поле <code>rate</code> заполнено, <code>use_external_rate = false</code></li>
            <li>Применяется для всех партнеров, у которых нет своих курсов</li>
        </ul>
    </div>
    <div class="priority-item">
        <span class="priority-number">4</span>
        <strong>Общий внешний курс</strong>
        <ul>
            <li>В таблице <code>external_rates</code> с <code>partner_id = NULL</code></li>
            <li>ИЛИ <code>exchange_rates</code> с <code>use_external_rate = true</code></li>
            <li>Использует API по умолчанию</li>
        </ul>
    </div>
    <div class="priority-item">
        <span class="priority-number">5</span>
        <strong>Расчет через USDT</strong> (резервный вариант)
        <ul>
            <li>Вычисляется как <code>BTC → USDT → RUB</code> если нет прямого курса</li>
            <li>Использует курсы USDT для расчета кросс-курса</li>
            <li>Работает для любых пар, где есть через USDT</li>
        </ul>
    </div>
</div>

<h2>🧪 Тестирование</h2>
<p>В проекте используются следующие типы тестов:</p>
<ul>
    <li><strong>Unit тесты</strong> - для сервисов и моделей (PHPUnit)</li>
    <li><strong>Feature тесты</strong> - для контроллеров и API</li>
    <li><strong>Ручное тестирование</strong> через административную панель</li>
</ul>

<h3>Команды для тестирования:</h3>
<pre><code># Тест SMTP подключения
php artisan smtp:test admin@example.com

# Проверка устаревших курсов
php artisan rates:check-stale --threshold=30 --send-email

# Принудительное обновление курсов
php artisan rates:force-update

# Синхронизация валют
php artisan currencies:sync
</code></pre>

<h2>🔧 Устранение неисправностей</h2>

<table>
    <thead>
    <tr>
        <th>Проблема</th>
        <th>Причина</th>
        <th>Решение</th>
    </tr>
    </thead>
    <tbody>
    <tr>
        <td>502 Bad Gateway</td>
        <td>PHP-FPM не запущен</td>
        <td><code>sudo systemctl restart php8.1-fpm</code></td>
    </tr>
    <tr>
        <td>Ошибки миграции</td>
        <td>Нет прав на базу данных</td>
        <td>Проверить пользователя MySQL, выполнить <code>php artisan migrate:fresh</code></td>
    </tr>
    <tr>
        <td>Медленная загрузка</td>
        <td>Нет OPCache или Redis</td>
        <td>Включить OPCache, настроить Redis для сессий и кэша</td>
    </tr>
    <tr>
        <td>Не отправляются email</td>
        <td>Неправильные SMTP настройки</td>
        <td>Проверить в админ-панели Настройки → Email, выполнить <code>php artisan smtp:test</code></td>
    </tr>
    <tr>
        <td>Не обновляются курсы</td>
        <td>Не настроен API по умолчанию или проблемы с API</td>
        <td>В админ-панели Курсы обмена → Установить API по умолчанию → Обновить курсы</td>
    </tr>
    <tr>
        <td>Курсы на сайте не отображаются</td>
        <td>Нет записей в <code>external_rates</code> или <code>exchange_rates</code></td>
        <td>Запустить <code>php artisan rates:update-from-apis</code>, проверить настройки валют</td>
    </tr>
    </tbody>
</table>

<div class="note">
    <strong>📝 Примечание:</strong> Все логи хранятся в <code>storage/logs/laravel.log</code>. Для мониторинга используйте <code>tail -f storage/logs/laravel.log</code>.
</div>

<div class="warning">
    <strong>⚠️ Важно:</strong> Супер-администратор только один: <code>odeveloper@internet.ru</code>. Его нельзя удалить или изменить роль.
    Все остальные администраторы создаются с правами, которые задает супер-админ.
</div>

</body>
</html>