Alexander Musikhin 1 napja
szülő
commit
2c31115e28

+ 10 - 8
docs/refactor/menu.md

@@ -39,8 +39,8 @@ Manager
 ├── Каталог общий
 │   ├── Позиции
 │   └── Карточка позиции
+│       └── Техническое описание / экспорт
 ├── Документация
-├── Технич. описание
 ├── Калькуляции
 └── Администратор
     ├── Подрядчики
@@ -147,8 +147,8 @@ Manager
 | Карточка позиции | Реализовано | `common-catalog.show` | Центральная карточка общей позиции/МАФ со всеми полями шаблона. |
 | Фото МАФ | Реализовано | `common-catalog.image.*` | Фото хранится через текущий файловый механизм и выводится в списке/карточке. |
 | Документы | Реализовано | `common-catalog.documents.*` | Поддержан набор сопутствующих документов позиции. |
-| Техническое описание | Подготовлено место внутри карточки | `common-catalog.show` | Экспорт будет подключен после получения готового Laravel-модуля. |
-| Калькуляция | Подготовлена кнопка | `common-catalog.show` | API-запрос будет подключен после получения контракта API. |
+| Техническое описание | Источник изучен, готово к реализации | `common-catalog.show` | Данные и DOCX-экспорты `to.stroyprofit.com` переносятся внутрь карточки общего каталога. |
+| Калькуляция | Подготовлена кнопка | `common-catalog.show` | Финальное действие кнопки определяется отдельным ТЗ; `calc.stroyprofit.com` изучен как источник модели и экспортов. |
 
 ### Документация
 
@@ -160,15 +160,15 @@ Manager
 
 ### Технич. описание
 
-Статус: **Встроить в каталог**.
+Статус: **Источник изучен, встроить в каталог**.
 
-Это не отдельный пункт меню и не самостоятельный модуль. Функциональность технического описания должна быть доступна из карточки позиции `Каталог общий`: по сути это те же данные позиции, но с выгрузками в определенном формате. Есть готовый Laravel-модуль, из которого нужно взять экспорт.
+Это не отдельный пункт меню и не самостоятельный модуль. Функциональность технического описания должна быть доступна из карточки позиции `Каталог общий`: по сути это те же данные позиции, но с выгрузками в определенном формате. Модуль `to.stroyprofit.com` уже изучен; из него переносятся недостающие данные, массовый DOCX и отдельные DOCX в ZIP.
 
 ### Калькуляции
 
-Статус: **Нужно реализовать позже**.
+Статус: **Исходный модуль изучен, ожидается отдельное ТЗ**.
 
алькуляции работают через внешний API: запрос выполняется по артикулу, в ответ возвращается калькуляция, если она найдена. Подробное описание API будет предоставлено отдельно.
нопка калькуляции остается в карточке общего каталога. Финальная архитектура пока не утверждена: отдельное ТЗ должно определить внутренний расчёт в Laravel либо интеграцию. `calc.stroyprofit.com` используется как источник сущностей, формул и Excel-выгрузок, но не переносится без проверки.
 
 ### Администратор
 
@@ -201,4 +201,6 @@ Manager
 
 ## Открытые вопросы
 
-1. Какой точный контракт внешнего API калькуляций?
+1. Когда будет передано отдельное ТЗ на `График заказов`?
+2. Будет ли отдельное ТЗ на `Калькуляции` и какую архитектуру оно определит?
+3. Где находятся актуальные исходные данные старого калькулятора?

+ 66 - 29
docs/refactor/plan.md

@@ -37,7 +37,13 @@
 - [x] Заглушки новых модулей показываем всем авторизованным пользователям.
 - [x] На новые модули выбранный год не влияет.
 - [x] `Технич. описание` встроено в модуль `Каталог общий`; готовый Laravel-модуль используем как источник экспорта.
-- [x] `Калькуляции` работают через внешний API: запрос по артикулу, возврат калькуляции при наличии.
+- [x] Модуль техописаний `to.stroyprofit.com` изучен: его данные и DOCX-экспорты переносятся в `Каталог общий` без отдельного раздела.
+- [x] Цена из `to.stroyprofit.com` не является полем техописания и не дублируется в `Каталог общий`: единственным источником актуальной цены должен быть модуль `Склад`, а DOCX-экспорт только читает её оттуда.
+- [x] Исходный калькулятор `calc.stroyprofit.com` используется как источник модели данных, формул и экспортов, но его код и текущие формулы не переносятся без проверки.
+- [x] Финальный состав и способ реализации `Калькуляций` определяются отдельным ТЗ; допустимы внутренняя реализация в Laravel и интеграционный вариант.
+- [x] Старый `График отгрузок` и действующий обработчик 1С в `manager.stroyprofit.com` изучены как исходная система для `Графика заказов`.
+- [x] `График заказов` проектируется максимально нормализованно: заказ, позиции, доставки и загрузки 1С хранятся отдельными сущностями, без сериализованных полей и фиксированных колонок для нескольких доставок.
+- [x] Финальные поля, статусы, права и пользовательские сценарии `Графика заказов` определяются отдельным ТЗ заказчика.
 - [x] `Рекламации -> ДКР` реализуется как отдельная вкладка на основе текущего списка с обязательным фильтром по типу `dkr`.
 - [x] Тип рекламации хранится через обязательную связь со справочником `reclamation_types`; начальные типы `ДКР` и `Прочее` создаются сидером.
 - [x] В интерфейсе рекламаций обязательны отдельные вкладки `Все` и `ДКР`.
@@ -74,10 +80,10 @@
 | 3. Рекламации: вкладки и тип | Реализован, ожидает пользовательской проверки | Добавлены вкладки, справочник типов, перенос существующих данных и запрет платежных документов для `Прочее`; создание из графика остается в этапе 10. |
 | 4. Общий каталог: ядро | Реализован и проверен | Пользователь проверил создание, редактирование, импорт и экспорт; отдельная модель данных, права, фото и документы покрыты автоматическими тестами. |
 | 5. Документация | Реализован и проверен | Пользователь проверил дерево папок, работу с документами и версиями; права и приватное хранение дополнительно покрыты автоматическими тестами. |
