⟨/⟩ Ntr/70_Infrastructure/AisOiaPeo/ActualConsumptionImport.cs

128 строк · в начало

using Rugrid.Sdaid.Notation.Documents;
using Rugrid.Sdaid.Notation.Glossary;
using AisTerm = Rugrid.Sdaid.Epas.Ntr.Glossary.Terms.AisOiaPeo;

namespace Rugrid.Sdaid.Epas.Ntr.Infrastructure.AisOiaPeo
{
    /// <summary>
    /// Контракт загрузки данных учёта фактического потребления из АИС ОИА ПЭО: что берётся из
    /// источника, какие преобразования выполняются и куда записывается результат.
    /// </summary>
    public class DOC_ActualConsumptionImport : IInfrastructureDocument, IHasStructuralLinks
    {
        public SdaidLink[] Links => new[]
        {
            Rel.Uses<DOC_AisDataImport>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.ActualConsumptionModel.DOC_EeConsumption>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.ActualConsumptionModel.DOC_TeConsumption>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.Reference.DOC_Period>(),
            Rel.Uses<Rugrid.Sdaid.Epas.Ntr.Domain.BuildingModel.DOC_Building>(),
        };

        public static string _refName = "Загрузка данных учёта";

        public string Name => "Загрузка данных учёта фактического потребления";

        public string Description =>
            @"Блок импорта, переносящий в Сервис фактическое потребление электрической и тепловой энергии: месячные значения точек учёта сводятся к зданию.";

        public string Version => "0.1";
        public string Status => "draft";
        public string[] Comments => new string[0];

        public static string Place = $"""
            ## Место в импорте

            Блок выполняется в составе общего прогона
            {SdaidAnchors.RefTo<DOC_AisDataImport>()} — отдельной точки входа нет.

            Потребление загружается после справочников и зданий: оно ссылается на учётные периоды и
            привязывается к зданиям.
            """;

        public static string Source = $"""
            ## Что берётся из АИС ОИА ПЭО

            Каждый вид ТЭР ведётся в {GlossaryAnchors.RefTo<AisTerm>(AisTerm.Name)} собственным набором
            таблиц одинаковой структуры; вид ТЭР задан суффиксом в наименовании таблицы: `_ee` —
            электрическая энергия, `_te` — тепловая.

            | Таблица | Модель АИС | Назначение | Поля |
            |---|---|---|---|
            | `ref_building_points_ee` / `_te` | `RefBuildingPointsEe` / `…Te` | Точка учёта здания | `id`, `building_fk` → `ref_e_buildings.id`, обязательное |
            | `doc_ter_buildings_ee` / `_te` | `DocTerBuildingsEe` / `…Te` | Документ учёта по точке за год | `id`, `year`, `building_point_fk` |
            | `doc_ter_buildings_ee__values` / `_te__values` | `DocTerBuildingsEeValues` / `…TeValues` | Значение за период | `docid`, `period_fk`, `payload` |
            | `ref_periods` | `RefPeriods` | Учётный период | `id`, `name`, `code`, `number`, `type` |

            Модели АИС лежат в `NrjPack.Bizmod.Eo.EfCoreData.Models` — это код АИС ОИА ПЭО.

            **Отбор:**

            | Условие | Назначение |
            |---|---|
            | `ref_periods.type = 'month'` | Учёт ведётся месяцами; периоды иных типов не загружаются |
            | `doc_ter_buildings_*.year >= 2017` | Глубина истории в источнике |
            | Здание точки учёта (`ref_building_points_*.building_fk`) есть в Сервисе | Потребление привязывается к зданию Сервиса |
            """;

        public static string Transform = """
            ## Преобразования

            **Сведение точек учёта к зданию.** Значение расхода по точке учёта здания суммируется в
            значение расхода по зданию. Группировка — здание, `doc_ter_buildings_*.year`,
            `doc_ter_buildings_*__values.period_fk`; агрегат — сумма `payload`. Точки учёта в Сервис не
            переносятся.

            **Разрешение ссылок.** Внешний ключ в таблице АИС хранит `id` записи АИС. Здание и учётный
            период в Сервисе несут `ais_id` — по нему находится нужная запись, и её `id` пишется в
            загружаемую запись потребления: в `build_id` — здания, в `period_id` — учётного периода.

            **Единицы измерения не пересчитываются:** значение переносится как есть — тыс. кВт·ч для
            электрической энергии, Гкал для тепловой.

            **Отсутствующее значение переносится как отсутствующее.** `payload` может быть не задан;
            такое значение не приравнивается к нулю и из выборки не исключается.
            """;

        public static string Target = $"""
            ## Куда записывается

            | Источник | Сущность Сервиса |
            |---|---|
            | Таблицы с суффиксом `_ee` | {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Ntr.Domain.ActualConsumptionModel.DOC_EeConsumption>()} |
            | Таблицы с суффиксом `_te` | {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Ntr.Domain.ActualConsumptionModel.DOC_TeConsumption>()} |

            Поля записи потребления: `build_id` — здание точки учёта, `year` — год документа,
            `period_id` — период значения, `consumption` — значение расхода.

            Справочник учётных периодов из `ref_periods` —
            {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Ntr.Domain.Reference.DOC_Period>()}: `ais_id` ← `id`
            источника, `name`, `code`, `number`, `type` — без изменений.
            """;

        public static string Idempotency = """
            ## Повторная загрузка

            Запись потребления — агрегат нескольких строк источника, поэтому `ais_id` у неё, в отличие
            от прочих загружаемых записей, нет. Повторная загрузка находит её по естественному ключу —
            здание, год, период: найденная запись обновляется значением, отсутствующая создаётся.
            Незаданное значение записывается так же, как заданное: если в источнике значения нет, ранее
            загруженное затирается.

            Удаление записи в источнике Сервисом не отслеживается: блок не удаляет записи, которых нет
            в текущей выборке.
            """;

        public static string Volume = $"""
            ## Объём

            Учёт ведётся только по зданиям, подключённым к сторонним источникам энергии: 235 точек
            учёта электрической энергии и 108 точек учёта тепловой.

            Верхняя оценка на год учёта: 343 точки × 12 месяцев ≈ 4,1 тысячи записей, и меньше после
            сведения точек к зданию. При глубине с 2017 года это порядка 40 тысяч записей за десять
            лет.
            """;
    }
}