Skip to content

План разработки: модуль «Статистика» (часть 1)

Документ для поэтапной реализации. По мере выполнения отмечайте пункты: [ ][x].
Последнее обновление: 2026-08-26


1. Цель и scope

Модуль для учёта эффективности каналов трафика: ежедневный ввод фактических показателей сотрудниками (подрядчики, SMM), постановка месячных планов директором, отображение статистики с разрезами по дням, неделям и месяцу (% выполнения = факт / план).

Входит в часть 1

  • Роли: подрядчик (contractor), SMM-специалист (расширение существующей роли), МОП (mop) — роль создаётся, но отдельные поля МОП — этап 2
  • Справочник каналов трафика с привязкой к пользователям (роли contractor, smm_specialist)
  • Ежедневные отчёты по каналам (обязательная модалка в начале дня)
  • Месячные планы (директор)
  • Дашборд с разрезами по дням / неделям / месяцу

Не входит в часть 1 (следующие этапы)

  • Отдельные поля и отчёты для МОП
  • Интеграция с AmoCRM (автоподтягивание заявок)
  • Экспорт Excel/PDF, графики, Telegram-напоминания, аудит-лог планов

2. Согласованные решения

#ВопросРешение
1Формула «Конверсия в квал. заявку»кол-во квал. заявок / кол-во заявок
2Что заполняет МОП?Отдельные поля — следующий этап. В части 1 роль создаётся, права на просмотр статистики — да; ежедневная форма МОП — нет
3Один пользователь — несколько каналов?Да, через pivot traffic_channel_users
4Пропуск дня (отпуск, болезнь)Модалка при следующем входе за последний незаполненный рабочий день
5Выходные (сб, вс)Не требуют отчёта и не входят в план
6Распределение планадневной план = месячный / кол-во рабочих дней в месяце (пн–пт); в сб/вс план = 0
7Праздники РФНе учитываем в v1 (только сб/вс)

3. Роли и права доступа

3.1. Роли

SlugОписаниеСтатус
smm_specialistSMM-специалистУже есть — добавить permissions модуля
contractorПодрядчик (рекламные организации)Создать
mopМОП (менеджер отдела продаж)Создать (заполнение — этап 2)

Миграция по образцу:
backend/modules/Core/database/migrations/2026_07_13_180000_add_smm_specialist_role.php

3.2. Permissions (module: 'statistics')

PermissionРолиНазначение
view_statisticsdirector, administrator, superadmin, mop, contractor, smm_specialistДоступ к модулю в меню
view_statistics_alldirector, administrator, superadmin, mopВсе каналы и все сотрудники
view_statistics_owncontractor, smm_specialistТолько свои каналы
fill_statistics_dailycontractor, smm_specialistЗаполнение ежедневного отчёта по каналам
manage_statistics_channelsdirector, administrator, superadminCRUD каналов, привязка пользователей
manage_statistics_plansdirector, superadminУстановка месячных планов

Slug module в permissions должен совпадать с module в frontend/utils/menuConfig.jsstatistics.


4. Метрики канала

4.1. Заполняемые пользователем (факт)

ПолеКлюч APIТип
Охватreachinteger ≥ 0
Количество визитовvisitsinteger ≥ 0
Количество заявокapplicationsinteger ≥ 0
Кол-во квал. заявокqualified_applicationsinteger ≥ 0
Расходыexpensesdecimal ≥ 0

4.2. Вычисляемые (не хранить в БД)

МетрикаФормулаПри делении на 0
Конверсия в визитvisits / reachnull
Конверсия в заявкуapplications / visitsnull
Конверсия в квал. заявкуqualified_applications / applicationsnull
CPL фактexpenses / applicationsnull
CPQL фактexpenses / qualified_applicationsnull

Вычисление — в StatisticsMetricsService (backend) и дублирование для UI при необходимости.

4.3. Плановые значения (директор, на месяц)

Те же метрики, что заполняются вручную: reach, visits, applications, qualified_applications, expenses.
Конверсии и CPL/CPQL для плана считаются из плановых базовых полей теми же формулами.


5. Модель данных

5.1. ER-схема

traffic_channels
├── id
├── name
├── description (nullable)
├── is_active (boolean, default true)
├── created_at, updated_at

traffic_channel_users (pivot)
├── id
├── traffic_channel_id  → traffic_channels.id
├── user_id             → users.id
├── created_at, updated_at
UNIQUE (traffic_channel_id, user_id)

statistics_daily_reports
├── id
├── traffic_channel_id  → traffic_channels.id
├── user_id             → users.id (кто заполнил)
├── report_date         (date — за какой день данные)
├── reach, visits, applications, qualified_applications
├── expenses (decimal 12,2)
├── submitted_at (timestamp)
├── created_at, updated_at
UNIQUE (traffic_channel_id, report_date)