-| 6. Склад: ядро | Реализован, ожидает пользовательской проверки | Наличие, заказы, карточка, бронирование, списание, отмена, история, импорт и RBAC реализованы; PDF-экспорт ожидает отдельного шаблона. |
-| 7. Техническое описание | Готово к анализу Laravel-модуля | Место в карточке общего каталога подготовлено, но нужно получить модуль и форматы выгрузки. |
-| 8. Калькуляции | Не готово к полной реализации | Нужен контракт внешнего API. Можно сделать только место/кнопку в карточке общего каталога. |
-| 9. Графики заказов и доставок | Не готово к полной реализации | Нужны формат обмена с 1С, поля, статусы и правила доставок/отгрузок. |
+| 6. Склад: ядро | Ядро проверено, запланировано расширение цены | Ядро склада принято после пользовательской проверки; единый источник и история цены добавлены в план после анализа техописаний. PDF-экспорт остается отдельной задачей. |
+| 7. Техническое описание | Анализ завершён, готово к реализации | Изучены данные, импорт, изображения, DOCX-шаблоны и массовый/раздельный экспорт `to.stroyprofit.com`; требуется перенос в общий каталог. |
+| 8. Калькуляции | Исходник изучен, ожидается отдельное ТЗ | Восстановлены сущности, формулы и экспорты `calc.stroyprofit.com`; финальная архитектура, формулы и сценарии не фиксируются до ТЗ. Рабочая база источника сейчас не содержит расчётных данных. |
+| 9. Графики заказов и доставок | Исходная система изучена, ожидается отдельное ТЗ | Найдены старый график и фактический формат обмена с 1С. Нормализация принята как архитектурный принцип, но финальные поля, статусы и правила уточнит заказчик. |
 | 10. Рекламации из графика заказов | Готово только после графика заказов | Сценарий согласован, но точка входа зависит от карточки заказа в графике. |
 
 ## Этап 1. Реорганизация меню и заглушки
@@ -172,7 +178,7 @@
 
 ## Этап 6. Склад: ядро
 
-Статус: **реализован, ожидает пользовательской проверки**.
+Статус: **ядро реализовано и проверено пользователем; управление ценой добавлено в план как расширение**.
 
 Ядро склада можно реализовывать после появления позиций общего каталога. PDF-экспорт по шаблону вынесен отдельным подпунктом, потому что точный шаблон еще не согласован.
 
@@ -189,44 +195,72 @@
 - [x] Реализовать импорт заказов/остатков.
 - [x] Настроить права: `Наличие` всем, `Заказы` админу и роли `assistant_head`.
 - [x] Покрыть критичную логику расчетов тестами.
+- [ ] Уточнить назначение цены из старого модуля: отпускная, закупочная или иная.
+- [ ] Добавить в `Склад` единый источник актуальной цены позиции без дублирования в общем каталоге и техописании.
+- [ ] Сохранять историю изменения цены и пользователя, выполнившего изменение.
+- [ ] Добавить цену в список/карточку `Склад` и отдельные права на её просмотр/редактирование.
 - [ ] После согласования шаблона реализовать экспорт наличия в PDF.
 
 ## Этап 7. Техническое описание в общем каталоге
 
-Статус: **готово после этапа 4 и анализа готового Laravel-модуля**.
-
-- [ ] Получить и изучить готовый Laravel-модуль техописаний.
-- [ ] Составить карту данных модуля техописаний.
-- [ ] Составить карту экспортов и форматов выгрузки.
-- [ ] Сопоставить данные техописаний с полями `Каталог общий`.
-- [ ] Решить, какие данные хранятся прямо в карточке позиции, а какие требуют связанных таблиц.
+Статус: **анализ источника завершён, готово к реализации**.
+
+- [x] Получить и изучить готовый Laravel-модуль техописаний `to.stroyprofit.com`.
+- [x] Составить карту данных модуля техописаний.
+- [x] Составить карту экспортов и форматов выгрузки.
+- [x] Сопоставить данные техописаний с полями `Каталог общий`.
+- [x] Решить, что данные техописаний расширяют `common_catalog_items`, а не образуют отдельный модуль каталога.
+- [x] Исключить цену из полей техописания и общего каталога: её владельцем является `Склад`.
+- [ ] Добавить остальные недостающие поля техописаний в `Каталог общий` с безопасной миграцией.
+- [ ] Подготовить перенос или обогащение 938 позиций по артикулу в согласованном режиме без потери уже заполненных полей общего каталога.
+- [ ] Использовать цену источника только для начального заполнения цены в `Склад` после подтверждения её назначения; не импортировать её в техописание.
+- [ ] Перенести изображения через текущий файловый механизм CRM.
 - [ ] Встроить просмотр/редактирование техописания в карточку общего каталога.
 - [ ] Перенести или адаптировать экспорт из готового Laravel-модуля.
+- [ ] Подставлять в DOCX актуальную цену из `Склад`, не сохраняя отдельную копию цены в данных техописания.
+- [ ] Реализовать общий DOCX и отдельные DOCX в ZIP через очередь и приватное хранение файлов.
+- [ ] Покрыть миграцию данных и варианты экспорта автоматическими тестами.
 
 ## Этап 8. Калькуляции
 
-Статус: **не готово к полной реализации**.
+Статус: **исходный Python-модуль изучен, ожидается отдельное ТЗ**.
 
-До получения контракта API можно реализовать только место под кнопку/блок в карточке общего каталога.
+Текущий `calc.stroyprofit.com` рассматривается как источник предметной модели и экспортов. Финальное решение — перенос расчётного движка в Laravel либо интеграция — принимается после отдельного ТЗ. Формулы источника не считаются согласованными автоматически.
 
