# Аналитика компании Аналитика встроена во вкладку «Аналитика компании» на странице `/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|projects` - `GET /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 добавляют клиента продажи, внешний справочник, локальные проекты и журнал фактов. Для старых документов без имени клиента может потребоваться повторная синхронизация. ```bash 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 ``` ```bash 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 сохраняет прежнюю внешнюю связь ручной записи для аудита и заполняет локальный проект там, где уже существовала точная привязка. Обычная синхронизация включает проекты и исходящие платежи. Для отдельной загрузки без товаров и изображений: ```bash python manage.py sync_moysklad_projects ``` Контракты API: [проекты](https://github.com/moysklad/remap-1.2-java-sdk/blob/master/docs/Project.md), [исходящие платежи](https://github.com/moysklad/remap-1.2-java-sdk/blob/master/docs/PaymentOut.md), [расходные ордера](https://github.com/moysklad/remap-1.2-java-sdk/blob/master/docs/CashOut.md).