Направление работ: Back Код раздела: 2.1 Объекты и предложения > Объекты партнеров Статус: черновик Ответственный: Панкова Л.А. Версия: 0.1 Обновлено: 24.07.26
1. Назначение
Раздел описывает объект партнера как корневую сущность предложения партнера в системе.
Система хранит основные, контактные и навигационные данные объекта, связывает объект с площадками и задает базовые параметры работы, которые используются при бронировании.
2. Ключевые понятия
Объект партнера — сущность, которая группирует площадки партнера по сфере, местоположению и контактным данным.
Слой “Объекты и предложения” — слой, который описывает структуру предложения партнера от объекта до площадок, позиций и условий бронирования.
Площадка — помещение, привязанное к объекту партнера и доступное для бронирования.
Правила работы с заказами — связанные правила бронирования, отмены и оплаты, которые могут использовать параметры объекта, но раскрываются в отдельном разделе.
Настройки партнерской зоны — стандартные настройки партнера, которые применяются по умолчанию для правил работы с заказами.
3. Scope
Входит
S1 Объект партнера: сущность, которая группирует площадки партнера по сфере, местоположению и контактным данным.
S2 Основная информация объекта: сфера, название, описание, логотип, схема объекта, правила оказания услуг.
S3 Контактные данные объекта: основной и дополнительные телефоны/email, привязка типов уведомлений как параметров контакта.
S4 Местоположение и навигация: город, адрес, метро, остановка, координаты объекта/проходной/подъезда, признак документа для проходной, парковка, маршрут.
S5 Базовые параметры работы объекта: режим работы и формат работы объекта, включая значения по умолчанию; детальная логика условий заказа не раскрывается.
S6 Транслируемые связанные данные: площадки, позиции, цены, скидки, показатели объекта и последние записи истории; логика связанных сущностей раскрывается в отдельных разделах.
Не входит
- Площадки объекта: Back 2.2, Back 2.2.1.
- Правила работы с заказами: Back 2.4, Back 2.4.1, Back 2.4.2, Back 2.4.3.
- Позиции, цены и скидки: Back 2.5, Back 2.6, Back 2.7, Back 2.7.3.
- Настройки партнерской зоны: Back 2.8.
- Справочники, файлы и уведомления: Back 8.2.1, Back 8.2.3, Back 9.6.1, Back 7.2.1.
- Отзывы, история и статистика объекта: Back 3.4, Back 9.1, Back 9.2, Back 9.4.1.
- UI и фронтовые сценарии по объектам партнера: WebLk 3.4, WebLk 4.1, Mobile 2.4, Widget 1.2, Catalog 2.2.
4. Требования
Правила и ограничения бизнеса на уровне данных, источник истины в системе
| ID | Требование | Комментарий | Тип требования | Вес | Статус |
|---|---|---|---|---|---|
| S1: #BR2.1-1 | Система должна хранить объект партнера как сущность, группирующую площадки партнера | Объект связывает площадки с конкретной сферой, местоположением и контактными данными; по объекту транслируется список привязанных площадок со сводными данными, логика площадок раскрывается в Back 2.2 и Back 2.2.1 | Системное | 1 | Реализовано |
| S2: #BR2.1-2 | Карточка объекта партнера должна хранить основную информацию объекта | Состав данных: * сфера (логика справочника раскрывается в Back 8.2.1) * название * описание * логотип * схема объекта (хранится как PDF-файл с размерами и планировкой объекта и площадок; логика загрузки файлов раскрывается в Back 9.6.1) * правила оказания услуг (хранятся как HTML-содержимое) | Системное | 1 | Частично \ #OQ2.1-2 |
| S3: #BR2.1-3 | Карточка объекта партнера должна хранить контактные данные объекта | Состав данных: * основной телефон * дополнительные телефоны * основной email * дополнительные email-адреса Логика настройки уведомлений раскрывается в Back 7.2.1 | Системное | 1 | Реализовано |
| S4: #BR2.1-4 | Карточка объекта партнера должна хранить местоположение объекта | Состав данных: * город * адрес * метро * остановка общественного транспорта * координаты объекта * координаты проходной * координаты подъезда | Системное | 1 | Частично \ #OQ2.1-9 |
| S4: #BR2.1-5 | Координаты объекта должны формироваться автоматически на основании адреса с возможностью изменения | Системное | 1 | Частично \ #OQ2.1-8 | |
| S4: #BR2.1-6 | Если для объекта указаны координаты проходной, должен быть задан признак необходимости документа, удостоверяющего личность | Допустимые значения признака: да/нет | Системное | 2 | Не реализовано \ #OQ2.1-4 |
| S4: #BR2.1-7 | Карточка объекта партнера должна хранить данные о парковке объекта | Состав данных: * условия парковки * тип парковки * координаты парковки * стоимость парковки (обязательна, если для парковки указано значение “платная”) * порядок оформления * вместимость парковки | Бизнес | 3 | Не реализовано \ #OQ2.1-3 |
| S4: #BR2.1-8 | Карточка объекта партнера должна хранить материалы маршрута к объекту | Допустимые типы материалов: * видео маршрут * фото маршрут (минимум 3 фотографии) * файл маршрута * текстовое описание маршрута | Системное | 2 | Частично \ #OQ2.1-10 |
| S5: #BR2.1-9 | Для объекта партнера должен задаваться режим работы | По умолчанию объект работает круглосуточно без перерывов и выходных. Режим задается списком дней недели с диапазонами рабочих часов | Бизнес | 1 | Частично \ #OQ2.1-5 \ #OQ2.1-12 |
| S5: #BR2.1-10 | Для объекта партнера должен задаваться формат работы | Допустимые значения: * онлайн-бронирование (значение по умолчанию) * по заявке | Бизнес | 1 | Частично \ #OQ2.1-11 |
| S5: #BR2.1-11 | Система должна поддерживать настройку отдельных режимов и форматов работы объекта по условиям (после релиза реализация) | Условия включают: * периоды действия * опции * диапазоны опций * дни недели | Системное | 3 | Не реализовано (по плану) \ #OQ2.1-15 |
| S5: #BR2.1-12 | Если для объекта не заданы отдельные правила работы с заказами, должны применяться стандартные настройки партнерской зоны | Правило относится к условиям создания, оплаты и отмены; детальная логика раскрывается в соседних разделах Логика раскрывается в разделе Back 2.8 | Бизнес | 1 | Не реализовано \ #OQ2.1-1 |
| S6: #BR2.1-13 | По объекту партнера должны транслироваться привязанные позиции, цены и скидки | Транслируются: * справочник привязанных позиций ( Back 2.5) * список привязанных цен (Back 2.6) * список привязанных скидок с возможностью редактирования (Back 2.7 и Back 2.7.3) | Системное | 1 | Частично \ #OQ2.1-13 |
| S6: #BR2.1-14 | По объекту партнера должны транслироваться показатели объекта | Состав показателей: * диапазон стоимости по всем площадкам объекта “От-До” * средний рейтинг объекта * количество отзывов по объекту * количество заказов на объекте по источникам Логика сбора данных и статистики раскрывается в Back 9.1 и Back 9.4.1 | Системное | 1 | Частично \ #OQ2.1-6 |
| S6: #BR2.1-15 | По объекту партнера должны транслироваться последние записи истории объекта | Логика истории операций с сущностями раскрывается в Back 9.2 | Системное | 2 | Не реализовано \ #OQ2.1-14 |
5. Открытые вопросы
Вопросы прогнаны через гайдбук 2.1 «Объекты партнеров». Гайдбук подтвердил: наследование правил от настроек партнёрской зоны (не от сферы), координаты проходной и подъезда, обязательность признака документа при заданной проходной, семантику парковки (условия платная/бесплатная ≠ тип городская/частная), минимум 3 фото и файл маршрута, дефолты «круглосуточно» и «онлайн-бронирование», автогенерацию координат из адреса, статус «в версии 3.0 не реализовано» для условных режимов. Гайдбук не подтверждает жёсткость валидации режима работы (5/2/7, запрет касания интервалов) и молчит про максимальный процент баллов лояльности.
| ID | Источник | Вопрос | Кому | Статус | Рекомендации |
|---|---|---|---|---|---|
| #OQ2.1-1 | Код BR2.1-12 | Требование говорит: если для объекта не заданы отдельные правила, применяются стандартные настройки партнёрской зоны (условия создания, оплаты, отмены). В коде фолбэк реализован, но идёт не от настроек зоны, а от дефолтов сферы: цепочка Площадка → База → дефолт сферы. Сам объект правил не хранит; PartnerZoneSettings хранит лишь тип по умолчанию и в разрешении правил не участвует. \ CancelRuleRepository.cs:202; GetCancelRuleOrDefaultByBookingConditionsQueryHandler.cs:74; BookingRuleSetRepository.cs:28; PartnerZoneSettings.cs:6 | Бизнес/Разработка | Open | Гайдбук 2.1 подтверждает BRD трижды подряд: для 2.4.1 «Условия создания», 2.4.3 «Правила отмены» и 2.4.2 «Условия оплаты» — «по умолчанию всегда действуют стандартные условия из настроек партнёрской зоны (см. 2.8)». Значит вариант «привести BRD к коду / это была сфера» отпадает — код наследует не от того источника, и это требование веса 1. Рекомендация: реализовать фолбэк от настроек партнёрской зоны (новый источник в цепочке разрешения). Осталось согласовать с владельцем 2.4/2.8: как соотносятся дефолты сферы и настройки зоны — сфера остаётся вторым уровнем фолбэка или уходит совсем. Затрагивает 2.4.1/2.4.2/2.4.3 и 2.8. |
| #OQ2.1-2 | Код BR2.1-2 | Требование говорит: карточка хранит логотип, схему объекта (PDF) и правила оказания услуг (HTML). В коде как поля объекта есть только название, описание и сфера. Логотипа, схемы и правил нет ни в домене, ни в БД; заготовленная таблица base_media мертва (не зарегистрирована, не пишется, не читается). Файлы отдаются обобщённо метаданными, без типизации. \ Info.cs:11; BaseMedia.cs:10 (мёртвая); GetBasesQueryResponse.cs:32 | Бизнес/Разработка | Open | Гайдбук частично на стороне кода: «Логотип — см. 9.6.1 Загруженные файлы», «Схема объекта — PDF-файл… см. 9.6.1» → логотип и схема по замыслу внешние файлы, хранение их как полей не требуется. А вот «Правила оказания услуг — HTML-содержимое» ссылки на файловый сервис не имеет → это контент объекта, и его в коде нет вовсе. Рекомендация: (1) по логотипу и схеме — привести BRD к коду: не «хранит поля», а «прикрепляет файлы (9.6.1)»; при этом нужна типизация файла (логотип / схема), иначе отличить их нельзя — согласовать с 9.6.1. (2) по правилам оказания услуг — завести поле HTML, это недостающая функциональность. Мёртвую base_media задействовать под типизацию либо удалить. |
| #OQ2.1-3 | Код BR2.1-7 | Требование говорит: карточка хранит данные о парковке (условия, тип, координаты, стоимость — обязательна если «платная», порядок оформления, вместимость). В коде структура есть целиком (сущность, VO, таблица, маппер, репозиторий), но ни одна команда не кладёт парковку в агрегат: Create передаёт пустой список с комментарием «Parking — пока не используется», у Update параметра парковки нет. Через API данные о парковке задать нельзя; правило «стоимость обязательна если платная» недостижимо. \ BaseAggregate.cs:270; UpdateBaseCommand.cs:15; ParkingInfo.cs:30 | Бизнес (Герман) | Open | Гайдбук снимает половину вопроса Влада («как „платная“ соотносится с Free/ParkingType»): он разводит два независимых параметра — «Условия парковки: платная / бесплатная» и «Тип парковки: городская / частная». То есть Free = условия, ParkingType {Public, Private} = тип. Модель верна, путаницы нет. Осталось бизнесу: парковка — действующая функция (тогда нужен путь ввода в Create/Update) или отложена. Вес 3, поэтому «отложена» — рабочий ответ; тогда зафиксировать в BRD «структура есть, ввод отложен». |
| #OQ2.1-4 | Код BR2.1-6 | Требование говорит: если указаны координаты проходной — должен быть задан признак необходимости документа. В коде признак есть (Location.IdRequired, bool, по умолчанию false), но он безусловный и ни к каким координатам не привязан — отдельных координат проходной у объекта нет. Заготовленная сущность Entrance (с признаком и координатами) в агрегат не подключена и не сохраняется. Связь «есть проходная → обязателен признак» не enforce-ится. \ Location.cs:34; Entrance.cs:16 (orphan) | Разработка | Закрывает PM | Гайдбук подтверждает обе части дословно: «Проходная — координаты расположения проходной… Поле необязательное» и «Документ, удостоверяющий личность: да/нет. Поле обязательно для заполнения, если указаны координаты проходной». Значит проходная нужна как отдельные координаты, и условная обязательность — целевое правило; вариант «упростить BRD до признака объекта» отпадает. Закрываю сам: подключить Entrance к агрегату (координаты + признак) с персистентностью и enforce-ить условие «координаты заданы → признак обязателен» → тикет в Bitrix. Решается вместе с OQ2.1-9. |
| #OQ2.1-5 | Код BR2.1-9 | Требование говорит: по умолчанию объект работает круглосуточно без перерывов и выходных. В коде дефолт нигде не материализуется: при пустом списке часов валидация делает ранний выход, расписание 24/7 не создаётся. Пустой режим = «часов не задано», и трактовать пустоту как 24/7 должен потребитель, а не бэкенд. \ BaseAggregate.cs:284 | Бизнес/Разработка | Open | Гайдбук подтверждает само правило: «По умолчанию объект работает круглосуточно, без перерывов и выходных» — но не говорит, кто материализует дефолт. Решение: (А, рекоменд.) закрепить, что дефолт задаёт бэкенд (пусто → 24/7), и материализовать — тогда поведение однозначно для всех потребителей; (Б) оставить дефолт на стороне ввода/фронта и пометить в BRD как «значение по умолчанию на UI», не как инвариант хранения. Общая природа с OQ2.1-11 (дефолт формата) — решать одним ответом. |
| #OQ2.1-6 | Код BR2.1-14 | Требование говорит: по объекту транслируются 4 показателя — диапазон стоимости «От-До», средний рейтинг, количество отзывов, количество заказов по источникам. В коде хранится 2 из 4: средний рейтинг и количество отзывов (пересчитываются из площадок). Диапазон стоимости на объекте не хранится (цены считаются в сервисе цен на чтении). Количество заказов по источникам не хранится и не считается. Дополнительно хранится room_count, которого в BRD нет. \ BaseStatistics.cs:10; BaseRepository.cs:118; OrderUpdatedPartnerZoneConsumer.cs:62 | Бизнес/Разработка | Open | Гайдбук подтверждает все 4 показателя в составе «Показатели объекта», но сам же помечает их как витрину: «См. 9.1 Порядок сбора и структура работы с данными», а заказы — «см. 9.4.1». То есть требование про трансляцию, а не про хранение на объекте. (А, рекоменд.) уточнить BR2.1-14: рейтинг и число отзывов материализованы на объекте, диапазон цен и заказы по источникам — витрина из сервисов цен/заказов; заодно внести room_count в состав; (Б) если все 4 должны храниться на объекте — доработка статистики. Согласовать с владельцем 9.1/9.4.1. |
| #OQ2.1-7 | Код вне BRD (обратный проход) | Что нашли: на объекте хранится максимальный процент баллов лояльности на заказ (MaxLoyaltyPointsForOrder, decimal) — задаётся при создании и обновлении. В требованиях 2.1 такого параметра нет. \ BaseAggregate.cs:39; CreateBaseCommand.cs:40 | Бизнес (Герман) | Open | Дом просматривается: гайдбук 2.1 содержит блок «2.7.3 Скидки баллами — отображается список привязанных правил приёма баллов с возможностью редактирования», и 2.7.3 уже в «Не входит». Но сам параметр «максимальный процент баллов на заказ» в гайдбуке 2.1 не описан — подтвердить нечем, не додумываю. Решение бизнеса: это параметр объекта (тогда внести требованием в 2.1 со ссылкой на 2.7.3) или атрибут правил приёма баллов из 2.7.3 (тогда «Не входит»). |
| #OQ2.1-8 | Код BR2.1-5 | Требование говорит: координаты объекта формируются автоматически на основании адреса (с возможностью изменения). В коде бэкенд геокодинг не выполняет: координаты — обязательный вход команды, обработчик кладёт их как есть; геокодера среди зависимостей нет, логики «координаты из адреса» не найдено. Валидируются только диапазоны широты/долготы. Автоформирование живёт вне бэкенда (вероятно фронт). \ CreateBaseCommandHandler.cs:84; CreateBaseCommand.cs:35; Coordinates.cs:11 | Бизнес/Разработка | Open | Гайдбук подтверждает правило: «Координаты объекта… генерируются автоматически на основании адреса с возможностью последующего изменения» — но, как и BRD, не указывает где. Нужно подтверждение: где именно реализован геокодинг (фронт WebLk 4.1 / внешний сервис) и считается ли BR2.1-5 выполненным вне этого сервиса. Без фиксации места реализации требование невозможно валидировать. (А, рекоменд.) зафиксировать место в BRD как границу; (Б) если геокодинг должен быть на бэкенде — завести задачу здесь. |
| #OQ2.1-9 | Код BR2.1-4 | Требование говорит: местоположение хранит координаты объекта, проходной и подъезда. В коде есть город, адрес, метро, остановка и одна пара координат объекта; отдельных координат проходной и подъезда нет (в хранилище две пары: объекта и парковки). Сущность Entrance с координатами входа есть в домене, но не подключена к агрегату и не имеет таблицы. \ Location.cs:38; Parking.cs:35; Entrance.cs:16 (orphan) | Разработка | Закрывает PM | Гайдбук подтверждает обе точки: «Проходная — координаты расположения проходной на территорию комплекса зданий» и «Подъезд — координаты конкретного входа в здание». Значит одной точки объекта недостаточно, вариант «сократить BRD» отпадает. Закрываю сам: расширить модель и БД на координаты проходной и подъезда, подключить Entrance → тикет в Bitrix. Решается одной правкой с OQ2.1-4 (там же условная обязательность признака документа). |
| #OQ2.1-10 | Код BR2.1-8 | Требование говорит: материалы маршрута — видео, фото (минимум 3), файл маршрута, текст. В коде маршрут — три одиночных поля: видео-ссылка, одно изображение (не коллекция) и текст. Отдельного поля «файл маршрута» нет. Проверки «минимум 3 фото» нет и структурно быть не может. \ Location.cs:41 | Разработка | Закрывает PM | Гайдбук подтверждает состав дословно: «Видеомаршрут — ссылка на видео; Фотомаршрут — минимум три фотографии; Маршрут, файл — файл в формате pdf, png, jpg, mov или mp4; Маршрут, текст». Значит вариант «привести BRD к коду» отпадает. Закрываю сам: заменить одиночное поле фото на коллекцию с валидацией «минимум 3» и добавить поле файла маршрута (форматы — по гайдбуку) → тикет в Bitrix. |
| #OQ2.1-11 | Код BR2.1-10 | Требование говорит: формат работы, значение по умолчанию — онлайн-бронирование. В коде набор значений совпадает, но дефолт бэкендом не задаётся: формат — обязательный ненулевой параметр команды создания, фолбэка нет. На «онлайн» значение попадёт лишь по совпадению (первый член перечисления), а не как осознанный дефолт. \ CreateBaseCommand.cs:42; WorkingFormat.cs:3 | Бизнес/Разработка | Open | Гайдбук подтверждает дефолт: «Онлайн-бронирование — значение по умолчанию». Вопрос тот же, что в OQ2.1-5: кто его материализует. (А, рекоменд.) enforce-ить дефолт на бэкенде, не полагаясь на случайное соответствие первого члена перечисления; (Б) описать как дефолт ввода/UI. Решать одним ответом с OQ2.1-5. |
| #OQ2.1-12 | Код BR2.1-9 | Проблема: валидация режима работы жёстче, чем описано: допускаются только наборы дней «5 будних / 2 выходных / все 7» (произвольное подмножество, напр. «пн-ср», отклоняется); все будние обязаны иметь одинаковые часы, все выходные — одинаковые; интервалы внутри дня не должны не только пересекаться, но и касаться; в каждой записи ровно один день. \ BaseAggregate.cs:289,296,360 | Бизнес (Герман) | Open | Гайдбук этих ограничений не подтверждает: он говорит лишь «режим работы представляет собой список дней недели с указанием диапазонов рабочих часов» — без наборов 5/2/7, без требования одинаковых часов и без запрета касания интервалов. Подтвердить нечем, не додумываю. Решение бизнеса: это намеренная модель (тогда описать ограничения в BR2.1-9 и в гайдбуке) или код избыточно жёсткий (тогда ослабить валидацию). Особо подтвердить запрет касания интервалов — он мешает задать смежные диапазоны (например 10:00–14:00 и 14:00–18:00). |
| #OQ2.1-13 | Код BR2.1-13 | Требование говорит: по объекту транслируются привязанные позиции (2.5), цены (2.6), скидки (2.7). В коде объект их не хранит: цены и скидки появляются только в мобильных витринах объекта и вычисляются на чтении сторонним сервисом; поля «позиции» в моделях и запросах объекта не найдено. \ GetBaseWithRoomsMobileQuery.cs:202 | Разработка | Закрывает PM | Гайдбук подтверждает, что это витрина, а не хранение: «Позиции объекта — см. 2.5… отображается справочник привязанных позиций», «Цены — см. 2.6… отображается список», «Скидки — см. 2.7». Все три уже в «Не входит». Продуктового вопроса нет — вопрос границы. Закрываю сам: уточнить формулировку BR2.1-13 — данные отображаются из сервисов 2.5/2.6/2.7 на чтении, объект их не хранит → правка BRD. Оговорка: позиции в этом сервисе не обнаружены вовсе — при реализации витрины проверить, что источник (2.5) подключён. |
| #OQ2.1-14 | Код BR2.1-15 | Требование говорит: по объекту транслируются последние записи истории объекта. В коде истории объекта нет: таблицы истории есть для сферы, площадки и партнёрской зоны, но для объекта отсутствует, у модели нет ассоциации истории. Объект несёт только одиночный штамп последнего изменения (кто/когда создал/обновил) — это не журнал. \ BaseAggregate.cs:53 | Бизнес/Разработка | Open | Гайдбук подтверждает требование: «История — см. 9.2 История операций с сущностями. Отображается список последних записей в истории объекта». Дом — 9.2 (уже в «Не входит»), но у соседних сущностей (сфера, площадка, зона) история в этом сервисе есть, а у объекта — нет: это скорее пробел, чем граница. Решение: (А, рекоменд.) завести историю объекта по образцу площадки/сферы (тогда это доработка здесь); (Б) подтвердить, что журнал целиком живёт в 9.2 и объект лишь отображает — тогда согласовать с владельцем 9.2, откуда берутся записи. |
| #OQ2.1-15 | Код BR2.1-11 | Что подтверждено: отдельные режимы и форматы работы по условиям (периоды, опции, диапазоны опций, дни) не реализованы — у объекта один формат и записи особых дней без переопределения формата или часов по условиям. Структур «формат по периодам/опциям» не найдено. \ BaseProductionCalendar.cs:14; BaseSpecialDays.cs:17 | Разработка | Закрывает PM | Гайдбук прямо подтверждает статус: и для режима, и для формата работы стоит пометка «В версии 3.0 не реализовано» — что совпадает с пометкой BRD «после релиза». Расхождения нет. Закрываю сам: фиксируем как запланированное и не реализованное, действий не требуется. \ Подтверждение: статус BR2.1-11 подтверждён кодом и гайдбуком. |
| #OQ2.1-16 | Код вне BRD (обратный проход) | Что нашли, три инварианта поведения объекта: (1) смена формата на «по заявке» блокируется, если у площадок объекта есть активные заказы в статусе Reserv; (2) смена/снятие архива требует права objects_delete; (3) изменение часов работы триггерит синхронизацию часов площадок и пересоздание дефолтного набора правил по сфере. В BRD не описаны. \ UpdateBaseCommandHandler.cs:102,144 | Бизнес (Герман) | Open | В гайдбуке 2.1 этих инвариантов нет — подтвердить нечем. Разбор: (1) ограничивает пользователя (нельзя переключить формат при активных бронях) — рекомендую внести требованием, это заметное поведение; (2) права на архивирование — дом в 1.4.1 / 1.2 (модель доступа), достаточно ссылки; (3) каскад при смене часов связан с OQ2.1-1 (пересоздание правил по сфере, а гайдбук требует наследование от зоны) — решать вместе с ним. Решение бизнеса по пункту (1): внести в требования или считать деталью реализации. |
Вопросы по сверке с кодом
BRD 2.1 v0.1 · booking-monorepo · commit 9e19870 · 2026-06-30 · якорь src/services/booking.partner-management Сводка: вопросов 16 (бизнесовых 7 / программных 9) · подтверждено без вопросов BR2.1-1, BR2.1-3 · отрезано находок обратного прохода 4 Под особым вниманием: BR2.1-12 (наследование от зоны ≠ от сферы), BR2.1-2 (логотип/схема/правила), BR2.1-7 (парковка), BR2.1-4/6 (проходная/подъезд), BR2.1-5 (геокодинг), BR2.1-9/10 (дефолты).
Бизнесовые
| № | Связано с | Что в BRD | Что в коде | Где в коде |
|---|---|---|---|---|
| Б1 | BR2.1-12 | Если для объекта не заданы отдельные правила работы с заказами, применяются стандартные настройки партнёрской зоны (Back 2.8) — условия создания, оплаты, отмены. | Фолбэк правил реализован, но идёт не от настроек партнёрской зоны, а от дефолтов сферы. Сам объект правил не хранит (BaseAggregate не имеет полей booking/cancel-rules, только импорты). Цепочка разрешения: правило по scope Площадка → База → дефолт сферы (GetDefaultsBulkAsync(spheres), GetDefaultAsync(sphereId)). PartnerZoneSettings хранит лишь DefaultEntityType=Individual и в разрешении правил не участвует. — нужно решение/подтверждение: что является источником наследования (партнёрская зона по BRD или сфера по коду); это требование веса 1. | CancelRuleRepository.cs:202; GetCancelRuleOrDefaultByBookingConditionsQueryHandler.cs:74; BookingRuleSetRepository.cs:28; PartnerZoneSettings.cs:6; BaseAggregate.cs:6 |
| Б2 | BR2.1-2 | Карточка объекта хранит основную информацию: сфера, название, описание, логотип, схема объекта (PDF), правила оказания услуг (HTML). | Реально как поля объекта есть только название и описание (Info = {Name, Description}) и сфера (SphereId). Логотипа, схемы-PDF и правил-HTML как полей нет ни в домене, ни в БД (поиск по logo/scheme/serviceRules — 0 совпадений). Заготовленная таблица base_media (type/url/order) в коде есть, но мертва: не зарегистрирована в DbConnection, не пишется и не читается. Файлы объекта отдаются обобщённо метаданными (Files: FileMetadataDto, логика — Back 9.6.1), без типизации «логотип/схема/правила». — нужно решение: считать ли логотип/схему/правила атрибутами объекта (тогда нужны поля) или они остаются внешними файлами через файловый сервис. | Info.cs:11; GetBasesQueryResponse.cs:32; BaseMedia.cs:10 (мёртвая); BaseAggregate.cs:28 |
| Б3 | BR2.1-7 | Карточка объекта хранит данные о парковке: условия, тип, координаты, стоимость (обязательна, если «платная»), порядок оформления, вместимость. | Структура парковки есть целиком (сущность Parking, VO ParkingInfo с полями free/cost/instruction/capacity/type/coordinates, таблица parking, маппер, репозиторий пишет на создании/обновлении). НО ни одна команда не кладёт парковку в агрегат: Create передаёт [] с комментарием «Parking — пока не используется», у Update параметра парковки нет. То есть фактически данные о парковке через API задать нельзя. Признак платности — это bool Free, а не значение типа «платная» (enum ParkingType = {Public, Private}, члена «платная»/«бесплатная» нет); правило «стоимость > 0 если не бесплатно» живёт в VO, но недостижимо. — нужно решение: парковка — действующая функция (тогда нужен путь ввода) или отложена; и как «платная» из BRD соотносится с Free/ParkingType. | BaseAggregate.cs:270; UpdateBaseCommand.cs:15; ParkingInfo.cs:30; ParkingType.cs:9 |
| Б4 | BR2.1-6 | Если для объекта указаны координаты проходной, должен быть задан признак необходимости документа (да/нет). | Признак документа есть (Location.IdRequired, bool, по умолчанию false), но он безусловный и ни к каким координатам проходной не привязан — потому что отдельных координат проходной у объекта нет (одна пара координат объекта). Заготовленная сущность Entrance (с полями IdRequired, Coordinates) в агрегат не подключена и не сохраняется. Связь «есть проходная → обязателен признак» не enforce-ится. — нужно решение: нужна ли проходная как отдельная сущность с координатами и обязательным признаком, либо признак остаётся свойством объекта в целом. | Location.cs:34; Entrance.cs:16 (orphan); BaseAggregate.cs:32 |
| Б5 | BR2.1-9 | Для объекта задаётся режим работы; по умолчанию объект работает круглосуточно без перерывов и выходных. | Дефолт «круглосуточно» нигде не материализуется: при пустом списке часов валидация делает ранний выход, _hours остаётся пустым, расписание 24/7 не создаётся. Пустой режим = «часов не задано», и интерпретировать пустоту как 24/7 должен потребитель, а не бэкенд. — нужно решение: где живёт правило «пусто = круглосуточно» (бэкенд материализует дефолт или это договорённость для читателей/фронта). | BaseAggregate.cs:284 |
| Б6 | BR2.1-14 | По объекту транслируются показатели: диапазон стоимости «От-До», средний рейтинг, количество отзывов, количество заказов по источникам. | Хранится только 2 из 4 показателей: средний рейтинг (avg_rooms_rating) и количество отзывов (all_rooms_reviews_count) — оба пересчитываются из площадок, исходные данные приходят из сервиса отзывов. Диапазон стоимости «От-До» на объекте не хранится (цены считаются в сервисе цен на чтении, по площадкам). Количество заказов по источникам не хранится и не считается на объекте (консьюмер заказов статистику объекта не пишет). Дополнительно хранится room_count, которого нет в списке BRD. — нужно решение: какие из 4 показателей должны быть атрибутами объекта, а какие остаются витриной из других сервисов. | BaseStatistics.cs:10; BaseRepository.cs:118; OrderUpdatedPartnerZoneConsumer.cs:62 |
| Б7 | вне BRD (обратный проход) | — | На объекте хранится максимальный процент баллов лояльности на заказ (MaxLoyaltyPointsForOrder, decimal) — задаётся при создании/обновлении. В BRD раздела 2.1 такого параметра объекта нет. — нужно решение: должен ли этот параметр быть требованием раздела (или он относится к лояльности/другому разделу). | BaseAggregate.cs:39; CreateBaseCommand.cs:40 |
Рекомендация / варианты решения
- Б1 (наследование правил, вес 1). Это смысловое расхождение источника наследования. Вариант А (рекоменд.): согласовать с владельцем разделов 2.4/2.8 фактическую модель и привести BRD к коду — наследование идёт от дефолтов сферы (Площадка → База → Сфера), а не от настроек партнёрской зоны; если «партнёрская зона» в BRD означала именно сферу — поправить термин. Вариант Б: если бизнес-намерение именно «настройки партнёрской зоны» — это отдельная доработка в сервисе (новый источник фолбэка), и тогда требование остаётся как цель. Разблокирует трактовку BR2.1-12 и смежные 2.4/2.8.
- Б2 (логотип/схема/правила). Вариант А: оставить как есть (внешние файлы через Back 9.6.1) и привести BRD — убрать формулировку «хранит логотип/схему/правила как поля», заменить на «прикрепляет файлы». Вариант Б (рекоменд., если это атрибуты карточки): ввести типизированные поля/типы медиа (логотип, схема-PDF, правила-HTML) — тогда мёртвую
base_mediaлибо задействовать, либо удалить как вводящую в заблуждение. Решение продуктовое: являются ли эти материалы свойствами объекта или вложениями. - Б3 (парковка). Вариант А (рекоменд. краткосрочно): зафиксировать в BRD текущий статус «структура есть, ввод отложен», раз API не принимает парковку. Вариант Б: если парковка нужна сейчас — добавить путь ввода (параметры в Create/Update) и определить семантику платности; заодно согласовать, «платная» — это
Free=falseили отдельный тип. Без решения правило «стоимость обязательна, если платная» остаётся недостижимым. - Б4 (проходная + признак документа). Вариант А: упростить BRD до «признак документа — свойство объекта» (как в коде), без отдельных координат проходной. Вариант Б (рекоменд., если навигация к проходной важна): достроить
Entranceдо части агрегата (координаты + обязательный признак) и подключить персистентность; сейчас тип мёртв. Согласовать с продуктом, нужна ли проходная как сущность. - Б5 (дефолт круглосуточно) + BR2.1-10 (дефолт формата, см. П-блок). Общая первопричина — дефолты не материализуются бэкендом. Вариант А (рекоменд.): закрепить, что дефолты задаёт бэкенд (пусто → 24/7; формат → онлайн), и реализовать материализацию — тогда поведение однозначно. Вариант Б: оставить дефолты на стороне ввода/фронта и в BRD пометить их как «значения по умолчанию на UI», не как инвариант хранения.
- Б6 (показатели). Вариант А (рекоменд.): привести BRD к коду — на объекте материализованы рейтинг и число отзывов (+room_count); диапазон цен и заказы по источникам пометить как витрину из сервисов цен/заказов, не как хранимые показатели объекта. Вариант Б: если все 4 должны быть на объекте — доработка статистики (хранить диапазон цен и заказы по источникам).
- Б7 (баллы лояльности). Вариант А (рекоменд.): добавить параметр в раздел или явно отнести его к разделу лояльности — сейчас это необъявленный атрибут объекта. Вариант Б: если параметр устарел/перенесён — согласовать удаление с владельцем кода.
Программные
| № | Связано с | Что в BRD | Что в коде | Где в коде |
|---|---|---|---|---|
| П1 | BR2.1-5 | Координаты объекта должны формироваться автоматически на основании адреса (с возможностью изменения). | Бэкенд геокодинг не выполняет: Coordinates — обязательный вход команды, обработчик кладёт их как есть; геокодера среди зависимостей нет, по сервису и библиотекам логики «координаты из адреса» не найдено (все упоминания yandex — ссылки на вики в атрибутах). Coordinates валидирует только диапазоны широты/долготы. Значит автоформирование живёт вне бэкенда (вероятно фронт). — нужно подтверждение: где именно реализован геокодинг и считается ли BR2.1-5 выполненным вне этого сервиса. | CreateBaseCommandHandler.cs:84; CreateBaseCommand.cs:35; Coordinates.cs:11 |
| П2 | BR2.1-4 | Местоположение хранит: город, адрес, метро, остановку, координаты объекта/проходной/подъезда. | Есть город (CityId), адрес, метро (Subways), остановка (PublicTransport, одна строка) и одна пара координат объекта (Coordinates?). Отдельных координат проходной и подъезда нет — в хранилище ровно две пары координат: объекта (nullable) и парковки (non-nullable). Сущность Entrance с координатами входа есть в домене, но не подключена к агрегату и не имеет таблицы на стороне базы (orphan). — нужно решение: нужны ли отдельные координаты проходной/подъезда (тогда модель и БД надо расширять), или достаточно одной точки объекта. | Location.cs:38; Parking.cs:35; Entrance.cs:16 (orphan) |
| П3 | BR2.1-8 | Материалы маршрута: видео, фото (минимум 3), файл маршрута, текст. | В Location маршрут — это три одиночных поля: RouteVideoUrl (видео), RouteImageUrl (одно фото, не коллекция), RouteDescription (текст). Отдельного поля «файл маршрута» нет. Проверки «минимум 3 фото» нет и структурно быть не может (одно поле-строка). — нужно решение: фото маршрута — коллекция с минимумом 3 (нужно поле-список и валидация) или одно изображение; нужен ли отдельный файл маршрута. | Location.cs:41 |
| П4 | BR2.1-10 | Формат работы; значение по умолчанию — онлайн-бронирование. | Набор значений совпадает (WorkingFormat = {Online, OnRequest}). Но дефолт «онлайн» бэкендом не задаётся: WorkingFormat — обязательный ненулевой параметр команды создания, фолбэка нет. На «онлайн» при пропуске значение попадёт лишь по совпадению (Online=0 — первый член enum), а не как осознанный дефолт. — нужно решение: enforce-ить дефолт «онлайн» на бэкенде или это договорённость ввода. | CreateBaseCommand.cs:42; WorkingFormat.cs:3 |
| П5 | BR2.1-9 | Режим задаётся списком дней недели с диапазонами рабочих часов. | Валидация строже и жёстче, чем описано в BRD: допускаются только наборы дней «5 будних / 2 выходных / все 7» (произвольное подмножество, напр. «пн-ср», отклоняется); все будние обязаны иметь одинаковые часы, все выходные — одинаковые; интервалы внутри дня не должны не только пересекаться, но и касаться (prev.To >= curr.From); в каждой записи ровно один день (Day.Count == 1). — нужно подтверждение: эти ограничения — намеренная бизнес-модель режима (тогда стоит описать их в BRD), или код избыточно жёсткий. | BaseAggregate.cs:289; BaseAggregate.cs:296; BaseAggregate.cs:360 |
| П6 | BR2.1-13 | По объекту транслируются привязанные позиции (2.5), цены (2.6), скидки (2.7). | Граница сервисов: объект не хранит позиции/цены/скидки. Цены и скидки появляются только в мобильных витринах объекта и вычисляются на чтении сторонним сервисом (IRoomProcessingService.ProcessRoomsAsync), а не транслируются самим объектом. Поля «позиции» в моделях/запросах объекта не найдено за обход. — граница: трансляция цен/скидок живёт в сервисах цен/скидок; позиции в этом сервисе не обнаружены. | GetBaseWithRoomsMobileQuery.cs:202; (позиции — не найдено за обход в Queries/Base, Persistence/Bases) |
| П7 | BR2.1-15 | По объекту транслируются последние записи истории объекта (логика — Back 9.2). | В этом сервисе истории объекта нет: таблицы *History есть для сферы, площадки, партнёрской зоны (у последней ассоциация закомментирована), но BaseHistory отсутствует, и у модели Base нет ассоциации истории. Объект несёт только одиночный штамп последнего изменения (AuditableInfo — кто/когда создал/обновил), это не журнал. — граница: сборка последних записей истории объекта здесь не реализована (вероятно Back 9.2); за обход в этом сервисе не найдено. | BaseAggregate.cs:53; (BaseHistory — не найдено за обход в Persistence) |
| П8 | BR2.1-11 | Отдельные режимы/форматы по условиям (периоды, опции, диапазоны опций, дни) — после релиза. | Не реализовано (что согласуется с пометкой «после релиза»): у объекта один Format и записи особых дней (BaseProductionCalendar/BaseSpecialDays = дата/день/описание/архив) без переопределения формата или часов по условиям. Структур «формат по периодам/опциям» не найдено за обход. — подтверждение границы: фиксируем как нереализованное по плану. | BaseProductionCalendar.cs:14; BaseSpecialDays.cs:17 |
| П9 | вне BRD (обратный проход) | — | Смена формата на «по заявке» (OnRequest) блокируется, если у площадок объекта есть активные заказы в статусе Reserv (иначе исключение). Это инвариант поведения объекта, в BRD не описан. Дополнительно: смена/снятие архива требует прав objects_delete, изменение часов триггерит синхронизацию часов площадок и пересоздание дефолтного набора правил по сфере. — нужно решение: нужны ли эти инварианты как требования. | UpdateBaseCommandHandler.cs:102; UpdateBaseCommandHandler.cs:144 |
Рекомендация / варианты решения
- П1 (геокодинг) + П6, П7 (границы трансляции). Общая природа — функциональность живёт вне сервиса объекта. Вариант А (рекоменд.): в BRD явно пометить эти пункты как границы (геокодинг — фронт/внешний сервис; цены/скидки — сервисы 2.6/2.7 на чтении; история — Back 9.2) и сослаться на владельцев; так требование не выглядит «нереализованным в 2.1». Вариант Б: если что-то из этого должно жить именно в объекте — завести отдельную задачу в этом сервисе. Для геокодинга — обязательно зафиксировать место реализации, иначе BR2.1-5 невозможно валидировать.
- П2 (координаты проходной/подъезда). Привязано к Б4. Вариант А (рекоменд., если не нужны): сократить BRD до одной точки объекта. Вариант Б: расширить модель/БД на координаты проходной и подъезда и подключить
Entrance; пока тип мёртв, хранения нет. - П3 (фото маршрута ≥3 / файл маршрута). Вариант А (рекоменд., если минимум 3 — намерение): заменить одиночный
RouteImageUrlна коллекцию и добавить валидацию количества + отдельное поле файла маршрута. Вариант Б: привести BRD к коду — одно фото, видео и текст, без минимума и без отдельного файла. - П4 (дефолт формата). См. Б5: либо материализовать дефолт «онлайн» на бэкенде (рекоменд. для однозначности), либо описать его как UI-дефолт. Не полагаться на случайное соответствие Online=0.
- П5 (жёсткость режима работы). Вариант А (рекоменд.): если ограничения «5/2/7, одинаковые часы, запрет касания, один день на запись» — намеренная модель, дописать их в BRD как часть BR2.1-9, чтобы код и документ совпали. Вариант Б: если жёсткость избыточна (напр. произвольные подмножества дней или касающиеся интервалы должны быть допустимы) — ослабить валидацию. Решение продуктовое; «запрет касания интервалов» особенно стоит подтвердить.
- П8 (условные форматы). Подтвердить статус «после релиза» — расхождения нет, фиксируем как запланированное и не реализованное.
- П9 (инварианты сверх BRD). Вариант А (рекоменд.): внести значимые инварианты в требования — блокировку смены формата при активных заказах, право
objects_deleteна архив, каскад при смене часов (синхронизация площадок + пересоздание правил по сфере связано с Б1). Вариант Б: оставить как детали реализации, если бизнес-значимости нет; блокировку по заказам всё же рекомендуется отразить, т.к. она ограничивает пользователя.
Отрезано находок обратного прохода (4), как технический шум: оптимистичная версия объекта (
version), штампы аудита создан/обновлён (AuditableInfo), отсутствие жёсткого удаления объекта (только архив/восстановление), не-nullable координаты у строки парковки (учтено в Б3). Орфанныеbase_media,Entrance/SubwayToEntranceотражены в Б2/Б4/П2 как мёртвая модель.