Skip to content

Система документов и генерация ​

Как в системе работают загруженные файлы, шаблоны документов и генерация готовых артефактов для клиентов.


Два типа документов в системе ​

1. Файлы (Files) ​

Загруженные пользователем артефакты — ТЗ, чертежи, фотографии, спецификации, которые нужны для работы.

2. Документы (Documents) ​

Сгенерированные системой документы — счета, договоры, акты, отчеты, которые создаются на основе данных проекта и шаблонов.


Часть 1: Файлы (Files) ​

Что такое файл в системе ​

Файл — это любой загруженный в систему файл, привязанный к сущности проекта (или задаче, или чату).

Структура файла ​

File:
  - ID: 123
  - EntityType: "project" (к какой сущности привязан)
  - EntityID: 456 (ID этой сущности)
  - FolderID: 789 (в какую папку)
  - Bucket: "files" (где хранится)
  - Key: "project-456/2026-04-20/specifications.pdf" (путь в хранилище)
  - OriginalName: "specifications.pdf" (оригинальное имя)
  - MimeType: "application/pdf" (тип)
  - SizeBytes: 1234567 (размер в байтах)
  - Category: "document" (категория)
  - UploadedBy: 789 (кто загрузил)
  - CreatedAt: 2026-04-20 12:00:00 (когда загружено)
  - DeletedAt: null (если удален)

Категории файлов ​

КатегорияПримерыНазначение
generalЛюбые вложения, информационные материалыОбщие файлы проекта
documentТЗ, требования, регламентыСлужебная документация
imageФотографии, схемы, чертежи, макетыВизуальные материалы
contractДоговоры, контракты, соглашенияЮридические документы
invoiceСчета, накладные, акты, отчетыФинансовые документы
otherВсе остальноеРазное

Где находятся файлы ​

Хранилище:

  • По умолчанию: локально в tmp/files
  • Для масштабирования: S3-совместимое хранилище (AWS S3, MinIO и т.п.)
  • Максимальный размер загрузки: 1 GB
  • Исполняемые файлы и исполняемые MIME-типы не принимаются

Структура хранилища:

files/
  project-456/
    2026-04-01/
      specifications.pdf
      floor-plan.png
    2026-04-20/
      notes.md

Папки в проекте ​

При создании проекта триггер create_default_project_folders заводит стандартный набор (миграция 0138, по ТЗ «Создание проекта»):

typeПапкаЧто хранится
tzТЗТехническое задание и исходные материалы
proposalsКоммерческие предложенияКП и сметы для клиента
contractsДоговорыДоговоры, допсоглашения, акты
photoФотоотчётыФото монтажа, процесса и демонтажа
reportsОтчётностьОтчёты по проекту
otherПрочееВсё остальное

type стабилен и уникален в проекте, имя можно переименовать. Существующим проектам недостающие папки добавлены миграцией; старые системные имена TZ и Фото переименованы в ТЗ и Фотоотчёты, ручные имена не тронуты.

СценарийEndpoint
Папки проектаGET /api/v1/projects/:id/folders — конверт {items, meta}, дерево через children
Файлы папкиGET /api/v1/folders/:id/files
Загрузить в папкуPOST /api/v1/folders/:id/files
Все файлы проектаGET /api/v1/projects/:id/files (у каждого файла folder_id или null)

Как работает с файлами ​

Загрузка ​

  1. Открыть проект
  2. Перейти в раздел "Files"
  3. Нажать "Upload"
  4. Выбрать файл(ы)
  5. Выбрать категорию
  6. Нажать "Upload" — файл сохранен

Организация ​

  1. Можно создавать папки
  2. Перемещать файлы между папками
  3. Переименовывать файлы
  4. Удалять файлы (soft delete, т.е. помечаются как удаленные)

Поиск ​

  1. Фильтр по категориям
  2. Фильтр по дате загрузки
  3. Фильтр по пользователю (кто загрузил)
  4. Поиск по имени

Ограничения ​

  • Максимальный размер файла: опционально ограничивается (например, 100 МБ)
  • Форматы: опционально ограничиваются (например, только PDF, DOC, PNG)