-- [ ] Получить подробное описание внешнего API калькуляций.
-- [ ] Согласовать endpoint, HTTP-метод, авторизацию, параметры запроса и формат ответа.
-- [ ] Реализовать запрос по артикулу позиции общего каталога.
-- [ ] Реализовать отображение найденной калькуляции.
-- [ ] Реализовать состояние, когда калькуляция по артикулу не найдена.
-- [ ] Реализовать обработку ошибок API.
+- [x] Добавить пункт меню и страницу-заглушку `Калькуляции`.
+- [x] Подготовить место под кнопку `Калькуляция` в карточке общего каталога.
+- [x] Изучить код, сущности, связи, формулы и Excel-экспорты `calc.stroyprofit.com`.
+- [x] Зафиксировать отсутствие расчётных данных в активной базе источника и нерабочий источник восстановления `backup.sql`.
+- [ ] Получить отдельное ТЗ на калькуляции.
+- [ ] Найти резервную копию или исходные Excel-файлы материалов, станков, персонала и технологических связей.
+- [ ] Согласовать формулы, единицы коэффициентов, ставки, налоги, доставку, накладные расходы и прибыль.
+- [ ] Определить, нужны ли версии калькуляций и история изменения нормативов.
+- [ ] Выбрать по ТЗ внутреннюю Laravel-реализацию или интеграционный контракт.
+- [ ] Спроектировать нормализованную модель данных без общей изменяемой калькуляции на артикул.
+- [ ] Реализовать согласованные сценарии, права, импорт и экспорты.
+- [ ] Покрыть расчётные формулы и версионность автоматическими тестами.
 
 ## Этап 9. Графики заказов и доставок
 
-Статус: **не готово к полной реализации**.
+Статус: **исходная система и обмен с 1С изучены, ожидается отдельное ТЗ**.
 
-Текущий `График монтажей` переносится на этапе 2. Новые графики требуют уточнения обмена с 1С, полей, статусов и правил доставок.
+Старый `График отгрузок` является источником существующих данных и сценариев, но не переносится одной таблицей. Архитектура нового модуля должна оставаться нормализованной и расширяемой под дополнительные требования заказчика.
 
-- [ ] Описать источник данных для `График заказов`.
+- [x] Изучить старый `График отгрузок` в `manager.stroyprofit.com`.
+- [x] Описать найденный HTTP-обмен с 1С и состав текущего payload.
+- [x] Проанализировать существующие статусы, ручные поля, вложения и несколько доставок по заказу.
+- [x] Зафиксировать обязательную нормализацию заказов, позиций, доставок и загрузок 1С.
+- [ ] Получить и согласовать отдельное ТЗ на `График заказов`.
+- [ ] Уточнить стабильный внешний идентификатор заказа и передачу артикула каждой позиции из 1С.
+- [ ] Согласовать принадлежность полей источнику или ручному редактированию, чтобы повторная загрузка не уничтожала плановые данные.
+- [ ] Спроектировать нормализованные таблицы и связи после получения ТЗ.
 - [ ] Спроектировать загрузку данных через 1С.
-- [ ] Реализовать или перенести `График заказов`.
+- [ ] Реализовать безопасный идемпотентный импорт с журналом запусков и ошибок.
+- [ ] Реализовать `График заказов` без прямого копирования устаревшей таблицы `graf1`.
+- [ ] Подготовить отдельную миграцию исторических данных старого Manager с отчётом о конфликтах и дублях.
 - [ ] Добавить карточку заказа с выбором одного или нескольких МАФ.
 - [ ] Добавить создание рекламации из заказа через текущую форму.
+- [ ] Получить и согласовать требования к `Графику доставок`, если они не войдут в ТЗ графика заказов.
 - [ ] Реализовать `График доставок` в виде недельного списка.
 - [ ] Добавить ручное планирование занятости водителей.
 - [ ] Связать доставки с адресами из графика заказов.
@@ -256,9 +290,12 @@
 
 ## Открытые вопросы
 
-- [ ] Какой точный контракт внешнего API калькуляций?
-- [ ] Где находится готовый Laravel-модуль техописаний и какие форматы выгрузки из него переносим?
+- [ ] Когда будет передано отдельное ТЗ на `График заказов` и какие новые требования добавит заказчик?
+- [ ] Передаёт ли 1С стабильный GUID заказа и артикулы позиций, либо формат обмена нужно расширить?
+- [ ] Будет ли отдельное ТЗ на `Калькуляции` и выберет ли оно внутренний расчёт в Laravel или интеграцию?
+- [ ] Где находится актуальная резервная копия или исходные Excel-данные `calc.stroyprofit.com`?
+- [ ] Какие формулы и нормативы калькулятора подтверждены заказчиком?
+- [ ] Нужно ли переносить в общий каталог все 938 записей `to.stroyprofit.com` как исходные или только обогащать совпавшие артикулы?
+- [ ] Что означает цена в `to.stroyprofit.com`: отпускную, закупочную или иную цену, и является ли она общей для позиции либо зависит от складского заказа/партии?
 - [ ] Какой точный PDF-шаблон нужен для экспорта `Склад`?
-- [ ] Какой формат обмена с 1С для `График заказов`?
-- [ ] Какие поля, статусы и правила ручного редактирования нужны для `График заказов`?
 - [ ] Какие поля, статусы, правила отгрузок и связи с заказами нужны для `График доставок`?

+ 124 - 84
docs/refactor/tz-calculations.md

@@ -9,107 +9,147 @@
 
 ## 1. Назначение
 
-Модуль `Калькуляции` предназначен для связи Manager 2.0 с внешним API калькуляций.
+Модуль `Калькуляции` предназначен для расчёта стоимости изготовления позиции общего каталога, хранения расчётных нормативов и формирования согласованных выгрузок.
 
