⟨/⟩ Nts/70_Infrastructure/AisOiaPeo/AisImport.cs

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

using Rugrid.Sdaid.Notation.Documents;
using Rugrid.Sdaid.Epas.Nts.Domain;

namespace Rugrid.Sdaid.Epas.Nts.Infrastructure.AisOiaPeo
{
    /// <summary>
    /// Контракт приёма данных ЭНТС из АИС ОИА ПЭО: состав наборов, отбор записей, ключ
    /// сопоставления и карты «колонка выгрузки → атрибут сущности».
    /// </summary>
    public class DOC_NtsAisImport : IInfrastructureDocument, IHasStructuralLinks, IFolder<NtsInfrastructureFolder>
    {
        public SdaidLink[] Links => new[]
        {
            Rel.Uses<DOC_Vehicle>(),
            Rel.Uses<DOC_VehicleCalc>(),
            Rel.Uses<DOC_NtsAisLoadStatus>(),
            Rel.Uses<DOC_NavEntity>(),
            Rel.Uses<DOC_NtsImportRun>(),
        };

        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 Datasets = $$""""
## Состав наборов

Реестр транспортных средств и его справочники используются только модулем ЭНТС.
Организационная структура — общий источник для модулей ОПЭС, но каждый модуль ведёт
собственную копию.

| Набор | Таблица АИС | Сущность модуля |
|---|---|---|
| Реестр транспортных средств | `ref_cars` | {{SdaidAnchors.RefTo<DOC_Vehicle>()}} |
| Организационная структура | `navs`, `nav_o_fsk`, `nav_o_mes`, `nav_o_pmes` | {{SdaidAnchors.RefTo<DOC_NavEntity>()}} — локальная копия ЭНТС |
| Справочник «Виды ТС» | `ref_d_automobile_kinds` | {{SdaidAnchors.RefTo<DOC_VehicleKind>()}} |
| Справочник «Виды автомобильного топлива» | `ref_d_auto_fuel_kinds` | {{SdaidAnchors.RefTo<DOC_FuelKind>()}} |
| Справочник «Назначения ТС» | `ref_car_functions` | {{SdaidAnchors.RefTo<DOC_VehicleFunction>()}} |

Организационные объекты — владельцы ТС — загружаются из `navs` в **собственную копию
оргструктуры ЭНТС** ({{SdaidAnchors.RefTo<DOC_NavEntity>()}} и уровни компания → МЭС → ПМЭС).
Область и город приходят из типизированных записей АИС (`nav_o_fsk`, `nav_o_mes`,
`nav_o_pmes`, поля `LArea` и `LCity`). Субъект РФ у орг. объекта проставляется в модуле.

**Единица приёма.** Процедура принимает организационный объект и, необязательно, ТС —
`Import(nav, car?)`. Если ТС не задано, принимаются все ТС объекта и его подчинённых объектов;
если задано — только это ТС. Массовый запуск со страницы импорта передаёт корневую компанию
(ПАО «Россети») и не передаёт ТС; обновление из карточки ТС передаёт владельца ТС и само ТС.
Справочники АИС загружаются целиком при любом запуске.

Отбор транспортных средств: `ref_cars`, соединённые с организационным объектом-владельцем
по `navid`; при пакетном запуске — по объекту и его подчинённым, при одиночном — по `ais_id` ТС.
Это один и тот же контракт сопоставления и статуса загрузки.

Ключ сопоставления при повторном приёме — идентификатор записи в АИС (`ais_id`).

Приём данных обновляет только атрибуты, для которых есть карта `[MapsTo]`. Поля,
которые ведутся или вычисляются в модуле (марка, модель, модификация, условия
эксплуатации, параметры методики, статус обработки), приём данных не изменяет.

**Отсутствие в АИС.** ТС, которого нет в очередной выгрузке, не удаляется: у него
выставляется {{SdaidAnchors.RefTo<DOC_Vehicle>()}} — `IsAbsentInAis`. При появлении ТС в выгрузке
флаг снимается. Данные модуля и результаты расчёта при этом не меняются.

**История запусков.** Каждый запуск — пакетный и по одному ТС — фиксируется в
{{SdaidAnchors.RefTo<DOC_NtsImportRun>()}} со статусом
{{SdaidAnchors.RefTo<DOC_NtsImportRunStatus>()}}, счётчиками по наборам и ошибками.
"""";

        public static string MapCars = $$""""
## Карта: реестр транспортных средств

Таблица `ref_cars`, отобранная по организационному объекту-владельцу.

{{SdaidTable.OfClass<RefCarsMap>()}}
"""";

        public static string MapReferences = $$""""
## Карты справочников

### Виды ТС — `ref_d_automobile_kinds`

{{SdaidTable.OfClass<RefAutomobileKindsMap>()}}

### Виды автомобильного топлива — `ref_d_auto_fuel_kinds`

{{SdaidTable.OfClass<RefAutoFuelKindsMap>()}}

### Назначения ТС — `ref_car_functions`

{{SdaidTable.OfClass<RefCarFunctionsMap>()}}
"""";

        public static string LoadStatus = $$""""
## Статус загрузки

Статус загрузки — не результат отдельной проверки, выполняемой после приёма данных, а часть
**собственного результата самой процедуры приёма данных**: она и заполняет поля
{{SdaidAnchors.RefTo<DOC_Vehicle>()}} из АИС, и в рамках того же вызова возвращает, какие из
обязательных для расчёта полей (`RequiredForCalc = "Да"`, загружаемых из АИС — состав задан самими
атрибутами `Vehicle`, здесь не повторяется) остались не заполнены. Отдельной процедуры проверки
«после импорта» нет — проверять нечего отдельно от того, что процедура сама только что заполнила
или не заполнила.

**Контракт.** Вход — ТС (и выгрузка АИС); выход — обновлённое ТС **плюс** пара: статус загрузки
({{SdaidAnchors.RefTo<DOC_NtsAisLoadStatus>()}}, сохраняется в
{{SdaidAnchors.RefTo<DOC_VehicleCalc>()}}) и **перечень обязательных полей, которые не заполнены**
(пусто при статусе «Загрузка выполнена» → «Данных мало» при хотя бы одном пустом; «Не выполнена» —
до первого приёма). Перечень — не побочный продукт, а часть результата: карточка ТС использует
именно его, чтобы показать пользователю, какие конкретно поля у этого ТС нужно довнести в АИС —
не одну фразу на все случаи, а список, зависящий от ТС.

{{SdaidAnchors.RefTo<DOC_NtsAisLoadStatus>()}} — вход политики
{{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Backend.Calc.DOC_ProcessingStatusPolicy>()}}.
"""";

        public static string OpenQuestions = $""""
## Открытые вопросы

Открытые вопросы по приёму данных из АИС собраны в эпике: {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Epics.NtsFuelCalc.OQ_AisImport>()}.
"""";
    }
}