Где используются файлы ​

В проекте ​

  • В разделе "Files" проекта — видны все файлы, привязанные к проекту

В задачах ​

  • Файл может быть привязан к конкретной задаче
  • Помогает исполнителю понять требования

В чатах ​

  • В сообщениях чата могут быть прикреплены файлы
  • Файлы загружаются в entity type chat, а затем прикладываются к сообщению через file_ids
  • Команда обсуждает напрямую в общих чатах или в чате задачи

При генерации документов ​

  • Система может ссылаться на загруженные файлы (например, вставить чертеж в счет)

Часть 2: Документы (Documents) ​

Что такое документ в системе ​

Документ — это готовый артефакт, обычно сгенерированный на основе:

  • Данных проекта
  • Шаблона
  • Заданных параметров

Примеры:

  • Счет за выполненные работы
  • Договор с клиентом
  • Акт выполненных работ
  • Отчет о проделанной работе

Документы vs Файлы ​

ПараметрФайлДокумент
ИсточникЗагружен пользователемСгенерирован системой
СодержаниеИсходные данные (ТЗ, чертежи)Готовый артефакт (счет, договор)
ОбновлениеВручную загружается новая версияПересчитывается при изменении данных проекта
НазначениеСправочный материал для работыОтправка клиенту, архивирование

Типы документов ​

Invoice (Счет) ​

Когда создается: Когда нужно выставить счет клиенту.

Что включает:

  • Дату и номер счета
  • Реквизиты поставщика (ваша компания)
  • Реквизиты клиента: сначала карточка Company, затем primary-набор из Requisites, если он есть
  • Список работ/услуг с ценами
  • Список материалов/оборудования
  • Итоговую сумму
  • Условия оплаты

Источник данных:

  • Project: название, компания проекта
  • Requisites: internal-реквизиты поставщика и primary-реквизиты компании-клиента
  • Team: состав и ставки
  • Finance: все Cost Items
  • Tasks: список выполненных работ

Contract (Договор) ​

Когда создается: При инициации работ с клиентом.

Что включает:

  • Реквизиты сторон
  • Описание услуг/работ
  • Стоимость и условия оплаты
  • Сроки выполнения
  • Ответственность сторон
  • Подписи

Источник данных:

  • Project: название, сроки
  • Requisites: реквизиты исполнителя и заказчика
  • Finance: плановая стоимость
  • Custom fields: условия, ответственность

Act (Акт выполненных работ) ​

Когда создается: При завершении проекта или этапа.

Что включает:

  • Дату акта
  • Описание выполненных работ
  • Подтверждение качества
  • Подписи сторон

Источник данных:

  • Project: название, сроки
  • Requisites: реквизиты исполнителя и заказчика
  • Tasks: список закрытых задач
  • Team: кто выполнял

Addendum (Дополнительное соглашение) ​

Когда создаётся: Когда после подписания договора нужно зафиксировать изменение сроков, состава работ, стоимости или других условий.

  • Создаётся только для договора того же проекта через POST /api/v1/projects/:id/documents/addendum.
  • В запросе обязательны contract_id и непустой data.changes; data.new_total и notes опциональны.
  • Связь с договором хранится в documents.parent_document_id и возвращается как parent_document_id в едином snake_case DTO.
  • PDF содержит номер и дату исходного договора, нумерованный перечень изменений, опциональную новую стоимость, реквизиты и подписи сторон.
  • Удаление договора с существующими дополнительными соглашениями ограничено внешним ключом ON DELETE RESTRICT.

Report (Отчет) ​

Когда создается: По запросу для анализа хода работ.

Что включает:

  • Статус проекта
  • Выполненные задачи (%)
  • Израсходованный бюджет
  • Ожидаемые сроки завершения
  • Проблемы и риски

Источник данных:

  • Project: статус, сроки
  • Tasks: прогресс, статусы
  • Finance: затраты
  • Team: статус команды

Шаблоны документов ​