-По новым вводным калькуляции не реализуются внутри CRM как самостоятельный расчетный движок. CRM должна отправлять запрос во внешний API по артикулу позиции и отображать возвращенную калькуляцию, если она есть.
+Финальный состав модуля будет определён отдельным ТЗ. До его получения нельзя считать утверждённым ни вариант внешнего API, ни полный перенос расчётного движка внутрь CRM.
 
 ## 2. Статус
 
-Статус модуля: **будет разработан отдельно**.
+Статус: **исходный Python-модуль изучен, ожидается отдельное ТЗ**.
 
-На первом этапе:
+На первом этапе уже реализованы:
 
-- добавить пункт меню;
-- добавить страницу-заглушку;
-- подготовить кнопку `Калькуляция` в карточке позиции общего каталога.
+- пункт меню;
+- страница-заглушка;
+- место под кнопку `Калькуляция` в карточке позиции общего каталога.
 
-Заглушка доступна всем авторизованным пользователям.
+Исходный модуль `calc.stroyprofit.com` используется как источник:
 
-## 3. Место в меню
+- предметной модели;
+- существующих формул;
+- пользовательских сценариев;
+- импорта справочников;
+- форматов Excel и ZIP-выгрузок.
 
-Целевое меню:
+Код и формулы источника не переносятся без проверки и согласования.
 
-```text
-Калькуляции
-```
+## 3. Результаты анализа источника
 
-Также в карточке позиции `Каталог общий` должна быть кнопка `Калькуляция`.
+В `calc.stroyprofit.com` найдены сущности:
 
-## 4. Права доступа
+- изделие, связанное с артикулом;
+- материал;
+- количество материала в изделии;
+- станок;
+- профессия и ставка;
+- связь станка с персоналом;
+- допустимые станки для материала;
+- технологическая обработка материала с коэффициентом.
 
-На первом этапе:
+Источник рассчитывает:
 
-- текущую систему прав не менять;
-- заглушку показывать всем авторизованным пользователям.
+- материалы;
+- станко-часы;
+- труд персонала;
+- страховые взносы;
+- доставку;
+- накладные расходы;
+- прибыль;
+- НДС;
+- итоговую стоимость.
 
-Целевая модель прав определяется после появления платформы калькуляций.
+Также реализованы:
+
+- ручное изменение коэффициентов;
+- подгонка расчёта под целевую цену;
+- Excel-калькуляция;
+- технологическая карта;
+- ZIP с расчётом и подтверждающими документами.
+
+Текущее состояние данных источника:
+
+- активная PostgreSQL-база не содержит изделий, материалов, станков, персонала и технологических связей;
+- сохранился только один пользователь;
+- `backup.sql` является пустым каталогом и не может использоваться для восстановления;
+- на диске остались отдельные ранее сформированные файлы, но они не заменяют исходные справочники и связи.
+
+## 4. Архитектурные ограничения
+
+До отдельного ТЗ допускаются два варианта:
+
+1. Реализация расчётного модуля внутри текущего Laravel-приложения.
+2. Интеграция с отдельным сервисом по согласованному API.
+
+Независимо от выбранного варианта:
+
+- позиция калькуляции должна связываться с `common_catalog_items` по устойчивой связи, а не только по свободному тексту;
+- нормативы, ставки и проценты не должны быть зашиты в код без возможности версионирования;
+- изменение или подгонка одной калькуляции не должно незаметно менять исходные нормативы других расчётов;
+- необходимо разделять нормативные данные, черновик расчёта и зафиксированную версию;
+- импорт и длительные экспорты должны выполняться через очередь;
+- файлы должны выдаваться через текущий защищённый файловый механизм CRM;
+- расчётные формулы должны быть покрыты автоматическими тестами.
 
 ## 5. Интеграция с общим каталогом
 
-Требования:
+Сохраняются предварительные требования:
 
 - карточка позиции общего каталога содержит кнопку `Калькуляция`;
