Отчёты
Обновлено 2026-10-27
На этой странице
Отчёты о выполнении
Отчёт фиксирует выполненный объём работы по смете: к какой работе сметы он привязан, кто работал, какой объём и за какой период. По отчётам система считает факт по смете и суммы для исполнителей и бригадира.
Кто участвует в отчёте
В отчёте указываются исполнители и при необходимости бригадир. От состава участников и их ролей зависит, как рассчитаются суммы.
Роли исполнителей
- Партнёр — основной исполнитель, когда в отчёте нет помощников. Объём работы делится поровну между всеми партнёрами, каждому считается своя сумма по его ставке.
- Специалист — основной исполнитель, когда в отчёте есть хотя бы один помощник. То же, что партнёр: объём делится между специалистами, сумма считается по ставке каждого.
- Помощник — дополнительный участник. Объём тоже делится поровну между помощниками, сумма считается по ставке помощника. В одном отчёте не бывает одновременно партнёров и специалистов: либо только партнёры (без помощников), либо специалисты и помощники.
- Бригадир — указывается отдельно от исполнителей. Бригадиру сумма считается на весь объём отчёта по своей ставке (объём не делится с исполнителями).
Итог: у каждого исполнителя — своя доля объёма и своя сумма; у бригадира — сумма на полный объём. Общая сумма по отчёту складывается из сумм всех исполнителей и суммы бригадира.
Откуда берутся ставки
Ставки для расчёта сумм берутся из тарифов типа работ: для каждой роли (партнёр, специалист, помощник, бригадир) задаётся ставка по объекту и дате. Если для конкретного человека в тарифах указана персональная ставка — используется она, иначе ставка по умолчанию для этой роли.
Цена для расчёта берётся из прайса (тип работ, объект, дата). На неё могут действовать коэффициенты, заданные в работе сметы. Итоговая сумма по каждому участнику: цена (с коэффициентами) × ставка × его доля объёма (для бригадира — весь объём).
Для разработчиков
Роли: RoleEnum (PARTNER, SPECIALIST, ASSISTANT, FOREMAN, HANDYMAN). Партнёры и специалисты взаимоисключающие; при наличии помощников основные идут как SPECIALIST (getPartnerRole).
Расчёт: WorkTypeHelp::calcSums(); исполнители — calcGroupSums() (amountPerUser = amount/count); бригадир — отдельно, sum = priceRateAndCoef*amount.
Ставки: searchRates($work_type, $place_id, $date, $role). Суммы исполнителей — report_item_performers.sum; бригадир — report_items.foreman_sum, foreman_rate_id, foreman_rate_value.
Применение: ReportItemCalculatorService::applyCalculationToReportItem().
Как считаются суммы по элементам отчёта
Основные исполнители (партнёры или специалисты)
- Система смотрит, есть ли в отчёте помощники. Если нет — все основные считаются партнёрами, если есть — специалистами.
- Объём отчёта делится поровну между всеми основными (между всеми партнёрами или всеми специалистами).
- Для каждого человека берётся его ставка из тарифов (роль «партнёр» или «специалист», объект, дата).
- Сумма = (цена с коэффициентами × ставка) × доля объёма этого человека.
Пример: объём 10 м, два партнёра с одинаковой ставкой. Каждому — 5 м, сумма каждому считается от 5 м по его ставке.
Помощники
- Объём отчёта делится поровну между всеми помощниками (отдельно от основных).
- Для каждого помощника — ставка из тарифов (роль «помощник»).
- Сумма = (цена с коэффициентами × ставка помощника) × доля объёма помощника.
То есть у основных и у помощников считаются свои доли от одного и того же объёма отчёта; общая сумма по отчёту включает и тех и других.
Бригадир
- Бригадир указывается в отчёте отдельно (поле «Бригадир»).
- Если у типа работ включена опция «не считать бригадира» — сумма бригадиру не считается.
- Иначе берётся ставка бригадира из тарифов (роль «бригадир», объект, дата).
- Сумма бригадира считается на весь объём отчёта: (цена с коэффициентами × ставка бригадира) × объём отчёта. Объём не делится с исполнителями.
Сумма бригадира хранится отдельно от сумм исполнителей и участвует в общей сумме по отчёту и в отчётах по выплатам.
Для разработчиков
calcSums: rate_is_percent — цена из PriceHelp::findPriceForWork, иначе price=1. coefficient_value по коэффициентам работы.
Партнёры/специалисты: calcGroupSums(partners|specialists, amount, …, role) → amountPerUser = amount/count, userSum = priceRateAndCoef*amountPerUser → performers[].sum. Помощники: calcGroupSums(assistants, amount, …, ASSISTANT).
Бригадир: при !no_calc_for_foreman — searchRates(…,'foreman'), arForeman['sum'] = priceRateAndCoef*amount; сохраняется в foreman_sum.
Результат: performers (pivot sum) + foreman (foreman_sum). В смете sum_fact_performers: pivot.sum + foreman_sum по report_items работы.
Связь отчётов со сметой
Данные из отчётов попадают в смету и участвуют в расчёте фактических показателей по работе:
- Фактический объём по работе сметы — это сумма объёмов всех отчётов, привязанных к этой работе (с учётом пересчёта единиц измерения, если у типа работ настроена конвертация). Либо используется ручной факт, если его ввёл руководитель.
- Сумма по факту для заказчика по работе = цена работы × фактический объём (цена берётся из сметы, не из отчётов).
- Сумма по факту для исполнителей по работе — это сумма полей «сумма» всех исполнителей по всем отчётам этой работы плюс суммы бригадиров из этих отчётов.
Подробнее о том, как считаются объёмы, цены и суммы в смете — в разделе «Сметы: Объёмы, цены и суммы».
Для разработчиков
PlanHelp::getPlanWorkRowOptimized: amount_fact из ReportItem (конвертация через MeasureHelp::getConvertAmount при разных measure); sum_fact_performer += performer->pivot->sum + report_item->foreman_sum по report_items работы.
Привязка элемента отчёта к работе сметы
В форме отчёта можно указать, к какой смете, разделу и работе относится элемент. Если выбрать только смету или смету и раздел, но не выбирать конкретную работу, система сама решает, к какой работе привязать отчёт (или создаёт новую работу).
Как выбирается работа, если пользователь её не указал
- Раздел. Если указана только смета — берётся раздел по умолчанию в этой смете (если задан) или первый раздел. Если указан раздел — используется он.
- Поиск подходящей работы. Система смотрит только работы того же типа, что и элемент отчёта (например, «Штукатурка», «Укладка плитки»). В выбранном разделе ищется работа, у которой совпадают:
- Параметры типа работ (все значения параметров у отчёта и у работы в смете должны быть одинаковыми);
- Коэффициенты (набор коэффициентов у отчёта и у работы должен совпадать).
- Если такая работа найдена — отчёт привязывается к ней (к первой подходящей в списке).
- Если подходящей работы нет — в этом разделе создаётся новая работа: тот же тип работ, те же параметры и коэффициенты, что в отчёте. Название новой работы система формирует сама из названия типа работ и значений параметров (например, «Штукатурка | стена | 15 мм»). Отчёт привязывается к этой новой работе.
Итого: при указании только сметы (и при необходимости раздела) отчёт не «прилипает» к случайной работе — привязка идёт к работе с тем же типом и теми же параметрами/коэффициентами; если такой работы нет, создаётся новая с автогенерируемым названием.
Для разработчиков
Логика в
Help::addReportItemInPlan(ReportItem, plan, section, work). Приworkпустом: определяетсяplan_section_id(default_section_id плана, иначе первый раздел, иначе создаётся раздел «Раздел N»). Кандидаты:$planSection->works()->where('work_type_id', $reportItem->work_type_id)->get(). По каждому кандидату проверка: совпадениеdata['params'][param_id]по всем params типа работ и совпадение списков коэффициентов (reportItem->coefficients vs data['coefficients']). Первое совпадение — привязка к этой работе. Если совпадений нет — создаётсяnew PlanWork(name = '', plan_section_id, work_type_id, data из отчёта, amount 0, price/rate из отчёта),save(). При сохраненииPlanWork::beforeSave()при пустомnameвызываетHelp::getPlanWorkName($this->data, $this->work_type)и подставляет имя: название типа +|+ суффикс изgetSuffixPlanWork($data, $work_type)(параметры и calc_logic типа). Итог:reportItem->plan_work_id = $planWork->id.