statistics_monthly_plans
├── id
├── traffic_channel_id  → traffic_channels.id
├── year (smallint)
├── month (tinyint 1–12)
├── reach_plan, visits_plan, applications_plan, qualified_applications_plan
├── expenses_plan (decimal 12,2)
├── created_by          → users.id
├── created_at, updated_at
UNIQUE (traffic_channel_id, year, month)

5.2. Ограничения

  • В pivot traffic_channel_users допускаются только пользователи с ролями contractor или smm_specialist
  • Один отчёт на канал за календарный день
  • Один план на канал за календарный месяц

6. Архитектура модуля

6.1. Backend — backend/modules/Statistics/

Statistics/
├── module.json
├── Providers/
│   └── StatisticsServiceProvider.php
├── routes/
│   └── api.php
├── Http/
│   ├── Controllers/
│   │   ├── TrafficChannelController.php
│   │   ├── DailyReportController.php
│   │   ├── MonthlyPlanController.php
│   │   └── StatisticsSummaryController.php
│   └── Requests/
│       ├── StoreTrafficChannelRequest.php
│       ├── StoreDailyReportRequest.php
│       └── StoreMonthlyPlanRequest.php
├── Services/
│   ├── StatisticsMetricsService.php
│   ├── StatisticsPlanDistributionService.php
│   ├── StatisticsPendingReportService.php
│   └── StatisticsWorkingDaysService.php
├── Models/
│   ├── TrafficChannel.php
│   ├── TrafficChannelUser.php
│   ├── StatisticsDailyReport.php
│   └── StatisticsMonthlyPlan.php
└── database/
    └── migrations/
        ├── ..._create_traffic_channels_table.php
        ├── ..._create_traffic_channel_users_table.php
        ├── ..._create_statistics_daily_reports_table.php
        ├── ..._create_statistics_monthly_plans_table.php
        └── ..._add_statistics_permissions.php

Регистрация: module.json → автоподключение в app/Providers/ModuleServiceProvider.php.
Шаблон: модуль BotStats (backend/modules/BotStats/).

6.2. Frontend

frontend/
├── pages/dashboard/statistics/
│   ├── index.vue              # дашборд: день / неделя / месяц
│   ├── channels.vue           # управление каналами (директор)
│   └── plans.vue              # месячные планы (директор)
├── components/statistics/
│   ├── StatisticsDailyReportModal.vue
│   ├── StatisticsChannelForm.vue
│   ├── StatisticsPlanForm.vue
│   ├── StatisticsMetricsTable.vue
│   └── StatisticsWeekBreakdown.vue
└── composables/
    └── useStatistics.ts

7. API

Префикс: /api/v1/statistics.
Middleware группы: ['api', 'auth:sanctum'] + per-route permission:*.

7.1. Каналы

МетодURLPermissionОписание
GET/channelsview_statistics_own / view_statistics_allСписок (фильтр по роли)
POST/channelsmanage_statistics_channelsСоздание
PUT/channels/{id}manage_statistics_channelsРедактирование
DELETE/channels/{id}manage_statistics_channelsДеактивация (is_active = false)
PUT/channels/{id}/usersmanage_statistics_channelsПривязка пользователей

7.2. Ежедневные отчёты

МетодURLPermissionОписание
GET/pendingfill_statistics_dailyНезаполненные дни по каналам пользователя
POST/daily-reportsfill_statistics_dailyОтправка факта
GET/daily-reportsview_statistics_own / view_statistics_allИстория с фильтрами

POST /daily-reports — тело запроса:

json
{
  "traffic_channel_id": 1,
  "report_date": "2026-08-25",
  "reach": 10000,
  "visits": 150,
  "applications": 12,
  "qualified_applications": 5,
  "expenses": 25000.00
}

7.3. Планы

МетодURLPermissionОписание
GET/plans?year=&month=&channel_id=view_statistics_allПланы за месяц
POST/plansmanage_statistics_plansСоздание / обновление плана
GET/plans/distribution?year=&month=&channel_id=view_statistics_*План по дням и неделям

7.4. Сводная статистика

МетодURLОписание
GET/summary?from=&to=&channel_id=&group_by=day|week|monthФакт + план + % выполнения

Пример фрагмента ответа /summary:

json
{
  "period": { "from": "2026-08-01", "to": "2026-08-25" },
  "group_by": "week",
  "items": [
    {
      "week": 34,
      "from": "2026-08-18",
      "to": "2026-08-24",
      "metrics": {
        "visits": { "fact": 420, "plan": 500, "completion_pct": 84.0 },
        "applications": { "fact": 35, "plan": 40, "completion_pct": 87.5 }
      }
    }
  ]
}

8. Бизнес-логика

8.1. Ежедневная обязательная модалка

Backend — StatisticsPendingReportService:

  1. Получить каналы, привязанные к текущему пользователю
  2. Для каждого канала найти последний незаполненный рабочий report_date (пн–пт, начиная с вчера и ранее)
  3. Суббота и воскресенье пропускать — не попадают в очередь
  4. Вернуть очередь: [{ channel_id, channel_name, report_date }, ...]