-- кнопка выполняет запрос во внешний API калькуляций;
-- запрос выполняется по артикулу позиции;
-- если API возвращает калькуляцию, CRM должна показать ее пользователю;
-- если калькуляции нет, CRM должна показать понятное сообщение.
-- выбранный год в CRM не влияет на запрос и отображение калькуляций.
-
-Открыто:
-
-- endpoint API;
-- метод запроса;
-- параметры кроме артикула;
-- формат авторизации;
-- структура успешного ответа;
-- структура ответа, когда калькуляция не найдена;
-- требования к хранению или кешированию результата в CRM.
-
-## 6. Возможный функционал будущего модуля
-
-Предварительный список:
-
-- запрос калькуляции из позиции каталога по артикулу;
-- отображение результата, если калькуляция найдена;
-- сообщение об отсутствии калькуляции;
-- просмотр статуса калькуляции;
-- привязка результата к позиции каталога;
-- история калькуляций по позиции.
-
-Этот список предварительный и должен быть уточнен после отдельного ТЗ на платформу калькуляций.
-
-## 7. Что не входит в первый этап
-
-- реализация платформы калькуляций;
-- API-интеграция до получения подробного описания API;
-- хранение результатов калькуляций;
-- новые права;
-- синхронизация данных.
-
-## 8. Этапы реализации
-
-- [ ] Добавить пункт меню `Калькуляции`.
-- [ ] Добавить страницу-заглушку.
-- [ ] Добавить место под кнопку `Калькуляция` в карточке общего каталога.
-- [ ] Получить подробное описание внешнего API калькуляций.
-- [ ] Согласовать формат запроса по артикулу.
-- [ ] Реализовать запрос из карточки позиции.
-- [ ] Реализовать отображение возвращенной калькуляции.
-- [ ] Реализовать сообщение для случая, когда калькуляция не найдена.
-- [ ] При необходимости реализовать хранение истории калькуляций.
-
-## 9. Критерии приемки
-
-- Пункт `Калькуляции` есть в меню.
-- Заглушка открывается.
-- В карточке общего каталога предусмотрена кнопка `Калькуляция`.
-- После появления API запрос по артикулу работает для конкретной позиции каталога.
-- Если калькуляция найдена, пользователь видит результат.
-- Если калькуляция не найдена, пользователь видит понятное сообщение.
-
-## 10. Открытые вопросы
-
-- Какой endpoint, метод, авторизация и формат ответа у внешнего API?
-- Какие параметры кроме артикула нужно передавать?
-- Нужно ли хранить историю полученных калькуляций в CRM?
-- Какие роли имеют доступ к калькуляциям?
+- калькуляция открывается для конкретной позиции;
+- выбранный год CRM не влияет на доступность модуля;
+- при отсутствии калькуляции пользователь видит понятное состояние;
+- необходимость хранения истории определяется отдельным ТЗ.
+
+Точное поведение кнопки зависит от выбранной архитектуры: переход во внутреннюю карточку расчёта либо запрос к внешнему сервису.
+
+## 6. Что требует отдельного ТЗ
+
+- роли и права;
+- состав экранов и справочников;
+- утверждённые формулы;
+- единицы и смысл технологических коэффициентов;
+- источник целевой цены;
+- правила подгонки под цену;
+- версии нормативов и калькуляций;
+- актуальные налоговые и коммерческие ставки;
+- импорт исходных данных;
+- необходимые варианты Excel, ZIP и подтверждающих документов;
+- необходимость внешнего API.
+
+## 7. Этапы реализации
+
+- [x] Добавить пункт меню `Калькуляции`.
+- [x] Добавить страницу-заглушку.
+- [x] Добавить место под кнопку `Калькуляция` в карточке общего каталога.
+- [x] Изучить исходный Python-модуль.
+- [x] Составить предварительную карту сущностей, связей, формул и экспортов.
+- [x] Проверить наличие данных для миграции и зафиксировать их отсутствие в активной базе.
+- [ ] Получить отдельное ТЗ.
+- [ ] Найти резервную копию или исходные Excel-файлы справочников и связей.
+- [ ] Подтвердить формулы и нормативы с заказчиком.
+- [ ] Выбрать внутреннюю Laravel-реализацию или интеграционный вариант.
+- [ ] Спроектировать нормализованную и версионируемую модель.
+- [ ] Реализовать согласованные права, интерфейс, импорт и экспорт.
+- [ ] Покрыть критичные расчёты и историю автоматическими тестами.
+
+## 8. Предварительные критерии приемки
+
+Финальные критерии формируются после отдельного ТЗ. Обязательная техническая часть:
+
+- калькуляция однозначно связана с позицией общего каталога;
+- повторный расчёт воспроизводим на зафиксированной версии нормативов;
+- изменение черновика не меняет исторические калькуляции;
+- все коэффициенты и ставки имеют явный источник;
+- экспорт соответствует согласованному образцу;
+- ошибки расчёта и импорта диагностируются;
+- права доступа проверяются сервером.
+
+## 9. Открытые вопросы
+
+- Будет ли отдельное ТЗ и когда оно будет доступно?
+- Расчёт выполняется внутри Laravel или остаётся отдельным сервисом?
+- Где находятся актуальные данные старого калькулятора?
+- Формула времени — количество, умноженное на коэффициент, или количество, разделённое на производительность?
+- Какие проценты, ставки и правила подгонки считаются утверждёнными?
+- Требуется ли хранить версии и историю калькуляций?
+- Какие роли имеют доступ к просмотру и редактированию?

+ 9 - 7
docs/refactor/tz-catalog-common.md

@@ -145,6 +145,7 @@ SQL-таблицы названы `common_catalog_items` и `common_catalog_item
 - поле `Артикул` хранить строкой, чтобы сохранять ведущие нули;
 - `Внешний вид` отображает фото позиции;
 - состав полей общего каталога не зависит от состава полей каталога ДКР;
+- цена не является полем общего каталога: её единственным владельцем является модуль `Склад`;
 - обязательность заполнения и правила валидации полей уточняются при проектировании модели данных.
 
 Предварительная модель полей по шаблону:
@@ -223,11 +224,11 @@ SQL-таблицы названы `common_catalog_items` и `common_catalog_item
 | Модуль | Связь | Требование |
 |---|---|---|
 | ДКР | Имеет собственный каталог | Не смешивать каталог ДКР с общим каталогом. |
-| Склад | Использует картинку, артикул, наименование, характеристики, ед. изм. | Склад должен брать справочные поля из общего каталога. |
+| Склад | Использует картинку, артикул, наименование, характеристики, ед. изм.; хранит актуальную цену | Склад берёт справочные поля из общего каталога, но является единственным источником цены. |
 | Графики | Используют данные по позициям | При разработке графиков опираться на общий каталог. |
 | Рекламации | Используют данные по позициям | Сохранить/добавить связь рекламаций с позициями общего каталога. |
-| Технич. описание | Является частью общего каталога | Использовать готовый Laravel-модуль как источник экспорта/формата. |
-| Калькуляции | Запрашиваются из карточки позиции через внешний API | Запрос по артикулу, отображение возвращенной калькуляции при наличии. |
+| Технич. описание | Является частью общего каталога | Источник `to.stroyprofit.com` изучен; описательные поля и DOCX-экспорты переносятся в карточку, а цена читается из `Склад`. |
+| Калькуляции | Открываются из карточки позиции | Финальное поведение кнопки и способ реализации определяются отдельным ТЗ; исходный `calc.stroyprofit.com` используется как референс. |
 
 ## 11. Что не входит в первый этап
 
