Направление работ: 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: 2.8 Настройки партнерской зоны | Бизнес | 1 | Не реализовано OQ1.4-1 |
| S2: BR1.4-4 | Контактный email партнерской зоны после изменения или добавления требует подтверждения | По умолчанию используется email аккаунта-владельца. Используется для рассылки уведомлений по партнерской зоне | Системное | 2 | Не реализовано. Подтверждение Email впринципе на бэке отсутствует |
| S2: BR1.4-5 | Контактный телефон партнерской зоны не требует подтверждения при изменении | По умолчанию используется телефон аккаунта-владельца. Носит справочный характер — для жалоб и оспаривания сборов | Системное | 1 | Частично реализовано OQ1.4-6 |
| S3: BR1.4-6 | Партнерская зона должна быть связана с владельцем и с менеджером | Логика назначения владельца — Back: 1.4 Партнеры. Аккаунт Менеджера назначается на основании Параметров системы — Back: 8.4 Параметры системы | Системное | 1 | Частично реализовано OQ1.4-2 |
| S3: BR1.4-7 | При создании партнерской зоны автоматически привязываются каналы оплаты с признаком «По умолчанию» | Привязываются: канал оплаты для поступающих заказов и сервисный канал оплаты. Логика каналов — Back: 5.1 | Системное | 1 | Реализовано |
| S3: BR1.4-8 | Партнерская зона должна иметь доступ к группам настроек партнерской зоны | Состав: • организация • уведомления • платежная информация • параметры работы с заказами • сборы • заявки • абонементы • правила и условия работы с заказами • параметры активации и продления доступа • сотрудники партнерской зоны. Логика настройки групп раскрывается в Back: 2.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 | Реализовано |
| S4: BR1.4-12 | Создание партнерской зоны выполняется в три этапа: • прием обязательных данных • назначение аккаунта владельцем • привязка данных (Настроек) “По умолчанию” | При создании автоматически генерируются настройки по умолчанию: • информация об организации (только для типа “Юридическое лицо”); • платежная информация — метод оплаты “Наличными на месте” (Back: 5.1.2); • параметры работы с заказами (Back: 2.4); • доступ и условия размещения в интерфейсах — активный тариф доступа (Back: 2.8.1). Логика последующих настроек — Back: 2.8 | Системное | 1 | Частично реализовано OQ1.4-4 |
| S5: BR1.4-13 | Система должна проверять наличие обязательных параметров при создании партнерской зоны и соблюдение лимитов | Обязательный параметр — публичное название Партнерской зоны. Лимит на описание деятельности — не более 1000 символов | Системное | 1 | Не реализовано OQ1.4-8 |
5. Открытые вопросы
Пин сверки (повторная/дельта, по итогам дейликов): BRD 1.4 версия 0.1 (обновлено 29.06.26) · Репозиторий
booking-monorepo, веткаorigin/main, commit82359296(2026-09-07) · Дата сверки: 2026-09-08 · Предыдущая сверка — commit9e19870/dev/cms-conflict-warning, 2026-06-30 (см. «Вопросы по сверке с кодом» ниже) · Якорь в коде:src/services/booking.partner-management(PartnerZoneAggregate, AuthorizationService — ABAC-проверки),src/services/booking.authentication(PartnerEmployee, AssignAndInitialisePartnerZoneCommandHandler — назначение владельца),src/services/booking.abac(роли, права, PDP) · Гайдбук не передан — маршрутизация вопросов без сверки с гайдбуком.
| ID | Источник | Вопрос | Кому | Статус | Рекомендации | Итоговое решение |
|---|---|---|---|---|---|---|
| OQ1.4-1 | Код BR1.4-3 | Тип (EntityType) нигде не влияет на подбор тарифов или каналов оплаты. Единственное применение типа — проверка согласованности типа компании при создании (физлицо → только Individual; юрлицо → ИП/ООО). Логика тарифов/каналов тип не читает — нужно решение: правило целевое (ещё не реализовано) или избыточное PartnerZoneAggregate.cs:137-148; (использований EntityType в подборе тарифов/каналов не найдено за обход домена и persistence) | Бизнес | Open | реализовать влияние EntityType на доступные тарифы и сценарии каналов, как требует BRD (рекомендуется, если бизнес-смысл деления физ/юр в этом и состоит). | Необходимо обсудить на сколько эта бизнес-логика оправдана От бизнеса: Реализация корректная, требования и гайдбук скорректированы. Результат корректировки отразится в валидации типа партнерской зоны при работе с её настройками в Back: 2.8 Настройки партнерской зоны. |
| 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 «Не входит»). Вариант Б: если они должны храниться именно в партнёрской зоне — завести требования и реализацию здесь. Решение за продуктом: где источник истины. | «уведомления», «абонементы», «сотрудники» это ответственность других сервисов От бизнеса: Все настройки партнерской зоны описаны в Back: 2.8 Настройки партнерской зоны и не входят в Scope этого документа. Место их хранения является техническим вопросом. Разработке необходимо проверить реализацию доступности этих настроек через партнерскую зону. |
| OQ1.4-4 | Код BR1.4-9 | Подсистема активации/продления доступа в этом сервисе практически не реализована. «Активный тариф» (TariffId) при создании ставится в Guid.Empty и реальным тарифом нигде не заполняется. Не найдены: статус продления, данные по оплатам, платёжные документы; «доступные тарифы» выражены на стороне тарифа (AllowedZones), а не как список у зоны. BRD сам отсылает к Back: 2.8.1 — нужно подтвердить, что эти данные живут там | Бизнес | Open | См предыдущий вопрос | Не кажется корректным необходимость хранить активность тарифа с учётом того что мы вычисляем жто по другим параметрам, по поводу дополнительных параметров в сущности тарифа необходимо собирать встречу и собирать необходимые бизнес-требования От бизнеса: Все параметры и процессы по продлению партнерской зоны описаны в Back: 2.8.1 Продление доступа и не входят в Scope этого документа. |
| 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-3 и OQ1.4-4. |
| 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. | Необходимо завести задачу на добавление partner_zone.number уникального идентификатора (GUID), partner_zone_owner переезжает в ABAC От бизнеса: Доработка ABAC, вес 1. GUID и номер партнерской зоны — разные параметры: GUID является техническим идентификатором, номер партнерской зоны необходим для организации бизнес-процессов. Доработку необходимо внести в чек-лист задачи по ABAC. |
| OQ1.4-6 | Код BR1.4-5 | Часть «не требует подтверждения» соблюдается (телефон — обычная строка, верификации нет). Но «по умолчанию телефон владельца» не выполнено: при создании передаётся пустая строка, телефон владельца не копируется ContactInfo.cs:15; CreatePartnerZoneCommandHandler.cs:91 | Разработка | Open | См вопрос выше | Необходимы изменения на беке только если мы сходимся к тому что у нас гарантировано всегда должен быть номер телефона От бизнеса: Доработка, вес 1. |
| 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 | Нужно решение: достаточно ли «аутентифицирован» на шлюзе, или создание тоже должно проверять аккаунт/права | Нет необходимости выносить проверку JWT в сам сервис, это будет некорректно с точки зрения архитектуры, проверка прав будет реализована в ABAC От бизнеса: Ждем реализации ABAC. |
| 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 уже есть, но не вызывается; если уникальность нужна — подключить его и/или добавить уникальный индекс. | Необходимо сделать проверку на пустоту string и длину Description ≤ 1000 От бизнеса: Доработка, вес 1. |
| OQ1.4-9 | вне BRD (обратный проход) | Команда Update партнёрской зоны проверяет права через IAuthorizationService (право settings_write) — поведение авторизации на уровне приложения, не описанное в разделе 1.4. Стоит зафиксировать как требование (кто и что может менять в зоне) UpdatePartnerZoneCommandHandler.cs:31-53; AuthorizationService.cs:24-55 | Бизнес | Open | Не поняла формулировку, что нужно именно внести в БРД? | Все права будут проверяться в ABAC От бизнеса: Ждем реализации ABAC. |
| 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 | --- | Механика становления партнёром будет реализована в ABAC От бизнеса: Ждем реализации ABAC. Бизнесу не принципиальна внутренняя механика становления владельцем. В рамках этого документа в результате создания партнерской зоны аккаунт, выполнивший действие, должен стать владельцем этой партнерской зоны. Требование и реализация уже есть; вопрос избыточен, отсылка к партнерской зоне доступа не требуется. |
| OQ1.4-11 | вне BRD (обратный проход) | На зоне хранятся настройки штрафов ForfeitSettings (режим списания, формат бана, порог) и тайминги комиссии CommissionSettings (таймаут оплаты, период расчётов) — данные, не перечисленные в составе BR1.4-2/BR1.4-8 явно (BRD относит «сборы» к настройкам соседних разделов). Уточнить, входят ли они в состав данных зоны PartnerZoneAggregate.cs:49,51; ForfeitSettings.cs; CommissionSettings.cs | Бизнес | Open | Внести изменения в БРД? | Непонятно в чём заключается вопрос От бизнеса: Ответ отражен в итоговых решениях OQ1.4-3 и OQ1.4-4. |
| OQ1.4-12 | вне BRD (обратный проход) BR1.4-11 | Становление владельцем при создании зоны теперь выполняется двумя параллельными путями одновременно: (1) legacy — аккаунту добавляется системная роль "partner" (тот же путь, что описан в OQ1.4-10); (2) новый ABAC-путь — сервис получает/создаёт владельческую роль через EnsureOwnerRole и заводит PartnerEmployee с этой ролью, активного сразу, без приглашения. Неясно, сохраняет ли legacy-роль "partner" на аккаунте какое-то значение для авторизации, или это исторический путь, оставшийся нетронутым при переходе на ABAC AssignAndInitialisePartnerZoneCommandHandler.cs:68-96 | Разработка | Open | Подтвердить, что роль "partner" на аккаунте больше не используется для проверки прав (только для витрины/статистики или как признак «пользователь — партнёр» в других сервисах), и явно отразить это либо в BRD, либо убрать дублирующий путь как мёртвый код. |
Подстраницы
Вопросы по сверке с кодом
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 |