Перейти к содержанию

Покупатели сети и доступ к витрине

Статус документа

Документ фиксирует согласованную целевую модель. Модуль customer (вход по коду, refresh-сессии, access JWT) и HTTP-граница storefront реализованы частично — см. модуль customer и модуль storefront. Профиль, адреса, заказы и программа лояльности будут проектироваться и реализовываться отдельными принимаемыми этапами.

Область учётной записи

Покупатель регистрируется на уровне всей сети, а не отдельного франчайзи или ресторана. Один CustomerAccount используется во всех городах и ресторанах сети.

CustomerAccount (вся сеть)
├── CustomerProfile
├── CustomerAddress
└── Order
    └── Restaurant
        └── Franchisee определяется через цепочку владения рестораном

CustomerAccount не содержит franchiseeId и напрямую с Franchisee не связан. Первый заказ в ресторане другого франчайзи не создаёт новую учётную запись покупателя.

Граница модуля customer

Будущий модуль customer отвечает за покупательский контур:

  • единую учётную запись покупателя сети;
  • вход покупателя, первоначально по подтверждённому телефону и одноразовому коду;
  • покупательский профиль;
  • сохранённые адреса;
  • покупательские сессии и CustomerPrincipal.

Заказы и программа лояльности должны принадлежать отдельным предметным модулям. Они ссылаются на customerId, но не переносят покупателя в область конкретного ФЧ.

customer не обслуживает сотрудников ГК и ФЧ. Их учётными записями, членствами и доступом владеет iam.

Разделение покупателей и сотрудников

customer ── покупатели витрины, телефон и одноразовый код
iam      ── сотрудники ГК и ФЧ, email, пароль, приглашения и RBAC

Контуры имеют разные таблицы, principals, сессии и токены:

data class CustomerPrincipal(
    val customerId: UUID,
)

Совпадение телефона или email не связывает и не объединяет CustomerAccount и iam.UserAccount. Один человек может независимо выступать покупателем и сотрудником.

HTTP-пространство и токен

Покупательские API версионируются общим префиксом всего публичного API, а не отдельным сегментом storefront — так решено в разделе 12.3 технической постановки входа, чтобы внутреннее имя модуля не становилось частью публичного контракта:

/api/v1/**   aud = panam-storefront

Покупательский access token содержит CustomerPrincipal и принимается только витриной. Токен с aud=panam-storefront не принимается /api/admin/** и /api/franchise/**; административные токены не принимаются покупательским API.

Формат токена, срок жизни, refresh-сессии и защита входа зафиксированы и частично реализованы — см. модуль customer.

Доступ к данным покупателя

Заказ принадлежит одновременно покупателю и конкретному ресторану. Франчайзи получает доступ не к покупателю всей сети, а только к данным, необходимым для исполнения заказов его ресторанов.

Правила изоляции:

  • сотрудник ФЧ видит только заказы ресторанов своего franchiseeId;
  • сотрудник ФЧ не может искать покупателей по всей сети;
  • сотрудник ФЧ не видит полную историю заказов покупателя в других ФЧ;
  • данные покупателя передаются в кабинет ФЧ только в минимальном объёме, необходимом для заказа;
  • расширенный доступ сотрудников ГК требует отдельного permission и обязательного аудита;
  • область доступа вычисляется сервером через ресторан, а не принимается из request body.

Деактивация ФЧ или ресторана исключает ресторан из витрины и запрещает новые заказы, но не деактивирует сетевой аккаунт покупателя и не удаляет его историю.

Будущая лояльность

По умолчанию бонусный баланс, промокоды и история участия в программе лояльности проектируются на уровне всей сети. Ограничения конкретным брендом, регионом, франчайзи или рестораном должны быть явными правилами программы, а не свойством CustomerAccount.

Минимальный первый этап

Каркас customer (таблицы, вход по коду, refresh-сессии, access JWT) и минимальный storefront (HTTP /api/v1/auth/*, публичный security-контур) созданы — см. модуль customer и модуль storefront. Профиль покупателя, адреса, устройства-список, impersonation и перенос legacy-токенов остаются следующими этапами.