@@ -238,7 +239,7 @@ SQL-таблицы названы `common_catalog_items` и `common_catalog_item
 - внедрение новых прав доступа;
 - разработка модуля `Склад`;
 - отдельный модуль `Технич. описание`;
-- разработка интеграции с калькуляциями до получения подробного описания API;
+- разработка калькуляций до получения отдельного ТЗ и согласования архитектуры;
 - изменение бизнес-логики ДКР.
 
 ## 12. Этапы реализации
@@ -260,7 +261,7 @@ SQL-таблицы названы `common_catalog_items` и `common_catalog_item
 - [x] Реализовать фоновый импорт/экспорт по утвержденным 19 колонкам с обновлением по артикулу и поддержкой встроенных изображений.
 - [x] Реализовать блок документов как набор файлов.
 - [x] Зафиксировать, что `Технич. описание` включается внутрь карточки общего каталога.
-- [x] Добавить в карточку место под API-запрос `Калькуляции`.
+- [x] Добавить в карточку место под будущий модуль `Калькуляции`.
 - [x] Зафиксировать `common_catalog_items.id` как внешний ключ для будущих связей модулей; добавление связей выполняется вместе с соответствующими модулями.
 - [x] Настроить `common-catalog.view` для основных авторизованных ролей и отдельные права на изменение, файлы, импорт и экспорт.
 
