using Ban.Sdaid.Notation.Documents;
namespace Ban.Sdaid.Icd.Domain.Cards.Template.Vocabularies
{
/// <summary>
/// Каталог справочников, переданных заказчиком: что за справочник, к какому полю бланка
/// относится, из каких значений состоит.
/// </summary>
public class VocabularyCatalog : ISdaidDocument, IHasStructuralLinks
{
public static string _refName = "каталог справочников";
public string Name => "Справочники заказчика";
public string Description =>
@"Что передал заказчик для полей информационной карты, значения которых берутся из справочника, а не вписываются произвольным текстом.";
public string Version => "0.2";
public string Status => "draft";
public string[] Comments => new[]
{
"2026-08-27. Заведён по материалам заказчика: 19 файлов .mnu и список пользователей.",
"2026-08-27. Добавлено, как справочники ложатся в модель: типом значения, значения — в ограничениях.",
};
public SdaidLink[] Links => new[]
{
Rel.Uses<AttributeValueTypeSpec>(),
Rel.Uses<FormFieldSpec>(),
};
public static string S1_Purpose = $"""
## Зачем это
Бумажный бланк заполняется от руки, и написать в поле можно что угодно. Но часть полей —
это отметка в клетке с напечатанной подписью: «Кожа», «Пергамент», «Ткань». Такое значение
переносится в электронную карту не как текст, а как **значение справочника**: у него есть
код, и в АБИС уходит именно код.
Заказчик передал справочники в том виде, в каком они ведутся в его системе. Здесь описано,
что именно передано и к каким полям относится; сами файлы лежат в `Vocabularies/Source/`.
Вид значения атрибута «выбор из справочника» описан
в {SdaidAnchors.RefTo<AttributeValueTypeSpec>()}; критерий «справочник или перечисление» —
там же.
""";
public static string S2_Format = """
## Формат файлов
Файлы `.mnu` — меню АБИС ИРБИС: обычный текст в кодировке **cp1251**, строки идут парами
(код, затем значение), последняя строка — терминатор `*****`.
```
a
Кожа
b
Пергамент
*****
```
**Код — часть данных, а не порядковый номер.** Это буква подполя в записи ИРБИС: `a`, `b`,
`c`, у исполнителей — инициалы (`КИН`), у экспертов — кириллические буквы (`Х`, `К`, `Б`),
у языков — трёхбуквенный код (`rus`, `jpn`). Коды переиспользуются между справочниками
и означают в каждом своё, поэтому уникальны только внутри своего справочника.
Значение `0` («Ничего», «Нет тиснения», «Отсутствует») — не пустота, а **явное «ничего
не отмечено»**: сотрудник посмотрел и зафиксировал отсутствие. От незаполненного поля
оно отличается так же, как «Б.и.» отличается от пустого издательства.
""";
public static string S3_Catalog = """
## Что передано
Девятнадцать справочников. Все относятся к форме ИК на издание: восемнадцать — к листу 2
«Сохранность», один (язык издания) — к листу 1.
| Файл | Справочник | Поле бланка | Значений | «Ничего» |
|---|---|---|---|---|
| `sost1.mnu` | Состояние переплёта | Переплёт → Состояние | 5 | нет |
| `sostav.mnu` | Состав переплёта | Переплёт → Состав | 3 | `0` Ничего |
| `matpok.mnu` | Материалы покрытия | Переплёт → Материалы покрытия | 6 | `0` Отсутствует |
| `matosn.mnu` | Материалы основы | Переплёт → Материалы основы | 5 | `0` Без основы |
| `dekor1.mnu` | Тиснение | Переплёт → Декор → Тиснение | 4 | `0` Нет тиснения |
| `dekor2.mnu` | Украшения | Переплёт → Декор → Украшения | 5 | `0` Нет украшений |
| `dekor3.mnu` | Обрез | Переплёт → Декор → Обрез | 6 | `0` Нет обреза |
| `fismat1.mnu` | Физико-механические повреждения переплёта | Переплёт → Повреждения | 11 | `0` Ничего |
| `sost2.mnu` | Состояние блока | Блок → Состояние | 4 | `0` Ничего |
| `tet.mnu` | Состояние тетрадей | Блок → Тетради | 4 | `0` Ничего |
| `list.mnu` | Состояние листов | Блок → Листы | 3 | `0` Ничего |
| `fismat2.mnu` | Физико-механические повреждения блока | Блок → Повреждения | 10 | `0` Ничего |
| `mib.mnu` | Микробиологические повреждения | Повреждения → Биологические | 5 | `0` Нет |
| `enm.mnu` | Энтомологические повреждения | Повреждения → Биологические | 5 | `0` Нет |
| `stpov.mnu` | Степень повреждения | Степень повреждения (шесть мест на листе) | 4 | `0` Ничего |
| `exp.mnu` | Роль эксперта | Эксперт → роль | 3 | нет |
| `isp.mnu` | Исполнители | Мониторинг → Исполнитель; Эксперт → ФИО | 16 | нет |
| `jz.mnu` | Языки | лист 1 → Язык издания | 589 | нет |
`dekor3.mnu` перечислен как «Обрез», хотя часть его значений («Золото», «Тиснение»)
совпадает по словам с тиснением переплёта — коды у них разные, и это разные справочники.
""";
public static string S35_Model = $"""
## Как это ложится в модель
Каждый файл становится **типом значения**
({SdaidAnchors.RefTo<AttributeValueTypeSpec>()}) вида «выбор из перечисления»:
имя типа — из названия справочника, значения — парами «код — значение»
в ограничениях. Отдельного хранилища значений не заводим — почему именно так
и когда это изменится, сказано там же.
Поле бланка ссылается на тип не напрямую, а через атрибут вида документа: тип
выбирают, описывая атрибут. Поэтому один тип обслуживает столько полей, сколько нужно:
`stpov` — шесть мест на листе сохранности, `isp` — и мониторинг, и таблицу экспертов.
**Заведение справочников — наполнение данными, а не правка кода.** Ни новых сущностей,
ни миграций: типы значений и виды документов заводятся до начала оцифровки, вместе
с формами.
Исключение одно — `jz.mnu`: 589 языков в ограничениях типа вести нельзя. Это первый
кандидат на вид «выбор из справочника», и хранилище значений появится тогда же,
когда за него возьмёмся.
""";
public static string S4_Users = """
## Пользователи БАН
Отдельный файл `Пользователи БАН.docx` — не справочник значений поля. Это соответствие
**учётной записи АБИС месту хранения и фонду**: одиннадцать записей вида
`RADZSZ → ОФО, Радзивиллы Славянский фонд`, `BINKS → БИН, фонд по консервации
и сохранности`.
Он отвечает на вопрос, откуда берётся место хранения — обязательный реквизит карты,
которого на бланке нет и который подставляется из профиля пользователя. То есть это
материал сразу к двум вещам: к справочнику мест хранения и к настройке профиля.
""";
public static string S5_Observations = """
## Что видно по материалам
**Справочники частично дублируют друг друга.** `fismat1` и `fismat2` различаются одним
значением («Оторван» есть у переплёта, у блока нет); `sost1` и `sost2` — тем же способом.
Заказчик ведёт их как разные меню, потому что в его системе меню привязано к полю.
Соединять их в один справочник с ограничением по полю — решение, которое надо принимать
осознанно: список значений тогда придётся фильтровать на каждом поле.
**Бланк и справочник расходятся.** В `fismat1` есть «Общие загрязнения», на бланке
инв. 74870 такой клетки нет. Бланки разных редакций печатались с разным набором клеток,
а справочник один и накопительный. Значит распознавание опирается на **состав формы**,
а не на состав справочника: справочник говорит, какие значения бывают, форма — какие
клетки есть на этом листе.
**Один справочник — много полей.** `stpov` используется на листе 2 шесть раз, `isp` —
и в мониторинге, и в таблице экспертов. Это ровно тот случай, ради которого справочник
отделён от перечисления.
**Исполнители — живые данные.** `isp.mnu` состоит из фамилий сотрудников. Состав меняется,
это персональные данные, и в отличие от материалов покрытия такой справочник кто-то ведёт
постоянно.
**Опечатки заказчика сохранены.** В `mib.mnu` — «микробиолиогических», в `sost1.mnu` —
двойной пробел в «Не поврежден». Правим при загрузке или оставляем как есть — вопрос
к заказчику; молча менять переданные данные не следует.
""";
public static string S55_Decisions = """
## Принятые решения
**Близкие справочники держим раздельно, как передано.** `fismat1` и `fismat2`
различаются одним значением, `sost1` и `sost2` — тем же способом. Соединять их
в один набор и отбирать часть значений на каждом поле означало бы завести механизм
фильтрации, которого в модели нет, ради экономии двух записей. Тип значения стоит
дёшево — пусть их будет два.
**Значение «Ничего» — обычное значение набора.** `0` «Нет тиснения», «Отсутствует»,
«Без основы» хранится наравне с остальными, отдельного признака «это пустышка» нет.
Поле с «Нет тиснения» заполнено во всех смыслах: ни проверка обязательности, ни
выгрузка, ни показ его не различают, а признак, который нигде не читается, заводить
незачем. Пустое поле по-прежнему означает «значение не указано».
""";
public static string S6_OpenQuestions = """
## Открытые вопросы
| № | Вопрос |
|---|---|
| OQ-VC-1 | Справочники переданы к форме ИК на издание. Действуют ли те же значения для рукописи и графики, или для них будут свои файлы |
| OQ-VC-2 | Обязан ли Сервис сохранять коды ИРБИС при выгрузке в АБИС, или достаточно совпадения значений |
| OQ-VC-4 | Кто ведёт справочники после запуска: сопровождение, экран Сервиса или синхронизация из ИРБИС. Вопрос внутренний, не к заказчику: ему безразличен способ ведения |
| OQ-VC-5 | Исправлять ли опечатки в переданных значениях |
| OQ-VC-6 | Место хранения: справочник строится по файлу пользователей, или заказчик передаст его отдельно |
""";
}
}