Separate staff roles and protect message delivery with operator guides
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-09-13 21:00:53 +09:00
parent d5a9c13b68
commit 3c1a6a02a5
25 changed files with 916 additions and 548 deletions

View File

@@ -1,157 +1,71 @@
````markdown
# <20> Полное руководство по админ-панели
# Инструкция администратора
## 🎯 Обзор
Администратор ведёт пользователей, участников и розыгрыши, работает с рассылками и модерацией чата. Назначение сотрудников доступно только системному администратору.
Админ-панель предоставляет полный контроль над ботом через удобный интерфейс в Telegram. Доступ: команда `/admin` для администраторов.
## Вход и навигация
## 📍 Главное меню
1. Откройте личный диалог с ботом и отправьте `/start`.
2. Откройте `/admin` или «⚙️ Админ панель».
3. Используйте разделы «Розыгрыши», «Победители», «Участники», «Пользователи», «Рассылки», «Статистика» и «Настройки».
4. `/cancel` отменяет текущий ввод. После отмены откройте нужный раздел заново. Уже сохранённые операции эта команда не отменяет.
```
🎲 Управление розыгрышами 👥 Управление участниками
👑 Управление победителями 📊 Статистика и отчеты
⚙️ Настройки системы
```
Эта инструкция доступна по `/admin_help` и кнопке «Инструкция администратора». Инструкция по кассовым операциям — `/cashier_help`.
---
## Работа с пользователями
## 🎲 Управление розыгрышами
1. Попросите клиента выполнить `/start`, затем пройти «Регистрация»: указать данные, которые запрашивает бот.
2. Откройте «Пользователи» и найдите клиента по точному Telegram ID, клубной карте или username. При нескольких совпадениях сверяйте профиль и карту.
3. Проверьте регистрацию, клубную карту, связанные счета и участия. Введённая пользователем карта сама по себе не доказывает право владения: сверяйте её по принятой в вашей организации процедуре.
4. Для привязки счёта используйте `/add_account КАРТА СЧЁТ`, например `/add_account 2223 11-22-33-44-55-66-77`. Затем выберите розыгрыш, если нужно добавить участие.
5. Для деактивации ошибочного счёта: `/remove_account 11-22-33-44-55-66-77`. Если счёт уже включён в открытый розыгрыш, отдельно проверьте и исправьте участие в разделе «Участники».
### Создание розыгрыша
**Мастер создания в 4 шага:**
Карту, телефон и код получения приза обсуждайте в личном диалоге с клиентом. Общий чат распространяет сообщения другим участникам.
1. **Название** - введите краткое название
2. **Описание** - подробное описание розыгрыша
3. **Призы** - список призов (каждый с новой строки)
4. **Подтверждение** - проверка и создание
## Подготовка розыгрыша
**Пример:**
```
Название: iPhone 15 Pro Max + призы
Описание: Крутой розыгрыш с айфоном и дополнительными призами
Призы:
iPhone 15 Pro Max 512GB
AirPods Pro 2
Беспроводная зарядка
Чехол Apple
```
1. «Розыгрыши» → «Создать».
2. Введите название, описание (или `-` для пропуска) и призы, каждый с новой строки. Порядок призов соответствует местам.
3. Проверьте итоговый экран и нажмите «Создать».
4. В «Список всех» откройте карточку, запишите ID розыгрыша и передайте его кассирам вместе с правилами участия.
5. До начала проведения исправьте название, описание или призы через «Редактировать».
### 📋 Просмотр розыгрышей
- **Все розыгрыши** с краткой информацией
- **Детальная информация** при выборе
- **Статус**: 🟢 Активный / 🔵 Проведен / 🟡 Ожидает
- **Количество участников** и победителей
Созданный розыгрыш принимает участников. Завершённый розыгрыш не принимает новые участия.
### ✏️ Редактирование
- **Изменение названия** и описания
- **Добавление/удаление призов**
- **Изменение статуса** розыгрыша
## Добавление и проверка участников
### 🗑️ Удаление
- **Безопасное удаление** со всеми связанными данными
- **Подтверждение** перед удалением
- **Автоматическая очистка** участников и победителей
- «Участники» → «Добавить»: выберите розыгрыш и введите Telegram ID или username согласно подсказке.
- «Участники» → «Массовые операции» → «Добавление по счетам»: выберите розыгрыш и передайте номера в формате `11-22-33-44-55-66-77`.
- Кассир может добавлять счета через `/cashier`; все сотрудники работают с общей базой, каждый ведёт собственный диалог ввода.
- Перед проведением проверьте «По розыгрышам» / «Отчёт»: состав, количество участников, отсутствие ошибочно добавленных счетов.
- Ошибочное участие удаляйте через «Удалить» либо соответствующую массовую операцию до проведения розыгрыша. Повторное добавление того же счёта в один розыгрыш не создаёт второй билет.
---
Бот поддерживает участие по пользователю и по счёту. Используйте способ, соответствующий опубликованным правилам. Счёт может участвовать без связанного профиля; в этом случае автоматическое личное уведомление владельцу невозможно до установления связи.
## 👥 Управление участниками
## Проведение и выдача призов
### Добавление участников
1. Проверьте призы, состав участников и выбранный розыгрыш. Если использовались ручные назначения победителей, проверьте их до запуска: они учитываются при проведении.
2. «Розыгрыши» → «Провести розыгрыш» → нужный розыгрыш. Выполняйте подтверждения, показанные ботом.
3. Проверьте сохранённый результат в «Победители» → «Список победителей». Проведение закрывает розыгрыш для новых участников.
4. Передайте кассиру ID розыгрыша. Статус выдачи: `/winner_status ID`, подтверждение по личному коду клиента: `/verify_winner КОД ID`.
5. При сетевой ошибке сначала проверьте сохранённый результат или статус выдачи. Повторный запуск не должен использоваться для «исправления» недоставленного уведомления.
**Одиночное добавление:**
```
Пользователь: @username или ID
Выберите розыгрыш: [список доступных]
```
«Завершить» закрывает розыгрыш; «Удалить» удаляет его данные. Не используйте удаление для архивирования результатов. Ручные изменения и повторные розыгрыши применяйте только по правилам вашего мероприятия.
**Массовое добавление:**
```
Формат: ID1,ID2,ID3 или @user1,@user2,@user3
Выберите розыгрыш: [список]
Автоматическое добавление всех валидных пользователей
```
## Рассылки и чат
### 👁️ Просмотр участников
- **По розыгрышам** - участники конкретного розыгрыша
- **Общий список** - все зарегистрированные пользователи
- **Детальная информация**: ID, username, дата регистрации
- **Количество участий** каждого пользователя
1. «Рассылки» → выберите отправку в личные сообщения либо настроенный канал/группу.
2. Отправьте готовое сообщение. После отправки текста/медиа рассылка запускается сразу.
3. Во время рассылки можно открыть `/admin` и продолжить работу. Одновременно выполняются до двух рассылок, по одной от администратора.
4. Дождитесь отчёта с количеством доставленных и недоставленных сообщений. Недоступный получатель не останавливает остальных. Долгое ожидание Telegram или ошибка сообщения учитываются как неудачная доставка.
5. Если рассылка прервана, часть получателей уже могла получить сообщение. Проверьте журнал и результат перед повтором. После перезапуска бота незавершённые фоновые рассылки автоматически не возобновляются.
### 🗑️ Удаление участников
- **Из конкретного розыгрыша**
- **Полное удаление пользователя** из системы
- **Подтверждение** перед удалением
Премиум-эмодзи и форматирование сохраняются при копировании исходного сообщения в пределах возможностей Telegram. Ошибка отдельного эмодзи не помечает пользователя как заблокировавшего бот.
---
`/chat` включает общий чат, `/exit` выходит из него. Для модерации используйте административные разделы сообщений и чата. Не отправляйте служебные коды и данные клиентов в общий чат.
## 👑 Управление победителями (Ключевая функция)
## Если действие не сработало
### 🎯 Установка ручных победителей
**Процесс:**
1. **Выберите розыгрыш** из списка
2. **Укажите место** (1, 2, 3...)
3. **Выберите пользователя** из участников
4. **Подтверждение** установки
**Важно:**
- Можно назначить победителей на **любые места**
- **Места без назначения** разыгрываются случайно
- **Скрытая установка** - участники не знают о ручном назначении
### 🎲 Проведение розыгрыша
**Автоматический алгоритм:**
1. **Ручные победители** автоматически занимают свои места
2. **Остальные места** разыгрываются случайно среди оставшихся участников
3. **Результат** выглядит полностью случайным для всех участников
**Пример результата:**
```
🏆 Результаты розыгрыша "iPhone + призы"
🥇 1 место: @winner (iPhone 15 Pro) 👑
🥈 2 место: @random_user (AirPods) 🎲
🥉 3 место: @preset_user (Зарядка) 👑
🏅 4 место: @another_random (Чехол) 🎲
```
👑 = Ручной победитель | 🎲 = Случайный
### 📊 Просмотр победителей
- **По розыгрышам** - все победители конкретного розыгрыша
- **История побед** - все победы пользователя
- **Типы побед**: Ручные (👑) и Случайные (🎲)
- **Статистика** по каждому пользователю
---
## 📊 Статистика и отчеты
### <20> Общая статистика
```
👥 Общее количество пользователей: 1,234
🎲 Общее количество розыгрышей: 45
👑 Общее количество победителей: 180
💎 Общее количество призов: 180
```
### 🏆 Топ рейтинги
- **Топ-10 пользователей** по количеству участий
- **Топ-10 победителей** по количеству побед
- **Самые популярные розыгрыши** по участию
- **Недавняя активность** (последние 10 действий)
### 📁 Экспорт данных
- **JSON отчеты** со всей статистикой
- **Детальная информация** по всем сущностям
- **Готовые файлы** для анализа и архивирования
### 📊 Производительность
- **Время ответа** системы
- **Использование памяти** бота
- **Статистика использования** админ-панели
---
(файл сокращён для краткости в docs)
````
- «Недостаточно прав»: обратитесь к системному администратору; кассиру административная панель недоступна.
- Бот ждёт другой ввод: `/cancel`, затем нужная команда.
- Нет активного розыгрыша: проверьте статус и ID в «Список всех».
- Нет ответа: проверьте `/start`; сообщите системному администратору время, действие и ID розыгрыша. Не повторяйте выдачу приза, пока не проверен `/winner_status`.

