Skip to content

Latest commit

 

History

22 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

taskCRM

Веб-панель поверх Битрикс24 и 1С:УНФ: закрытые часы сотрудников, доска задач по проектам, дашборд, проверка качества задач, KPI и создание документов в УНФ одной кнопкой.

Развитие проекта task2bitrix24: сохранён весь функционал «Закрытых часов», сверху добавлена навигация с разделами.


Функциональность

Отчёт «Закрытые часы» → Excel

Выбираете месяц — получаете .xlsx со списанными часами по каждому сотруднику. Отчётный месяц определяется датой выполнения работ из результата задачи, а не датой её закрытия: работы часто сдают в другом месяце, и в счёт должен попасть тот месяц, когда работа фактически сделана.

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

Отчёт по выбранным компаниям

Тот же период, но только задачи выбранных клиентов, и в файле единственный лист Все задачи. Компании выбираются чипами (крестик — убрать), в выпадающем списке остаются только невыбранные. Целевые клиенты подставляются сразу (REPORT_DEFAULT_COMPANY_IDS). Справочник CRM кешируется в data/companies.json на сутки.

Доска задач

Колонки — проекты (рабочие группы Битрикс), листаются вправо; задачи внутри колонки листаются вниз. Две вкладки: «Активные задачи» и «Закрытые задачи» за выбранный месяц. Показываются задачи всей команды.

Дашборд — три разреза

Один и тот же месяц в трёх разрезах, переключаются вкладками:

  • По сотрудникам — кто сколько закрыл часов;
  • По организациям — сколько часов ушло каждому клиенту;
  • По проектам — сколько часов съел каждый проект (рабочая группа Битрикс).

Часы берутся из списаний, задачи считаются уникальными: задача с тремя списаниями — это одна задача. Строки «Без компании» и «Без проекта» всегда в конце.

Рядом с часами видно, что изменилось с прошлого обновления: зелёный +2.50 ч у того, кто прибавил, красный −1.00 ч у того, у кого стало меньше. Сравнение идёт с предыдущим снимком того же месяца, поэтому у самого первого снимка изменений нет — сравнивать не с чем. Считается в минутах, чтобы округление не рисовало «+0».

Страница не ходит в Битрикс — читает снимок data/dashboard-YYYY-MM.json. Снимок пересоздаётся при выгрузке Excel, при создании учётов времени в УНФ и вручную кнопкой «Обновить за этот месяц». Снимки, снятые до появления вкладок, содержат только сотрудников — организации и проекты появятся после следующего обновления.

Проверка корректности заполнения задач

Проверяет задачи, закрытые в выбранном месяце, и показывает, какие нельзя выставить в счёт как есть. Результат виден на экране и выгружается в Excel (листы Свод и Задачи с замечаниями).

Красный флаг:

  • не списаны часы;
  • нет результата задачи или в нём нет даты выполнения работ;
  • месяц в результате не совпадает с месяцем закрытия;
  • не заполнен элемент CRM;
  • не заполнен проект у ключевого клиента (QUALITY_RED_FLAG_COMPANY_IDS / ..._NAMES). У остальных компаний проект не проверяется.

Жёлтое предупреждение:

  • результат длиннее QUALITY_RESULT_LEN_WARN (300) символов — менеджер не вставит такой текст в счёт;
  • дата выполнения работ записана не в каноническом формате (дата выполнения работ ДД.ММ.ГГГГ).

Последний результат кешируется в data/quality-YYYY-MM.json, поэтому выгрузка Excel не опрашивает Битрикс повторно.

Расчёт зарплаты

Раздел из трёх вкладок, заменяющий ручной Excel: KPI по задачам (с галочкой, кому его начислить), Условия, оклады и ставка (схема оплаты по каждому сотруднику) и Расчёт ЗП (часы + KPI + оклад + ручные премии и штрафы = сумма к выплате).

Четыре схемы оплаты: несгораемый оклад, оклад + ставка, только ставка, фикс. Условия хранятся помесячно с журналом «кто и что поменял». Доступ только у администратора.

Подробно — Расчёт зарплаты.

