{{ pageTitle }}

Всего учеников: {{ dancerStats.total }} · активных: {{ dancerStats.active }} · в архиве: {{ dancerStats.archive }}
Все группы
{{ g.name }}
Не найдено
{{ initials(d.surname, d.first_name) }}
{{ d.surname }} {{ d.first_name }}
{{ d.patronymic }}
{{ statusLabel(d.status) }}
ДР {{ formatDate(d.birth_date) }} / {{ fmtYearsFull(calcAge(d.birth_date)) }}
Занятия Контакты {{ d.has_debt ? 'Долг' : 'Оплата' }}
{{ dancerSearch ? 'Ничего не найдено' : 'Нет данных' }}
{{ g.name || g.direction || '—' }}
{{ g.direction }}
{{ g.institution_name || '—' }}
{{ g.institution_address }}
{{ levelLabel(g.level) }} {{ g.status==='active'?'Активна':g.status==='archive'?'Архив':'Закрыта' }} {{ formatNum(g.subscription_price) }}₽
{{ groupSearch ? 'Ничего не найдено' : 'Нет данных' }}
{{ schedulePeriodLabel }}
Не найдено
{{ formatDate(grp.date) }}
{{ l.time_start }}–{{ l.time_end }}
{{ l.group_name || '—' }}
{{ l.institution_name || '—' }} · {{ l.teacher_name || 'без педагога' }}
{{ lessonKindLabel(l) }}
Нет данных
Запланировано Проведено Отменено / не проведено
{{ mo.label }} {{ mo.total }} занятий
{{ wd }}
{{ d.date.getDate() }}
{{ d.blueCount }} {{ d.greenCount }} {{ d.redCount }}
{{ WEEKDAY_FULL[(scheduleView.cursor.getDay()+6)%7] }}, {{ formatDate(ymd(scheduleView.cursor)) }} · {{ isoWeekNumber(scheduleView.cursor) }}-я неделя года
{{ l.time_start.slice(0,5) }}–{{ l.time_end.slice(0,5) }} {{ lessonKindLabel(l) }}
{{ l.group_name || '—' }}
{{ l.institution_name || '—' }} · {{ l.teacher_name || 'без педагога' }}
Нет занятий в этот день
{{ attend.lessonName }}
{{ idx+1 }}
{{ s.surname }} {{ s.first_name }}
Отмечено: {{ attend.students.filter(s=>s.present).length }} / {{ attend.students.length }}
Выберите занятие выше
{{ attendPeriodLabel }}
Не найдено
{{ l.group_name || '—' }}
{{ l.institution_name || '—' }} · {{ formatDate(l.lesson_date) }} {{ (l.time_start||'').slice(0,5) }}
{{ l.teacher_name || 'без педагога' }}
{{ l.present_count||0 }} / {{ l.total_students||0 }} 🤒 {{ l.sick_count }}
Нет занятий за выбранный период
Выберите филиал и группу
Ищу...
Ничего не найдено
Найдите танцора по фамилии
{{ p.dancer_name }}
{{ p.group_name }} · {{ p.period }}
₽{{ formatNum(p.amount) }} {{ payStatusLabel(p.status) }} {{ p.paid_at ? formatDate(p.paid_at) : '—' }}
Нет данных
{{ showPinModal.pin && showPinModal.pin.name }}

{{ showPinModal.pin.address || '—' }} · {{ showPinModal.pin.corpus }}

Уточнить точку на карте

Кликните на карте, чтобы поставить метку в нужном месте. Можно перетаскивать уже поставленную метку.

{{ coordPickModal.lat!=null ? coordPickModal.lat.toFixed(6) + ', ' + coordPickModal.lng.toFixed(6) : 'Метка не поставлена' }}

{{ payAction.mode==='partial' ? 'Частичная оплата' : payAction.mode==='edit' ? 'Изменить оплату' : 'Перерасчёт' }}

{{ payAction.dancerName }} · {{ payAction.groupName }}

