Направление работ: Back Код раздела: 1.4 Аккаунты и пользователи > Партнеры Статус: на валидации Ответственный: Рыженко И.С. Версия: 0.1 Обновлено: 29.06.26
1. Назначение
Раздел описывает партнерскую зону — сущность, через которую партнер представлен на платформе. Партнерская зона является обособленным пространством внутри системы, где хранится вся информация, необходимая для взаимодействия партнера с сервисом и его пользователями.
Система обеспечивает создание партнерской зоны, хранение ее данных и связь с аккаунтом-владельцем. При создании автоматически назначается владелец и присваиваются данные по умолчанию.
Партнер управляет данными зоны через личный кабинет (WebLk: 3.1, WebLk 3.3).
Сотрудники сервиса взаимодействуют с партнерскими зонами через административный кабинет (AdmLk: 3.3).
2. Ключевые понятия
Партнерская зона — сущность для хранения всей информации по площадкам и услугам партнера, представленным в интерфейсах платформы. Создается при регистрации в качестве партнера и привязывается к аккаунту-владельцу.
Партнер — пользовательская характеристика аккаунта МАРТ, присваиваемая при создании партнерской зоны
Владелец партнерской зоны — аккаунт, создавший партнерскую зону и назначенный ее владельцем системой в момент создания.
Менеджер по партнерской зоне — аккаунт сотрудника сервиса МАРТ, ответственного за отношения с партнером. Назначается вручную. Осуществляет модерацию контента (Back: 8.7).
Аккаунт — централизованная сущность пользователя в системе. Подробнее в Back: 1.1.
Данные “По умолчанию” — каналы оплаты и настройки, автоматически привязываемые к партнерской зоне при создании.
Тип партнерской зоны — физическое лицо (по умолчанию) или юридическое лицо. Определяет доступные тарифы и сценарии каналов оплаты.
3. Scope
Входит
S1 Партнерская зона обособленная сущность в системе, которая хранит всю информацию по площадкам и услугам партнера, представленным в интерфейсах платформы.
S2 Данные партнерской зоны: номер, тип (физическое / юридическое лицо), публичное название*, логотип, описание деятельности, контактные email и телефон, публичные страницы (Telegram, ВКонтакте, сайт).
S3 Связанные сущности и данные: владелец партнерской зоны (аккаунт-создатель), менеджер по партнерской зоне (сотрудник сервиса), каналы оплаты для поступающих заказов, сервисные каналы оплаты, группы настроек партнерской зоны, параметры активации и продления доступа.
S4 Создание партнерской зоны: три этапа — прием обязательных данных, назначение аккаунта владельцем, привязка данных «По умолчанию»; инициировать создание может только зарегистрированный пользователь.
S5 Валидация и лимиты: проверка обязательных параметров при создании; лимит описания деятельности — 1000 символов; подтверждение email при изменении контактной почты.
Не входит
-
Партнерская зона доступа (роли, permissions) — Back: 1.4.1
-
Расширение партнерских прав через тарифы — Back: 1.4.2
-
Настройки партнерской зоны (правила работы с заказами, параметры по умолчанию) — Back: 2.8
-
Продление доступа — Back: 2.8.1
-
Объекты партнера — Back: 2.1
-
Площадки партнера — Back: 2.2
-
Услуги партнера — Back: 2.3
-
Управление партнерами (административные операции) — Back: 8.6
-
Характеристики партнерских зон в административном кабинете — Back: 8.6.1
-
Модерация контента — Back: 8.7
-
UI профиля партнера — WebLk: 3.1, WebLk 3.3
4. Требования
Правила и ограничения бизнеса на уровне данных, источник истины в системе
5. Открытые вопросы
| ID | Источник | Вопрос | Кому | Статус | Рекомендации |
|---|---|---|---|---|---|
| OQ1.4-1 | Код BR1.4-3 | Тип (EntityType) нигде не влияет на подбор тарифов или каналов оплаты. Единственное применение типа — проверка согласованности типа компании при создании (физлицо → только Individual; юрлицо → ИП/ООО). Логика тарифов/каналов тип не читает — нужно решение: правило целевое (ещё не реализовано) или избыточное PartnerZoneAggregate.cs:137-148; (использований EntityType в подборе тарифов/каналов не найдено за обход домена и persistence) | Бизнес | Open | реализовать влияние EntityType на доступные тарифы и сценарии каналов, как требует BRD (рекомендуется, если бизнес-смысл деления физ/юр в этом и состоит). |
| OQ1.4-2 | Код BR1.4-6 | Менеджер обязателен при создании (ManagerId — не-nullable Guid, колонка manager_id NOT NULL) и не имеет операции ручного назначения/смены: Update не содержит ManagerId. «Может быть связана» и «назначается вручную» в коде не реализованы. Нужно решение: менеджер обязателен или опционален CreatePartnerZoneCommands.cs:28; PartnerZone.cs:29-30; UpdatePartnerZoneCommand.cs:18-41; PartnerZoneAggregate.cs:205-353 | Бизнес/Разработка | Open | Вариант А: привести код к BRD — сделать ManagerId опциональным и добавить операцию ручного назначения/смены менеджера (рекомендуется, т.к. BRD описывает менеджера как назначаемого вручную сотрудника сервиса, а не как обязательное поле создателя). Вариант Б: привести BRD к коду — если по факту менеджер обязателен и задаётся при создании, зафиксировать это; но тогда неясно, кто его задаёт (комментарий поля в коде ошибочно гласит «ID владельца»). Разблокирует решение бизнес-сторона. |
| OQ1.4-3 | Код BR1.4-8 | Из 10 групп 6 смоделированы (организация, платёжная информация, заявки, сборы, параметры/правила работы с заказами — отдельными агрегатами по PartnerZoneId). Не найдены в этом сервисе: «уведомления», «абонементы»; «сотрудники» хранятся не здесь — берутся по gRPC из сервиса идентификации. Нужно решение: где источник истины для этих трёх групп PartnerZoneAggregate.cs:38-58; Infrastructure/Services/EmployeeService.cs (сотрудники); («notification»/«абонемент» как настроек зоны не найдено за обход домена) | Разработка | Open | Вариант А: подтвердить, что «уведомления», «абонементы», «сотрудники», а также активация/продление доступа — зона ответственности других разделов (Back: 1.4.1, 2.8, 2.8.1) и других сервисов, и оставить BR1.4-8/BR1.4-9 как карту-ссылку, а не как требования к данным этого сервиса (рекомендуется — согласуется со Scope «Не входит»). Вариант Б: если они должны храниться именно в партнёрской зоне — завести требования и реализацию здесь. Решение за продуктом: где источник истины. |
| OQ1.4-4 | Код BR1.4-9 | Подсистема активации/продления доступа в этом сервисе практически не реализована. «Активный тариф» (TariffId) при создании ставится в Guid.Empty и реальным тарифом нигде не заполняется. Не найдены: статус продления, данные по оплатам, платёжные документы; «доступные тарифы» выражены на стороне тарифа (AllowedZones), а не как список у зоны. BRD сам отсылает к Back: 2.8.1 — нужно подтвердить, что эти данные живут там | Бизнес | Open | См предыдущий вопрос |
| OQ1.4-4 | Код BR1.4-12 | Реализована только платёжная информация по умолчанию («Оплата на месте (наличные)» + базовый фильтр). Компания (Company) создаётся всегда, без условия «только юрлицо». Параметры работы с заказами по умолчанию при создании не создаются. Активный тариф доступа по умолчанию не назначается (Guid.Empty). Нужно решение: какой набор «по умолчанию» обязателен CreatePartnerZoneCommandHandler.cs:137-184 (платёжные дефолты); PartnerZoneAggregate.cs:154-160 (Company всегда); PartnerZoneAggregate.cs:174 (TariffId=Guid.Empty) | Бизнес | Open | Вариант А: реализовать недостающие дефолты по BRD — условную организацию (только юрлицо), параметры работы с заказами, активный тариф доступа (рекомендуется, если эти дефолты обязательны для работы зоны). Вариант Б: согласовать с продуктом сокращённый набор дефолтов и привести BR1.4-12 к нему. Связано с предыдущим вопросом — закрывать совместно. |
| OQ1.4-5 | Код BR1.4-2 | Номер вычисляется как MAX(number)+1 без атомарности и без запрета дублей в базе: MAX читается отдельным запросом, +1 в C#, вставка позже. Два одновременных создания получат одинаковый номер. Уникального индекса на partner_zone.number нет (в DbInitializer уникальные индексы есть только для partner_tariffs, order-management, priority-placement) CreatePartnerZoneCommandHandler.cs:62; PartnerZoneRepository.cs:153-159; PartnerZone.cs:23-24; DbInitializer.cs:163,406-408,473 При создании email и телефон жёстко проставляются пустой строкой; данные владельца не копируются. У команды создания вообще нет полей email/phone. Модель partner_zone_owner с флагами email_confirmed/phone_confirmed существует, но нигде не используется (мёртвый код) CreatePartnerZoneCommandHandler.cs:91-92; CreatePartnerZoneCommands.cs:12-30; PartnerZoneOwner.cs:27,33 | Разработка | Open | 1. Убрать гонку — перейти на последовательность БД (SERIAL/GENERATED/nextval) либо добавить уникальный индекс на partner_zone.number + повтор при конфликте; это даёт и возрастание, и гарантию уникальности. 2. При создании подтягивать email/телефон владельца из сервиса аккаунтов и проставлять в ContactInfo, как требует BR1.4-2/BR1.4-5; заодно убрать или задействовать мёртвую модель partner_zone_owner. |
| OQ1.4-6 | Код BR1.4-5 | Часть «не требует подтверждения» соблюдается (телефон — обычная строка, верификации нет). Но «по умолчанию телефон владельца» не выполнено: при создании передаётся пустая строка, телефон владельца не копируется ContactInfo.cs:15; CreatePartnerZoneCommandHandler.cs:91 | Разработка | Open | См вопрос выше |
| OQ1.4-7 | Код BR1.4-11 | «Только аутентифицированный» обеспечивается на шлюзе: JWT проверяется, AccountId берётся из claim токена и перезаписывается (клиент его подменить не может), белый список анонимных методов в проде пуст. НО в самом обработчике создания нет проверки существования аккаунта и нет проверки прав — в отличие от Update, который вызывает IAuthorizationService. RpcProxyController.cs:385-388; RpcAnonByRouteAuthorization.cs:48-95; appsettings.json:40-41; CreatePartnerZoneCommandHandler.cs:52-135; UpdatePartnerZoneCommandHandler.cs:31-53 | Бизнес/Разработка | Open | Нужно решение: достаточно ли «аутентифицирован» на шлюзе, или создание тоже должно проверять аккаунт/права |
| OQ1.4-8 | Код BR1.4-13 | 1. Непустота PublicName не проверяется нигде: ни в VO PartnerZoneInfo, ни в команде/обработчике, ни на уровне базы (тип string даёт колонку NOT NULL, но пустая строка "" проходит). Метод IsNameUnique для названия существует, но не вызывается ни в Create, ни в Update PartnerZoneInfo.cs:19-25; CreatePartnerZoneCommandHandler.cs:89; PartnerZoneRepository.cs:147-151 2. Лимит описания деятельности — не более 1000 символов: Ограничение длины описания не проверяется нигде: ни в домене ( PartnerZoneInfo.Description — string? без проверки), ни в команде, ни в базе (на колонке description нет Length/HasMaxLength). Значения 1000 рядом с описанием в коде нет PartnerZoneInfo.cs:15,23; PartnerZone.cs:17-18; DbInitializer.cs (длины/HasMaxLength для description не найдено за обход) | Разработка | Open | Вариант А (рекомендуется): добавить проверки в доменные VO (PartnerZoneInfo): непустое PublicName (ThrowIfNullOrEmpty) и длина Description ≤ 1000 — единое место enforce для Create и Update. Вариант Б: продублировать проверки в обработчиках команд (ближе к API, но легче рассинхронизировать). Заодно решить (П6), нужна ли уникальность названия — метод IsNameUnique уже есть, но не вызывается; если уникальность нужна — подключить его и/или добавить уникальный индекс. |
| OQ1.4-9 | вне BRD (обратный проход) | Команда Update партнёрской зоны проверяет права через IAuthorizationService (право settings_write) — поведение авторизации на уровне приложения, не описанное в разделе 1.4. Стоит зафиксировать как требование (кто и что может менять в зоне) UpdatePartnerZoneCommandHandler.cs:31-53; AuthorizationService.cs:24-55 | Бизнес | Open | Не поняла формулировку, что нужно именно внести в БРД? |
| OQ1.4-10 | вне BRD (обратный проход) | При создании зоны на стороне сервиса аккаунтов её владельцу добавляется роль "partner" и запись OwnedPartnerZone (таблица owned_partner_zones_to_accounts) — это и есть реализация «аккаунт становится владельцем/партнёром» из BR1.4-11, но через роль и связь, а не через флаг IsPartner. Стоит отразить в BRD механику «становления партнёром» PartnerZoneCreatedEventConsumer.cs:9,19-24; AssignPartnerZoneCommand.cs:43-55 | Разработка/Бизнес | Open | --- |
| OQ1.4-11 | вне BRD (обратный проход) | На зоне хранятся настройки штрафов ForfeitSettings (режим списания, формат бана, порог) и тайминги комиссии CommissionSettings (таймаут оплаты, период расчётов) — данные, не перечисленные в составе BR1.4-2/BR1.4-8 явно (BRD относит «сборы» к настройкам соседних разделов). Уточнить, входят ли они в состав данных зоны PartnerZoneAggregate.cs:49,51; ForfeitSettings.cs; CommissionSettings.cs | Бизнес | Open | Внести изменения в БРД? |
Подстраницы
Вопросы по сверке с кодом
BRD 1.4 v0.1 · booking-monorepo · commit 9e19870 / dev/cms-conflict-warning · 2026-06-30 · якорь src/services/booking.partner-management Сводка: вопросов 14 (бизнесовых 6 / программных 8) · подтверждено без вопросов 3 (BR1.4-1, BR1.4-7, BR1.4-10) · находок обратного прохода 3 показано (П9–П11), 4 отрезано
Стек-примечание: сервис использует LinqToDB (не EF Core). Схема создаётся в
DbInitializer.csчерезCreateTable<T>+ ручныеCREATE [UNIQUE] INDEX; форма таблиц задаётся атрибутами[Table]/[Column]на моделях. Поэтому «ограничения в базе» проверялись поDbInitializer.csи атрибутам моделей, а не по EF-миграциям.
Бизнесовые
| № | Связано с | Что в BRD | Что в коде | Где в коде |
|---|---|---|---|---|
| Б1 | BR1.4-3 | Тип партнёрской зоны (физ/юр) определяет доступные тарифы и сценарии каналов оплаты | Тип (EntityType) нигде не влияет на подбор тарифов или каналов оплаты. Единственное применение типа — проверка согласованности типа компании при создании (физлицо → только Individual; юрлицо → ИП/ООО). Логика тарифов/каналов тип не читает — нужно решение: правило целевое (ещё не реализовано) или избыточное | PartnerZoneAggregate.cs:137-148; (использований EntityType в подборе тарифов/каналов не найдено за обход домена и persistence) |
| Б2 | BR1.4-4 | Контактный email после изменения/добавления требует подтверждения | Механизма подтверждения email нет вовсе: ни отправки письма, ни установки «подтверждён», ни сброса при смене email. Признак IsEmailVerified структурно всегда false (см. П5). Нужно решение: нужен ли процесс подтверждения email зоны и каков он | ContactInfo.cs:17,22-35; PartnerZoneAggregate.cs:238-244; (команд confirm/verify email не найдено за обход всего сервиса) |
| Б3 | BR1.4-6 | Зона связана с владельцем (обязательно) и может быть связана с менеджером (опционально, назначается вручную) | Менеджер обязателен при создании (ManagerId — не-nullable Guid, колонка manager_id NOT NULL) и не имеет операции ручного назначения/смены: Update не содержит ManagerId. «Может быть связана» и «назначается вручную» в коде не реализованы. Нужно решение: менеджер обязателен или опционален | CreatePartnerZoneCommands.cs:28; PartnerZone.cs:29-30; UpdatePartnerZoneCommand.cs:18-41; PartnerZoneAggregate.cs:205-353 |
| Б4 | BR1.4-8 | Зона хранит 10 групп настроек, в т.ч. уведомления, абонементы, сотрудники партнёрской зоны | Из 10 групп 6 смоделированы (организация, платёжная информация, заявки, сборы, параметры/правила работы с заказами — отдельными агрегатами по PartnerZoneId). Не найдены в этом сервисе: «уведомления», «абонементы»; «сотрудники» хранятся не здесь — берутся по gRPC из сервиса идентификации. Нужно решение: где источник истины для этих трёх групп | PartnerZoneAggregate.cs:38-58; Infrastructure/Services/EmployeeService.cs (сотрудники); («notification»/«абонемент» как настроек зоны не найдено за обход домена) |
| Б5 | BR1.4-9 | Зона хранит параметры активации и продления доступа: статус продления, активный тариф, доступные тарифы, предварительная комиссия, комиссии к оплате, данные по оплатам, платёжные документы | Подсистема активации/продления доступа в этом сервисе практически не реализована. «Активный тариф» (TariffId) при создании ставится в Guid.Empty и реальным тарифом нигде не заполняется. Не найдены: статус продления, данные по оплатам, платёжные документы; «доступные тарифы» выражены на стороне тарифа (AllowedZones), а не как список у зоны. BRD сам отсылает к Back: 2.8.1 — нужно подтвердить, что эти данные живут там | PartnerZoneAggregate.cs:54,174; PartnerTariffSetAggregate.cs:18,26; (renewal/payment-data/payment-documents не найдено за обход сервиса) |
| Б6 | BR1.4-12 | При создании генерируются настройки «по умолчанию»: организация только для юрлица; параметры работы с заказами; активный тариф доступа | Реализована только платёжная информация по умолчанию («Оплата на месте (наличные)» + базовый фильтр). Компания (Company) создаётся всегда, без условия «только юрлицо». Параметры работы с заказами по умолчанию при создании не создаются. Активный тариф доступа по умолчанию не назначается (Guid.Empty). Нужно решение: какой набор «по умолчанию» обязателен | CreatePartnerZoneCommandHandler.cs:137-184 (платёжные дефолты); PartnerZoneAggregate.cs:154-160 (Company всегда); PartnerZoneAggregate.cs:174 (TariffId=Guid.Empty) |
Рекомендация / варианты решения
- Тип зоны → тарифы/каналы (Б1). Вариант А: реализовать влияние
EntityTypeна доступные тарифы и сценарии каналов, как требует BRD (рекомендуется, если бизнес-смысл деления физ/юр в этом и состоит). Вариант Б: если на момент написания кода деление по типу осознанно не привязано к тарифам/каналам — согласовать с продуктом и уточнить формулировку BR1.4-3 (что именно определяет тип). Решение за продуктом, т.к. это целевая логика предметной области. - Подтверждение email (Б2) + бизнес-сторона дефекта (П5). Вариант А: ввести процесс подтверждения контактного email (отправка кода/ссылки, установка флага, сброс при смене) — рекомендуется, поскольку BR1.4-4 прямо этого требует, а сейчас флаг мёртв. Вариант Б: если подтверждение email зоны не нужно (email и так берётся из подтверждённого аккаунта) — согласовать с продуктом и снять требование. В обоих случаях программную часть (П5) закрыть нельзя без этого решения.
- Опциональность менеджера (Б3). Вариант А: привести код к BRD — сделать
ManagerIdопциональным и добавить операцию ручного назначения/смены менеджера (рекомендуется, т.к. BRD описывает менеджера как назначаемого вручную сотрудника сервиса, а не как обязательное поле создателя). Вариант Б: привести BRD к коду — если по факту менеджер обязателен и задаётся при создании, зафиксировать это; но тогда неясно, кто его задаёт (комментарий поля в коде ошибочно гласит «ID владельца»). Разблокирует решение бизнес-сторона. - Отсутствующие группы настроек (Б4) и параметры доступа (Б5). Вариант А: подтвердить, что «уведомления», «абонементы», «сотрудники», а также активация/продление доступа — зона ответственности других разделов (Back: 1.4.1, 2.8, 2.8.1) и других сервисов, и оставить BR1.4-8/BR1.4-9 как карту-ссылку, а не как требования к данным этого сервиса (рекомендуется — согласуется со Scope «Не входит»). Вариант Б: если они должны храниться именно в партнёрской зоне — завести требования и реализацию здесь. Решение за продуктом: где источник истины.
- Состав «по умолчанию» при создании (Б6). Вариант А: реализовать недостающие дефолты по BRD — условную организацию (только юрлицо), параметры работы с заказами, активный тариф доступа (рекомендуется, если эти дефолты обязательны для работы зоны). Вариант Б: согласовать с продуктом сокращённый набор дефолтов и привести BR1.4-12 к нему. Связано с Б5 (активный тариф) — закрывать совместно.
Программные
| № | Связано с | Что в BRD | Что в коде | Где в коде |
|---|---|---|---|---|
| П1 | BR1.4-2 | Номер уникальный, присваивается по возрастанию при создании | Номер вычисляется как MAX(number)+1 без атомарности и без запрета дублей в базе: MAX читается отдельным запросом, +1 в C#, вставка позже. Два одновременных создания получат одинаковый номер. Уникального индекса на partner_zone.number нет (в DbInitializer уникальные индексы есть только для partner_tariffs, order-management, priority-placement) | CreatePartnerZoneCommandHandler.cs:62; PartnerZoneRepository.cs:153-159; PartnerZone.cs:23-24; DbInitializer.cs:163,406-408,473 |
| П2 | BR1.4-2 | Электронная почта зоны по умолчанию — email владельца; телефон по умолчанию — телефон владельца | При создании email и телефон жёстко проставляются пустой строкой; данные владельца не копируются. У команды создания вообще нет полей email/phone. Модель partner_zone_owner с флагами email_confirmed/phone_confirmed существует, но нигде не используется (мёртвый код) | CreatePartnerZoneCommandHandler.cs:91-92; CreatePartnerZoneCommands.cs:12-30; PartnerZoneOwner.cs:27,33 |
| П3 | BR1.4-5 | Телефон по умолчанию — телефон владельца (подтверждение не требуется) | Часть «не требует подтверждения» соблюдается (телефон — обычная строка, верификации нет). Но «по умолчанию телефон владельца» не выполнено: при создании передаётся пустая строка, телефон владельца не копируется | ContactInfo.cs:15; CreatePartnerZoneCommandHandler.cs:91 |
| П4 | BR1.4-11 | Создать зону может только зарегистрированный пользователь; аккаунт становится владельцем | «Только аутентифицированный» обеспечивается на шлюзе: JWT проверяется, AccountId берётся из claim токена и перезаписывается (клиент его подменить не может), белый список анонимных методов в проде пуст. НО в самом обработчике создания нет проверки существования аккаунта и нет проверки прав — в отличие от Update, который вызывает IAuthorizationService. Нужно решение: достаточно ли «аутентифицирован» на шлюзе, или создание тоже должно проверять аккаунт/права | RpcProxyController.cs:385-388; RpcAnonByRouteAuthorization.cs:48-95; appsettings.json:40-41; CreatePartnerZoneCommandHandler.cs:52-135; UpdatePartnerZoneCommandHandler.cs:31-53 |
| П5 | BR1.4-4 | Контактный email требует подтверждения (значение признака должно быть осмысленным) | Дефект: конструктор ContactInfo принимает параметр isEmailVerified, но никогда не присваивает поле IsEmailVerified (поле readonly без init), поэтому оно всегда false. Даже если бы флаг где-то выставляли, значение бы терялось | ContactInfo.cs:17,24,30-34 |
| П6 | BR1.4-13 | Обязательный параметр — публичное название; проверка обязательных параметров при создании | Непустота PublicName не проверяется нигде: ни в VO PartnerZoneInfo, ни в команде/обработчике, ни на уровне базы (тип string даёт колонку NOT NULL, но пустая строка "" проходит). Метод IsNameUnique для названия существует, но не вызывается ни в Create, ни в Update | PartnerZoneInfo.cs:19-25; CreatePartnerZoneCommandHandler.cs:89; PartnerZoneRepository.cs:147-151 |
| П7 | BR1.4-13 | Лимит описания деятельности — не более 1000 символов | Ограничение длины описания не проверяется нигде: ни в домене (PartnerZoneInfo.Description — string? без проверки), ни в команде, ни в базе (на колонке description нет Length/HasMaxLength). Значения 1000 рядом с описанием в коде нет | PartnerZoneInfo.cs:15,23; PartnerZone.cs:17-18; DbInitializer.cs (длины/HasMaxLength для description не найдено за обход) |
| П8 | BR1.4-2 | Состав данных зоны (включая логотип и публичные страницы) | Внесено в БРД: Большинство полей присутствует. Уточнение по «признаку По умолчанию» для каналов оплаты (BR1.4-7): он хранится не на зоне, а на самом канале (IsDefault) в другом сервисе и читается оттуда при создании — на стороне зоны флага «канал по умолчанию» нет. Это влияет на трактовку «зона хранит каналы по умолчанию» | CreatePartnerZoneCommandHandler.cs:76-78,112-116 (выбор по IsDefault); PartnerZoneAggregate.cs:50 (на зоне — только CommissionPayChannelId) |
Рекомендация / варианты решения
- Уникальность номера (П1). Вариант А (рекомендуется): убрать гонку — перейти на последовательность БД (
SERIAL/GENERATED/nextval) либо добавить уникальный индекс наpartner_zone.number+ повтор при конфликте; это даёт и возрастание, и гарантию уникальности. Вариант Б: блокировка на запись (SELECT … FOR UPDATE/advisory lock) вокруг выдачи номера — проще, но дороже по конкуренции. Сейчас уникальность не гарантирована ни кодом, ни базой. - Дефолты email/телефона из владельца (П2, П3). Вариант А (рекомендуется): при создании подтягивать email/телефон владельца из сервиса аккаунтов и проставлять в
ContactInfo, как требует BR1.4-2/BR1.4-5; заодно убрать или задействовать мёртвую модельpartner_zone_owner. Вариант Б: если значения должны вводиться партнёром вручную позже — согласовать с продуктом и убрать из BRD формулировку «по умолчанию — данные владельца». Решение, копировать ли данные владельца, — продуктовое; реализация — программная. - Дефект
IsEmailVerified(П5). Вариант А (рекомендуется): исправитьContactInfo— присваивать поле в конструкторе (init/прямое присваивание), чтобы значение не терялось. Это необходимое условие для любого процесса подтверждения email (Б2); само по себе исправление поля не вводит процесс — его направление задаёт бизнес-решение Б2. - Проверка обязательного названия и лимита описания (П6, П7). Вариант А (рекомендуется): добавить проверки в доменные VO (
PartnerZoneInfo): непустоеPublicName(ThrowIfNullOrEmpty) и длинаDescription≤ 1000 — единое место enforce для Create и Update. Вариант Б: продублировать проверки в обработчиках команд (ближе к API, но легче рассинхронизировать). Заодно решить (П6), нужна ли уникальность названия — методIsNameUniqueуже есть, но не вызывается; если уникальность нужна — подключить его и/или добавить уникальный индекс. - Проверки прав при создании (П4). Вариант А (рекомендуется): согласовать, должно ли создание проверять права/существование аккаунта в обработчике (как это делает
UpdateчерезIAuthorizationService), или достаточно аутентификации на шлюзе. Вариант Б: оставить как есть, явно зафиксировав, что авторизация создания — целиком на шлюзе. Граница ответственности шлюз/сервис — частично продуктовое решение, поэтому смежно с бизнес-блоком. - Трактовка «каналы по умолчанию» (П8). Вариант А (рекомендуется): уточнить в BRD, что признак «По умолчанию» — атрибут канала оплаты (в сервисе каналов), а партнёрская зона лишь ссылается на выбранные при создании каналы; отдельного флага на зоне нет и не требуется. Вариант Б: если бизнес ждёт хранения признака на стороне зоны — завести его. Текущее поведение (выбор канала по
IsDefault) корректно покрывает BR1.4-7; вопрос только о формулировке хранения.
Находки обратного прохода (код сверх BRD)
Отрезано находок: 4 (плумбинг/чужие разделы — агрегаты Review, AdvertisingTariff, PriorityPlacement, расширенные настройки сборов Expense* — относятся к другим разделам BRD: 2.x/8.x). Ниже — бизнес-значимые находки, не покрытые требованиями раздела 1.4:
| № | Связано с | Что в BRD | Что в коде | Где в коде |
|---|---|---|---|---|
| П9 | вне BRD (обратный проход) | — | Команда Update партнёрской зоны проверяет права через IAuthorizationService (право settings_write) — поведение авторизации на уровне приложения, не описанное в разделе 1.4. Стоит зафиксировать как требование (кто и что может менять в зоне) | UpdatePartnerZoneCommandHandler.cs:31-53; AuthorizationService.cs:24-55 |
| П10 | вне BRD (обратный проход) | — | При создании зоны на стороне сервиса аккаунтов её владельцу добавляется роль "partner" и запись OwnedPartnerZone (таблица owned_partner_zones_to_accounts) — это и есть реализация «аккаунт становится владельцем/партнёром» из BR1.4-11, но через роль и связь, а не через флаг IsPartner. Стоит отразить в BRD механику «становления партнёром» | PartnerZoneCreatedEventConsumer.cs:9,19-24; AssignPartnerZoneCommand.cs:43-55 |
| П11 | вне BRD (обратный проход) | — | На зоне хранятся настройки штрафов ForfeitSettings (режим списания, формат бана, порог) и тайминги комиссии CommissionSettings (таймаут оплаты, период расчётов) — данные, не перечисленные в составе BR1.4-2/BR1.4-8 явно (BRD относит «сборы» к настройкам соседних разделов). Уточнить, входят ли они в состав данных зоны | PartnerZoneAggregate.cs:49,51; ForfeitSettings.cs; CommissionSettings.cs |