KPI по созданным задачам

Считает премию постановщика задач по трём формулам за выбранный месяц: объём, отсутствие просрочек и доля задач по шаблону. Результат — таблица по людям и список задач; выгружается в Excel, кешируется в data/kpi-YYYY-MM.json.

Документы в 1С:УНФ

Две кнопки создают документы прямо из отчёта:

  • «Создать Учеты времени»Документ.УчетВремени за первую полную неделю месяца, часы разложены по дням со временем «с»/«по». Если часов больше 168, в одну строку они не помещаются — добавляется вторая строка табличной части, и остаток раскладывается в ней снова с понедельника;
  • «Создать Задания на работу»Документ.ЗаданиеНаРаботу на 1-е число следующего месяца, план = факт × 1.1.

Документы проводятся автоматически (UNF_TIME_POST_DOCUMENTS). Повторный запуск не создаёт дублей. Подробно — Интеграция с 1С:УНФ через OData.

Роли и администрирование

Роль Просмотр Excel Документы УНФ Расчёт ЗП Админка Запросы в Битрикс Данные
Администратор да да да да да да открытые
Сотрудник да да нет нет нет да открытые
Внешний да нет нет нет нет да обезличенные
Гость (без пароля) да нет нет нет нет нет обезличенные

Пользователи хранятся в data/users.json (пароли — password_hash), учётка из APP_AUTH_USER / APP_AUTH_PASSWORD — всегда администратор.

Гостевой вход без пароля