Всего педагогов: {{ teacherStats.total }} · активных: {{ teacherStats.active }} · в архиве: {{ teacherStats.archive }}
{{ initials(t.surname, t.first_name) }}
{{ t.surname }} {{ t.first_name }}
{{ t.patronymic }}
{{ flagLabel(f) }}
{{ t.style || '—' }} · {{ fmtYears(t.experience_yrs) }}
{{ t.groups_list }}
{{ t.preferred_okrug_code }} · {{ t.preferred_rayon_name }}
{{ teacherStatusLabel(t.status) }} В резерве {{ t.staff_status==='active' ? 'Есть доступ' : 'Заблокирован' }} Нет доступа
Нет данных
{{ c.number }}
{{ c.dancer_name || '—' }}
{{ formatDate(c.signed_at) }}
{{ contractStatusLabel(c.status) }} СОД Подписан
Нет данных
{{ c.number }}
{{ c.title }}
{{ c.counterparty_name || '—' }}
{{ registryStatusLabel(c.status) }} {{ registryTypeLabel(c.contract_type) }}
Нет данных
Требуют ознакомления: {{ myPendingAcks.length }}
Откройте документ, ознакомьтесь и подтвердите согласие кнопкой ниже.
{{ j.title }}
{{ j.role_label || '—' }} · v{{ j.version }}
{{ j.status==='approved'?'Утверждена':'Черновик' }} Открыть файл Подтверждено {{ j.ack_done }}/{{ j.ack_total }}
Нет данных
Отправить на ознакомление
{{ ackAssignModal.title }}
{{ salaryPeriodLabel(p) }}
от
{{ salaryFromPicker.viewYear }}
{{ mName.slice(0,3) }}
до
{{ salaryToPicker.viewYear }}
{{ mName.slice(0,3) }}
{{ salaryPeriodRangeHint }}

Например, 10 — период считается с 10 числа по 9-е следующего месяца, а не с 1 по последнее число.

Ставки сотрудников
{{ t.surname }} {{ t.first_name }} {{ roleLabel(t.role) }} {{ salaryTypeLabel(t.salary_type) }}
Никого нет — измените фильтры
{{ s.teacher_name || '—' }}
{{ roleLabel(s.person_role) }} · {{ s.period }} · {{ s.lessons_cnt }} занятий
{{ s.status==='paid'?'Выплачено':'Начислено' }}
₽{{ formatNum(s.base_amount) }} +₽{{ formatNum(s.bonuses) }} = ₽{{ formatNum(s.total) }}
{{ filters.salary.period ? 'Нет данных за выбранный период' : 'Выберите период, чтобы увидеть данные' }}
Итого: {{ salaryTotals.count }} чел. · {{ salaryTotals.lessons }} занятий
₽{{ formatNum(salaryTotals.base) }} +₽{{ formatNum(salaryTotals.bonuses) }} = ₽{{ formatNum(salaryTotals.total) }}
Выбрано: {{ salarySelected.size }}

{{ salaryBreakdown.teacherName }}

{{ salaryBreakdown.period }} · Итого: ₽{{ formatNum(salaryBreakdown.total) }}

Системы расчёта

Готовые схемы оплаты — загружайте их в условия любого педагога или сотрудника, не вводя цифры заново

Вертикаль подчинения

% от выручки группы директору / рук. управляющему / управляющему — сверх зарплаты педагога, которая считается отдельно

{{ c.name }}
Размер: {{ c.size || '—' }} · {{ c.issued_name || 'на складе' }}
Вернуть до: {{ formatDate(c.return_by) }}
{{ {storage:'На складе',issued:'Выдан',lost:'Утерян'}[c.status] }}
Нет данных
{{ n.subject || notifTypeLabel(n.type) }}
{{ notifTypeLabel(n.type) }} · {{ n.sent_at ? formatDate(n.sent_at) : '—' }}
{{ n.channel }}
{{ {pending:'Ожидает',sent:'Отправлено',error:'Ошибка'}[n.status] }}
Нет данных
Нет данных
Не найдено
{{ l.name }}
{{ l.address || '—' }} · {{ l.corpus }}
{{ locationContactLabel(l) }} {{ (l.contacts && l.contacts[0] && l.contacts[0].phone) || l.contact_phone || '' }}
{{ s.name }}
Свободна В работе Архив
{{ locationSearch ? 'Ничего не найдено' : 'Нет данных' }}
Ничего не найдено
{{ branchHighlightLabel }} — найдено: {{ branchMapVisibleList.length }}
Готово: обработано {{ batchGeocodeProgress.total }}, найдено {{ batchGeocodeProgress.found }}, не найдено {{ batchGeocodeProgress.failed }} (наведите — список ненайденных)
Не задан ключ Яндекс.Карт (YANDEX_MAPS_API_KEY) — переключитесь на офлайн-карту или укажите ключ в .env.
Офлайн-карта показывает только уже сохранённые координаты. Поиск адреса ниже ищет по улицам и домам, уже загруженным в саму карту — для геокодирования совсем нового адреса переключитесь на Яндекс.
{{ branchMapError }}
Загрузка карты…
Zoom: {{ branchMapZoom.toFixed(1) }}
{{ b.kind==='location' ? 'Локация' : 'Филиал' }} {{ b.name }}
{{ b.address || '—' }}
Перетащите метку на карте…
Нет объектов с координатами
Всего кандидатов: {{ candidateStats.total }}
{{ c.surname }} {{ c.first_name }}
{{ c.patronymic }}
{{ c.style || '—' }} · {{ fmtYears(c.experience_yrs) }}
{{ c.preferred_okrug_code }} · {{ c.preferred_rayon_name }}
{{ '★'.repeat(c.scout_rating)+'☆'.repeat(5-c.scout_rating) }}
{{ candidateSearch ? 'Ничего не найдено' : 'Нет данных' }}
Не найдено
{{ b.name }}
Нет доступа к подробностям
{{ branchSearch ? 'Ничего не найдено' : 'Нет данных' }}
Ничего не найдено
{{ branchHighlightLabel }} — найдено: {{ branchMapVisibleList.length }}
Не найдено
Не задан ключ Яндекс.Карт (YANDEX_MAPS_API_KEY) — переключитесь на офлайн-карту или укажите ключ в .env.
Офлайн-карта показывает только уже сохранённые координаты. Поиск адреса ниже ищет по улицам и домам, уже загруженным в саму карту — для геокодирования совсем нового адреса переключитесь на Яндекс.
{{ branchMapError }}
Загрузка карты…
Zoom: {{ branchMapZoom.toFixed(1) }}
{{ b.kind==='location' ? 'Локация' : 'Филиал' }} {{ b.name }}
{{ b.address || '—' }}
Перетащите метку на карте…
Нет объектов с координатами
{{ branchNotesView.name }}
Общие заметки
{{ branchNotesView.notes }}
Заметки по контактам
{{ c.name || ('Контакт ' + (i+1)) }} · {{ c.position }}
{{ c.notes }}
Не найдено
{{ u.surname }} {{ u.first_name }}
{{ u.patronymic }}
{{ u.phone }}
{{ u.email }}
{{ rolesLabel(u.roles||[u.role]) }} {{ u.status==='active'?'Активен':u.status==='archive'?'Архив':'Заблокирован' }} {{ u.teacher_name }} Перс. данные Договор
{{ staffSearch ? 'Ничего не найдено' : 'Нет данных' }}
Редактирование структуры (холст) доступно только на компьютере — здесь показан список
{{ initials(item.node.surname, item.node.first_name) }}
{{ item.node.surname }} {{ item.node.first_name }} {{ rolesLabel(item.node.roles||[item.node.role]) }}
Структура пуста
Найдено: {{ trashData.found }} из {{ trashData.total }}
{{ it.name }}
{{ it.section_label }} {{ it.institution_name }}
{{ it.deleted_by_name }} ({{ it.deleted_by_role }}) · {{ formatDateTime(it.deleted_at) }}
{{ trashData.total ? 'По фильтрам ничего не найдено' : 'Корзина пуста' }}
Управление должностями

{{ roleManageError }}

