Юридические лица — Карточка

Три режима одного экрана: просмотр, создание, редактирование.

(Переработано в 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

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
5PayKeeperВсегдаПо 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 или ”—“
Emailcontact_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 — текущий режим + permissions
  • PUT /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 по PIN
  • stores.read — видеть свои ТТ
  • employees.read — видеть свой персонал

UI блокирует, бэк дополнительно валидирует и форсит включение этих permissions.

Edit implies Read — то же правило что и в обычной роли.

Кнопка «Сохранить»

  • Применяет изменения немедленно: PUT /api/v1/admin/legal-entities/{id}/owner-permissions
  • Toast: «Права владельца обновлены»
  • Все активные сессии владельца получат новые permissions со следующего запроса (см. Роли)

Состояния

СостояниеЧто показываем
ЗагрузкаSkeleton матрицы permissions
Без владельцаИнформер «У ЮЛ нет владельца. Назначение владельца — вне MVP»
Ошибка сохраненияToast с текстом ошибки

Вкладка «ТТ»

  • “Привязанных ТТ: N” — число + список названий ТТ (кликабельные → карточки ТТ)

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
EmailText inputНетemail

Данные договора (только 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_DUPLICATE
    • OWNER_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: “Юридическое лицо создано”

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)
СозданиеСписокКнопка “Отмена”
РедактированиеКарточкаПосле сохранения или “Отмена”

Ссылки