Направление работ: Back Код раздела: 1.4 Аккаунты и пользователи > Партнеры Статус: на валидации Ответственный: Рыженко И.С. Версия: 0.1 Обновлено: 22.07.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-7 \ #OQ1.4-8 \ #OQ1.4-14 |
| S2: BR1.4-3 | Тип партнерской зоны определяет доступные тарифы, сценарии сервисных каналов оплаты и каналов оплаты для поступающих заказов | По умолчанию — физическое лицо. Логика тарифов раскрывается в Back: 1.4.2 и Back: 8.3 | Бизнес | 1 | Не реализовано \ #OQ1.4-1 |
| S2: BR1.4-4 | Контактный email партнерской зоны после изменения или добавления требует подтверждения | По умолчанию используется email аккаунта-владельца. Используется для рассылки уведомлений по партнерской зоне | Системное | 2 | Не реализовано \ #OQ1.4-2 \ #OQ1.4-11 |
| S2: BR1.4-5 | Контактный телефон партнерской зоны не требует подтверждения при изменении | По умолчанию используется телефон аккаунта-владельца. Носит справочный характер — для жалоб и оспаривания сборов | Системное | 2 | Частично \ #OQ1.4-9 |
| S3: BR1.4-6 | Партнерская зона должна быть связана с владельцем и может быть связана с менеджером | Логика назначения владельца — Back: 1.4. Менеджер может осуществлять модерацию контента — Back: 8.7 | Системное | 1 | Частично \ #OQ1.4-3 |
| S3: BR1.4-7 | При создании партнерской зоны автоматически привязываются каналы оплаты с признаком «По умолчанию» | Привязываются: канал оплаты для поступающих заказов и сервисный канал оплаты. Логика каналов — Back: 5.1 | Системное | 1 | Реализовано |
| S3: BR1.4-8 | Партнерская зона должна хранить группы настроек партнерской зоны | Состав: • организация • уведомления • платежная информация • параметры работы с заказами • сборы • заявки • абонементы • правила и условия работы с заказами • параметры активации и продления доступа • сотрудники партнерской зоны. Логика настройки групп раскрывается в соседних разделах. | Системное | 1 | Частично \ #OQ1.4-4 |
| S3: BR1.4-9 | Партнерская зона должна хранить параметры активации и продления доступа | Состав: • статус продления • активный тариф • доступные тарифы • предварительная комиссия • комиссии к оплате • данные по оплатам • платежные документы. Логика активации и продления доступа раскрывается в Back: 2.8.1. | Системное | 1 | Не реализовано \ #OQ1.4-5 |
| 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-10 \ #OQ1.4-16 |
| S4: BR1.4-12 | Создание партнерской зоны выполняется в три этапа: • прием обязательных данных • назначение аккаунта владельцем • привязка данных (Настроек) “По умолчанию” | При создании автоматически генерируются настройки по умолчанию: • информация об организации (только для типа “Юридическое лицо”); • платежная информация — метод оплаты “Наличными на месте” (Back: 5.1.2); • параметры работы с заказами (Back: 2.4); • доступ и условия размещения в интерфейсах — активный тариф доступа (Back: 2.8.1). Логика последующих настроек — Back: 2.8 | Системное | 1 | Частично \ #OQ1.4-6 |
| S5: BR1.4-13 | Система должна проверять наличие обязательных параметров при создании партнерской зоны и соблюдение лимитов | Обязательный параметр — публичное название Партнерской зоны. Лимит на описание деятельности — не более 1000 символов | Системное | 1 | Не реализовано \ #OQ1.4-12 \ #OQ1.4-13 |
5. Открытые вопросы
Вопросы прогнаны через гайдбук 1.4 (Партнеры, включая 2.8 / 2.8.1). Гайдбук подтвердил правила по типу зоны, подтверждению email, ручному назначению менеджера, дефолтам контактов от владельца, «организации только для юрлица», обязательности названия и лимиту 1000 символов — эти вопросы переведены в «Закрывает PM» или потеряли развилку. Открытыми остались: гонка номера (архитектура), проверка прав при создании, обязательный набор дефолтов и уникальность названия — последнего в гайдбуке нет.
| ID | Источник | Вопрос | Кому | Статус | Рекомендации |
|---|---|---|---|---|---|
| #OQ1.4-1 | Код BR1.4-3 | Требование говорит: тип зоны (физ/юр) определяет доступные тарифы и сценарии каналов оплаты. В коде тип (EntityType) нигде не влияет на подбор тарифов или каналов: единственное применение — проверка согласованности типа компании при создании (физлицо → Individual; юрлицо → ИП/ООО). Логика тарифов/каналов тип не читает. \ PartnerZoneAggregate.cs:137-148 | Бизнес/Разработка | Open | Гайдбук 1.4 говорит дословно: «Тип определяет: доступные для покупки тарифы; сценарии сервисных каналов оплаты; сценарии каналов оплаты для поступающих заказов» — значит правило целевое, вариант «избыточное / уточнить формулировку» отпадает. Это недоработка, а не спорный вопрос. Рекомендация: реализовать влияние типа на подбор тарифов и сценарии каналов. Объём и этапность — за архитектурой; сама логика тарифов — Back 1.4.2 / 8.3, каналов — 5.1. |
| #OQ1.4-2 | Код BR1.4-4 | Требование говорит: контактный email после изменения/добавления требует подтверждения. В коде механизма подтверждения нет вовсе: ни отправки письма, ни установки «подтверждён», ни сброса при смене. Признак IsEmailVerified структурно всегда false (см. OQ1.4-11). \ ContactInfo.cs:17,22-35; PartnerZoneAggregate.cs:238-244 | Разработка | Закрывает PM | Гайдбук 1.4 прямо говорит: «По умолчанию используется электронная почта владельца аккаунта. После изменения нового адреса требуется подтверждение» — правило есть, вариант «снять требование» отпадает, продуктового выбора нет. Закрываю сам: реализовать процесс подтверждения контактного email зоны (отправка кода/ссылки, установка признака, сброс при смене) → тикет в Bitrix. Предпосылка — исправить дефект признака (OQ1.4-11), без него флаг всё равно теряется. Механику подтверждения переиспользовать из уже существующей (Mobile 1.2.2 / 5.2.1). |
| #OQ1.4-3 | Код BR1.4-6 | Требование говорит: зона связана с владельцем (обязательно) и может быть связана с менеджером (опционально, назначается вручную). В коде менеджер обязателен при создании (ManagerId — не-nullable, колонка NOT NULL) и не имеет операции ручного назначения/смены: Update не содержит ManagerId. \ CreatePartnerZoneCommands.cs:28; PartnerZone.cs:29-30; UpdatePartnerZoneCommand.cs:18-41 | Разработка | Закрывает PM | Гайдбук 1.4 говорит: менеджер — «аккаунт сотрудника сервиса… назначается вручную». Ручное назначение несовместимо с обязательным полем при создании (создаёт-то партнёр, а не сотрудник сервиса) — значит код неверен, вариант «привести BRD к коду» отпадает. Закрываю сам: сделать ManagerId опциональным и добавить операцию ручного назначения/смены менеджера → тикет в Bitrix. Заодно исправить ошибочный комментарий поля в коде («ID владельца»). Назначение менеджера как административная операция — смежно с Back 8.6. |
| #OQ1.4-4 | Код BR1.4-8 | Требование говорит: зона хранит 10 групп настроек, в т.ч. уведомления, абонементы, сотрудники. В коде из 10 групп 6 смоделированы (организация, платёжная информация, заявки, сборы, параметры/правила работы с заказами — отдельными агрегатами по PartnerZoneId). Не найдены: «уведомления», «абонементы»; «сотрудники» хранятся не здесь — берутся по gRPC из сервиса идентификации. \ PartnerZoneAggregate.cs:38-58; EmployeeService.cs | Разработка | Закрывает PM | Гайдбук отвечает по каждой из трёх: «Уведомления» — перечень шаблонов, ссылка на 7.2.1; «Абонементы» — часть «Параметров работы с заказами» (сборы/заявки/абонементы), то есть 2.8; «Сотрудники партнёрской зоны» — ссылка на 1.4.1. То есть все три по замыслу живут в других разделах, а не в данных этого сервиса — код верен. Закрываю сам: оставить BR1.4-8 картой-ссылкой (состав групп + ссылки на 7.2.1 / 2.8 / 1.4.1), требования к данным там; в 1.4 не дублировать → правка BRD. |
| #OQ1.4-5 | Код BR1.4-9 | Требование говорит: зона хранит параметры активации и продления доступа (статус продления, активный тариф, доступные тарифы, комиссии, данные по оплатам, платёжные документы). В коде подсистема практически не реализована: «активный тариф» (TariffId) при создании ставится в Guid.Empty и реальным тарифом нигде не заполняется; не найдены статус продления, данные по оплатам, платёжные документы; «доступные тарифы» выражены на стороне тарифа (AllowedZones), а не как список у зоны. \ PartnerZoneAggregate.cs:54,174; PartnerTariffSetAggregate.cs:18,26 | Разработка | Закрывает PM | Гайдбук подтверждает дом: весь состав (статус продления, активный тариф, доступные тарифы, предварительная комиссия, комиссии к оплате, платёжные документы) раскрыт в разделе 2.8.1 «Активация и продление доступа», туда же отсылает и BRD. Гайдбук заодно даёт то, чего нет в требовании: статус продления принимает значения Активен / Пролонгация / Не продлен / Архивирован. Закрываю сам: оставить BR1.4-9 картой-ссылкой на 2.8.1 (добавив значения статуса продления), требования к данным вести там → правка BRD. Оговорка: «активный тариф» пересекается с 1.4.1/OQ1.4.1-9 (связь тариф↔зона неоднозначна) — техническую часть решать там. |
| #OQ1.4-6 | Код BR1.4-12 | Требование говорит: при создании генерируются настройки «по умолчанию»: организация только для юрлица; параметры работы с заказами; активный тариф доступа. В коде реализована только платёжная информация по умолчанию («Оплата на месте (наличные)» + базовый фильтр). Компания (Company) создаётся всегда, без условия «только юрлицо». Параметры работы с заказами по умолчанию не создаются. Активный тариф не назначается (Guid.Empty). \ CreatePartnerZoneCommandHandler.cs:137-184; PartnerZoneAggregate.cs:154-160,174 | Бизнес/Разработка | Open | Гайдбук закрывает часть вопроса: «Организация — информация об организации и договоре. Доступно только для партнёрских зон с типом „Юридическое лицо“» → создание компании всегда — баг, спорить не о чем, беру на себя. Гайдбук также подтверждает три этапа создания и привязку данных «По умолчанию» (со ссылкой на 8.4 Параметры системы). Осталось бизнесу: гайдбук не перечисляет обязательный набор дефолтов поимённо — подтвердить, обязательны ли при создании параметры работы с заказами и активный тариф доступа, или достаточно платёжной информации. Состав дефолтов — 8.4; активный тариф — связать с OQ1.4-5. |
| #OQ1.4-7 | Код BR1.4-2 | Проблема: номер вычисляется как MAX(number)+1 без атомарности и без запрета дублей в базе: MAX читается отдельным запросом, +1 в C#, вставка позже — два одновременных создания получат одинаковый номер. Уникального индекса на partner_zone.number нет. \ CreatePartnerZoneCommandHandler.cs:62; PartnerZoneRepository.cs:153-159; DbInitializer.cs:163,406-408,473 | Разработка (Влад) | Open | Требование «номер уникальный» держится ни на чём: ни код, ни база уникальность не гарантируют. Вопрос к Владу: (А, рекоменд.) перейти на последовательность БД (SERIAL/nextval) либо уникальный индекс + повтор при конфликте — даёт и возрастание, и уникальность; (Б) блокировка на запись (advisory lock) вокруг выдачи номера — проще, но дороже по конкуренции. |
| #OQ1.4-8 | Код BR1.4-2 | Требование говорит: email зоны по умолчанию — email владельца; телефон по умолчанию — телефон владельца. В коде при создании email и телефон жёстко проставляются пустой строкой, данные владельца не копируются; у команды создания вообще нет полей email/phone. Модель partner_zone_owner с флагами email_confirmed/phone_confirmed существует, но нигде не используется (мёртвый код). \ CreatePartnerZoneCommandHandler.cs:91-92; CreatePartnerZoneCommands.cs:12-30; PartnerZoneOwner.cs:27,33 | Разработка | Закрывает PM | Гайдбук 1.4 говорит прямо: «По умолчанию используется электронная почта владельца аккаунта» и «По умолчанию используется телефон владельца аккаунта» — правило есть, вариант «убрать из BRD» отпадает, продуктового выбора нет. Закрываю сам: при создании подтягивать email/телефон владельца из сервиса аккаунтов и проставлять в контактные данные; заодно убрать или задействовать мёртвую модель partner_zone_owner → тикет в Bitrix. Закрывает и OQ1.4-9 (телефон). |
| #OQ1.4-9 | Код BR1.4-5 | Требование говорит: телефон по умолчанию — телефон владельца, подтверждение не требуется. В коде часть «не требует подтверждения» соблюдается (телефон — обычная строка, верификации нет), но «по умолчанию телефон владельца» не выполнено: при создании передаётся пустая строка. \ ContactInfo.cs:15; CreatePartnerZoneCommandHandler.cs:91 | Разработка | Закрывает PM | Гайдбук подтверждает обе части: «По умолчанию используется телефон владельца аккаунта. Подтверждение номера не требуется». Вторая часть выполнена, первая — тот же корень, что OQ1.4-8 (данные владельца не копируются). Закрываю сам: решается той же правкой, что OQ1.4-8, отдельного тикета не требует. |
| #OQ1.4-10 | Код BR1.4-11 | Требование говорит: создать зону может только зарегистрированный пользователь; аккаунт становится владельцем. В коде «только аутентифицированный» обеспечивается на шлюзе: JWT проверяется, AccountId берётся из claim токена и перезаписывается (клиент подменить не может), белый список анонимных методов в проде пуст. Но в самом обработчике создания нет проверки существования аккаунта и нет проверки прав — в отличие от Update, который вызывает IAuthorizationService. \ RpcProxyController.cs:385-388; CreatePartnerZoneCommandHandler.cs:52-135; UpdatePartnerZoneCommandHandler.cs:31-53 | Бизнес/Разработка | Open | Решение: достаточно ли «аутентифицирован» на шлюзе, или создание тоже должно проверять аккаунт/права. (А, рекоменд.) согласовать и добавить проверку в обработчик, как в Update; (Б) оставить как есть, явно зафиксировав, что авторизация создания — целиком на шлюзе. Граница ответственности шлюз/сервис — частично продуктовое решение. |
| #OQ1.4-11 | Код BR1.4-4 | Проблема (дефект): конструктор ContactInfo принимает параметр isEmailVerified, но никогда не присваивает поле IsEmailVerified (поле readonly без init) — оно всегда false. Даже если бы флаг где-то выставляли, значение бы терялось. \ ContactInfo.cs:17,24,30-34 | Разработка | Закрывает PM | Явный дефект: значение теряется молча. Продуктового выбора нет — присваивание поля нужно при любом решении по OQ1.4-2. Закрываю сам: исправить ContactInfo — присваивать поле в конструкторе (init/прямое присваивание) → тикет в Bitrix. Сам процесс подтверждения этим не вводится (его направление задаёт OQ1.4-2). |
| #OQ1.4-12 | Код BR1.4-13 | Требование говорит: обязательный параметр — публичное название; проверка обязательных параметров при создании. В коде непустота PublicName не проверяется нигде: ни в VO PartnerZoneInfo, ни в команде/обработчике, ни на уровне базы (тип string даёт NOT NULL, но пустая строка проходит). Метод IsNameUnique для названия существует, но не вызывается ни в Create, ни в Update. \ PartnerZoneInfo.cs:19-25; CreatePartnerZoneCommandHandler.cs:89; PartnerZoneRepository.cs:147-151 | Разработка | Закрывает PM | Гайдбук подтверждает: «Публичное название — обязательное поле» (видно пользователям при начислении штрафов и выдаче промокодов). Закрываю сам: добавить проверку непустого PublicName в доменный VO PartnerZoneInfo — единое место enforce для Create и Update → тикет в Bitrix. Отдельная оговорка: про уникальность названия ни BRD, ни гайдбук не говорят, а метод IsNameUnique в коде есть и не вызывается — подтвердить нечем, уточнить у Германа (не додумываю за гайдбук). |
| #OQ1.4-13 | Код BR1.4-13 | Требование говорит: лимит описания деятельности — не более 1000 символов. В коде ограничение длины не проверяется нигде: ни в домене (Description — string? без проверки), ни в команде, ни в базе (на колонке нет HasMaxLength). Значения 1000 рядом с описанием в коде нет. \ PartnerZoneInfo.cs:15,23; PartnerZone.cs:17-18 | Разработка | Закрывает PM | Гайдбук подтверждает: «Описание деятельности… Максимальная длина — 1000 символов». Спорить не о чем. Закрываю сам: добавить проверку длины Description ≤ 1000 в доменный VO PartnerZoneInfo (вместе с OQ1.4-12, одна правка) → тикет в Bitrix. |
| #OQ1.4-14 | Код BR1.4-2, BR1.4-7 | Что подтверждено: большинство полей состава зоны присутствует. Уточнение по признаку «По умолчанию» для каналов оплаты: он хранится не на зоне, а на самом канале (IsDefault) в другом сервисе и читается оттуда при создании — на стороне зоны флага «канал по умолчанию» нет. \ CreatePartnerZoneCommandHandler.cs:76-78,112-116; PartnerZoneAggregate.cs:50 | Разработка | Закрывает PM | Текущее поведение (выбор канала по IsDefault) корректно покрывает BR1.4-7 — вопрос только в формулировке хранения. Уже внесено в BRD (комментарий к BR1.4-2). Закрываю сам: формулировка зафиксирована, дополнительных действий не требуется. \ Подтверждение: состав данных зоны подтверждён кодом. |
| #OQ1.4-15 | Код вне BRD (обратный проход) | Что нашли: команда Update партнёрской зоны проверяет права через IAuthorizationService (право settings_write) — поведение авторизации на уровне приложения, не описанное в разделе 1.4. \ UpdatePartnerZoneCommandHandler.cs:31-53; AuthorizationService.cs:24-55 | Разработка | Закрывает PM | Дом у находки есть по скоупу: права и проверка доступа — Back 1.4.1 (партнёрская зона доступа) и Back 1.2 (общая модель доступа), оба уже в «Не входит». Закрываю сам: «Не входит → 1.4.1 / 1.2»; в 1.4 при необходимости оставить одну строку-ссылку «операции над зоной ограничены правами (см. 1.4.1)», правила не дублировать. Оговорка: сама проверка сейчас не работает — резолвер IsAuthorized заглушка (см. 1.4.1). |
| #OQ1.4-16 | Код вне BRD (обратный проход) | Что нашли: при создании зоны на стороне сервиса аккаунтов её владельцу добавляется роль "partner" и запись OwnedPartnerZone (таблица owned_partner_zones_to_accounts) — это и есть реализация «аккаунт становится владельцем/партнёром» из BR1.4-11, но через роль и связь, а не через флаг IsPartner. \ PartnerZoneCreatedEventConsumer.cs:9,19-24; AssignPartnerZoneCommand.cs:43-55 | Разработка | Закрывает PM | Не расхождение — механика требования, просто не описанная. Ключевое понятие «Партнер — характеристика аккаунта, присваиваемая при создании зоны» в разделе уже есть. Закрываю сам: отразить в комментарии к BR1.4-11 механику «становления партнёром» (роль partner + связь владения, а не флаг) → правка BRD. |
| #OQ1.4-17 | Код вне BRD (обратный проход) | Что нашли: на зоне хранятся настройки штрафов ForfeitSettings (режим списания, формат бана, порог) и тайминги комиссии CommissionSettings (таймаут оплаты, период расчётов) — данные, явно не перечисленные в составе BR1.4-2/BR1.4-8 (BRD относит «сборы» к настройкам соседних разделов). \ PartnerZoneAggregate.cs:49,51; ForfeitSettings.cs; CommissionSettings.cs | Разработка | Закрывает PM | Гайдбук даёт дом: «Параметры работы с заказами» включают сборы, заявки, абонементы — то есть настройки штрафов/сборов относятся к группе настроек зоны (2.8), а логика начисления — 3.2.1. Тайминги комиссии — к параметрам активации и продления доступа (2.8.1 / 4.4). Продуктового выбора нет, дом подтверждён. Закрываю сам: «Не входит → 2.8 / 2.8.1»; в 1.4 достаточно упоминания групп в BR1.4-8, детальный состав не дублировать. |
Подстраницы
Вопросы по сверке с кодом
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 |