У директора всегда полный доступ ко всем разделам — это не редактируется.
{{ m.label }}
Выберите сотрудника, чтобы настроить персональные права
{{ docTypeLabel(d) }}
Документы не загружены
Удалить документ?
{{ docConfirmDelete.title }}
Файл будет удалён безвозвратно
{{ p.title }}
{{ taskPriorityLabel(p.priority) }}
{{ m.assignee_name }} · {{ taskStageLabel(m.stage) }}
Нет групповых проектов
Поставил: {{ g.creator_name }}
{{ t.title }} → {{ t.assignee_name }} {{ taskStageLabel(t.stage) }}
Нет задач
{{ taskModal.mode==='create' ? 'Новая задача' : 'Задача' }}

Можно выбрать несколько — каждому создастся своя задача со своим этапом.

Комментарии
{{ c.author_name }} · {{ formatDateTime(c.created_at) }}
{{ c.text }}
Пока нет комментариев
{{ registryModal.id ? 'Договор' : 'Новый договор' }} {{ registryStatusLabel(registryModal.status) }}
Файл договора
Текущий файл Файл не загружен
Лист согласования
{{ a.step_order }}. {{ a.approver_name }} {{ a.status==='approved'?'Согласовано':a.status==='rejected'?'Отклонено':'Ожидает' }}
Выберите согласующих (по порядку):
Отправлено в Диадок, ожидает подписания контрагентом.
Договор подписан и активен.
{{ jobDescModal.id ? 'Должностная инструкция' : 'Новая инструкция' }}
Запустить бекап вручную
Сценарии автоматического бекапа
Сценариев пока нет — добавьте первый
{{ s.name }} {{ s.enabled ? 'Включён' : 'Выключен' }}
{{ s.types.map(t=>BACKUP_TYPE_LABELS[t]||t).join(', ') }} · {{ s.frequency==='weekly' ? ('раз в неделю, '+BACKUP_WEEKDAY_LABELS[(s.day_of_week||1)-1]) : 'каждый день' }} в {{ (s.time_of_day||'').slice(0,5) }} (МСК) · {{ s.destinations.map(d=>d==='local'?'сервер':'Яндекс.Диск').join(' + ') }} · хранить {{ s.retention_days }} дн.
Восстановление базы данных из файла
Загрузите файл .sql или .sql.gz — текущая база данных будет полностью перезаписана его содержимым. Перед восстановлением система автоматически сохранит копию текущей базы в «Файлы на сервере», чтобы это можно было отменить.
Файлы на сервере
Локальных бекапов пока нет
{{ f.filename }}
{{ BACKUP_TYPE_LABELS[f.type] || f.type }} · {{ (f.size_kb/1024).toFixed(1) }} МБ · {{ formatDateTime(f.created_at) }}
История запусков
{{ BACKUP_TYPE_LABELS[b.type] || b.type }} · {{ b.destination==='local' ? 'Сервер' : 'Яндекс.Диск' }}
{{ formatDateTime(b.started_at) }} → {{ formatDateTime(b.finished_at) }}
{{ {success:'Успех',failed:'Ошибка',partial:'Частично'}[b.status] }}
{{ b.file_size_kb ? (b.file_size_kb/1024).toFixed(1)+' МБ' : '—' }}
Нет данных
Новый пароль — {{ passwordModal.staffName }}
{{ scenarioModal.id ? 'Сценарий бекапа' : 'Новый сценарий' }}
Что бекапить
Куда сохранять
{{ r.user_name ? r.user_name.trim() : '—' }} · {{ auditActionLabel(r.action) }}
{{ r.entity }} #{{ r.record_id }} · {{ formatDateTime(r.timestamp) }}
Было
{{ JSON.stringify(r.old_value, null, 1) }}
Стало
{{ JSON.stringify(r.new_value, null, 1) }}
Нет данных
{{ auditLog.page }} / {{ auditLog.pages }}
{{ c.name || (c.type==='dm' ? 'Личная переписка' : 'Группа') }}
{{ c.participants }}
{{ c.message_count }} сообщ. · {{ c.deleted_count }} удалено
Нет диалогов
Выберите диалог слева
{{ m.author_name }} · {{ formatDateTime(m.created_at) }} · удалено {{ m.deleted_by_name ? '('+m.deleted_by_name+')' : '' }} {{ formatDateTime(m.deleted_at) }}
{{ m.call_status==='completed' ? (m.call_mode==='video' ? 'Видеозвонок' : 'Аудиозвонок') : (m.call_status==='declined' ? 'Звонок отклонён' : 'Пропущенный звонок') }}
{{ formatCallDuration(m.voice_duration) }}
{{ m.file_name }}
{{ m.text }}
Сообщений нет
{{ s.user_name ? s.user_name.trim() : '—' }}
Вход: {{ s.login_at ? formatDateTime(s.login_at) : '—' }}
Выход: {{ s.logout_at ? formatDateTime(s.logout_at) : '—' }}
{{ formatSessionDuration(s.duration_sec) }} {{ s.status==='active' ? 'В сети' : s.status==='expired' ? 'Сессия истекла' : 'Завершена' }}
Нет данных
{{ auditSessions.page }} / {{ auditSessions.pages }}
v{{ v.version }} {{ v.title }} Авто Вручную {{ v.files_changed }} файлов · {{ v.change_pct }}%
{{ formatDate(v.released_at) }}
{{ v.notes }}
Нет данных о версиях
Сбор за месяц
{{ reports.totalRevenue ? '₽'+formatNum(reports.totalRevenue) : '—' }}
Долги
{{ reports.totalDebt ? '₽'+formatNum(reports.totalDebt) : '—' }}
Посещаемость
{{ reports.avgAttendance ? reports.avgAttendance+'%' : '—' }}
Детальные отчёты по финансам и посещаемости

