Проби та вмілості
Модуль відстежує складання проб і здобуття вмілостей членами куреня. Каталог (вимоги проб,
перелік вмілостей, зображення) не зберігається в базі: його віддає сервіс каталогу
(https://catalog.lileyka.app, опис API — /docs).
Джерело каталогу
Section titled “Джерело каталогу”Секція Catalog в appsettings:
BaseUrl— адреса сервісу каталогу;Krai— лише записи цього краю (?krai=); порожнє — увесь каталог (як це поєднується з профілем краю — у розділі «Вмілості куреня»);RefreshMinutes— як часто питати сервіс знову (незмінений каталог коштує відповідь 304);TimeoutSeconds— тайм-аут одного запиту;SnapshotPath— копія останньої вдалої відповіді на диску (відносний шлях — від теки застосунку).
CatalogSyncBackgroundService під час старту читає копію з диска; якщо її немає, чекає першої
відповіді сервісу, щоб API не відкрився з порожнім каталогом. Якщо й сервіс не відповів, API бере
копію, вбудовану в збірку (ProjectK.Infrastructure/Services/Catalog/Seed/catalog.json). Ця копія
ніколи не пишеться на диск. Невдалий запит лишає те, що вже завантажено, а відповідь без жодної
вмілості й проби не замінює наявний каталог.
Поки сервіс не відповів жодного разу (а копії з диска немає), API питає знову частіше: за хвилину,
далі вдвічі довше після кожної невдачі, але не рідше за RefreshMinutes. Після першої вдалої
відповіді — звичайний інтервал.
Вбудовану копію оновлюй перед релізом: bash scripts/update-catalog-seed.sh (або
pwsh scripts/update-catalog-seed.ps1). Скрипт перевіряє, що каталог говорить схемою 2.
Сервіс каталогу стоїть за Cloudflare. Bot Fight Mode відповідає запитам з адрес дата-центрів
(Azure, раннери GitHub) перевіркою, яку HttpClient не пройде, тож API лишається без каталогу.
Тому на обох зонах, lileyka.app і rostyslav-mukha.dev, він вимкнений: правилами WAF його не
обійти, пропускають повз нього лише IP Access Rules.
Зображення вмілостей — абсолютні адреси каталогу, браузер бере їх напряму. Зображення відзначень
API віддає за старою адресою /api/awards/images/{level}, беручи їх із каталогу.
Вмілості куреня
Section titled “Вмілості куреня”Які вмілості курінь може почати, вирішує профіль його краю: Catalog.BadgeSources — з яких
країв брати вмілості (за міткою краю в каталозі; без значення — лише власний край), і
Catalog.HiddenBadges — окремі вмілості, які край прибирає. Вмілість без мітки краю не
пропонується нікому. Проби не фільтруються: три юнацькі проби однакові для всього Пласту.
Каталог мітить вмілості лише як ua чи pl. Тому засіяні краї мають BadgeSources у профілі:
Польща читає pl, решта — ua. Без цього край зі своєю міткою (скажімо, de) не побачив би жодної
вмілості. Україна й Чехія засіяні з порожнім профілем, тож Чехія так само лишається без вмілостей,
доки адміністратор не задасть їй джерело.
Два фільтри стоять один за одним. Catalog:Krai в appsettings звужує те, що інстанс узагалі
завантажує з сервісу; профіль краю вибирає вже з завантаженого. Тож інстанс із Catalog:Krai=ua не
покаже польському краю польських вмілостей, хоч би що стояло в його BadgeSources — для кількох
країв Catalog:Krai лишають порожнім.
IKurinCatalog (ProbesAndBadgesModule/Services/KurinCatalog.cs) збирає цей перелік. Його читає
KurinCatalogController (GET api/kurin/{kurinKey}/catalog/badges, Kurin:Read; з нього картка
члена бере, які вмілості можна почати) і SubmitBadgeProgressCommand: новий початок вмілості, якої край не пропонує,
відхиляється з 400 BadgeNotOffered. Вмілість, уже взята в роботу, лишається за людиною, навіть
якщо профіль її більше не пропонує, а все, що людина вже має, читається з повного каталогу
(api/catalog/badges).
Контролери
Section titled “Контролери”ProbesCatalogController— каталог проб;BadgesCatalogController— каталог вмілостей;KurinCatalogController— вмілості, які пропонує курінь (див. вище);MemberProgressController— проби й вмілості конкретного члена;- черга розгляду вмілостей куреня —
KurinController.GetBadgeReviewQueue.
Сутності
Section titled “Сутності”- ProbeProgress — проба члена; ProbePointProgress — кожна точка проби з підписом того, хто її прийняв;
- BadgeProgress — вмілість;
- ProbeProgressAuditEvent / BadgeProgressAuditEvent — журнал змін.
Права: підписати точку і розглянути вмілість може впорядник у своїх гуртках (OwnGroups) або
Звʼязковий у всьому курені (KurinWide) — гранти на ProbeProgress і BadgeProgress у
RolePermissionMap мають лише вони й адміністратор. Провід куреня (курінний, писар, скарбник) цих
грантів не має: усі записи MemberProgressController захищені ResourceAuthorize по учаснику.
Фронтенд
Section titled “Фронтенд”Екрани в kurinModule: member-probe-page (проба з точками), skills-review-page (черга на
розгляд), картка члена (member-card) із вкладками проби й вмілостей.
Кнопка «Деталі» стоїть зліва від кнопок дій біля кожної вмілості: у діалогах «Усі вмілості» й
«Додати вмілість» та в черзі розгляду. Вона відкриває badge-details-dialog — картку вмілості, як на
сайті каталогу: край, рівень, улад, спеціалізація, вимоги по пунктах, вимоги до інструктора, автор і
дата оновлення. Картка бере вмілість за badgeId із кешованого BadgesCatalogService.getById.
Позначки **…** з каталогу показуються жирним без innerHTML. Поля requirements, author і
ulady API додає до вмілості окремо; seekerRequirements лишається тим самим суцільним текстом
для старих клієнтів.