Смета, счёт, акт, договор и доп. соглашение собираются из шаблона Word — стандартного или загруженного на экране «Администрирование → Шаблоны документов» (общего или для одного нашего юрлица). Документ хранится в Word и PDF; PDF делает конвертер Gotenberg. Синтаксис полей, выбор шаблона и настройка — в Шаблоны документов в Word.

Как было до шаблонов Word ​

В текущей реализации дефолтные HTML-шаблоны создаются миграцией для типов invoice, estimate, act, contract с locale ru. Структурированный PDF-рендер используется как основной путь для сметы, standalone-счета, акта и договора, а HTML-шаблоны остаются доступными для проектного счета и fallback/template-flow.

Проектный счёт без явно переданного template_id также генерируется структурированным fpdf-рендерером. Он выводит позиции, НДС, сумму прописью, назначение платежа и блок подписей. Явно выбранный HTML-шаблон сохраняет прежний fallback-flow.

Для сметы поддерживаются два режима детализации:

  • detail: "categories" — агрегированные категории бюджета (режим по умолчанию);
  • detail: "items" — исходные статьи затрат и налоговые строки.

Акт не дублирует итоговую строку и показывает НДС. В договоре реквизиты заказчика дополняются основным банковским счётом компании, а формулировка «в лице …» и блок подписей используют director_name и director_title обеих сторон, если эти поля заполнены.

Список сгенерированных документов доступен через GET /api/v1/documents с фильтрами project_id, type, status, limit, offset; фильтр type принимает также addendum. Для пользователей без глобального доступа project_id обязателен и проверяется доступ к проекту. Ответы создания и изменения статуса используют единый snake_case DTO, включая parent_document_id.

Правила формирования и статусов ​

  • Продавец (исполнитель) — набор «Моей компании», выбранный в проекте как плательщик (payer_requisite_id); если он не выбран или удалён — основной набор. Реквизиты попадают в PDF и payload документа на момент формирования, id набора — в documents.seller_requisite_id. Реквизитов нашей компании нет вовсе — документ не выпускается: 400 documents_seller_requisites_required («Заполните их в разделе „Моя компания“»).
  • НДС документа — по продавцу: переопределение проекта, иначе режим и ставка набора-продавца (плательщик, иначе основной набор), иначе без НДС. Счёт своими строками (и счёт компании без проекта) считает цены окончательными: НДС «в том числе» по ставке продавца, продавец без НДС — «НДС не облагается».
  • Закрытый проект (status = closed): документы не формируются и не меняют статус — 409 documents_project_closed. Проверка идёт до выдачи номера и до сохранения, поэтому отказ финансов не оставляет «полусохранённый» счёт.
  • Счёт на ноль не выставляется: 400 documents_invoice_total_must_be_positive (проектный счёт — итог сметы; счёт компании без проекта — сумма позиций). Номер при отказе не расходуется.
  • Документ выпускается сразу выпущенным (issued) — с номером и PDF; черновик (draft) без номера бывает только у счёта по проекту (см. «Счёт по проекту»). Черновик не выпускается сменой статуса — PATCH …/status {"status":"issued"} выпускает его как POST /documents/:id/issue, а отмена черновика отклоняется (409 documents_draft_cancel: его удаляют). Старые акты и договоры в статусе draft с номером живут по прежним правилам.
  • Статусы по типу (ValidateStatusTransitionForType): draft → issued | cancelled; из issued счёт — в paid или cancelled, акт — в acted или cancelled, смета, договор и доп. соглашение — только в cancelled. «Оплачен» бывает только у счёта (documents_paid_only_for_invoice), «Актирован» — только у акта (documents_acted_only_for_act).
  • Отмена счёта с платежами: если на счёт разнесены платежи (payment_allocations, платёж не отменён) — 409 documents_invoice_has_payments; сначала отмените платёж или уберите разнесение.
  • Договоры и доп. соглашения формируют legal.manage или documents.manage; интерфейс узнаёт это из capability legal_documents_manage в /org/me, а не из матрицы «договоры».

Счёт по проекту ​