{{ gamesArcadeGame ? gamesArcadeGame.name : 'Выберите игру' }}

{{ gamesScoreLabel }}
Рейтинг игроков
{{ g.name }}
{{ idx+1 }} {{ entry.name }} {{ entry.score }}
Пока никто не играл
{{ dancerGroupsView.name }}
Загрузка...
{{ dancerGroupsView.search ? 'Ничего не найдено' : 'Группы не назначены' }}
{{ g.name }}
{{ g.institution_name }} · {{ g.schedule_text }}
с {{ formatDate(g.joined_at) }}
{{ g.status==='active'?'Активна':'Архив' }}
{{ dancerPaymentsView.name }}
Загрузка...
{{ dancerPaymentsView.search ? 'Ничего не найдено' : 'Нет платежей' }}
Дата Период Группа Сумма Статус
{{ p.paid_at ? formatDate(p.paid_at) : '—' }} {{ p.period || '—' }} {{ p.group_name || '—' }} {{ formatNum(p.amount) }} ₽ {{ p.status==='paid'?'Оплачено':p.status==='partial'?'Частично':'Долг' }}
Итого: {{ dancerPaymentsFiltered.length }} записей {{ formatNum(dancerPaymentsFiltered.reduce((s,p)=>s+(+p.amount||0),0)) }} ₽
{{ dancerContactsView.name }}
Ученик
{{ dancerContactsView.phone }}
{{ dancerContactsView.email }}
{{ dancerContactsView.address }}
Контакты
Контакты не указаны
{{ c.name || ('Контакт ' + (i+1)) }} {{ c.relation === 'другое' ? (c.relation_custom || 'другое') : c.relation }}
{{ c.email }}
{{ c.notes }}
Скопировано
{{ photoGalleryView.name }} — Фото
Нет фото
{{ videoGalleryView.name }} — Видео
Моя корзина — {{ sectionTrash.label }}
{{ it.name }}
{{ formatDateTime(it.deleted_at) }}
Пусто

Полная очистка корзины

В корзине находится {{ trashData.total }} объектов. Все они будут окончательно удалены. Это действие невозможно отменить.

Для подтверждения введите: УДАЛИТЬ ВСЁ

