using Rugrid.Sdaid.Notation.Documents;
namespace Rugrid.Sdaid.Epas.Nts.Backend.Calc
{
/// <summary>
/// Политика реакции подбора модификации и расчёта на приём данных ТС из АИС — единая и для
/// первого приёма (при открытии только что загруженного ТС), и для повторного (иконка
/// «Обновить из АИС» в карточке): это один факт, не два разных механизма. Приём самих данных
/// и статус загрузки — контракт DOC_NtsAisImport, здесь не повторяется.
/// </summary>
public class DOC_AisRefreshPolicy : ISdaidDocument, IHasStructuralLinks, IFolder<NtsBackendFolder>
{
public SdaidLink[] Links => new[]
{
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Infrastructure.AisOiaPeo.DOC_NtsAisImport>(),
Rel.Uses<DOC_CalcValidators>(),
Rel.Uses<DOC_NtsCalcErrors>(),
Rel.Uses<DOC_ProcessingStatusPolicy>(),
Rel.Uses<DOC_InputModel>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleCalc>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Backend.ModificationSelection.DOC_ModificationGroupSelection>(),
};
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 Body = $$"""
## Назначение
Приём данных ТС из АИС — один факт с двумя точками запуска: **первый приём** (ТС только
что появилось в модуле или открывается впервые после загрузки) и **повторный приём**
(иконка «Обновить из АИС» в карточке). Обе — один и тот же контракт
{{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Infrastructure.AisOiaPeo.DOC_NtsAisImport>()}}
(раздел «Состав наборов»), просто с разной гранулярностью отбора и разной «предыдущей
группой подбора» (при первом приёме её попросту нет). Статус загрузки возвращается этим же
вызовом, не вычисляется отдельным шагом «после» (см. раздел «Статус загрузки» в
{{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Infrastructure.AisOiaPeo.DOC_NtsAisImport>()}}).
Эта политика описывает, что происходит дальше в обеих точках запуска — с подбором
модификации и расчётом. Это две независимые друг от друга реакции.
## Подбор модификации
**Независимо от статуса загрузки** (в т. ч. когда он всё равно «Данных мало» из-за
какого-то другого, не относящегося к подбору поля — например, не заполненной даты начала
эксплуатации): подбору нужны только Вид ТС и Вид топлива, а не полный набор обязательных
для расчёта полей. Вид ТС — техническое условие: без него у автоподбора нет базовой группы,
по которой можно что-то искать
({{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Backend.ModificationSelection.DOC_ModificationGroupSelection>()}},
раздел «Базовая группа»; сама процедура сужает группу по топливу мягко, если оно известно).
Вид топлива
дополнительно требуется этой политикой как условие запуска — чтобы подбор не выполнялся
по заведомо неполным данным, даже если алгоритм технически мог бы отработать и без него.
Если Вид ТС или Вид топлива неизвестны — подбор не проводится, способ остаётся «не
определён».
Когда Вид ТС и Вид топлива известны, действие зависит от того, изменились ли они
относительно того, что было до этого приёма данных (сравнение по `Id` записи справочника,
не по наименованию — наименование в АИС теоретически может быть переименовано без смены
идентичности записи), и, если нет — от способа подбора
({{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_ModificationSelectionModal>()}}, правило 1
«Текущая группа»). При первом приёме данных «до этого» не было ничего — это частный случай
строки «Изменились» ниже (нет прежнего значения, значит оно равносильно любому новому) и
одновременно строки «подбор становится возможен впервые»:
| Вид ТС / Вид топлива | Способ подбора до приёма данных | Действие |
|---|---|---|
| Не изменились (включая случай отсутствия предыдущего приёма) | Эксперт (пользователь нажал «Применить») | Группа и базовая норма не трогаются — это явный выбор пользователя, не зависящий от текста наименования ТС |
| Не изменились | Авто, либо подбор становится возможен впервые (до этого Вид ТС был неизвестен, способ «не определён») | Автоподбор выполняется (повторно или впервые) по актуальному наименованию ТС; способ становится «авто» |
| Изменились | Любой | Прежняя группа (если была) отбрасывается целиком; выполняется новый автоподбор по новым виду/топливу и текущему наименованию ТС; способ становится «авто» |
## Расчёт
Запускается безусловно, независимо от статуса загрузки — у методики уже есть валидаторы на
каждую секцию ({{SdaidAnchors.RefTo<DOC_CalcValidators>()}}), и при нехватке обязательных
данных калькулятор не падает, а штатно возвращает «Выполнен с ошибкой» с классифицированным
текстом (например, «Дата начала эксплуатации не задана» —
{{SdaidAnchors.RefTo<DOC_NtsCalcErrors>()}}). Видимый итоговый «Статус обработки» в этом
случае всё равно показывает «Мало данных загружено» — правило 1
{{SdaidAnchors.RefTo<DOC_ProcessingStatusPolicy>()}} перекрывает внутренний статус расчёта
независимо от него; то же относится и к случаю «Нет модификаций» (правило 2 той же
политики) — валидатор секции `fuel.base_norm` вернёт свою ошибку «Базовая норма не
определена» тем же путём, без отдельного исключения из безусловности.
Расчёт — чистая функция от {{SdaidAnchors.RefTo<DOC_InputModel>()}}: если входные данные по
сути не изменились, пересчёт даёт тот же результат, статус и журнал — сравнивать их заранее
не нужно, отдельной проверки это не требует. Дата расчёта
({{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleCalc>()}}) обновляется на
текущую в любом случае — она показывает, когда расчёт выполнялся фактически, и не входит в
«результаты расчёта, статус и журнал», которые не меняются при неизменных данных.
""";
}
}