25 KiB
Аналитика компании
Аналитика встроена во вкладку «Аналитика компании» на странице /finances.
Внутренние вкладки: проекты, продажи, сотрудники, производство и журнал фактов.
Выбранные вкладки запоминаются для пользователя; обычный и широкий режимы
используют то же переключение, что и управление зарплатой. Фильтры открываются модальным окном по кнопке в шапке финансов;
под внутренними вкладками остаётся короткая строка применённых фильтров.
Отмена закрывает окно без изменения отчёта. Карточки адаптируются к ширине
рабочей области. В обычном режиме и при ширине рабочей области меньше 928px
списки по умолчанию свёрнуты до заголовка со счётчиком и стрелкой.
После открытия списка табличные строки представлены карточками с раскрывающимися
подробностями. В широком режиме списки всегда открыты и показывают таблицы.
Это относится к сводным отчётам, документам выплат и журналу фактов.
В широком режиме при ширине рабочей области от 928px основной блок сочетает
график и таблицу в двух колонках, если таблица помещается без горизонтальной
прокрутки. Иначе график располагается сверху, а таблица — снизу на всю ширину.
Компоновка пересчитывается при изменении размера области и данных таблицы.
Дополнительные блоки располагаются попарно.
Таблицы имеют собственную прокрутку и закреплённые заголовки.
В обычном и узком режиме графики открываются только модальным окном по кнопке
в заголовке списка, в том числе когда список свёрнут.
У каждого списка есть график с выбором показателя: разные единицы не смешиваются.
Месячные данные представлены линией с разрывами на неизвестных значениях;
остальные — сравнением до семи позиций. Высота области всех графиков — 280px.
Для явно отмеченных суммируемых показателей при числе позиций больше семи
показываются шесть крупнейших по модулю и «Прочее» — сумма остальных с учётом
знака. Число объединённых позиций видно в подписи и подсказке. Неизвестные
значения исключаются и отмечаются отдельно. Проценты, средние, возраст и стаж
не суммируются; для них показываются семь крупнейших значений.
Месячные ряды сохраняют все месяцы. Полные списки и CSV не сокращаются.
Графики сводных списков учитывают поиск по всем страницам результата.
Для документов и журнала используется только текущая загруженная страница,
что явно подписано над графиком; аннулированные записи журнала исключены.
Поиск, страницы, CSV и права на действия сохраняются в обоих режимах. Методика и инструкции открываются по вопросику в шапке,
пояснения к отдельным таблицам — по вопросику рядом с названием. Предупреждения
о качестве данных остаются в отчётах. Старый адрес /finances/analytics
перенаправляет на /finances?tab=analytics, открывая встроенную вкладку.
Используются визуальные компоненты и темы портала. Изображения из локальных
материалов служат примерами; их показатели, числа и оформление не являются ТЗ.
Возможности
- Продажи по товарам, каналам, сочетанию товара и канала, клиентам и месяцам.
- Выручка, себестоимость, привязанные расходы, прибыль по учтённым расходам и маржа.
- Зарплата каждого сотрудника, изменение зарплаты, дни работы, отпуска и больничного, уплаченные налоги, возраст, стаж и динамика численности команды.
- Выпуск, продажи произведённых товаров, производственные закупки и графики с переключением между закупками, выручкой и прибылью. Прибыль по товарам и каналам повторно доступна в производственном отчёте и рассчитывается тем же сервисом.
- Журнал подтверждённых фактов: выпуск, производственные закупки, уплаченные налоги сотрудника, общие расходы, поступления и выплаты денег.
- Локальные проекты объединяют продажи, расходы и платежи связанных внешних объектов; подтверждённые часы получают предварительную оценку до закрытия зарплатного периода и точную оценку по его итоговому начислению после закрытия.
- Выбор дат включительно, валюты и источника продаж. Поиск, страницы таблиц и CSV всех строк текущей группировки с учётом поиска. Диапазон ограничен 367 днями.
Источники и методика
Продажи и возвраты берутся из commerce.Sale и SaleLine, расходы — из Cost.
Операции с counts_as_sale=False и связанные с ними расходы исключаются.
Возвраты уменьшают количество, выручку и себестоимость. Расходы учитываются по
собственной дате; их знак сохраняется, в том числе для компенсаций.
Выручка равна сумме после скидок и возвратов в денежной базе источника. Сервис не пересчитывает НДС. Прибыль по учтённым расходам равна выручке минус себестоимость минус привязанные расходы. Общие расходы и налоги не распределяются автоматически. Этот показатель не следует принимать за окончательную чистую прибыль компании. Правила распределения общехозяйственных расходов и налогов требуют согласования.
Себестоимость с metadata.cost_source="unavailable" считается неизвестной.
Нулевая себестоимость без подтверждения manual или known_zero также считается
неизвестной. Для затронутых групп прибыль и маржа возвращаются null, в UI — «—».
API дополнительно возвращает арифметический результат по известным расходам
contribution_profit, но интерфейс не показывает его как подтверждённую прибыль.
Клиенты имеют внешний ID и имя на продаже. Миграция восстанавливает их из
сохранённого SourceRecord.payload.agent, если информация присутствует. Новая
синхронизация МойСклад запрашивает контрагента вместе с документом. ID клиента
дополняется ID источника, поэтому одинаковые внешние ID разных систем не
объединяются. Когда имеется только имя, используется имя внутри источника;
для надёжного сопоставления необходимо заполнить внешний ID.
Расходы без привязки к продаже остаются в группе неизвестного клиента.
Валюты не суммируются и автоматически не конвертируются. Продажи разных систем не дедуплицируются по предполагаемым совпадениям: при дублирующем импорте одного оборота следует выбрать один источник.
Зарплата берётся из опубликованного расчёта каждого периода. Новая черновая ревизия не заменяет опубликованную. Учитываются только периоды, целиком входящие в выбранные даты. Начисления нескольких периодов одного месяца складываются по месяцу окончания расчётного периода. Средняя зарплата сотрудника — начисленная сумма до удержаний, делённая на число месяцев с расчётами. Среднее компании — по парам «сотрудник / месяц» с расчётами. Неопубликованные и отсутствующие расчёты не заменяются нулями. Рост сравнивает первый и последний месяц с опубликованными расчётами внутри диапазона. Границы сравнения едины для всех сотрудников и показаны в интерфейсе. Сотрудник включается в сравнение только при наличии обоих расчётов и ненулевой начальной зарплате.
Рабочие дни — записи успешного анализа посещаемости с положительными часами и без признака отсутствия. Отпуска и больничные — календарные дни по кадровым событиям с существующим приоритетом пересекающихся событий. Стаж учитывает увольнения и повторный приём, а не дату создания учётной записи. При отсутствии кадровой истории текущая численность использует активность учётной записи; историческая динамика включает только известную кадровую историю. Неизвестные даты рождения и найма исключаются из средних и учитываются в счётчиках пропусков.
Налоги берутся только из фактически оплаченных записей журнала. Удержания расчётного листка не означают уплаты налога. Производственный отчёт включает продажи товаров с неаннулированным фактом выпуска не позже конца периода. Количество выпуска вводится в единицах соответствующего товара и не зависит от выбранной валюты. Закупка может относиться к конкретному конечному товару либо оставаться общей. Производственные закупки не вычитаются повторно из прибыли поверх себестоимости продаж.
Фильтр проекта использует локальную карточку и применяется к продажам через её внешние привязки, а к ручному журналу и трудозатратам — напрямую. Фильтр источника влияет на продажи и связанные расходы; журнал остаётся общим. Денежный поток считается только по поступлениям и выплатам из журнала. Нулевое число записей не подтверждает отсутствие фактических выплат, налогов или выпуска.
Доступ и журнал
Все endpoints требуют авторизации и существующего доступа к управлению финансами,
включая allow-list FinanceSettings.management_users. Ответы имеют private, no-store; фронтовое скрытие ссылки не подменяет серверную проверку.
Для добавления фактов нужно finance.add_reportingentry, для аннулирования —
finance.change_reportingentry. Действует существующий временный административный
доступ SIMPLE_ADMIN_ACCESS. Права на просмотр финансов сами по себе не дают права
изменять журнал.
Номер документа уникален внутри вида записи. Записи не редактируются и не удаляются: исправление выполняется аннулированием и новой записью с новым номером. Автор и дата создания, автор и дата аннулирования сохраняются. Повторное аннулирование идемпотентно. Будущие факты, отрицательные суммы и несовместимые с видом записи поля отклоняются.
API
GET /api/v1/finance/analytics/report/?section=sales|people|production|projectsGET /api/v1/finance/analytics/options/?search=...GET|POST /api/v1/finance/analytics/entries/POST /api/v1/finance/analytics/entries/{id}/void/
Параметры отчёта и списка фактов: date_from, date_to, currency, локальный
project либо unassigned; параметр source применяется к продажам и внешним
привязкам. Список фактов использует стандартную пагинацию API. options
возвращает локальные проекты и первые 100 товаров и сотрудников по строке поиска.
CSV экранирует кавычки, переносы строк и потенциальные формулы в текстовых полях.
Подключение и проверка
Перед запуском обновлённого backend выполните python manage.py migrate:
миграции Commerce 0012–0014, Projects 0001 и Finance 0032–0034 добавляют клиента
продажи, внешний справочник, локальные проекты и журнал фактов.
Для старых документов без имени клиента может потребоваться повторная синхронизация.
cd backend
pytest tests/finance/test_analytics.py tests/finance/test_projects.py tests/commerce -q
python manage.py makemigrations --check --dry-run
python manage.py check
cd frontend
node --import tsx --test src/lib/analytics.test.js
npx tsc --noEmit
Исходная книга учёта оплат автоматически не импортируется: в ней есть внешние ссылки с ошибками и лист с учётными данными. Импорт этой книги требует отдельного сопоставления колонок, подтверждения исходных сумм и подготовки безопасной копии. Фраза «всё из годового финансового отчёта» требует отдельного перечня показателей или самого годового отчёта: книга оплат не задаёт полный состав такого отчёта. Индекс здоровья, планы и прогнозы из примерных изображений не включены в объём реализации текстового ТЗ.
Локальные проекты и внешние источники
Раздел «Проекты» использует локальную карточку портала как основную строку. В неё по точным внешним привязкам собираются оплаченные расходы, документы платежей, продажи и прямые расходы всех подключённых сервисов. Ручные выплаты, закупки и общие расходы журнала ссылаются на локальную карточку напрямую. Подтверждённые распределения сотрудников добавляют трудозатраты в часах, число дней учёта и участников. Пока расчётный период открыт, стоимость часа предварительная: система использует текущий расчёт зарплаты, а до его появления — действующую утверждённую базовую ставку, разделённую на норму часов периода. После закрытия периода стоимость становится точной: итоговое начисление из опубликованного расчётного листка, включая премии, доплаты и корректировки, распределяется по фактически отработанным часам. Полученная стоимость часа умножается только на подтверждённые часы проекта. Черновые ставки не используются. Закрытый период без итогового листка, а также часы без периода, нормы или фактических часов сохраняются как неоценённые и не превращаются в ноль.
Фильтр локального проекта работает в продажах, производстве, проектах и журнале. Вариант «Без привязки» объединяет внешние документы, для которых ещё не выбрана локальная карточка, а также документы без проекта источника. В списке платежей сохраняются и локальное имя, и исходное имя проекта для проверки происхождения.
Синхронизация получает /entity/project (включая архив), /entity/paymentout
и /entity/cashout с проектом, статьёй расходов, получателем и валютой. Продажи
получают связь project из отгрузки или возврата. Для старых продаж связь
восстанавливается из сохранённого исходного документа, если поле присутствует.
Проекты идентифицируются сочетанием источника и внешнего ID, а не названием.
«Оплачено по источникам» — сумма проведённых исходящих платежей и расходных ордеров за период в выбранной валюте. Проект определяется по явному полю документа; из связанных заказов и приёмок он не угадывается. Непроведённые документы и документы, исчезнувшие после полностью успешного обхода источника, исключаются. Повторный импорт обновляет ту же запись. Последние полученные исходные документы сохраняются; отсутствующие платежи помечаются флагом и не удаляются. Импортированные платежи доступны только для чтения. При ошибке обхода оставшиеся документы не помечаются отсутствующими.
Платёж может быть переводом между счетами, авансом, погашением долга, закупкой или возвратом: его нельзя автоматически вычитать из прибыли поверх себестоимости. Поэтому оплаченные суммы, ручные выплаты, закупки и общие расходы показаны отдельными колонками. Ручные записи не следует создавать повторно для уже импортированных платежей. При фильтре источника ручные факты относятся к нему через выбранный проект; ручные факты без проекта не включаются в конкретный источник.
Дополнительный API: GET /api/v1/finance/analytics/project-payments/ с обычной
пагинацией. section=projects возвращает сводку, строки проектов, статьи и месяцы.
Параметр project — локальный ID проекта либо unassigned. Поле project
доступно в ручной записи, продаже и прямом расходе. Справочник проектов возвращается
в analytics/options/. Права и no-store совпадают с остальной аналитикой.
Миграции: Commerce 0014, Projects 0001 и Finance 0033–0034. Миграция 0034 сохраняет прежнюю внешнюю связь ручной записи для аудита и заполняет локальный проект там, где уже существовала точная привязка. Обычная синхронизация включает проекты и исходящие платежи. Для отдельной загрузки без товаров и изображений:
python manage.py sync_moysklad_projects <UUID-подключения>
Контракты API: проекты, исходящие платежи, расходные ордера.