using Rugrid.Sdaid.Notation.Documents;
namespace Rugrid.Sdaid.Epas.Nts.ChangeRequests
{
/// <summary>
/// Алиасы марки ТС выделены в отдельную сущность «Алиас марки ТС» (вместо абстрактного
/// string[] Aliases на «Марка ТС»), снимает OQ-20. Заодно специфицирован и достроен типовой
/// трёхуровневый механизм ведения справочников ЭНТС (Справочники → Записи справочника →
/// Карточка записи), которым теперь управляется и новый справочник алиасов.
/// </summary>
public class DOC_CR_2026_11_02_VehicleMarkAlias : IChangeRequestDocument, IHasStructuralLinks, IFolder<NtsChangeRequestsFolder>
{
public SdaidLink[] Links => new[]
{
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleMark>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleMarkAlias>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleModel>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Backend.ModificationSelection.DOC_ModificationNameRecognition>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Epics.NtsFuelCalc.EPIC_NtsFuelCalc>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Ui.DOC_NtsReferenceRegistry>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Ui.DOC_NtsReferenceRecords>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Ui.DOC_NtsReferenceRecordCard>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleMarkRegistry>(),
Rel.Uses<Rugrid.Sdaid.Epas.Nts.Vision.DOC_NtsVision>(),
};
public static string _refName = "CR 2026-11-02: алиасы марки ТС отдельной сущностью";
public string Name => "Алиасы марки ТС отдельной сущностью, типовой механизм справочников";
public string Description =>
@"Алиасы марки ТС выделены в отдельную сущность «Алиас марки ТС» вместо string[] Aliases на «Марка ТС» — снимает OQ-20. Специфицирован и достроен типовой трёхуровневый механизм ведения справочников ЭНТС (Справочники → Записи справочника → Карточка записи), которым управляется и новый справочник алиасов.";
public string Version => "0.1";
public string Status => "done";
public string[] Comments => new string[0];
public static string Source = """
## Источник (как есть)
> мы обсуждали как хранить алиасы по OQ-20. Мастер-список марок и алиасы
> решили для каждой записи справочника марок хранить список алиасов, это надо
> отобразить на схеме данных не абстрактным полем string[] Aliases, а отдельной
> связанной сущностью
> давай так: не зависимо от наличия удобных точек доступа через UI к редактированию
> какого-то справочника, всегда должен поддерживаться стнадратный механизм работы со
> правочниками: администратор идет в справочники, в реестре справочников выбирает
> справочник, на странице справочника или выбирает запись справочника и проваливается
> в карточку или жмёт +Создать
> этот механизм работы со справочниками должен быть специфицирован. Справочник
> алиасов должен управляться через этот стандартный механизм
> я карточки алиаса не увидел
> Это ожидаемо — по решению, зафиксированному в плане, у «Алиасов марки ТС» нет
> отдельной карточки. - не ожидаемо, ожидаемо стандартный механизм работы со
> правочниками: реестр справочников --> реестр записей справочника --> карточка
> записи, я как-то не так написал выше про стандартный механизм работы со
> справочниками?
> мы обсуждали как хранить алиасы по OQ-20. ... только алиасы для марок используются
> для формирования маски поиска?
> почему в карточке алиаса Марка - строковое поле?
> в карточке модификации Модель - текстовое поле
> через окно подбора/создать модификацию - карточка другая? почему карточка зависит
> от точки её вызова?
> не вижу что изменилось в окно подбора/создать модификацию?
> хорошо, раз это за рамками задачи по алиасам, давай завершать задачу по алиасам,
> что осталось?
> CR на справочник алиасов делал?
""";
public static string Analysis = $"""
## Разбор
Принятые решения (обсуждение с пользователем):
1. **Алиас марки — отдельная сущность, не `string[]`.** `VehicleMarkAlias` — дочерняя
к {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleMark>()} по уже
принятому в модуле паттерну 1-ко-многим (как
{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Domain.DOC_VehicleModel>()} → «Марка ТС»):
`[Relation]`-поле на стороне ребёнка, FK `vehicle_mark_id`. Один алиас — одна
марка. Это полностью снимает OQ-20 — вопрос сформулирован именно про хранение
мастер-списка марок и алиасов, и покрывает оба места их потребления в
{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Backend.ModificationSelection.DOC_ModificationNameRecognition>()}
(`DetectBrand`/`DetectBrandIn` и `BuildNameRemainder`) — моделям алиасы не нужны,
`DetectModel` ищет прямо по имени модели.
2. **Стандартный механизм ведения справочников — обязателен, независимо от удобных
путей через UI.** Первая попытка (контекстный попап «Указать алиас» в окне подбора
модификаций) была отклонена: администратор всегда должен попадать к любому
справочнику ЭНТС через единый путь
{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_NtsReferenceRegistry>()} →
{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_NtsReferenceRecords>()} →
карточка записи. Третьего звена («карточка записи») в спеке не было —
`{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleMarkRegistry>()}` годами
ссылался на несуществующую «карточку марки» прозой, без документа. Оформлен новый
типовой документ {SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_NtsReferenceRecordCard>()},
закрывающий эту висящую ссылку и обслуживающий любой справочник ЭНТС, включая новый
справочник алиасов.
3. **FK-поля в карточке — выбор, не текст.** В первой версии generic-карточки все
колонки рендерились одинаковым текстовым полем — баг, найденный пользователем
(поле «Марка» в карточке алиаса, затем «Модель» в карточке модификации).
Исправление: привязка «какая колонка — связь» задаётся для конкретного
справочника, а не по имени колонки (одно и то же имя «Модель» означает разное:
собственное наименование записи у «Модели ТС» и FK у «Марки, модели и модификации
ТС»).
4. **«Марки, модели и модификации ТС» — не предмет этого CR.** У этого справочника уже
есть собственный специализированный путь
({SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleModificationRegistry>()} →
{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleModificationCard>()}), и он
ошибочно был заведён в generic-механизм прототипа ещё до этого CR — убран оттуда.
Сам реестр и карточка модификаций в прототипе не реализованы (нет html/JS для пути
«справочник → карточка»); единственная рабочая реализация карточки — JS-инструмент
`openCreateModTool` (`Ntr/65_Ui/html/shell.js`), доступный только из окна подбора
модификаций. Обсуждено с пользователем и сознательно оставлено за рамками — отдельная
задача, не связанная с алиасами.
""";
public static string BlastRadius = """
## Blast radius
### Спецификация
| Документ | Правка |
|---|---|
| `Nts/50_Domain/Reference/VehicleMarkAlias.cs` | новый: сущность «Алиас марки ТС» |
| `Nts/50_Domain/Reference/VehicleMark.cs` | `Description` — ссылка на новую сущность алиасов |
| `Nts/55_Backend/ModificationSelection/ModificationNameRecognition.cs` | секция `Brand` переписана через `VehicleMark`/`VehicleMarkAlias`; связь в `Links` |
| `Nts/60_Epics/NtsFuelCalc/EPIC_NtsFuelCalc.cs` | OQ-20 закрыт («снят»), текст переведён на typed-ссылки; `Links` эпика |
| `Nts/65_Ui/NtsReferenceRecordCard.cs` | новый: типовая карточка записи справочника — третье звено механизма |
| `Nts/65_Ui/NtsReferenceRecords.cs` | ссылка на карточку записи; связь на алиасы |
| `Nts/65_Ui/NtsReferences.cs` | строка «Алиасы марки ТС» в группе «Справочники ЭНТС»; связь |
| `Nts/65_Ui/VehicleMarkRegistry.cs` | висящая ссылка «карточка марки» заменена на typed-ссылку; дедуп текста |
| `Nts/10_Vision/NtsVision.cs` | связи + строки в таблице экранов для новых документов |
### Прототип
| Файл | Правка |
|---|---|
| `Nts/65_Ui/html/references.html` | строка «Алиасы марки ТС»; «Марки, модели и модификации ТС» — без ссылки (свой нереализованный путь) |
| `Nts/65_Ui/html/reference-records.html` | запись `vehicle-mark-aliases`; первая колонка и «Создать» — ссылки на карточку; запись `vehicle-modifications` убрана |
| `Nts/65_Ui/html/reference-record-card.html` | новый: типовая карточка; FK-колонки — `<select>` по конкретному справочнику, не по имени колонки; guard для справочников АИС/системных (только просмотр) |
""";
public static string Plan = """
## План
1. `VehicleMarkAlias.cs` — новая сущность (сделано).
2. `VehicleMark.cs`, `ModificationNameRecognition.cs`, `EPIC_NtsFuelCalc.cs`,
`NtsVision.cs` — правки спеки, снятие OQ-20 (сделано).
3. `NtsReferenceRecordCard.cs` — типовой документ карточки записи; `NtsReferenceRecords.cs`,
`NtsReferences.cs`, `VehicleMarkRegistry.cs` — встраивание в типовой механизм (сделано).
4. Прототип: `references.html`, `reference-records.html`, `reference-record-card.html` —
wireframe нового справочника и типовой карточки (сделано).
5. Собрать (`dotnet build`, `build-html.cmd`) (сделано).
6. `doc` — проверка соответствия методологии, 2 прогона, все находки исправлены:
цикл структурных связей между карточкой и записями справочника, дублирование
текста правила «клик → карточка» и примера алиасов, голые имена без typed-ссылок
в OQ-20 (сделано).
7. `testovich` — проверка прототипа, 2 прогона: состав колонок/группа ents-ais-system
совпадают со спекой, отсутствие отдельной карточки и шортката подтверждены как
ожидаемые; найден и исправлен отсутствующий guard для АИС/системных справочников в
`reference-record-card.html` (сделано).
8. По замечаниям пользователя (не от агентов): FK-поля «Марка»/«Марка ТС»/«Модель»
переведены на `<select>`, привязка — по конкретному справочнику; «Марки, модели и
модификации ТС» убраны из generic-механизма (сделано).
9. Оформить это изменение как CR (сделано — этот документ).
""";
public static string Result = $"""
## Итог
Выполнено полностью. Спека: сущность «Алиас марки ТС», снятие OQ-20, типовой документ
«Карточка записи справочника» (закрывает ранее висящую ссылку «карточка марки» у
«Марка ТС»), встраивание нового справочника в типовой механизм — во всех пяти
документах (`VehicleMarkAlias`, `VehicleMark`, `ModificationNameRecognition`,
`EPIC_NtsFuelCalc`, `NtsVision`, `NtsReferenceRecordCard`, `NtsReferenceRecords`,
`NtsReferences`, `VehicleMarkRegistry`). Прототип синхронизирован: новый справочник,
FK-поля как выбор (привязка по справочнику, не по имени колонки — одно и то же имя
колонки означает разное в разных справочниках), guard от открытия карточки для
АИС/системных справочников, «Марки, модели и модификации ТС» исключены из
generic-механизма как имеющие свой путь.
`doc` (3 прогона) нашёл и были исправлены: цикл структурных связей между карточкой
записи и записями справочника, дублирование текста (пример алиасов в трёх местах,
голые текстовые упоминания страниц без typed-ссылок в OQ-20), формат самого этого CR
(убран несвойственный CR раздел Acceptance criteria — такие критерии по методологии
принадлежат эпику/use-case) и повторяющийся пересказ правила «клик/«Создать» →
карточка» в `VehicleMarkRegistry` — заменён на ссылку на типовую страницу записей.
`testovich` (2 прогона) подтвердил соответствие прототипа спеке; исправлены
отсутствовавший guard для АИС/системных справочников в generic-карточке и
несогласованность демо-данных (значения в таблице алиасов, не входившие в список
выбора марки).
Сознательно вне этого CR: реестр и карточка модификаций ТС
({SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleModificationRegistry>()} /
{SdaidAnchors.RefTo<Rugrid.Sdaid.Epas.Nts.Ui.DOC_VehicleModificationCard>()}) не
реализованы в прототипе — единственная рабочая реализация карточки модификации
(`openCreateModTool` в `Ntr/65_Ui/html/shell.js`) доступна только из окна подбора
модификаций, путь «справочник → карточка» для модификаций остаётся без макета.
Отдельная задача.
**Уточнение (после закрытия этого CR).** Статичный wireframe для этого пути позже
добавлен отдельным {SdaidAnchors.RefTo<DOC_CR_2026_11_03_ModificationStaticWireframe>()} —
без генератора и без общего пути сохранения с окном подбора, то есть решение этого CR
(«отдельная задача», реестр/карточка не через типовой механизм) по существу не
отменяется, только появилась структурная витрина экрана.
""";
}
}