Юридические лица — Карточка
Три режима одного экрана: просмотр, создание, редактирование.
(Переработано в BR 1.4.4)
- Карточка ЮЛ организована по вкладкам: «Реквизиты», «Владелец» (только
type=franchisee), «Права» (толькоtype=franchisee), «ТТ»- Новая вкладка «Права» управляет правами владельца партнёра (системная роль «Администратор» либо скрытая персональная роль)
- В форме создания ЮЛ партнёра — новый блок «Права владельца» с тем же UI
- Раздел «Юр. лица» скрыт при
franchise.type=individual(см. Франшизы)
Доступность раздела
- При
franchise.type=individual: пункт меню «Юр. лица» скрыт. Прямой URL/admin/legal-entities/*→ страница «404 Не найдено» (или редирект на дашборд)franchise.typeфронт получает изGET /api/v1/admin/auth/meи хранит в PermissionContext
Просмотр (/legal-entities/:id) — карточка с вкладками
API: GET /api/v1/legal-entities/{id}, GET /api/v1/admin/auth/me (для franchise.type)
Шапка карточки
- Breadcrumb: «Юр. лица» → «{name}»
- Заголовок — наименование ЮЛ
- Бейджи: тип («Франшиза» / «Франчайзи»), статус, «Главное» (если
is_primary) - Кнопки в шапке (видимость по scope):
- “Редактировать” →
/legal-entities/{id}/edit - “Приостановить” / “Возобновить” (владелец франшизы + type=franchisee)
- “Удалить” (владелец франшизы + нет ТТ)
- “Редактировать” →
Вкладки
| # | Вкладка | Когда показывается | Доступ |
|---|---|---|---|
| 1 | Реквизиты | Всегда | По scope (владелец партнёра видит только своё ЮЛ) |
| 2 | Владелец | Только type=franchisee | Владелец франшизы — полный; владелец партнёра — у своего ЮЛ readonly |
| 3 | Права | Только type=franchisee (новое в BR 1.4.4) | Только владелец франшизы. Владелец партнёра у своего же ЮЛ — не видит вкладку (не может сам себе давать/снимать права) |
| 4 | ТТ | Всегда | По scope |
| 5 | PayKeeper | Всегда | По integrations.read. Подключение и webhook URLs. Детали — отдельная спека. (Добавлено в BR 3.3) |
Default tab — «Реквизиты». Переключение вкладок не меняет URL.
Вкладка «Реквизиты»
Основные данные:
| Поле | Значение |
|---|---|
| Тип | Франшиза / Франчайзи |
| Наименование | name |
| ИНН | inn |
| КПП | kpp или ”—“ |
| ОГРН | ogrn |
| Юридический адрес | legal_address |
Банковские реквизиты:
| Поле | Значение |
|---|---|
| Банк | bank_name или ”—“ |
| БИК | bank_bik или ”—“ |
| Расчётный счёт | bank_account или ”—“ |
| Корр. счёт | bank_corr_account или ”—” |
Контакты:
| Поле | Значение |
|---|---|
| Телефон | contact_phone или ”—“ |
contact_email или ”—” |
Данные договора (только type=franchisee):
| Поле | Значение |
|---|---|
| Номер договора | contract_number или ”—“ |
| Дата договора | contract_date или ”—“ |
Вкладка «Владелец» (type=franchisee)
(Лейбл обновлён в BR 1.4.4 — без enum-роли admin_franchisee)
| Поле | Значение |
|---|---|
| ФИО | ФИО сотрудника по owner_user_id |
| Email (логин) | owner.email |
| Телефон | owner.phone или ”—“ |
| Статус | ”Активен” / “Деактивирован” |
| Режим прав | «Полный доступ (системная роль «Администратор»)» / «Настроенные права» — берётся с эндпоинта GET /api/v1/admin/legal-entities/{id}/owner-permissions |
Ссылка «Открыть карточку сотрудника» → /employees/{owner.id}.
Для legacy-записей без владельца — текст «Не назначен» + кнопка «Назначить владельца» (вне MVP).
Вкладка «Права» (новая, type=franchisee)
(Введено в BR 1.4.4 §5.2)
API:
GET /api/v1/admin/legal-entities/{id}/owner-permissions— текущий режим + permissionsPUT /api/v1/admin/legal-entities/{id}/owner-permissions— сохранитьGET /api/v1/admin/roles/permission-catalog— лейблы permissions
Доступ: только владелец франшизы. Владелец партнёра у своего ЮЛ вкладку не видит (UI скрывает).
Layout
─ Права владельца ──────────
Режим:
○ Полный доступ
Системная роль «Администратор» — все permissions включая pos.access
● Настроенные права
Скрытая персональная роль с выбранными ниже permissions
[когда выбран «Настроенные права» — раскрывается матрица:]
Разделы Бэк-офиса Чтение Редактирование
Меню ☑ ☑
Прейскуранты ☑ ☐
Публикация ТТ ☐ ☐
Сотрудники ☑ (заблок.) ☐
...
Функции POS
☑ Доступ к POS (заблокировано)
☑ Открытие смены
...
[Сохранить]
Радио режимов
| Режим | Что происходит при сохранении |
|---|---|
| Полный доступ (default при создании) | Скрытая роль владельца (если была) отсоединяется от него; назначается системная роль «Администратор» |
| Настроенные права | Создаётся (или обновляется) скрытая роль с owner_legal_entity_id={id ЮЛ} и выбранными permissions; назначается владельцу |
Матрица permissions
Та же что в Роли — Карточка § Разделы Бэк-офиса и § Функции POS. Источник лейблов — GET /api/v1/admin/roles/permission-catalog.
Обязательный минимум (всегда отмечены, чекбоксы disabled — нельзя снять):
pos.access— логин на POS по PINstores.read— видеть свои ТТemployees.read— видеть свой персонал
UI блокирует, бэк дополнительно валидирует и форсит включение этих permissions.
Edit implies Read — то же правило что и в обычной роли.
Кнопка «Сохранить»
- Применяет изменения немедленно:
PUT /api/v1/admin/legal-entities/{id}/owner-permissions - Toast: «Права владельца обновлены»
- Все активные сессии владельца получат новые permissions со следующего запроса (см. Роли)
Состояния
| Состояние | Что показываем |
|---|---|
| Загрузка | Skeleton матрицы permissions |
| Без владельца | Информер «У ЮЛ нет владельца. Назначение владельца — вне MVP» |
| Ошибка сохранения | Toast с текстом ошибки |
Вкладка «ТТ»
- “Привязанных ТТ: N” — число + список названий ТТ (кликабельные → карточки ТТ)
Создание (/legal-entities/new)
API: POST /api/v1/legal-entities
Доступ: только владелец франшизы. Скрыто при franchise.type=individual (форма недоступна, прямой URL → 404)
Шаг 1 — Выбор типа
Radio: “ЮЛ Франшизы” / “ЮЛ Франчайзи”. При выборе типа — показываются/скрываются блоки «Владелец» и «Права владельца».
Основные данные (оба типа)
| Поле | Тип ввода | Обязательно | Маска/Валидация |
|---|---|---|---|
| Наименование | Text input | Да | max 255 |
| ИНН | Text input | Да | 10 или 12 цифр, контрольная сумма |
| КПП | Text input | Нет | 9 цифр |
| ОГРН | Text input | Да | 13 или 15 цифр |
| Юридический адрес | Textarea | Да |
Банковские реквизиты
| Поле | Тип ввода | Обязательно | Маска/Валидация |
|---|---|---|---|
| Банк | Text input | Нет | |
| БИК | Text input | Нет | 9 цифр |
| Расчётный счёт | Text input | Нет | 20 цифр |
| Корр. счёт | Text input | Нет | 20 цифр |
Контакты
| Поле | Тип ввода | Обязательно | Маска/Валидация |
|---|---|---|---|
| Телефон | Text input | Нет | +7 (XXX) XXX-XX-XX |
| Text input | Нет |
Данные договора (только type=franchisee)
| Поле | Тип ввода | Обязательно |
|---|---|---|
| Номер договора | Text input | Нет |
| Дата договора | Date picker | Нет |
Блок «Владелец» (type=franchisee)
(Источник: BR 1.4.2; обновлено в BR 1.4.4 — enum admin_franchisee удалён, владельцу назначается либо системная «Администратор», либо скрытая роль)
Блок обязателен для type=franchisee
Владелец создаётся одной транзакцией с ЮЛ. Нельзя создать ЮЛ Франчайзи без владельца.
| Поле | Тип ввода | Обязательно | Маска/Валидация |
|---|---|---|---|
| Имя | Text input | Да | max 100 |
| Фамилия | Text input | Да | max 100 |
| Email (логин) | Text input | Да | email, уникален в рамках франшизы |
| Телефон | Text input | Нет | +7 (XXX) XXX-XX-XX |
| Пароль | Password input | Нет | min 6 символов; если пусто — генерируется системой |
Для type=franchise блок «Владелец» не показывается.
Блок «Права владельца» (type=franchisee)
(Введено в BR 1.4.4 §5.2)
Тот же UI что во вкладке «Права» карточки:
- Радио «Полный доступ» (default) / «Настроенные права»
- Матрица permissions (раскрывается при «Настроенные права»)
- Минимум
pos.access,stores.read,employees.read— заблокированы
При POST бэк в одной транзакции:
- Создаёт ЮЛ + сотрудника-владельца
- В режиме «Полный доступ» — назначает системную роль «Администратор»
- В режиме «Настроенные права» — создаёт скрытую персональную роль с
owner_legal_entity_id={новый id ЮЛ}и назначает её
Валидация
- Клиент: маски ИНН/телефона, обязательные поля, email формат
- Сервер:
INVALID_INN_CHECKSUM,INN_DUPLICATEOWNER_FIELDS_REQUIRED— “Заполните данные владельца партнёра”OWNER_EMAIL_DUPLICATE— “Сотрудник с таким email уже существует”FRANCHISE_TYPE_INDIVIDUAL(403) — “Создание партнёров недоступно при типе франшизы «ИП»” (теоретический кейс — UI не должен пускать к форме)OWNER_PERMISSIONS_INVALID— некорректный набор permissions для скрытой роли (например, нарушен Edit implies Read)
Кнопки
- “Сохранить” — отправить форму
- “Отмена” — возврат на список (с подтверждением если есть несохранённые данные)
После успеха
Для type=franchise:
- Redirect на
/legal-entities/{new_id}(карточка просмотра) - Toast: “Юридическое лицо создано”
Для type=franchisee:
- Сначала модалка “Партнёр создан” поверх карточки:
- Заголовок: “Партнёр создан”
- Email владельца (крупно, с кнопкой “Скопировать”)
- Временный пароль (крупно, моноширинным шрифтом, с кнопкой “Скопировать”) — показывается только если
owner.temporary_passwordв ответе не null - Callout-предупреждение: “Сохраните эти данные — восстановить пароль партнёра можно будет только через сброс”
- Инструкция: “Передайте эти данные партнёру. Пароль можно изменить после первого входа.”
- Подпись: «Режим прав: Полный доступ» / «Настроенные права»
- Кнопка “Закрыть”
- После закрытия модалки — redirect на
/legal-entities/{new_id}(карточка просмотра) - Toast: “Юридическое лицо создано”
Редактирование (/legal-entities/:id/edit)
API: PATCH /api/v1/legal-entities/{id}
Доступ: владелец франшизы — все поля кроме ИНН и типа; владелец партнёра — ограниченный набор
Что видит пользователь
Та же форма что при создании, но:
- Поле ИНН —
disabled, серый фон, tooltip “ИНН нельзя изменить после создания” - Поле Тип —
disabled(нельзя сменить тип) - Блок «Владелец» — readonly (управляется через отдельную операцию, вне MVP)
- Блок «Права владельца» — отсутствует на форме редактирования (управляется через вкладку «Права» карточки)
- Предзаполнены текущие значения
Владелец партнёра — ограничения
Видит только редактируемые поля:
- Юридический адрес
- Банковские реквизиты (все 4 поля)
- Контакты (телефон, email)
Остальные поля — отображаются как текст (read-only), не как поля формы.
Кнопки
- “Сохранить” — отправить PATCH
- “Отмена” — возврат на карточку просмотра
После успеха
- Redirect на
/legal-entities/{id}(карточка просмотра) - Toast: “Изменения сохранены”
Состояния
| Состояние | Что показываем |
|---|---|
franchise.type=individual + прямой URL | Страница «404 Не найдено» или редирект на / |
| Загрузка (просмотр/edit) | Skeleton-блоки вместо полей |
| ЮЛ не найдено (404) | “Юридическое лицо не найдено” + кнопка “Вернуться к списку” |
| Ошибка сохранения | Ошибки под полями (validation) или toast (серверная ошибка) |
| Несохранённые изменения | При уходе со страницы: “У вас есть несохранённые изменения. Покинуть страницу?” |
Переходы
| Откуда | Куда | Триггер |
|---|---|---|
| Карточка | Список | Кнопка “Назад” / breadcrumb |
| Карточка | Редактирование | Кнопка “Редактировать” |
| Карточка → вкладка «Владелец» | Карточка сотрудника | Ссылка «Открыть карточку сотрудника» |
| Создание | Карточка | После успешного сохранения (через модалку для type=franchisee) |
| Создание | Список | Кнопка “Отмена” |
| Редактирование | Карточка | После сохранения или “Отмена” |
Ссылки
- Бизнес-спека: Юридические лица
- Бизнес-спека: Франшизы —
franchises.typeуправляет видимостью раздела - Бизнес-спека: Роли — системная и скрытые роли
- Ролевая модель — scope
- User Service API
- Auth Service API —
/auth/meсfranchise.typeи scope - Список ЮЛ
- Роли — Карточка — матрица permissions