POST /api/v1/projects/:id/documents/invoice — счёт клиенту проекта. Выставляют менеджер, который ведёт бюджет клиента этого проекта (запись client_budget и право задавать бюджет именно этого проекта — то же правило, что для сметы), финансы и documents.manage. Отметку «Оплачен» и остальные статусы ставят только финансы (PATCH /documents/:id/status).

kindСуммаСтроки PDF
full (по умолчанию)итог сметы (с налогами)статьи сметы, наценка внутри цен
advancepercent сметы (0–100] или amountодна строка «Аванс N % по проекту …», НДС в той же доле, что в смете
remainderсмета минус выставленные счета проекта (не черновики и не отменённые)«Окончательный расчёт по проекту …»
customсумма items (name, qty, unit, unit_price)свои строки, НДС по продавцу

Ещё в теле: due_date (YYYY-MM-DD, «Оплатить до» в PDF и списке), notes (назначение платежа; пусто — «Оплата по счёту № … по проекту …»), issue (по умолчанию true). Пустое тело — счёт на всю смету, выпущенный сразу (как раньше); с template_id — прежний путь по шаблону.

issue: false сохраняет черновик: без номера и PDF, ввод хранится в payload.invoice_input и возвращается в ответе полем invoice. Черновик:

  • PUT /api/v1/documents/:id — правка (то же тело; issue: true — сохранить и выпустить);
  • POST /api/v1/documents/:id/issue — выпустить: сумма аванса и остатка пересчитывается от сметы на момент выпуска;
  • DELETE /api/v1/documents/:id — удалить (204).

Менять и удалять можно только черновик счёта проекта: выпущенный документ — 409 documents_not_draft. Ошибки вида: documents_invoice_estimate_required (аванс или остаток от пустой сметы), documents_invoice_advance_required, documents_invoice_above_estimate, documents_invoice_nothing_left (всё уже выставлено), documents_invoice_kind_unknown.

Выпуск регистрирует плановую выручку проекта (RegisterPlannedRevenue), как и раньше.

Счёт компании без проекта — POST /api/v1/companies/:id/invoices (финансы, documents.manage): свои строки, notes, due_date; продавец — основной набор «Моей компании», PDF — в файлах компании. В интерфейсе — «Выставить счёт» в меню карточки компании.

Документ для клиента ​

Строки и итоги сметы PDF и счёта на всю смету (аванс, остаток) берутся из действующей сметы проекта (Смета проекта): разделы или строки с количеством и периодом, скидки строками со знаком минус, УСН и НДС сверху строками. Без сметы — из бюджета (статьи по категориям).

Смета и счёт — документы для клиента:

  • наценки нет отдельной строкой — она разнесена по позициям пропорционально их сумме; «Сумма без наценки» не печатается;
  • фактических сумм и заметок нет — только плановые позиции; факт без плана (часы, платежи) в смету не попадает; позиция без названия подписана названием статьи («Логистика», а не logistics);
  • налоги — строками (УСН, НДС сверху) или «В том числе НДС»;
  • место для подписи: в смете — блок «Исполнитель / Заказчик» (организация, ИНН, ФИО, подпись, М. П.), в счёте — «Руководитель / Бухгалтер» и М. П.

PDF ложится в папку проекта по виду: счёт — «Счета» (invoices, заводится для всех проектов миграцией 0165), смета — «Коммерческие предложения», договор, акт и доп. соглашение — «Договоры». Имя файла — «Счёт № 12.pdf». Загрузку делает система: права на документ уже проверены, отдельное право на файлы проекта не нужно.

Процесс генерации документа ​

Пример: Генерация счета ​

Шаг 1: Подготовка

Менеджер проекта:
  - Проверяет, что все данные в проекте заполнены
  - Проверяет финальный бюджет
  - Проверяет реквизиты клиента

Шаг 2: Выбор шаблона

Менеджер:
  1. Открывает проект
  2. Нажимает "Generate Document"
  3. Выбирает "Invoice"
  4. Выбирает шаблон (стандартный или кастомный)

Шаг 3: Подстановка данных

Система автоматически собирает:
  - DocNumber: 2026-001 (следующий номер)
  - DocDate: 2026-04-20
  - ClientName: ООО "Клиент"
  - ClientAddress: ул. Примерная, 1
  - ClientTIN: 123456789
  - SellerRequisites: набор «Моей компании», выбранный плательщиком в проекте
    (projects.payer_requisite_id), иначе primary internal-реквизиты из
    /settings/my-company/requisites
  - ClientRequisites: primary-реквизиты компании из /requisites
  - Tasks: [
      {Name: "Setup chairs", Amount: 10000},
      {Name: "Setup tables", Amount: 5000}
    ]
  - Equipment: [
      {Name: "Chairs", Qty: 10, Amount: 0}, // со склада
      {Name: "Projector rental", Qty: 1, Amount: 10000}
    ]
  - LogisticsCost: [
      {Description: "Delivery", Amount: 2000}
    ]
  - TotalAmount: 27000
  - TaxAmount: 4860
  - FinalAmount: 31860

Шаг 4: Генерация

Система:
  1. Берет шаблон
  2. Заменяет все {{Переменные}} на реальные данные
  3. Генерирует готовый документ (PDF или DOCX)

Шаг 5: Результат

Готовый счет (PDF):
  - Красиво оформлен
  - Все данные подставлены
  - Готов к отправке клиенту
  - Сохранен в проекте как Document (не как File)

Управление документами ​

Просмотр ​

  1. Открыть проект
  2. Перейти в раздел "Documents"
  3. Видно все сгенерированные документы

Регенерация ​

Если данные проекта изменились, документ можно пересоздать:

  1. Нажать "Regenerate" на готовом документе
  2. Система заново соберет данные и создаст новую версию
  3. Старая версия архивируется (с отметкой "superseded")

Скачивание ​

  1. Выбрать документ
  2. Нажать "Download"
  3. Получить PDF или DOCX

Отправка клиенту ​

  1. Скачать документ
  2. Отправить по email (вручную или через систему, если есть интеграция)

Акт по счёту ​

Акт формируется по одному из двух оснований (POST /api/v1/projects/:id/documents/act):

  • по счёту — basis_invoice_id: строки, сумма и НДС берутся из выставленного счёта проекта, у акта parent_document_id = счёт, в печатной форме — строка «Основание: Счёт № N от ДД.ММ.ГГГГ» (поле шаблона Word basis). По одному счёту — один неотменённый акт: второй даёт 409 documents_invoice_already_acted; черновик, отменённый счёт или счёт другого проекта — 400 documents_act_basis_must_be_invoice;
  • по смете целиком — без basis_invoice_id, как раньше: итоговый акт по действующей смете проекта.

Договоры одним списком ​

Договор, сформированный в проекте, сервер сразу заносит в реестр договоров (contracts): контрагент — клиент проекта, номер «N от ДД.ММ.ГГГГ», предмет «Договор по проекту «…»», сумма, document_id — PDF. Доп. соглашение прикрепляется к договору реестра связью amendment (contract_links). Срабатывает по событию document.created (internal/app/document_events.go → contracts.SyncGenerated), повтор ничего не дублирует; сбой реестра выпуск документа не отменяет. Миграция 0184 перенесла уже сформированные договоры и соглашения.

Реестр документов для финансов ​

GET /api/v1/finance/documents — счета, акты, договоры и соглашения всех проектов (и счета без проекта) одним списком для бухгалтерии. Видят финансы, бухгалтерия (accounting.*), юристы и затраты «все».

  • Отбор: type (через запятую: invoice, act, contract,addendum), status, preset (unpaid, overdue, unacted, paid, draft, signed, pending), company_id, project_id, date_from, date_to, q (номер, клиент, проект), limit (до 200), offset.
  • Строка: клиент и проект по имени, paid_amount (проведённые разнесения платежей; «Оплачен» вручную — вся сумма), outstanding, overdue_days, номер и вид основания (parent_number, parent_type), act_numbers — акты по счёту.
  • summary — итоги по отбору без пресета: к оплате, просрочено, оплачено, без акта, акты подписанные и ждущие подписи, черновики и aging — остаток к оплате: в срок, 1–30, 31–60, больше 60 дней просрочки.