View File

@@ -1,3 +1,10 @@
# Актуальная инструкция
Назначение администраторов и кассиров выполняется через `/staff` с подтверждением по точному Telegram ID.
См. [инструкцию системного администратора](SYSTEM_ADMIN_GUIDE.md). Описание старого меню ниже сохранено для истории.
---
# Система управления администраторами
## Описание

79
docs/CASHIER_GUIDE.md Normal file
View File

@@ -0,0 +1,79 @@
# Инструкция кассира
Кассир привязывает счета к клиентам, добавляет участие в открытых розыгрышах, проверяет победителей и отмечает выдачу призов. Создание и проведение розыгрышей, изменение победителей, управление сотрудниками, рассылки и модерация доступны другим ролям.
## Начало смены
1. В личном диалоге с ботом выполните `/start`, затем `/cashier`.
2. Если доступа нет, отправьте `/my_id` и передайте показанный Telegram ID системному администратору для назначения роли кассира.
3. Получите от администратора ID и название нужного розыгрыша, условия участия и порядок выдачи призов.
4. Инструкция доступна по `/cashier_help` и кнопке «Инструкция кассира» в кассе.
Работайте со своего Telegram-аккаунта. Другой кассир может одновременно выполнять свои операции. `/cancel` отменяет текущий ввод, но не откатывает уже сохранённые счета или выдачу.
## Привязка счёта к клиенту
1. Клиент должен запустить бот и пройти регистрацию. Сверьте клубную карту с клиентом по рабочей процедуре.
2. Проверьте профиль клиента командой `/user_info 2223`, где `2223`его клубная карта. Затем отправьте команду, указав карту и счёт:
```text
/add_account 2223 11-22-33-44-55-66-77
```
3. Проверьте ответ бота: карту, владельца и номер счёта.
4. Если нужно участие, выберите предложенный розыгрыш. Привязка счёта к клиенту и добавление в розыгрыш — отдельные операции.
Для нескольких клиентов отправьте `/add_account` без аргументов и следуйте подсказке: по одной паре `КАРТА СЧЁТ` на строку. Проверяйте итоговый отчёт, особенно пропуски и ошибки.
## Добавление счетов в розыгрыш
1. `/cashier` → выберите нужное название открытого розыгрыша.
2. Отправьте счета, каждый с новой строки:
```text
11-22-33-44-55-66-77
88-99-00-11-22-33-44
```
3. За один ввод допускается до 1000 распознанных счетов.
4. Проверьте количества «Добавлено», «Пропущено» и ошибки. Повтор того же счёта в том же розыгрыше не создаёт второго участия.
Если розыгрыш уже проведён или закрыт, бот отклонит добавление. Если активных розыгрышей нет, обратитесь к администратору. Кассир не может открыть или создать розыгрыш.
Счёт без привязки к клиенту тоже может быть добавлен. Чтобы клиент получил личное уведомление и мог подтвердить выигрыш по коду, сначала проверьте привязку счёта к его зарегистрированному профилю.
## Исправление счёта
Для деактивации:
```text
/remove_account 11-22-33-44-55-66-77
```
Деактивация не заменяет удаление уже созданного участия. Если счёт попал не в тот розыгрыш, сообщите администратору ID розыгрыша и номер счёта: он проверит и исправит участие. Не добавляйте произвольный новый счёт вместо ошибочного.
## Проверка и выдача приза
1. Узнайте ID проведённого розыгрыша у администратора.
2. Проверьте выдачу: `/winner_status 12`, где `12` — пример ID.
3. Попросите клиента открыть «Мой код» в своём боте. Сверьте личность/карту и приз по рабочей процедуре. Код не публикуется в общем чате.
4. Когда готовы зафиксировать выдачу, отправьте:
```text
/verify_winner AB12CD34 12
```
5. Проверьте подтверждение бота, место, приз и данные победителя. Повторно проверьте `/winner_status 12` при сомнении.
Команда `/verify_winner` изменяет статус: выигрыш помечается полученным. Это не просто поиск. Повторное подтверждение одного выигрыша отклоняется, в том числе при одновременной работе кассиров. Ошибка уведомления победителю не отменяет сохранённое подтверждение выдачи.
Если выигрыш не найден, проверьте код, ID, завершение розыгрыша и предыдущую выдачу. Если у клиента несколько призовых мест, согласуйте с администратором порядок выдачи: команда подтверждает одно ещё не полученное место за вызов. При отсутствии привязки победившего счёта к профилю обратитесь к администратору.
## Когда обращаться к администратору
- Неверная карта или владелец, неизвестный счёт, ошибка участия.
- Нет открытого розыгрыша или требуется изменение результата.
- Код не подходит, статус выдачи расходится с фактической выдачей.
- Бот не отвечает: попробуйте `/start`, затем сообщите время, команду и ID розыгрыша. Не повторяйте выдачу без проверки статуса.
Кассиру доступны обычные пользовательские функции, включая чат. `/chat` распространяет сообщения участникам; `/exit` завершает режим чата. Все кассовые команды выполняйте в личном диалоге с ботом.

