{
  "schema_version": "1.0",
  "title": "База знаний цифрового сотрудника-аналитика «Конструктор отчётов по энергобиллингу РРЭ»",
  "provenance": {
    "service": "https://sol-mspg313y-6zr.apps.sreda-ai.ru",
    "snapshot_date": "2026-08-12",
    "dictionary_source": "data-dictionary.md (отдан сервисом в /api/agent/context.dictionary), собран 11.08.2026 из 7 выгрузок + C#-генератора отчёта ПУНЦ «Код к отчету.txt»"
  },
  "sources": [
    {
      "key": "accruals",
      "title": "Начисления (00102)",
      "export_code": "00102",
      "rows": 386,
      "grain": "строка начисления (R_Id) внутри документа (D_Id)",
      "fact_rules_apply": true,
      "dimensions": [
        "year",
        "month",
        "period",
        "doc_type",
        "doc_number",
        "doc_state",
        "calc_name",
        "contract_id",
        "contract",
        "contract_number",
        "contragent",
        "contragent_inn",
        "division_code",
        "division",
        "region",
        "price_zone",
        "nomenclature",
        "row_name",
        "category",
        "voltage",
        "power_range",
        "unit",
        "row_group",
        "row_id"
      ],
      "measures": [
        "volume",
        "price",
        "cost_without_vat",
        "vat_amount",
        "cost_vat"
      ]
    },
    {
      "key": "details",
      "title": "Детализация компонентов цены (00101 + 00102)",
      "export_code": "00101",
      "rows": 1396,
      "grain": "компонент цены строки начисления (RowId)",
      "fact_rules_apply": true,
      "dimensions": [
        "year",
        "month",
        "period",
        "doc_type",
        "doc_number",
        "doc_state",
        "calc_name",
        "contract_id",
        "contract",
        "contract_number",
        "contragent",
        "contragent_inn",
        "division_code",
        "division",
        "region",
        "price_zone",
        "nomenclature",
        "row_name",
        "category",
        "voltage",
        "power_range",
        "unit",
        "row_group",
        "row_id",
        "component",
        "detail_calc_name",
        "con_obj_id",
        "calc_scheme",
        "store"
      ],
      "measures": [
        "volume",
        "price",
        "cost_without_vat",
        "vat_amount",
        "cost_vat",
        "detail_volume",
        "detail_price",
        "price_without_discount",
        "detail_cost"
      ]
    },
    {
      "key": "contracts",
      "title": "Договоры РРЭ (00211)",
      "export_code": "00211",
      "rows": 14,
      "grain": "договор (C_Id)",
      "fact_rules_apply": false,
      "dimensions": [
        "id",
        "code",
        "number",
        "name",
        "state",
        "begin_dt",
        "end_dt",
        "railway",
        "contragent_id"
      ],
      "measures": []
    },
    {
      "key": "contragents",
      "title": "Организации-контрагенты (01113)",
      "export_code": "01113",
      "rows": 12,
      "grain": "организация-контрагент (C_Id)",
      "fact_rules_apply": false,
      "dimensions": [
        "id",
        "name",
        "short_name",
        "inn",
        "kpp",
        "type"
      ],
      "measures": []
    },
    {
      "key": "divisions",
      "title": "Структурные подразделения (01112)",
      "export_code": "01112",
      "rows": 15,
      "grain": "структурное подразделение (D_Id)",
      "fact_rules_apply": false,
      "dimensions": [
        "id",
        "code",
        "name",
        "short_name",
        "type"
      ],
      "measures": []
    },
    {
      "key": "regions",
      "title": "Субъекты РФ / энергорайоны (01115)",
      "export_code": "01115",
      "rows": 85,
      "grain": "субъект РФ / энергорайон (R_Id)",
      "fact_rules_apply": false,
      "dimensions": [
        "id",
        "code",
        "name",
        "price_zone",
        "time_zone"
      ],
      "measures": []
    },
    {
      "key": "signers",
      "title": "Подписанты (01114)",
      "export_code": "01114",
      "rows": 5,
      "grain": "подписант (S_Id)",
      "fact_rules_apply": false,
      "dimensions": [
        "id",
        "surname",
        "name",
        "job_title",
        "email",
        "company_id"
      ],
      "measures": []
    }
  ],
  "mart_rules": {
    "enforcement": "Правила зашиты в витрину и подставляются в WHERE автоматически для источников с fact_rules_apply = true. Проверено 12.08.2026 запросом POST /api/report: в ответе sql содержит все три предиката, в результате нет ни строк «Средневзвешенный…», ни документов кроме АПП. Агенту НЕ нужно (и нечем — оператора not_starts_with в API нет) дублировать их фильтрами; их нужно ЗНАТЬ, чтобы правильно объяснять цифры пользователю.",
    "mandatory": [
      {
        "rule": "D_Type = 'АПП'",
        "rationale": "СЧФ описывает то же начисление, что и АПП; КАПП/КСЧФ — корректировки. Любой другой набор типов документов даёт двойной счёт."
      },
      {
        "rule": "R_CalcName = 'Текущий расчет' (в 00101 — RowCalcName = 'Текущий расчет')",
        "rationale": "Альтернативные сценарии закупки несопоставимы с текущим по цене."
      },
      {
        "rule": "исключить строки R_Nomenclature LIKE 'Средневзвешенный%'",
        "rationale": "Это расчётные итоги по договору (средневзвешенные тарифы), а не первичные начисления; их включение задваивает объём и стоимость."
      }
    ],
    "consequences_for_agent": [
      "Спрашивать про альтернативные сценарии расчёта бессмысленно для источников accruals/details: витрина отдаёт только «Текущий расчет». Если пользователь просит альтернативный сценарий — честно сказать, что витрина его не отдаёт.",
      "Аналогично по корректировкам: КАПП/КСЧФ через /api/report недоступны, доступны только АПП.",
      "Значения doc_type/calc_name из enum_values описывают СЫРЫЕ данные data.db, а не то, что вернёт витрина."
    ],
    "antipatterns": [
      "Суммировать АПП вместе с СЧФ — двойной счёт.",
      "Складывать объёмы в кВт·ч и кВт в один показатель.",
      "Включать строки «Средневзвешенный тариф …» в сумму объёма или стоимости.",
      "Смешивать «Текущий расчет» с альтернативными сценариями в одной цене.",
      "Группировать разбором текста R_Name вместо атрибутных полей category / voltage / power_range."
    ]
  },
  "key_enums": {
    "nomenclature": [
      "Мощность АТС",
      "Мощность СО",
      "Средневзвешенный тариф на собственные нужды",
      "Средневзвешенный тариф по ВН",
      "Средневзвешенный тариф по НН",
      "Средневзвешенный тариф по СН1",
      "Средневзвешенный тариф по СН2",
      "Средневзвешенный тариф по ФСК220",
      "Средневзвешенный тариф по договору",
      "Средневзвешенный тариф по населению",
      "Средневзвешенный тариф по потерям транзита",
      "Электроэнергия",
      "Электроэнергия (потери)",
      "Электроэнергия (услуги)",
      "Электроэнергия день",
      "Электроэнергия ночь"
    ],
    "category": [
      "-",
      "1ЦК",
      "3ЦК",
      "4ЦК",
      "Население: Городское население с газ.плитами",
      "Население: Городское население с эл.плитами",
      "Население: Сельское население"
    ],
    "voltage": [
      "ВН",
      "НН",
      "СН1",
      "СН2",
      "ФСК220"
    ],
    "power_range": [
      "более 10 МВт",
      "менее 670 кВт",
      "от 670 до 10 МВт"
    ],
    "unit": [
      "кВт",
      "кВтч"
    ],
    "contract": [
      "\"Россети Центр\" - \"Смоленскэнерго\"",
      "\"Россети Центр\" - \"Смоленскэнерго\" Import_test",
      "«РУСЭНЕРГОСБЫТ» (Смоленск)",
      "«РУСЭНЕРГОСБЫТ» (Смоленск) Import_test",
      "Переток от Юго-Восточной дирекции",
      "Тест - «РУСЭНЕРГОСБЫТ»"
    ],
    "period": [
      "2024-08"
    ]
  },
  "operators": {
    "eq": "равно",
    "ne": "не равно",
    "in": "одно из",
    "not_in": "не входит в",
    "gt": "больше",
    "gte": "больше или равно",
    "lt": "меньше",
    "lte": "меньше или равно",
    "between": "в диапазоне",
    "contains": "содержит",
    "starts_with": "начинается с",
    "is_null": "не заполнено",
    "is_not_null": "заполнено"
  },
  "aggregations": {
    "sum": "Сумма",
    "avg": "Среднее",
    "wavg": "Средневзвешенное по объёму",
    "min": "Минимум",
    "max": "Максимум",
    "count": "Количество",
    "count_distinct": "Количество уникальных"
  },
  "data_coverage": {
    "periods_available": [
      "2024-08"
    ],
    "periods_missing": [
      "2024-09 — в 00102 присутствует только D_Year=2024, D_Month=8; лист «Сравнение» двух периодов на этих данных не проверить"
    ],
    "test_data_note": "Договоры с суффиксом Import_test и «Тест - «РУСЭНЕРГОСБЫТ»» — тестовые; в боевых итогах их наличие нужно оговаривать."
  },
  "clarification_policy": {
    "principle": "Если запрос неоднозначен — задать уточняющий вопрос, а не додумать. За один ход задаётся один вопрос по самому важному незаполненному слоту.",
    "slots": [
      {
        "slot": "period",
        "title": "Период",
        "why": "Без периода выборка смешивает месяцы; в данных сейчас только 2024-08.",
        "detect": "в запросе нет года и месяца (или интервала) и нет фильтра по period/year/month",
        "question": "За какой период считаем? В базе сейчас есть только август 2024 (2024-08) — берём его?",
        "fields": [
          "period",
          "year",
          "month"
        ],
        "default_allowed": false
      },
      {
        "slot": "contract",
        "title": "Договор / контрагент",
        "why": "В данных 6 договоров, включая тестовые (Import_test, «Тест - …»); итог «по всем» смешивает боевые и тестовые.",
        "detect": "не назван договор, контрагент или явно «по всем договорам»",
        "question": "По какому договору считаем? Доступны: {contracts}. Или свести по всем сразу (включая тестовые Import_test)?",
        "fields": [
          "contract",
          "contract_id",
          "contract_number",
          "contragent"
        ],
        "default_allowed": false
      },
      {
        "slot": "breakdown",
        "title": "Разрез (группировка)",
        "why": "Одна и та же сумма в разрезе номенклатуры, напряжения или ценовой категории отвечает на разные вопросы.",
        "detect": "запрошены цифры, но не указано «в разрезе чего»",
        "question": "В каком разрезе показать: по видам начисления, по уровням напряжения, по ценовым категориям, по договорам или по подразделениям?",
        "fields": [
          "nomenclature",
          "voltage",
          "category",
          "power_range",
          "contract",
          "division",
          "region"
        ],
        "default_allowed": false
      },
      {
        "slot": "measure_units",
        "title": "Показатель и единицы",
        "why": "Объём в 00102 хранится в двух единицах: кВт·ч (энергия) и кВт (мощность); суммировать их вместе нельзя. Стоимость бывает с НДС и без.",
        "detect": "сказано «объём»/«сумма» без указания единиц или отношения к НДС",
        "question": "Что считаем: объём (кВт·ч по энергии или кВт по мощности) или стоимость — без НДС или с НДС?",
        "fields": [
          "volume",
          "unit",
          "cost_without_vat",
          "cost_vat",
          "vat_amount",
          "price"
        ],
        "default_allowed": false
      },
      {
        "slot": "calc_scenario",
        "title": "Сценарий расчёта",
        "why": "Кроме «Текущий расчет» в сырых данных два альтернативных сценария, но витрина отдаёт только текущий.",
        "detect": "пользователь просит цены по альтернативному сценарию закупки",
        "question": null,
        "answer_instead": "Не спрашивать, а сообщить: витрина зафиксирована на «Текущий расчет» (правило mart_rules.calc_current), альтернативные сценарии через конструктор недоступны.",
        "fields": [
          "calc_name"
        ],
        "default_allowed": true,
        "default_value": "Текущий расчет",
        "default_note": "Жёсткое правило витрины, изменить его через конфигурацию отчёта нельзя."
      },
      {
        "slot": "doc_scope",
        "title": "Учитывать ли корректировки",
        "why": "Открытый вопрос №2: неизвестно, замещает КАПП/КСЧФ исходный АПП или дополняет его; при включении сумма может задвоиться (открытый вопрос №3).",
        "detect": "пользователь просит «актуальные» данные с учётом корректировок",
        "question": null,
        "answer_instead": "Не спрашивать, а предупредить: выборка содержит только первичные АПП (правило mart_rules.doc_type_app); корректировки КАПП/КСЧФ витрина не отдаёт, а методика их учёта не подтверждена (открытые вопросы №2 и №3).",
        "fields": [
          "doc_type"
        ],
        "default_allowed": true,
        "default_value": "АПП",
        "default_note": "Жёсткое правило витрины."
      },
      {
        "slot": "source",
        "title": "Уровень детализации",
        "why": "Один и тот же вопрос решается по 00102 (строки начислений) или по 00101 (компоненты цены) — гранулярность и меры разные.",
        "detect": "запрос про составляющие цены/тарифа, но источник не выбран",
        "question": "Считать по строкам начислений (00102) или разложить по компонентам цены (00101 — сбытовая надбавка, передача, инфраструктура, УИРП)?",
        "fields": [
          "source"
        ],
        "default_allowed": true,
        "default_value": "accruals",
        "default_note": "Если в вопросе фигурируют компоненты цены — переключиться на details."
      }
    ],
    "answer_rules": [
      "Не додумывать неуказанное: если не хватает периода, договора, разреза или единиц — задать ОДИН уточняющий вопрос по самому важному пропущенному слоту, а не перечислять все сразу.",
      "Не выдумывать значения справочников: подставлять только те, что есть в enum_values.",
      "Каждую цифру подкреплять конфигурацией отчёта (source + dimensions + measures + filters), чтобы пользователь мог её воспроизвести кнопкой в конструкторе.",
      "Строки «Средневзвешенный тариф …» не суммировать: это расчётные итоги, а не первичные начисления.",
      "Объёмы в кВт·ч и кВт не складывать в один показатель — разделять по полю unit.",
      "Если вопрос упирается в один из открытых вопросов (open_questions) — ответить, но явно назвать допущение и его номер.",
      "Тестовые договоры (Import_test, «Тест - …») по умолчанию не исключаются автоматически; если они попали в выборку — предупредить об этом в ответе."
    ]
  },
  "open_questions": [
    {
      "id": 1,
      "title": "«Прочерк» в эталоне приравнен к нулю"
    },
    {
      "id": 2,
      "title": "КАПП/КСЧФ замещают или дополняют АПП"
    },
    {
      "id": 3,
      "title": "Два одинаковых КАПП"
    },
    {
      "id": 4,
      "title": "Сопоставление одноимённых позиций между периодами"
    }
  ],
  "report_api": {
    "endpoint": "POST /api/report",
    "config_shape": {
      "name": "строка — название отчёта",
      "source": "строка — ключ источника из sources[].key",
      "dimensions": "список ключей полей role=dimension",
      "measures": "список объектов {field: ключ поля, agg: ключ из aggregations}",
      "filters": "список объектов {field, op: ключ из operators, value}",
      "sort": "список объектов {key: '<field>_<agg>' или ключ измерения, desc: bool}",
      "limit": "целое число"
    },
    "validation_note": "Элементы measures/filters/sort должны быть объектами указанной формы; иначе сервис отвечает 400 с mart.ConfigError (индекс элемента + список допустимых ключей)."
  },
  "glossary": [
    {
      "term": "ПУНЦ",
      "definition": "Предельный уровень нерегулируемых цен на электроэнергию для конечного потребителя. Итог расчёта; в 00101 присутствует готовыми компонентами «ПУНЦ ЭЭ», «ПУНЦ мощность АТС», «ПУНЦ мощность СО»."
    },
    {
      "term": "РРЭ",
      "definition": "Розничный рынок электроэнергии."
    },
    {
      "term": "АПП",
      "definition": "Акт приёма-передачи — первичный документ начисления. Базовый тип документа для витрины."
    },
    {
      "term": "СЧФ",
      "definition": "Счёт-фактура. Описывает то же начисление, что и АПП; сложение АПП+СЧФ даёт двойной счёт."
    },
    {
      "term": "КАПП / КСЧФ",
      "definition": "Корректировочные акт и счёт-фактура. В базовую выборку не входят (см. открытый вопрос №2)."
    },
    {
      "term": "ЦК",
      "definition": "Ценовая категория потребителя (1ЦК…6ЦК); в данных встречаются 1ЦК, 3ЦК, 4ЦК и «-»."
    },
    {
      "term": "СВНЦ",
      "definition": "Средневзвешенная нерегулируемая цена электроэнергии на оптовом рынке."
    },
    {
      "term": "ГП",
      "definition": "Гарантирующий поставщик."
    },
    {
      "term": "АТС",
      "definition": "Администратор торговой системы оптового рынка; «Мощность АТС» — вид начисления мощности."
    },
    {
      "term": "СО",
      "definition": "Системный оператор ЕЭС; «Мощность СО» — вид начисления мощности."
    },
    {
      "term": "УИРП",
      "definition": "Услуги по управлению изменением режима потребления."
    },
    {
      "term": "Котловой тариф",
      "definition": "Единый тариф на услуги по передаче электроэнергии; в 00101 — компонент «Услуги по ЭЭ 1ст»."
    },
    {
      "term": "Уровень напряжения",
      "definition": "ВН / СН1 / СН2 / НН / ФСК220 — точка присоединения потребителя, влияет на тариф передачи."
    },
    {
      "term": "Двухставочный тариф",
      "definition": "Тариф передачи из двух ставок: «Ставка за содержание сетей» + «Услуги ЭЭ 2ст: Ставка за потери»."
    }
  ]
}