Нумерация документов ​

Номер выдаётся нашим юрлицом-продавцом по виду документа и году: у счетов ООО и ИП своя нумерация, у счетов и смет — своя (document_counters, scope = 'seller', seller_requisite_id). Первый номер года продолжает уже выданные этим видом (раньше нумерация шла по клиенту) — номера не повторяются.

Номер берётся в той же транзакции, что рендер PDF, загрузка файла и запись документа (DocumentsRepository.IssueNumbered): строка счётчика блокируется до конца транзакции, сбой рендера или загрузки номер не тратит, два одновременных выпуска получают разные номера. Черновик номера не получает — только при выпуске.


Интеграция Files и Documents ​

Как они связаны ​

Сценарий:

  1. Менеджер загружает ТЗ в Files
  2. При генерации счета система может ссылаться на ТЗ (прикрепить QR код или ссылку)
  3. Клиент видит в счете ссылку на требования

Пример: Полный цикл проекта ​

1. Проект создан
   ├─ Upload: specifications.pdf (File)
   ├─ Upload: floor-plan.png (File)
   └─ Upload: nda.pdf (File)

2. Проект выполнен
   ├─ Tasks: все закрыты
   ├─ Team: все отработали часы
   └─ Finance: все затраты учтены

3. Генерируются документы
   ├─ Generate: Invoice (Document)
   │  └─ Ссылка на specification.pdf внутри
   ├─ Generate: Act (Document)
   │  └─ Список выполненных Tasks
   └─ Generate: Report (Document)
       └─ Анализ бюджета

4. Документы готовы к отправке
   ├─ Invoice (PDF) → отправка клиенту
   ├─ Act (PDF) → подпись
   └─ Report (PDF) → архив

Важные правила ​

1. Данные должны быть полными перед генерацией ​

Чтобы счет выглядел хорошо:

  • У проекта должна быть привязана Company
  • Реквизиты клиента должны быть заполнены в Company и, для банковских данных, в primary-наборе Requisites компании
  • Реквизиты поставщика должны быть заполнены в primary internal-реквизитах
  • Все работы должны быть в Tasks
  • Все затраты должны быть в Finance
  • Все участники должны быть в Team с ставками

2. Документы "привязаны" к моменту времени ​

Когда вы генерируете счет, он отражает данные на момент генерации. Если потом меняется проект, счет не обновляется автоматически (нужно его перегенерировать или отредактировать вручную).

3. Файлы — "сырьё", документы — "готовый продукт" ​

  • Файлы: техническое задание, чертежи, черновики
  • Документы: счета, контракты, официальные акты

4. История версий ​

Система может хранить историю сгенерированных документов:

  • Версия 1 (2026-04-15): первый черновик
  • Версия 2 (2026-04-20): после корректировок
  • Версия 3 (2026-04-25): финальная

Чек-лист перед генерацией документа ​

Перед тем как генерировать важный документ (счет, акт), менеджер должен проверить:

  • [ ] Проект имеет статус in_progress, done или closed, а не начальный planned
  • [ ] Все члены команды добавлены и имеют ставки
  • [ ] Все задачи имеют плановые и фактические часы
  • [ ] Все оборудование добавлено через логистические операции
  • [ ] Все затраты учтены в Finance
  • [ ] Плановый бюджет заполнен (если требуется)
  • [ ] Реквизиты клиента указаны в Company/Contact
  • [ ] Нет открытых логистических операций (все завершены)
  • [ ] Сроки проекта соответствуют действительности

Резюме ​

Файлы (Files):

  • Загруженные пользователем исходные материалы
  • Организованы в папки и категории
  • Используются для справки и работы

Документы (Documents):

  • Сгенерированные на основе шаблонов артефакты
  • Содержат данные проекта, подставленные в шаблон
  • Готовы к отправке клиенту
  • Имеют номера и историю версий

Процесс:

Project Data + Template → Generate → Document → Download/Send

Система автоматизирует создание официальных документов, менеджер лишь выбирает шаблон и нажимает "Generate".

Загружаем документацию…