Сайт открывается любому: без логина посетитель получает роль Гость — данные обезличены, кнопки недоступны, скачать или создать он ничего не может. На месте «Администрирования» у него кнопка ХОЧУ ТАКЖЕ (GUEST_TELEGRAM_URL, по умолчанию https://t.me/DED_GENA).

Обезличивание не превращает страницу в тарабарщину: вместо ФИО и названий подставляются «Сотрудник #3», «Компания #7», «Проект #2», «Задача #15» — понятно, что за данные, но не видно, какие именно. Номер выдаётся по порядку первого появления в пределах страницы, поэтому одно и то же имя везде на странице выглядит одинаково, а разные сущности не сливаются. Часы и счётчики скрыты как •••, изменения на дашборде показываются только направлением (▲/▼) без величины.

Своим войти: кнопка «Войти» справа в меню (она ведёт на ?login=1 — браузер покажет форму пароля только в ответ на 401, поэтому нужен отдельный адрес).

Гостю запрещены живые запросы в Битрикс — страница открыта всему интернету, а каждая сборка доски стоит десятков REST-запросов:

  • доска задач отдаётся из общего кеша data/board-<режим>-<месяц>.json, он пересобирается не чаще раза в BOARD_CACHE_TTL (15 минут), причём пересобирает всегда только один процесс — остальные в это время получают предыдущую версию;
  • KPI и проверка задач показывают последний сохранённый снимок, пересчёт по ?run игнорируется;
  • дашборд и так читает снимок, поэтому работает у гостя в полном объёме.

Выключить гостевой режим и вернуть закрытый сайт: APP_GUEST_ACCESS=0 (или LOCAL_APP_GUEST_ACCESS в config.local.php).


Как подключаемся к Битриксу

Используется входящий webhook Bitrix24 REST API. Реальный URL в репозитории не хранится и задаётся одним из двух способов:

# переменная окружения (рекомендуется на сервере)
BITRIX_WEBHOOK="https://<portal>.bitrix24.ru/rest/<user-id>/<webhook-code>/"

либо константой LOCAL_BITRIX_WEBHOOK в config.local.php (файл в .gitignore). Переменная окружения приоритетнее — см. configValue() в config.php.

ТранспортbitrixRequest() в lib.php:

  • POST, application/x-www-form-urlencoded, URL склеивается как <webhook>/<метод>;
  • curl, если расширение доступно, иначе fallback на file_get_contents() со stream context;
  • у bitrix24.ru много A-записей, и часть IP периодически не отвечает: включён CURLOPT_DNS_SHUFFLE_ADDRESSES, а сетевые ошибки (6, 7, 28, 35, 52, 55, 56) ретраятся до 6 раз с нарастающей паузой — один обрыв не должен ронять часовую выгрузку;
  • QUERY_LIMIT_EXCEEDED ретраится до 8 раз с паузой в секунду;
  • любая другая error из ответа поднимается как исключение с текстом Битрикса.

Массовые запросыbitrixBatch() / bitrixBatchAll(): команды режутся по 50 штук на batch, halt=0 (одна упавшая команда не рвёт пачку), ошибки внутри пачки собираются и поднимаются одним сообщением. Пагинация — через start и поле next.

Права, которые нужны webhook:

Метод Зачем
tasks.task.list задачи для отчёта, доски, проверки и KPI
tasks.task.result.list результат задачи — из него берётся дата выполнения работ
task.elapseditem.getlist списанное время, основа всех часов
user.get ФИО сотрудников
crm.company.list названия компаний по UF_CRM_TASK
sonet_group.get названия проектов для доски — необязателен

Если у webhook нет прав на sonet_group.get, доска продолжает работать: названия проектов берутся из объекта group, который отдаёт сам tasks.task.list, а в худшем случае колонка называется Проект #<id>.

Проверить настройку целиком, ничего не меняя:

php tools/preflight.php --online

Как парсим задачи

Отчёт «Закрытые часы» (buildClosedHoursReport())

  1. Пользователь выбирает месяц.
  2. Берутся задачи, закрытые в окне ±REPORT_CLOSED_WINDOW_MONTHS (по умолчанию 2) месяца вокруг отчётного — работы могли сдать заметно позже или раньше закрытия.
  3. Из них только полностью завершённые: REAL_STATUS = REPORT_CLOSED_STATUSES (по умолчанию [5]). Статус 4 «условно завершена» ждёт одобрения и в счёт не идёт.
  4. По всем задачам разом читаются результаты (tasks.task.result.list пачками).
  5. Ключевой шаг: в отчёт попадает только задача, в тексте результата которой есть дата, попадающая в выбранный месяц. Приоритет — у результатов со status = 1 (завершающих), среди них берётся последний по времени. Дату ищут два регулярных выражения: сначала конструкция «дата выполнения работ …», и только если её нет — любая дата в тексте. Понимаются форматы ДД.ММ.ГГГГ, ДД/ММ/ГГ, Д.М.ГГГГ.
  6. По прошедшим фильтр задачам читается списанное время (task.elapseditem.getlist, пачками по задачам, с добором страниц если записей больше 50).
  7. Часы относятся к тому, кто списал время (USER_ID записи), а не к ответственному. Фильтра по списку пользователей здесь нет — поэтому новые сотрудники попадают в отчёт автоматически.
  8. Дата списания — DATE_START записи, при пустом — CREATED_DATE.
  9. Итоги суммируются по сотрудникам и по задачам; сотрудники без часов и задач отбрасываются.

Необязательный фильтр по компаниям применяется после шага 5 — по UF_CRM_TASK задачи.

Доска задач (buildProjectBoard())

Фильтр по RESPONSIBLE_ID из reportUserIds() (закреплённый список REPORT_USER_IDS + активные сотрудники портала, чтобы новички появлялись сразу) и по REAL_STATUS:

  • «Активные»: [2, 3, 6] — ждёт выполнения, выполняется, отложена; без ограничения по датам;
  • «Закрытые»: [4, 5] и CLOSED_DATE внутри выбранного месяца.

Задачи группируются по GROUP_ID в колонки-проекты, не более BOARD_TASKS_PER_PROJECT_LIMIT (200) карточек на колонку.

Проверка задач (buildTaskQualityReport())

Берёт задачи, закрытые внутри выбранного месяца, со статусами [4, 5] (здесь «условно завершена» тоже проверяется), читает результат и списания и прогоняет через taskQualityIssues() — правила перечислены выше в разделе про функциональность.

Как парсим KPI

buildKpiReport() считает премию постановщика задач, а не исполнителя.

Выборка: задачи с CREATED_DATE внутри выбранного месяца и REAL_STATUS [4, 5] — то есть созданные и уже закрытые за этот месяц, по всему порталу. Группировка — по CREATED_BY.

По каждой задаче считается:

  • часы — сумма MINUTES всех списаний;
  • просрочка по датеCLOSED_DATE позже DEADLINE; без срока задача не просрочена;
  • просрочка по тегу — среди тегов есть KPI_OVERDUE_TAG (Просрочил), это ручная отметка;
  • по шаблону — в описании встречается KPI_TEMPLATE_MARKER (Название базы).

Дальше на сотрудника:

зачётные   = все задачи − задачи без списанных часов
просрочки  = просрочки по дате + просрочки по тегу
по шаблону = задачи по шаблону − задачи без часов   (не меньше нуля)
в срок     = зачётные − просрочки                   (не меньше нуля)

KPI 1 = зачётные / KPI_TASKS_BASE (100) × KPI_TASKS_RATE (30 000 ₽)
KPI 2 = в срок / зачётные × KPI_OVERDUE_RATE (25 000 ₽)
KPI 3 = по шаблону / зачётные × KPI_TEMPLATE_RATE (25 000 ₽)   (доля не больше 1)
Итого = KPI 1 + KPI 2 + KPI 3

Задача без списанных часов не идёт в зачёт нигде — это главное правило, оно повторяет рабочий файл «РезультатыМесяца». Ставки и пороги переопределяются через KPI_* в конфиге. Сотрудники без зачётных задач уходят вниз списка.

Документы: как формируются Excel-файлы

.xlsx собирается без сторонних библиотек — напрямую как ZIP-пакет с XML-частями (createXlsxFromSheets() в lib.php), нужно только расширение zip. Отсюда же берутся стили: рамки, чередующаяся заливка, ширина колонок, числовые форматы.

Кнопка Листы
Закрытые часы Свод, Все задачи, далее по листу на сотрудника
Отчёт по выбранным компаниям только Все задачи
Проверка задач Свод, Задачи с замечаниями
KPI KPI по сотрудникам, Задачи

Особенности листа Все задачи: поля задачи продублированы в каждой строке, чтобы фильтры Excel работали по всем строкам списаний; задачи отделены рамками и чередующейся заливкой; рядом с Затрачено стоит Итого по задаче.

Имена листов чистятся от запрещённых символов и обрезаются до 31 знака, дубликаты разводятся суффиксом (uniqueWorksheetName()).

Документы: 1С:УНФ

Создание УчетВремени и ЗаданиеНаРаботу через OData вынесено на отдельную страницу:

docs/ODATA.md — как подключаемся, что создаём, как это устроено.


Запуск

cp config.local.example.php config.local.php

Заполните LOCAL_BITRIX_WEBHOOK, LOCAL_APP_AUTH_PASSWORD и, если нужны кнопки УНФ, LOCAL_UNF_ODATA_USER / LOCAL_UNF_ODATA_PASSWORD.

Проверить, что всё настроено (ничего не меняет, только читает):

php tools/preflight.php

Локальный сервер из папки проекта:

php -S 127.0.0.1:8080

Открыть http://127.0.0.1:8080/. Логин по умолчанию: admin.

Папка data/ должна быть доступна на запись веб-серверу и закрыта от прямой раздачи — в снимках ФИО, часы и хеши паролей.

Состав файлов

  • index.php — главная (отчёт, кнопки УНФ, полезные кнопки); tasks.php — доска; dashboard.php — дашборд; quality.php — проверка задач; kpi.php — KPI; admin.php — управление пользователями;
  • report.php, unf_time.php, unf_workorder.php, dashboard_refresh.php — обработчики;
  • lib.php — Битрикс REST, отчёт, доска, дашборд, проверка, KPI и генерация .xlsx;
  • unf.php — интеграция с 1С:УНФ по OData;
  • auth.php — роли и Basic Auth; config.php — конфигурация; partials/ — общая разметка; effects.js, style.css;
  • tools/preflight.php — предполётная проверка настройки.

Документация

About

Контроль качества задач и закрытых часов Bitrix24, Excel-отчёты и автоматизация документов 1С:УНФ

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages