Направление работ: 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. Требования

Правила и ограничения бизнеса на уровне данных, источник истины в системе

IDТребованиеКомментарийТип требованияВесСтатус
S1: BR1.4-1Система должна хранить партнерскую зону как обособленную сущностьПартнерская зона хранит всю информацию, необходимую для взаимодействия партнера с сервисом и его пользователямиСистемное1Реализовано
S2: BR1.4-2Партнерская зона должна хранить данные партнерской зоныСостав: • номер (уникальный, присваивается по возрастанию при создании); • владелец партнерской зоны; • тип (физическое / юридическое лицо, по умолчанию — физическое); • менеджер по партнерской зоне; • каналы оплаты для поступающих заказов (расчеты партнер–клиент); • сервисные каналы оплаты (расчеты партнер–сервис); • публичное название; • логотип; • описание деятельности (до 1000 символов); • электронная почта (по умолчанию — email владельца, для уведомлений по ПЗ); • телефон (по умолчанию — телефон владельца, справочно для жалоб и оспаривания сборов); • публичные страницы (Telegram, ВКонтакте, сайт)

Признак «По умолчанию» — атрибут канала оплаты (в сервисе каналов), а партнёрская зона лишь ссылается на выбранные при создании каналы
Системное1Частично реализовано OQ1.4-5
S2: BR1.4-3Тип партнерской зоны определяет доступные тарифы, сценарии сервисных каналов оплаты и каналов оплаты для поступающих заказовПо умолчанию — физическое лицо. Логика тарифов раскрывается в Back: 1.4.2 и Back: 8.3Бизнес1Не реализовано OQ1.4-1
S2: BR1.4-4Контактный email партнерской зоны после изменения или добавления требует подтвержденияПо умолчанию используется email аккаунта-владельца. Используется для рассылки уведомлений по партнерской зонеСистемное2Не реализовано. Подтверждение Email впринципе на бэке отсутствует
S2: BR1.4-5Контактный телефон партнерской зоны не требует подтверждения при измененииПо умолчанию используется телефон аккаунта-владельца. Носит справочный характер — для жалоб и оспаривания сборовСистемное2Частично реализовано OQ1.4-6
S3: BR1.4-6Партнерская зона должна быть связана с владельцем и может быть связана с менеджеромЛогика назначения владельца — Back: 1.4. Менеджер может осуществлять модерацию контента — Back: 8.7Системное1Частично реализовано OQ1.4-2
S3: BR1.4-7При создании партнерской зоны автоматически привязываются каналы оплаты с признаком «По умолчанию»Привязываются: канал оплаты для поступающих заказов и сервисный канал оплаты. Логика каналов — Back: 5.1Системное1Реализовано
S3: BR1.4-8Партнерская зона должна хранить группы настроек партнерской зоныСостав: • организация • уведомления • платежная информация • параметры работы с заказами • сборы • заявки • абонементы • правила и условия работы с заказами • параметры активации и продления доступа • сотрудники партнерской зоны. Логика настройки групп раскрывается в соседних разделах.Системное1Частично реализовано OQ1.4-3
S3: BR1.4-9Партнерская зона должна хранить параметры активации и продления доступаСостав: • статус продления • активный тариф • доступные тарифы • предварительная комиссия • комиссии к оплате • данные по оплатам • платежные документы. Логика активации и продления доступа раскрывается в Back: 2.8.1.Системное1Не реализовано OQ1.4-4
S3: BR1.4-10В рамках партнерской зоны создаются и хранятся связанные сущностиСостав: • объекты (Back: 2.1), • площадки и услуги (Back: 2.2, 2.3), • правила работы с заказами (Back: 2.4), • позиции (Back: 2.5), цены (Back: 2.6), • скидки и акции (Back: 2.7); логика каждой сущности раскрывается в соответствующем разделеСистемное1Реализовано
S4: BR1.4-11Создать партнерскую зону может только зарегистрированный пользовательВ результате создания аккаунт пользователя становится владельцем партнерской зоныБизнес1Частично реализовано OQ1.4-7
S4: BR1.4-12Создание партнерской зоны выполняется в три этапа: • прием обязательных данных • назначение аккаунта владельцем • привязка данных (Настроек) “По умолчанию”При создании автоматически генерируются настройки по умолчанию: • информация об организации (только для типа “Юридическое лицо”); • платежная информация — метод оплаты “Наличными на месте” (Back: 5.1.2); • параметры работы с заказами (Back: 2.4); • доступ и условия размещения в интерфейсах — активный тариф доступа (Back: 2.8.1). Логика последующих настроек — Back: 2.8Системное1
S5: BR1.4-13Система должна проверять наличие обязательных параметров при создании партнерской зоны и соблюдение лимитовОбязательный параметр — публичное название Партнерской зоны. Лимит на описание деятельности — не более 1000 символовСистемное1Не реализовано OQ1.4-8

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
РазработкаOpen1. Убрать гонку — перейти на последовательность БД (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.Descriptionstring? без проверки), ни в команде, ни в базе (на колонке 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Что в кодеГде в коде
Б1BR1.4-3Тип партнёрской зоны (физ/юр) определяет доступные тарифы и сценарии каналов оплатыТип (EntityType) нигде не влияет на подбор тарифов или каналов оплаты. Единственное применение типа — проверка согласованности типа компании при создании (физлицо → только Individual; юрлицо → ИП/ООО). Логика тарифов/каналов тип не читает — нужно решение: правило целевое (ещё не реализовано) или избыточноеPartnerZoneAggregate.cs:137-148; (использований EntityType в подборе тарифов/каналов не найдено за обход домена и persistence)
Б2BR1.4-4Контактный email после изменения/добавления требует подтвержденияМеханизма подтверждения email нет вовсе: ни отправки письма, ни установки «подтверждён», ни сброса при смене email. Признак IsEmailVerified структурно всегда false (см. П5). Нужно решение: нужен ли процесс подтверждения email зоны и каков онContactInfo.cs:17,22-35; PartnerZoneAggregate.cs:238-244; (команд confirm/verify email не найдено за обход всего сервиса)
Б3BR1.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
Б4BR1.4-8Зона хранит 10 групп настроек, в т.ч. уведомления, абонементы, сотрудники партнёрской зоныИз 10 групп 6 смоделированы (организация, платёжная информация, заявки, сборы, параметры/правила работы с заказами — отдельными агрегатами по PartnerZoneId). Не найдены в этом сервисе: «уведомления», «абонементы»; «сотрудники» хранятся не здесь — берутся по gRPC из сервиса идентификации. Нужно решение: где источник истины для этих трёх группPartnerZoneAggregate.cs:38-58; Infrastructure/Services/EmployeeService.cs (сотрудники); («notification»/«абонемент» как настроек зоны не найдено за обход домена)
Б5BR1.4-9Зона хранит параметры активации и продления доступа: статус продления, активный тариф, доступные тарифы, предварительная комиссия, комиссии к оплате, данные по оплатам, платёжные документыПодсистема активации/продления доступа в этом сервисе практически не реализована. «Активный тариф» (TariffId) при создании ставится в Guid.Empty и реальным тарифом нигде не заполняется. Не найдены: статус продления, данные по оплатам, платёжные документы; «доступные тарифы» выражены на стороне тарифа (AllowedZones), а не как список у зоны. BRD сам отсылает к Back: 2.8.1 — нужно подтвердить, что эти данные живут тамPartnerZoneAggregate.cs:54,174; PartnerTariffSetAggregate.cs:18,26; (renewal/payment-data/payment-documents не найдено за обход сервиса)
Б6BR1.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Что в кодеГде в коде
П1BR1.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
П2BR1.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
П3BR1.4-5Телефон по умолчанию — телефон владельца (подтверждение не требуется)Часть «не требует подтверждения» соблюдается (телефон — обычная строка, верификации нет). Но «по умолчанию телефон владельца» не выполнено: при создании передаётся пустая строка, телефон владельца не копируетсяContactInfo.cs:15; CreatePartnerZoneCommandHandler.cs:91
П4BR1.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
П5BR1.4-4Контактный email требует подтверждения (значение признака должно быть осмысленным)Дефект: конструктор ContactInfo принимает параметр isEmailVerified, но никогда не присваивает поле IsEmailVerified (поле readonly без init), поэтому оно всегда false. Даже если бы флаг где-то выставляли, значение бы терялосьContactInfo.cs:17,24,30-34
П6BR1.4-13Обязательный параметр — публичное название; проверка обязательных параметров при созданииНепустота PublicName не проверяется нигде: ни в VO PartnerZoneInfo, ни в команде/обработчике, ни на уровне базы (тип string даёт колонку NOT NULL, но пустая строка "" проходит). Метод IsNameUnique для названия существует, но не вызывается ни в Create, ни в UpdatePartnerZoneInfo.cs:19-25; CreatePartnerZoneCommandHandler.cs:89; PartnerZoneRepository.cs:147-151
П7BR1.4-13Лимит описания деятельности — не более 1000 символовОграничение длины описания не проверяется нигде: ни в домене (PartnerZoneInfo.Descriptionstring? без проверки), ни в команде, ни в базе (на колонке description нет Length/HasMaxLength). Значения 1000 рядом с описанием в коде нетPartnerZoneInfo.cs:15,23; PartnerZone.cs:17-18; DbInitializer.cs (длины/HasMaxLength для description не найдено за обход)
П8BR1.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