Резюме — быстрый просмотр Открыть в новой вкладке
Формат файла не поддерживает встроенный просмотр — откройте в новой вкладке
{{ attendMarkView.lesson?.group_name }}
{{ attendMarkView.lesson?.institution_name }} · {{ formatDate(attendMarkView.lesson?.lesson_date) }} {{ (attendMarkView.lesson?.time_start||'').slice(0,5) }} · {{ attendMarkView.lesson?.teacher_name || 'без педагога' }}
Посетили: {{ attendPresentCount }} / {{ attendMarkView.students.length }}
Загрузка...
{{ grp.letter }}
{{ s.surname }} {{ s.first_name }} 🤒
Отметить посещение
Болеет
Убрать из группы
Исправить ФИО
В группе нет учеников
Исправить ФИО
Добавить человека

Например, для пробного занятия — сразу добавит в группу и позволит отметить посещение.

{{ groupStudentsView.name }} — Ученики
{{ groupStudentsView.addSearch ? 'Не найдено' : 'Начните вводить имя...' }}
{{ d.surname }} {{ d.first_name }} {{ fmtYearsFull(calcAge(d.birth_date)) }}
Загрузка...
{{ groupStudentsView.search ? 'Ничего не найдено' : 'В группе нет учеников' }}
{{ (d.surname||'?')[0] }}
{{ d.surname }} {{ d.first_name }} {{ d.patronymic }}
{{ formatDate(d.birth_date) }} · {{ fmtYearsFull(calcAge(d.birth_date)) }}
Дубликат (ID {{ d.id }})
{{ groupTeacherView.name }} — Педагог
{{ groupTeacherView.teacher_name }}
Педагог не назначен
{{ groupManagerView.name }} — Управляющий
{{ groupManagerView.manager_name }}
Управляющий не назначен
Изменить управляющего может только Руководитель или Директор
{{ institutionManagerView.name }} — Управляющий
{{ institutionManagerView.manager_name }}
Управляющий не назначен
Изменить управляющего может только Руководитель или Директор
{{ staffQuotaView.name }} — Штатный план

Укажите нужное количество — появятся поля для выбора конкретных сотрудников на каждое место. Не ограничивает фактическое назначение.

— не выбрано —
{{ s.surname }} {{ s.first_name }}
Не найдено
— не выбрано —
{{ s.surname }} {{ s.first_name }}
Не найдено
— не выбрано —
{{ s.surname }} {{ s.first_name }}
Не найдено
Перевод в филиал

Перевести «{{ locationConvertView.location?.name }}» в раздел «Филиалы»?

После перевода объект будет редактироваться только в разделе «Филиалы», а здесь останется доступен для просмотра.

Можно назначить позже в разделе «Филиалы».

«{{ locationConvertView.doneName }}» переведён в работу.

Объект теперь в разделе «Филиалы».

{{ candidateHireView.name }} — {{ candidateHireView.action==='reserve' ? 'В резерв' : 'В штат' }}

Создаст профиль педагога в разделе «Педагоги» со статусом «На рассмотрении». Доступ к системе можно выдать позже — после назначения групп и филиала.

Расписание
{{ modalTitle }}
{{ activeHint }}
Скопировано!
{{ c.flag }} {{ c.name }} {{ c.dial }}
Чат {{ badges.chat }}
{{ chatView==='thread' && activeChatConv ? activeChatConv.name : 'Чат' }}
Реакции
{{ r.emoji }} {{ r.staff_name }} {{ formatDateTime(r.created_at) }}
Нет реакций
Переслать в...
{{ c.name }}
Участники чата
{{ m.name }} Админ
Загрузка...
Ссылка:{{ chatCallInvite.url }}
Пароль:{{ chatCallInvite.password }}
Действует до {{ formatDateTime(chatCallInvite.expires_at) }}, одноразовая
{{ (callState.peerName||'?').trim().charAt(0).toUpperCase() }}
{{ callState.peerName }}
{{ callState.isGroup ? 'Групповой ' : '' }}{{ callState.mode==='video' ? 'видеозвонок' : 'аудиозвонок' }}...
Отклонить
Принять
{{ callState.isGroup ? 'Групповой звонок' : callState.peerName }}
{{ callState.peerName }}
{{ callState.isGroup ? 'Звоним группе...' : 'Вызов...' }}
Переподключение...