@@ -272,10 +273,11 @@ SQL-таблицы названы `common_catalog_items` и `common_catalog_item
 - Рабочий раздел `Каталог общий` доступен основным авторизованным ролям через право `common-catalog.view`.
 - После реализации общий каталог не смешивает данные с каталогом ДКР без отдельной миграции/синхронизации.
 - Список, импорт и экспорт общего каталога используют утвержденный состав и порядок колонок из файла `docs/refactor/Шаблон Каталог ощий.xlsx`.
-- Карточка позиции общего каталога поддерживает фото и набор документов; места интеграции техописания и калькуляции подготовлены до получения внешних вводных.
+- Карточка позиции общего каталога поддерживает фото и набор документов; места интеграции техописания и калькуляции подготовлены до реализации соответствующих этапов.
 - ДКР продолжает использовать свой каталог без поломки существующих связей.
 - Реорганизация меню выполнена как часть общей структуры Manager 2.0.
 
 ## 14. Открытые вопросы
 
-- Какой точный формат API калькуляций: endpoint, параметры, авторизация, структура ответа?
+- Какие дополнительные поля техописания добавляются напрямую в `common_catalog_items` после переноса источника?
+- Какое поведение кнопки калькуляции будет утверждено отдельным ТЗ?

+ 50 - 15
docs/refactor/tz-schedules.md

@@ -19,7 +19,7 @@
 
 ## 2. Статус
 
-Статус модуля: **частично реализован**.
+Статус модуля: **частично реализован; исходная система графика заказов изучена, финальное ТЗ ожидается**.
 
 В текущей CRM реализован:
 
@@ -39,6 +39,15 @@
 - новую верхнюю группу меню `Графики`;
 - связи между графиками.
 
+После анализа `manager.stroyprofit.com` установлено:
+
+- текущий `График отгрузок` хранится в одной таблице `graf1` и совмещает данные заказа, статусы, доставку, монтаж и ручные комментарии;
+- данные поступают из 1С HTTP-запросом с JSON в поле `data`;
+- payload содержит заказ, клиента, договор, оплату, доставку, менеджера и список позиций;
+- позиции сейчас не нормализуются, а сохраняются только в сформированный Excel-файл;
+- поддерживаются до трёх доставок через фиксированные колонки;
+- финальные требования нового `Графика заказов` будут переданы отдельным ТЗ и могут расширить существующие сценарии.
+
 ## 3. Место в меню
 
 Целевое меню:
@@ -77,7 +86,7 @@
 
 ## 5. График заказов
 
-Статус: **нужно реализовать**.
+Статус: **исходная реализация изучена; проектирование и разработка начинаются после отдельного ТЗ**.
 
 Назначение:
 
@@ -94,6 +103,18 @@
 - связь с `Каталог общий`;
 - связь с `График монтажей`.
 
+Архитектурные требования, принятые до получения финального ТЗ:
+
+- не переносить таблицу `graf1` как есть;
+- хранить заказ, позиции заказа, доставки и загрузки 1С отдельными нормализованными сущностями;
+- не использовать сериализованные данные для монтажей, позиций и доставок;
+- не ограничивать заказ фиксированным количеством доставок;
+- отделить поля, которыми управляет 1С, от полей ручного планирования;
+- повторная загрузка должна быть идемпотентной и не должна сбрасывать ручные статусы и комментарии;
+- сохранять журнал загрузок, ошибки сопоставления и исходный payload для диагностики;
+- предусмотреть миграцию исторических данных старого Manager с отчётом о дублях и конфликтах;
+- сохранять возможность расширения модели без денормализации после получения дополнительных требований заказчика.
+
 Предварительный функционал:
 
 - список заказов/позиций в производственном графике;
@@ -122,12 +143,13 @@
 
 Открытые вопросы:
 
-- какой источник данных 1С и формат обмена;
-- какие поля приходят из 1С;
+- какой финальный состав полей и сценариев будет утверждён отдельным ТЗ;
+- может ли 1С передавать стабильный GUID заказа вместо ключа, собранного из номера и года;
+- может ли 1С передавать артикул позиции для связи с `Каталог общий`;
 - нужен ли ручной ввод/редактирование или график полностью загружается;
-- что именно в текущем/старом manager называется `график отгрузок`;
 - какие статусы производства должны отображаться;
-- как связывать строку графика с позицией `Каталог общий`.
+- какие поля принадлежат 1С, а какие должны сохраняться при повторной синхронизации;
+- какие части старых заявок на доставку и монтаж нужно сохранить в новом модуле.
 
 ## 6. График доставок
 
@@ -225,22 +247,32 @@
 
 Для `График монтажей` использовать текущие модели и таблицы.
 
-Для `График заказов` и `График доставок` модели проектируются отдельно после уточнения данных.
+Для `График заказов` и `График доставок` модели проектируются отдельно после получения финального ТЗ. Независимо от точных имён таблиц модель должна быть нормализована.
 
-Предварительно потребуются сущности:
+Минимально потребуются сущности:
 
-- производственная запись графика заказов;
-- строка/позиция производственного заказа;
-- запись доставки;
+- производственный заказ;
+- позиция производственного заказа со ссылкой на `Каталог общий`, когда сопоставление возможно;
+- произвольное количество доставок по заказу;
 - водитель или ответственный доставки;
 - журнал загрузок из 1С.
+- журнал ошибок и результатов сопоставления;
+- безопасно сохранённый исходный payload или ссылка на него для диагностики.
+
+Запрещённые варианты модели:
+
+- одна таблица, совмещающая заказ, позиции, доставки и монтаж;
+- колонки вида `delivery_1`, `delivery_2`, `delivery_3`;
+- сериализованные массивы в текстовых колонках как основная модель данных;
+- перезапись ручных плановых данных значениями по умолчанию при импорте из 1С.
 
 Открыто:
 
 - точные имена таблиц и моделей;
 - структура полей;
 - необходимость истории изменений;
-- связь с существующими `Order`, `Product`, `ProductSKU`.
+- связь с существующими `Order`, `Product`, `ProductSKU`;
+- правила миграции дублей и некорректных дат старого `graf1`.
 
 ## 10. Первый этап реализации
 
@@ -276,7 +308,9 @@
 - [x] Проверить создание записи графика из площадки/заказа.
 - [x] Проверить создание записи графика из рекламации.
 - [x] Проверить экспорт графика монтажей.
-- [ ] Составить отдельный список полей для будущего графика заказов.
+- [x] Изучить старый график заказов/отгрузок и существующий обмен с 1С.
+- [x] Зафиксировать нормализованную модель как обязательный архитектурный принцип.
+- [ ] Получить отдельное ТЗ и составить по нему финальный список полей графика заказов.
 - [ ] Составить отдельный список полей для будущего графика доставок.
 - [ ] Реализовать карточку заказа с выбором одного или нескольких МАФ.
 - [ ] Добавить действие `Добавить рекламацию`.
@@ -299,8 +333,9 @@
 
 ## 13. Открытые вопросы
 
-- Какой формат обмена с 1С для графика заказов?
-- Какие поля должны отображаться в графике заказов?
+- Какие дополнительные требования войдут в отдельное ТЗ графика заказов?
+- Передаёт ли 1С стабильный GUID заказа и артикулы позиций?
+- Какие поля должны отображаться в графике заказов по финальному ТЗ?
 - Нужен ли ручной ввод в графике заказов?
 - Где хранить список водителей для графика доставок?
 - Нужен ли отдельный модуль `Отгрузки`, или график доставок закрывает эту задачу?

+ 25 - 1
docs/refactor/tz-stock-availability.md

@@ -16,7 +16,7 @@
 
 ## 2. Статус
 
-Статус модуля: **ядро реализовано, ожидает пользовательской проверки**.
+Статус модуля: **ядро реализовано и проверено; управление ценой добавлено в план как расширение**.
 
 Реализованы `Наличие`, `Заказы`, карточка позиции, бронирование, списание, отмена, история движений, импорт и постоянные права. PDF-экспорт ожидает согласованного шаблона.
 
@@ -192,6 +192,21 @@
 - расчет остатка по заказу;
 - отображение активных броней.
 
+### Цена позиции
+
+`Склад` является единственным владельцем актуальной цены позиции. Цена не должна дублироваться в `Каталог общий` или данных технического описания.
+
+Требования:
+
+- цена связана с позицией общего каталога по `common_catalog_item_id`;
+- актуальная цена отображается в списке наличия и карточке позиции склада;
+- изменение цены не изменяет справочные и технические данные позиции;
+- сохраняются история значений, дата изменения и пользователь;
+- права просмотра и редактирования цены проверяются отдельно на сервере;
+- техническое описание получает актуальную цену из склада при формировании DOCX;
+- цена из `to.stroyprofit.com` может быть использована только как начальное значение после подтверждения её назначения;
+- если цена зависит от складского заказа или партии, это хранится нормализованно и не заменяет историю общей цены без явно согласованного правила.
+
 ## 11. Экспорт
 
 Требования:
@@ -207,6 +222,7 @@
 | Модуль | Связь | Требование |
 |---|---|---|
 | Каталог общий | Источник картинки, артикула, наименования, характеристик, ед. изм. | Обязательная связь. |
+| Технич. описание | Использует актуальную цену при формировании DOCX | Цена хранится только в `Склад`; техописание её не дублирует. |
 | График отгрузок / График заказов | Данные об отгрузках | Уточнить после реализации графиков. |
 | Запчасти | Эталон логики | Использовать паттерны реализации. |
 
@@ -223,6 +239,8 @@
 
 Отдельная таблица остатков не создаётся: физическое наличие, активная бронь, доступный остаток и заказанное количество рассчитываются из заказов и броней. Заказ связан с общей позицией по `common_catalog_item_id`; при импорте позиция разрешается по уникальному артикулу общего каталога.
 
+Цена относится к складскому учёту позиции и должна храниться отдельно от технических характеристик. Финальная таблица цены проектируется после уточнения, является ли цена общей для позиции или относится к конкретному заказу/партии; в любом варианте изменение не должно уничтожать историю.
+
 ## 14. Отложенная функциональность
 
 - PDF-шаблон;
@@ -248,6 +266,10 @@
 - [ ] Реализовать PDF-экспорт.
 - [x] Настроить права доступа.
 - [x] Покрыть расчеты остатков тестами.
+- [ ] Уточнить назначение и область действия цены.
+- [ ] Реализовать единый источник и историю цены в модуле `Склад`.
+- [ ] Добавить цену в список/карточку склада, права и интерфейс управления ценой.
+- [ ] Подключить чтение актуальной цены в экспорте техописаний.
 
 ## 16. Критерии приемки
 
@@ -267,3 +289,5 @@
 
 - Какой точный PDF-шаблон нужен для экспорта?
 - Как будет выглядеть связь с графиком отгрузок/заказов?
+- Что означает цена из `to.stroyprofit.com`: отпускную, закупочную или иную цену?
+- Цена общая для позиции или зависит от складского заказа/партии?

+ 58 - 17
docs/refactor/tz-technical-description.md

@@ -15,15 +15,17 @@
 
 ## 2. Статус
 
-Статус: **встроить в модуль `Каталог общий`**.
+Статус: **источник изучен, встроить в модуль `Каталог общий`**.
 
-Есть готовый модуль на Laravel. Его нужно изучить и использовать как источник:
+Laravel-модуль `to.stroyprofit.com` изучен и используется как источник:
 
 - структуры данных технического описания;
 - правил формирования выгрузок;
 - шаблонов/форматов экспорта;
 - возможных UI-решений, если они применимы к текущей CRM.
 
+В источнике находятся 938 позиций из 24 серий. Для всех позиций заполнены цена, характеристики, полное и краткое техническое описание, группа, название для формы и изображение. Наличие цены в старом модуле зафиксировано как факт анализа, но цена не считается частью техописания в новой CRM.
+
 ## 3. Место в меню
 
 Отдельный пункт меню `Технич. описание` не нужен. Целевая модель:
@@ -61,34 +63,73 @@
 - формирование выгрузки технического описания в установленном формате;
 - использование готового Laravel-модуля как основы для экспорта;
 - хранение данных в структуре общего каталога или связанной таблице, если данные нельзя уложить в основную карточку позиции.
+- получение актуальной цены для DOCX из модуля `Склад` без собственной копии цены в техописании.
 
-## 6. Что не входит до анализа готового модуля
+## 6. Что не переносим из готового модуля
 
 - отдельный самостоятельный раздел техописаний;
 - отдельная модель прав, не связанная с каталогом;
-- перенос данных без анализа структуры готового Laravel-модуля;
-- финальная схема таблиц.
-
-## 7. Этапы реализации
-
-- [ ] Получить и изучить готовый Laravel-модуль техописаний.
-- [ ] Составить карту данных модуля техописаний.
-- [ ] Составить карту экспортов и форматов выгрузки.
-- [ ] Сопоставить данные техописаний с полями `Каталог общий`.
-- [ ] Решить, какие данные хранятся прямо в карточке позиции, а какие требуют связанных таблиц.
+- прямое копирование устаревшего механизма авторизации и публичного хранения экспортов;
+- перезапись актуальных данных общего каталога без сопоставления по артикулу.
+- поле цены в таблицах общего каталога или техописания.
+
+## 7. Результаты анализа
+
+Источник хранит:
+
+- артикул;
+- серию;
+- наименование;
+- наименование для печатной формы;
+- группу;
+- цену;
+- характеристики;
+- полное техническое описание;
+- краткое техническое описание;
+- изображение.
+
+Экспорт поддерживает:
+
+- выбор нескольких позиций;
+- общий DOCX;
+- отдельный DOCX для каждой позиции в ZIP;
+- выбор полного, краткого или комбинированного описания;
+- отдельный и массовый DOCX-шаблоны.
+
+В текущем `common_catalog_items` отсутствуют готовые поля для названия печатной формы, текстовых характеристик, полного и краткого технического описания. Эти описательные поля должны дополнять общий каталог.
+
+Цена обрабатывается отдельно: единственным источником актуального значения является `Склад`. Значение из `to.stroyprofit.com` можно использовать только для начального заполнения складской цены после подтверждения её назначения. Техописание читает актуальную цену при формировании DOCX и не хранит собственную копию.
+
+## 8. Этапы реализации
+
+- [x] Получить и изучить готовый Laravel-модуль техописаний.
+- [x] Составить карту данных модуля техописаний.
+- [x] Составить карту экспортов и форматов выгрузки.
+- [x] Сопоставить данные техописаний с полями `Каталог общий`.
+- [x] Решить, что данные хранятся в карточке общего каталога, а не в отдельном модуле.
+- [x] Исключить цену из модели техописания и общего каталога.
+- [ ] Добавить остальные недостающие поля общего каталога.
+- [ ] Перенести данные по артикулу с защитой уже заполненных полей.
+- [ ] После уточнения назначения цены перенести её начальное значение в единый источник модуля `Склад`.
+- [ ] Перенести изображения в текущий файловый механизм CRM.
 - [ ] Встроить просмотр/редактирование техописания в карточку общего каталога.
 - [ ] Перенести или адаптировать экспорт из готового Laravel-модуля.
+- [ ] Подставлять в экспорт актуальную цену из `Склад`.
+- [ ] Выполнять массовые экспорты через очередь и выдавать результат из приватного хранилища.
 - [x] Не добавлять отдельный пункт меню `Технич. описание` в финальную навигацию.
 
-## 8. Критерии приемки
+## 9. Критерии приемки
 
 - Техническое описание доступно из карточки позиции общего каталога.
 - Данные техописания не дублируют общий каталог без необходимости.
+- Цена не хранится в техописании и берётся из единого источника модуля `Склад`.
 - Экспорт техописания работает в согласованном формате.
 - Готовый Laravel-модуль использован как источник экспортной логики.
 - Права просмотра/редактирования согласованы с правами общего каталога.
 
-## 9. Открытые вопросы
+## 10. Открытые вопросы
 
-- Где находится готовый Laravel-модуль техописаний и какие его части можно переносить напрямую?
-- Какие точные форматы выгрузки нужны?
+- Переносить все 938 позиций как источник данных или только обогащать артикулы, уже существующие в общем каталоге?
+- Сохраняются ли оба текущих DOCX-шаблона без визуальных изменений?
+- Нужна ли история изменения текстов технического описания?
+- Какой вид цены хранится в старом модуле и зависит ли она от конкретного складского заказа/партии?