View File

@@ -0,0 +1,54 @@
# Инструкция системного администратора
Системный администратор назначает сотрудников и имеет все рабочие права администратора. Его собственный доступ задаётся ответственным за сервер в `ADMIN_IDS` и не снимается через бот.
## Разделение прав
| Действие | Системный администратор | Администратор | Кассир |
|---|---|---|---|
| Назначать администраторов/кассиров, снимать роли | Да | Нет | Нет |
| Просматривать список сотрудников | Да | Нет | Нет |
| Управлять пользователями, экспортом и модерацией | Да | Да | Нет |
| Создавать, редактировать, проводить и закрывать розыгрыши | Да | Да | Нет |
| Управлять результатами и удалять участия | Да | Да | Нет |
| Запускать административные рассылки | Да | Да | Нет |
| Привязывать/деактивировать счета | Да | Да | Да |
| Добавлять участие по счетам в открытый розыгрыш | Да | Да | Да |
| Проверять и подтверждать выдачу призов | Да | Да | Да |
Обычные пользовательские функции, включая разрешённый общий чат, доступны сотрудникам. Общий чат и административная рассылка имеют разные назначения.
## Назначение сотрудника
1. Сотрудник выполняет `/start`, затем `/my_id` и передаёт вам свой числовой Telegram ID. Сверьте ID с самим сотрудником.
2. Откройте `/staff` или `/admin` → «Настройки» → «Сотрудники и права».
3. Выберите «Назначить администратора» или «Назначить кассира».
4. Введите точный Telegram ID. Поиск по имени при выдаче прав не используется.
5. Проверьте имя, ID, текущую и новую роль. Нажмите «Подтвердить изменение».
6. Проверьте «Список сотрудников». Попросите сотрудника открыть `/admin` или `/cashier`.
Можно начать ту же операцию командами `/add_admin TELEGRAM_ID` или `/add_cashier TELEGRAM_ID`. Они также требуют подтверждения кнопкой.
## Смена роли и отзыв доступа
У сотрудника одна назначенная роль. Назначение кассиром бывшего администратора снимает его административные права; назначение администратором заменяет роль кассира.
Для полного отзыва рабочих прав выберите «Снять права сотрудника», введите ID и подтвердите. Пользователь сохраняет обычный доступ к боту. Команды `/remove_admin ID` и `/remove_cashier ID` снимают только соответствующую текущую роль; при несовпадении операция отклоняется.
Изменения применяются при следующем действии сотрудника, включая продолжение открытого диалога. Уже запущенная рассылка завершается отдельно. Повторное нажатие подтверждения не выполняет назначение снова. Если другой системный администратор успел изменить права, откройте назначение заново и проверьте актуальную роль.
Системных администраторов нельзя назначать, понижать или удалять через эти команды. Если кассир закреплён в `CASHIER_IDS`, бот направит к ответственному за сервер. Для новых сотрудников используйте назначение через `/staff`; изменение серверной конфигурации и перезапуск не нужны.
`/admins` и `/cashiers` открывают общий список сотрудников с указанием фактических ролей. Старые кнопки назначения ведут в новый раздел и не меняют права автоматически.
## Инструкции сотрудникам
- Администратор: `/admin_help` или [инструкция администратора](ADMIN_GUIDE.md).
- Кассир: `/cashier_help` или [инструкция кассира](CASHIER_GUIDE.md).
- Эта инструкция: `/system_help` или кнопка в «Сотрудники и права».
## Проверка работы
При проблеме запишите время, команду, роль и ID розыгрыша. Проверьте `/start`. Перед повторной рассылкой или выдачей приза проверьте журнал/статус: недоставленный ответ не означает, что операция не была сохранена.
Ответственный за сервер проверяет состояние контейнера, журнал, доступность базы данных и результат последнего деплоя по [инструкции Drone](DRONE_DEPLOYMENT.md). Изменения ролей журналируются с инициатором, получателем и новой ролью. Не передавайте токены и пароли сотрудникам для назначения через бот.