# Слои показателей - Базовый модуль **name**: mklab_base_indicators **version**: 19.0.2025.11.17 **author**: MK.Lab **depends:** `base` ## Архитектура Модуль реализует структуру данных **направленного гиперграфа** для аналитики KPI. ``` mklab_base_indicators ├── hg.node — вершина графа (generic: res_model + res_id) ├── hg.index — показатель (метрика), привязан к вершине ├── hg.index.code — классификатор показателей ├── hg.value — значение показателя (план/факт/дата/формула) ├── hg.link — направленная связь: source_node к [target_nodes] └── hg.hg_mixin — AbstractModel: подключает любую модель к графу ``` --- ## Модели ### `hg.node` — Вершина графа **Файл:** `models/hg_node.py` Вершина представляет конкретный объект Odoo в структуре гиперграфа. Хранит generic-ссылку на запись через пару `(res_model, res_id)`. При подключении модели через `hg.hg_mixin` вершина создаётся автоматически при создании записи. | Поле | Тип | Описание | |---|---|---| | `name` | Char | Название вершины | | `res_id` | Integer | ID записи в Odoo | | `res_model` | Char | Техническое имя модели (`project.task`, `sale.order` и др.) | #### Методы **`goto_related()`** — возвращает действие `ir.actions.act_window` для открытия связанной записи в диалоге. Используется для навигации из графа к исходному объекту. --- ### `hg.index` — Показатель **Файл:** `models/hg_index.py` Показатель — именованная KPI-метрика, привязанная к конкретной вершине графа. Хранит историю значений через связанные записи `hg.value` и вычисляет актуальное значение на текущую дату. | Поле | Тип | Описание | |---|---|---| | `name` | Char | Название показателя | | `node_id` | Many2one → `hg.node` | Вершина-владелец показателя | | `internal_code_id` | Many2one → `hg.index.code` | Внутренний классификатор | | `external_code` | Char | Внешний код для интеграций | | `public` | Boolean | Признак публичного показателя | | `value_ids` | One2many → `hg.value` | История значений показателя | | `current_value` | Float | Текущее значение на сегодня | #### Методы **`_compute_current_value()`** — вычисляет `current_value` на основе `value_ids`. Из всех значений отбираются те, у которых `date_due <= сегодня`. Среди отобранных берётся запись с наибольшей датой — её `value_float_actual` становится текущим значением. Если подходящих значений нет — возвращается `0`. **`calc()`** — метод вычисления значения показателя по формуле или связанным вершинам. Вызывается явно при необходимости пересчёта. --- ### `hg.index.code` — Классификатор показателей **Файл:** `models/hg_index_code.py` Справочник внутренних кодов для группировки показателей. Позволяет объединять показатели разных вершин в один срез при аналитике (например, «Выручка» по всем задачам проекта). | Поле | Тип | Описание | |---|---|---| | `name` | Char | Название кода | | `index_ids` | One2many → `hg.index` | Показатели с данным кодом | --- ### `hg.value` — Значение показателя **Файл:** `models/hg_value.py` Хранит конкретное числовое значение (плановое и фактическое) для показателя на определённую дату. Поддерживает два режима: простое значение и вычисление по формуле. | Поле | Тип | Описание | |---|---|---| | `name` | Char | Название значения | | `index_id` | Many2one → `hg.index` | Родительский показатель | | `date_due` | Date (required) | Дата значения | | `value_float_plan` | Float | Плановое значение | | `value_float_actual` | Float | Фактическое значение | | `type` | Selection | `alone` — простое значение; `formula` — вычисляется по формуле | | `formula` | Char | Python-выражение для вычисления (используется при `type='formula'`) | #### Методы **`calc()`** — вычисляет `value_float_actual` для значений с `type='formula'`. Вычисление выполняется через `safe_eval` с контекстом: | Переменная | Значение | |---|---| | `node_value` | текущая запись `hg.value` | | `node_index` | родительский показатель `hg.index` | | `datatime` | текущая дата `fields.Date.today()` | --- ### `hg.link` — Матрица связности **Файл:** `models/hg_link.py` Представляет направленное гиперребро графа: один источник и множество вершин-приёмников. Используется для построения отчётов по связанным объектам и визуализации зависимостей. | Поле | Тип | Описание | |---|---|---| | `name` | Char | Название строки связи | | `source_id` | Many2one → `hg.node` | Вершина-источник | | `target_ids` | Many2many → `hg.node` | Множество вершин-приёмников | --- ### `hg.hg_mixin` — Миксин для моделей **Файл:** `models/hg_mixin.py` **Тип:** `models.AbstractModel` Абстрактная модель, подключаемая через `_inherit` к любой модели Odoo. После подключения модель автоматически становится участником гиперграфа: при создании записи создаётся соответствующая вершина `hg.node`. #### Подключение к модели ```python class ProjectTask(models.Model): _name = 'project.task' _inherit = ['project.task', 'hg.hg_mixin'] ``` #### Поля, добавляемые в модель | Поле | Тип | Описание | |---|---|---| | `node_id` | Many2one → `hg.node` | Вершина графа для данной записи | | `index_ids` | Many2many → `hg.index` | Показатели, привязанные к вершине записи | | `related_ids` | Many2many → `hg.node` | Вершины-приёмники из матрицы связности | #### Методы **`create()`** — переопределён: после создания записи автоматически создаёт `hg.node` с `res_model` и `res_id` текущей записи, устанавливает `node_id`. **`_compute_indexes()`** — ищет все `hg.index` с `node_id` равным вершине записи, заполняет `index_ids`. **`_compute_related()`** — ищет все `hg.link` где `source_id` равен вершине записи, собирает все `target_ids` из найденных связей, заполняет `related_ids`. --- ## Представления и меню **Файл:** `views/views.xml` Создаёт корневое меню **«Слои показателей»** со следующей структурой: ``` Слои показателей ├── Граф │ ├── Вершины графа → hg.node (list / form) │ └── Матрица связности → hg.link (list / form) └── Показатели ├── Показатели → hg.index (list / form) ├── Значения показателей → hg.value (list / form) └── Внутренний код → hg.index.code (list / form) ``` --- ## Безопасность **Файл:** `security/res_groups.xml` Группа `group_indicators_admin` — **«Администратор Слоёв показателей»**. Полный CRUD-доступ ко всем моделям модуля. **Файл:** `security/ir.model.access.csv` | Модель | Группа | Права | |---|---|---| | `hg.node` | `group_indicators_admin` | CRUD | | `hg.index` | `group_indicators_admin` | CRUD | | `hg.index.code` | `group_indicators_admin` | CRUD | | `hg.value` | `group_indicators_admin` | CRUD | | `hg.link` | `group_indicators_admin` | CRUD | | `hg.hg_mixin` | `group_indicators_admin` | CRUD | --- ## Тесты **Файл:** `tests/` | Файл | Что покрывает | |---|---| | `test_hg_node.py` | Создание вершины, метод `goto_related()` | | `test_hg_index.py` | Создание показателя, вычисление `current_value` в различных сценариях | | `test_hg_value.py` | Создание значения, вызов `calc()` для типов `alone` и `formula` | | `test_hg_link.py` | Создание связи с вершинами-приёмниками и без них | | `test_indicators.py` | Интеграционный тест цепочки модулей | ---