Customer Service

Ответственность

CRM-сервис: управление клиентами (end-users сети, не сотрудниками), их адресами доставки, группами клиентов (статические и динамические с правилами автозаполнения) и привязкой к заказам.

Вынесен из User Service в отдельный микросервис (BR 3.1, см. Roadmap — Скидки и лояльность) так как:

  • Customer — внешний user со своим жизненным циклом (регистрируется кассиром / через сайт / через мобильное приложение), отдельным от сотрудников
  • Write-heavy нагрузка: каждый заказ потенциально создаёт запись / обновляет customer.last_visit
  • Customer BFF (:3021 — сайт и мобильное приложение клиентов) независимо от Admin BFF потребляет этот сервис
  • Будущий Loyalty Service (:3007) активно читает и пишет связанные сущности (баллы, транзакции) — отдельный микросервис с чистыми event-контрактами упрощает интеграцию

Ключевые функции

Клиенты (BR 3.1)

  • CRUD клиентов с soft delete + анонимизацией PII по ФЗ-152
  • Поиск по нормализованному телефону (E.164) — основной ключ
  • Фильтры по источнику регистрации, группе, диапазону даты регистрации
  • Быстрое создание клиента на POS — минимальная форма (phone + имя) + автоматическое прикрепление к заказу
  • Merge дубликатов (API-only в MVP) — объединение двух клиентов в одного с переносом адресов и истории
  • Ролевой доступ:
    • Владелец франшизы / партнёра с customers.read / customers.edit — полный CRUD в админке
    • Кассир с customers.create_quick — поиск по phone + quick-create + прикрепление к заказу на POS (без доступа к списку в админке)

Адреса клиентов (BR 3.1)

  • CRUD адресов (один клиент — N адресов: дом / работа / …)
  • Ровно один default на клиента (переключение в одной транзакции)
  • Ссылка на delivery_zones Store Service — логическая, без синхронной валидации в MVP

Группы клиентов (BR 3.1)

  • CRUD групп двух типов:
    • Статические — админ добавляет/удаляет клиентов вручную
    • Динамические — членство рассчитывается по правилам (JSONB rules_json)
  • Каталог правил автозаполнения (MVP): total_spent_all_time, total_spent_period, days_inactive, birthday_window, city, delivery_zone, gender, registration_source, include_groups, exclude_groups. До 5 правил на группу, логика AND.
  • Пересчёт динамических групп:
    • Scheduler раз в сутки (03:00 МСК) — полный пересчёт всех dynamic групп всех франшиз. Fallback на случай пропущенных событий
    • Триггерно через Kafka consumer order.completed и customer.updated — точечный пересчёт для одного клиента
    • Ручной через POST /customer-groups/{id}/recompute
  • Ролевой доступ: CRUD групп — только Владелец франшизы (customer_groups.edit)

Kafka producer/consumer

  • Публикует: customer.created, customer.updated, customer.deleted, customer-group.member-changed (для будущих Loyalty / Notification Service)
  • Потребляет: order.completed (Order Service) — для точечного пересчёта dynamic групп

Авторизация

JWT валидируется локально (HS256 + shared JWT_SECRET). Паттерн как в User Service / Store Service / Warehouse Service.

  • Public API — Bearer JWT сотрудника (scope франшизы вычисляется в Auth Service / User Service; Customer Service использует franchise_id из JWT + проверку permissions)
  • Internal APIX-Service-Token (один на все internal-вызовы между нашими сервисами, не меняется per-user)

Клиентская авторизация (регистрация end-user’а через мобильное приложение / сайт через OTP по SMS) — out of scope BR 3.1. Появится в BR 3.5 (Customer auth). Пока Customer Service только хранит клиента; сам клиент в систему не логинится.

Зависимости

  • PostgreSQL (customer_db) — основное хранилище (отдельная БД, не разделяется с user_db)
  • Kafka — producer (customer.* events) + consumer (order.completed)
  • Внешние сервисы — НЕТ синхронных вызовов в MVP:
    • Валидация delivery_zone_id в правилах dynamic групп — без cross-service check. Если zone удалена в Store Service, правило перестанет попадать ни в одного клиента (не критично; можно добавить internal check в отдельной BR)
    • Валидация registered_by_employee_id — без cross-service check (логическая ссылка, при удалении сотрудника значение остаётся, исторически корректно)
    • Валидация customer_id при order.completed — если customer не существует, событие логируется и игнорируется

Конфигурация

VariableDescriptionDefault
DATABASE_URLPostgreSQL connection string
SERVICE_TOKENТокен для internal API
JWT_SECRETКлюч для локальной валидации JWT (HS256)
KAFKA_BOOTSTRAP_SERVERSKafka brokers
CUSTOMER_GROUPS_RECOMPUTE_CRONРасписание полного пересчёта dynamic групп0 0 3 * * *
PORTHTTP порт3013

Ссылки