Frontend — StatisticsDailyReportModal.vue:

  • Подключить в layouts/dashboard.vue
  • При загрузке layout → GET /statistics/pending
  • Если очередь не пуста → v-dialog persistent (нельзя закрыть без submit)
  • Поля: канал (если несколько), дата (readonly), метрики факта
  • После успешного POST — убрать элемент из очереди; при пустой очереди — закрыть
  • Паттерн: frontend/components/inspection/inspectionCreateModal.vue

Права: только роли contractor, smm_specialist (permission fill_statistics_daily).

8.2. Распределение плана

StatisticsPlanDistributionService + StatisticsWorkingDaysService:

working_days_in_month = COUNT(даты месяца, где день недели пн–пт)

daily_plan[metric][date] =
  monthly_plan[metric] / working_days_in_month   // если date — рабочий день
  0                                              // если date — сб или вс

weekly_plan[metric][week] = SUM(daily_plan[metric] for dates in ISO week)

completion_pct = (SUM(fact) / SUM(plan)) * 100   // план периода — только рабочие дни

Недели: ISO (пн–вс). В выходные дни план = 0, отчёт не требуется.

API /plans/distribution возвращает workingDaysInMonth и isWorkingDay для каждого дня.

8.3. Разграничение доступа к данным

РольВидит
contractor, smm_specialistТолько каналы, к которым привязан
mopТолько своя статистика МОП (без каналов и «По сотрудникам»)
director, administratorВсе каналы + сотрудники + планы

9. Frontend — экраны

9.1. Дашборд /dashboard/statistics

  • Фильтры: месяц, канал, группировка (день / неделя / месяц)
  • Таблица: План | Факт | % выполнения по каждой метрике
  • Accordion / вкладки по неделям
  • Для director/mop — все каналы; для contractor/smm — только свои
js
definePageMeta({
  layout: 'dashboard',
  middleware: ['auth', 'role'],
  roles: ['director', 'administrator', 'superadmin', 'mop', 'contractor', 'smm_specialist'],
})

9.2. Каналы /dashboard/statistics/channels

  • Только manage_statistics_channels
  • CRUD + multiselect пользователей (роли contractor, smm_specialist)

9.3. Планы /dashboard/statistics/plans

  • Только manage_statistics_plans
  • Выбор месяца и канала, форма плановых значений, превью раскладки по неделям

9.4. Меню

Добавить в frontend/utils/menuConfig.js:

js
{
  module: 'statistics',
  title: 'Статистика',
  icon: 'mdi-chart-bar',
  to: '/dashboard/statistics',
  roles: ['director', 'administrator', 'superadmin', 'mop', 'contractor', 'smm_specialist'],
}

10. Этапы разработки

Этап 1 — Фундамент (2–3 дня)

Этап 2 — Ежедневные отчёты (2–3 дня)

Этап 3 — Планы и распределение (2–3 дня)

Этап 4 — Дашборд и разрезы (3–4 дня)

Этап 5 — Полировка (1–2 дня)

Оценка части 1: ~10–15 рабочих дней


11. Риски и митигация

РискМитигация
МОП без формы в части 1Роль и view_statistics_all создаются сразу; форма МОП — отдельная миграция/таблица на этапе 2
Конфликт с существующей ролью smm_specialistТолько добавить statistics-permissions, не менять текущие
Модалка блокирует работу при ошибке APIПоказать ошибку + «Повторить», не давать закрыть без успешного submit
Часовой пояс «начало дня»Carbon с timezone из config/app.php
Несколько незаполненных дней подрядОчередь в /pending, заполнение по одному дню за submit

12. Этап 2 — статистика МОП

Подробный план: STATISTICS_MOP_PLAN.md

Кратко:

  • Отдельная сущность / таблица отчётов МОП (собственные поля, без привязки к каналу)
  • Permission fill_statistics_mop_daily
  • Отдельная модалка ежедневного отчёта
  • Дашборд и месячные планы по каждому МОП

13. Связанные файлы проекта

НазначениеПуть
Регистрация модулейbackend/app/Providers/ModuleServiceProvider.php
Middleware permissionbackend/modules/Core/Http/Middleware/CheckPermission.php
Меню APIbackend/modules/Core/Http/Controllers/MenuController.php
Меню frontendfrontend/utils/menuConfig.js
Auth / modulesfrontend/stores/auth.js
API-клиентfrontend/composables/useApiFetch.ts
Dashboard layoutfrontend/layouts/dashboard.vue
Пример analytics-модуляbackend/modules/BotStats/
Пример persistent modalfrontend/components/inspection/inspectionCreateModal.vue
Пример migration ролейbackend/modules/Core/database/migrations/2026_07_13_180000_add_smm_specialist_role.php

14. Порядок первых коммитов

  1. Модуль + миграции + роли + permissions
  2. CRUD каналов (API + admin UI)
  3. Ежедневная модалка (happy path)
  4. Планы директора
  5. Дашборд с недельными разрезами