Каталог клиентов¶
Каталог клиентов — стартовый экран раздела «Клиенты». Это таблица всех участников программы лояльности с серверным поиском, фильтрами и сортировкой. Отсюда оператор открывает карточку клиента, создаёт клиента, выполняет действия над одним клиентом или над выделением (блокировка, архив, удаление, теги, операции с баллами) и открывает мастер импорта.
Все параметры выборки — поиск, фильтры, сортировка, тумблер архива, страница — уходят на сервер
одним запросом GET /v1/customers. Фильтрация идёт по всей базе, а не по загруженной странице.
Панель инструментов¶
| Элемент | Назначение |
|---|---|
| Поле «Поиск: ФИО, ID, email, телефон» | Свободный поиск (см. Поиск) |
| Переключатель «Показать архивные» | Показать всю базу вместе с архивными клиентами (см. Архив) |
| Иконка ⚙ «Настроить таблицу» | Состав и порядок колонок (см. Настройка колонок) |
| Иконка «Импорт клиентов из файла» | Мастер импорта CSV (см. Импорт клиентов) |
| Иконка «Экспорт списка клиентов» | Зарезервировано: выгрузка списка пока не реализована, кнопка ничего не делает |
| Кнопка «Добавить» | Модалка «Новый клиент» (роль LOYALTY_CUSTOMER_WRITE) |
Состояние таблицы — поиск, фильтры, сортировка, тумблер архива, ширины и настройка колонок — запоминается в браузере пользователя и восстанавливается при следующем входе.
Колонки¶
| Колонка | Содержимое | Сортировка | Фильтр |
|---|---|---|---|
| ID | Внешний идентификатор клиента (externalId); обязательная, скрыть нельзя |
— | — |
| ФИО | Фамилия, имя, отчество. Если ФИО в профиле нет — выводится ID | ✓ (по фамилии) | — |
| Телефон | Телефон из профиля | — | — |
| Email из профиля | — | — | |
| Уровень | Последний посчитанный уровень клиента (см. Фильтры) | — | ✓ список уровней |
| Баланс | Баланс баллов | — | — |
| Статус | «Активен» / «Заблокирован» | — | ✓ |
| Архив | Пилюля «В архиве» у архивных клиентов | — | — |
| Тест | Пилюля «Тест» у тестовых клиентов | — | — |
| Теги | Теги клиента из справочника тегов, по алфавиту | — | ✓ по справочнику |
| Дата регистрации | Дата регистрации из профиля; если её нет — дата заведения клиента в реестре | ✓ | ✓ период |
| Сегменты | Сегменты клиента из системы кампаний — названиями из справочника «Сегменты клиентов»; сегмент без записи в справочнике — кодом. Скрыта по умолчанию | — | — |
| Город | Город из профиля — скрыта по умолчанию | — | — |
| Последняя активность | Дата последней бонусной операции — скрыта по умолчанию | — | — |
Пустое значение отображается прочерком. Длинный текст обрезается до двух строк, полный — во всплывающей подсказке.
Настройка колонок¶
Иконка ⚙ открывает панель «Настройка таблицы»: переключатели видимости и перетаскивание для смены порядка. Изменения применяются по кнопке «Сохранить». Колонку ID скрыть и переместить нельзя.
Поиск¶
Поиск — подстрока без учёта регистра одновременно по:
- ФИО, склеенному в одну строку («Иванов Иван» находит клиента с фамилией Иванов и именем Иван);
- внешнему идентификатору;
- email;
- телефону — в том числе по одним цифрам: ввод
9161234567находит+7 916 123-45-67. Поиск «по цифрам» включается, если во вводе не меньше трёх цифр.
Символы % и _ ищутся буквально, а не как шаблоны.
Фильтры¶
| Фильтр | Правило |
|---|---|
| Статус | Один или оба статуса: «Активен», «Заблокирован» |
| Уровень | Один или несколько уровней активной конфигурации программы. Сравнивается код последнего посчитанного уровня клиента — того, что записан у клиента (ручное назначение в нём уже учтено); если записи нет — базовый уровень активной конфигурации |
| Теги | Значения из справочника тегов с серверным поиском. В интерфейсе — «есть хотя бы один из выбранных тегов». Фильтр доступен при роли LOYALTY_TAG_READ или LOYALTY_CUSTOMER_TAG_WRITE |
| Дата регистрации | Период «с — по», обе границы включительно (с начала первого дня до конца последнего) |
Значения внутри одного фильтра соединяются по «ИЛИ», разные фильтры и поиск — по «И».
Уровень после смены конфигурации программы
После активации новой конфигурации клиент живёт по прежней до первой операции или пересмотра, и каталог показывает его последний посчитанный уровень — в том числе уровень прежней конфигурации. Варианты фильтра — уровни активной конфигурации, сравнение идёт по коду уровня: уровень прежней конфигурации с кодом, которого в активной нет, виден в колонке, но фильтром не выбирается. Поэтому сразу после активации число клиентов уровня в каталоге может отличаться от отчёта по уровням, где клиенты прежних конфигураций выводятся отдельно.
Фильтр по тегам в API
В API фильтр задаётся параметром tag (список значений, регистр не важен) и связкой
tagMatch: ANY (по умолчанию) — есть хотя бы один тег, ALL — есть все. Переключателя
«И/ИЛИ» в интерфейсе каталога нет.
Сортировка¶
- По умолчанию — «Дата регистрации», новые сверху.
- Сортировать можно по ФИО (по фамилии) и «Дате регистрации», в том числе по обеим сразу.
- Клиенты без даты регистрации или без ФИО всегда идут в конце списка — при любом направлении.
- При равенстве значений порядок стабилен (дополнительно по ID), поэтому страницы не «перемешиваются».
- Сортировки по балансу и тегам нет.
API дополнительно принимает сортировку по createdAt (дата заведения в реестре), externalId,
status, lastActivity. Неизвестное поле сортировки игнорируется; без сортировки сервер
отдаёт клиентов по дате заведения, новые первыми.
Архивные клиенты¶
Архив — обратимое скрытие клиента из основного каталога. Он не меняет статус: архивный клиент может быть и активным, и заблокированным, у него сохраняются баланс и история.
- Тумблер выключен — в каталоге только неархивные клиенты.
- Тумблер «Показать архивные» включён — выводится вся база: сначала блок «Архивные», затем блок «Остальные»; внутри блоков действует выбранная сортировка.
Удалённые клиенты (статус DELETED) в каталоге не показываются никогда. Клиенты, слитые в другого
(статус MERGED), в каталоге остаются видны — их можно найти и отфильтровать по этому статусу.
Работа со строками и выделение¶
| Действие мышью | Результат |
|---|---|
| Один клик по строке | Выделить / снять выделение |
| Двойной клик | Открыть карточку клиента |
| Правый клик | Контекстное меню строки |
Выделение накапливается между страницами и сохраняется при смене поиска, фильтров и сортировки. При выделении снизу появляется панель действий: «Выбрано: N», кнопки действий и «Снять выделение».
Контекстное меню строки начинается с пункта «Открыть карточку», далее — те же действия, что на панели. Если строка входит в выделение, действие из меню применяется ко всему выделению.
Массовые действия¶
Действие показывается, только если у пользователя есть нужная роль и оно применимо ко всем выбранным клиентам.
| Действие | Когда доступно | Роль | Что делает |
|---|---|---|---|
| Начислить | Всегда | LOYALTY_ACCRUAL_WRITE |
Форма ручного начисления на всех выбранных — см. Ручные операции |
| Корректировка | Всегда | LOYALTY_REDEMPTION_WRITE |
Форма корректировки баллов — см. Ручные операции |
| Перевод уровня | Всегда | LOYALTY_TIER_WRITE |
Назначение уровня выбранным — см. Уровни |
| Заблокировать | Все выбранные активны | LOYALTY_CUSTOMER_WRITE |
Статус → BLOCKED |
| Разблокировать | Все выбранные заблокированы | LOYALTY_CUSTOMER_WRITE |
Статус → ACTIVE |
| Архивировать | Никто из выбранных не в архиве | LOYALTY_CUSTOMER_WRITE |
Скрыть из основного каталога |
| Разархивировать | Все выбранные в архиве | LOYALTY_CUSTOMER_WRITE |
Вернуть в основной каталог |
| Добавить теги | Всегда | LOYALTY_CUSTOMER_TAG_WRITE |
Присвоить теги — см. Теги клиента |
| Снять теги | Всегда | LOYALTY_CUSTOMER_TAG_WRITE |
Снять теги — см. Теги клиента |
| Удалить | Всегда | LOYALTY_CUSTOMER_WRITE |
Обезличить ПДн и скрыть клиента (необратимо) |
Смесь статусов в выделении скрывает «Заблокировать» и «Разблокировать»; смесь архивных и неархивных — «Архивировать» и «Разархивировать».
Подтверждение¶
Блокировка, разблокировка, архивирование, разархивирование и удаление подтверждаются модалкой со списком выбранных клиентов («ID — ФИО» и пилюли статуса/архива). Любого клиента можно снять галочкой — счётчик показывает, например, «Будет заблокировано: 5, пропущено: 1». Кнопка подтверждения — «Да, заблокировать», «Да, заархивировать» и т. п.
Удаление необратимо
У «Удалить» кнопка «Да, удалить» красная и помечена «Действие необратимо»:
«Персональные данные будут обезличены, клиент скрыт из каталога. История операций сохранится.»
Удаление = затирание всех полей ПДн профиля (телефон, email, ФИО, город, дата рождения),
вывод клиента из всех сегментов и перевод в статус DELETED одной транзакцией на клиента.
Счета, проводки и история операций остаются, смена статуса записывается в историю статуса.
Подробнее — Карточка клиента.
Результат¶
Каждый клиент обрабатывается отдельно, без общей транзакции: отказ по одному клиенту не откатывает уже обработанных.
- Всё выполнено — тост «Заблокировано клиентов: N», «Удалено клиентов: N» и т. п.
- Часть не выполнена — отчёт «Выполнено: N из M» с таблицей «Клиент — Причина» и пометкой «Успешно обработанные клиенты остаются обработанными — изменения не откатываются.» Клиенты, по которым был отказ, остаются выделенными.
- Запрос отклонён целиком (ошибка 4xx, например превышен размер пакета) — «Операция не выполнена. Ни один клиент не изменён.»
- Сбой сервера или сети — «Операция прервана. Часть клиентов могла быть обработана — обновите список и проверьте перед повторным запуском.»
Типовые причины отказа по клиенту: «Клиент не найден» (customer_not_found — клиента нет или он
уже удалён).
Размер пакета
Блокировка, разблокировка, архив и удаление принимают до 1000 различных клиентов за раз
(настройка loyalty.manual-operations.bulk-max-ids, общая с пакетами операций с баллами).
Больше — 400 bulk_size_exceeded, ни один клиент не изменён. Присвоение и снятие тегов —
до 10 000 клиентов (loyalty.tags.max-bulk-targets).
Создание клиента¶
Кнопка «Добавить» открывает модалку «Новый клиент». Секции формы:
| Секция | Поля и правила |
|---|---|
| Тип клиента | Флажок «Тестовый клиент»: бейдж «Тест», исключение из отчётов и рассылок; контакт для тестового клиента не обязателен |
| Идентификатор | «ID клиента» — обязательно, уникально в базе лояльности; формат не проверяется. «Реферальный код» — необязательный код пригласившего клиента (8 символов, приводится к верхнему регистру; неверный код молча игнорируется) |
| Личные данные | «Фамилия»*, «Имя»*, «Отчество» |
| Контакты | «Телефон» — 10 цифр номера, код страны +7 подставлен; «Email» — латиница, цифры и @ . _ - +, ровно один @ и домен. Для обычного клиента нужен хотя бы один контакт |
| Теги | Видна при роли LOYALTY_CUSTOMER_TAG_WRITE; выбор из справочника, см. Теги клиента |
| Согласия | «Участие в программе лояльности», «Обработка персональных данных» — отмечены по умолчанию |
Секции выбора бонусных счетов в форме нет: при создании клиенту автоматически открываются счета во всех включённых валютах — балльных и денежных, см. Баланс и операции.
Ошибки обязательных полей показываются после ухода из поля или по нажатию «Создать»; кириллица и пробел в email подсвечиваются сразу. Если ID занят, под полем — «Клиент с таким ID клиента уже существует» и ссылка «Открыть карточку» (в новой вкладке). Закрыть заполненную форму можно только через подтверждение «Закрыть без сохранения?».
После успеха — тост «Клиент {ID} создан.» со ссылкой «Открыть карточку».
Что сейчас сохраняется при создании из формы
Сервер создания клиента принимает: ID, признак тестового клиента, реферальный код и теги. ФИО, телефон, email и согласия, введённые в модалке, при создании не сохраняются — контракт создания их пока не принимает. После создания заполните профиль в карточке клиента кнопкой «Редактировать». До этого в каталоге вместо ФИО отображается ID клиента.
Создание по API¶
POST /v1/customers (роль LOYALTY_CUSTOMER_WRITE; при непустых тегах — ещё
LOYALTY_CUSTOMER_TAG_WRITE, иначе 403).
| Поле | Тип | Описание |
|---|---|---|
externalId |
строка, обязательно | Внешний идентификатор |
preCreateAccounts |
массив кодов валют | Устарело: принимается и игнорируется — счета открываются во всех включённых валютах |
test |
boolean | Тестовый клиент |
referralCode |
строка | Код пригласившего клиента; неверный/архивный/собственный код игнорируется |
tagIds |
массив id | Существующие теги справочника |
tags |
массив строк | Теги значениями; недостающие заводятся только при LOYALTY_TAG_WRITE |
Ответ 201 Created, заголовок Location: /v1/customers/{externalId}, тело
{externalId, referralCode} — referralCode здесь собственный код нового клиента. Создание
атомарно: при отказе по тегам не создаются ни клиент, ни теги. Ошибки: 409
customer_already_exists, 422 unknown_tag, 422 tag_value_invalid.
Импорт клиентов¶
Иконка «Импорт клиентов из файла» открывает мастер «Импорт клиентов» из четырёх шагов: «Файл» → «Предпросмотр» → «Проверка» → «Результат».
Требования к файлу¶
- Формат — CSV, кодировка UTF-8, разделитель колонок — точка с запятой.
- Первая строка — заголовки техническими именами; порядок колонок произвольный, лишние игнорируются.
- Кнопки «Скачать пример файла» / «Посмотреть пример файла» дают образец
Пример_импорта_клиентов.csv.
| Колонка | Обязательность | Содержимое |
|---|---|---|
external_id |
Обязательна | ID клиента; уникален и в базе, и внутри файла |
last_name |
Обязательна | Фамилия |
first_name |
Обязательна | Имя |
middle_name |
Необязательна | Отчество |
phone |
Контакт | Телефон |
email |
Контакт | |
tags |
Необязательна | Теги из справочника через запятую внутри ячейки, например vip,жалоба-2026 |
Контакт — хотя бы одна из колонок phone или email должна быть в файле и заполнена (в строгом
режиме).
Шаги мастера¶
- Файл. Выбор CSV перетаскиванием или кликом и параметры проверки:
- «Проверять дополнительные поля (ФИО, наличие и формат контактов)» — строгий режим, включён по умолчанию. ID клиента проверяется всегда; без галочки остальные поля принимаются «как есть».
- «Если ID клиента повторяется внутри файла»: «Пропустить все повторы» (по умолчанию) или «Оставить первую строку».
Браузер сразу проверяет файл: не CSV, битая кодировка, пустой файл, только заголовки, нет
обязательных колонок, нет ни phone, ни email.
2. Предпросмотр. «Распознано строк: N» и первые строки файла — убедиться, что колонки
определены верно. Кнопка «Проверить файл».
3. Проверка и 4. Результат.
Ограничение текущей версии интерфейса
Серверная проверка и загрузка в мастере ещё не подключены: на шаге «Проверка» выводится
уведомление, клиенты не создаются. Сама проверка и загрузка уже работают через API —
POST /v1/customers/import/validate и POST /v1/customers/import (см. ниже).
Закрыть мастер с выбранным файлом можно только через подтверждение «Закрыть без сохранения?».
Проверка и загрузка по API¶
Оба запроса — multipart/form-data с полем file, роль LOYALTY_CUSTOMER_WRITE; при
заполненной колонке tags дополнительно LOYALTY_CUSTOMER_TAG_WRITE (без неё — 403 на весь
файл). Проверка и загрузка идут по одному конвейеру: проверка показывает ровно тот результат,
который даст загрузка с теми же параметрами.
| Параметр | Значения | По умолчанию |
|---|---|---|
checkExtraFields |
true — строгий режим (ФИО, наличие и формат контактов); false — только ID и длина полей |
true |
duplicates |
SKIP_ALL — пропустить все строки группы повторов; KEEP_FIRST — загрузить первую |
SKIP_ALL |
mode (только загрузка, обязателен) |
SKIP_INVALID — создать корректные строки, проблемные пропустить; ALL_OR_NOTHING — при любой проблеме не создавать никого |
— |
Проверка (/import/validate) ничего не пишет и отвечает
{total, ready, duplicates, invalid, problems[], newTags[]}.
Загрузка (/import) отвечает {created, skippedDuplicates, skippedInvalid, problems[]}.
В режиме ALL_OR_NOTHING весь файл, включая заведение новых тегов, — одна транзакция; в
SKIP_INVALID каждая строка — своя транзакция, и сбой записи строки (import_row_failed) не
мешает остальным.
Элемент problems[]: {row, externalId, type: duplicate|invalid, code, detail}. Отчёт
ограничен 200 строками (loyalty.import.max-problems), счётчики — полные.
| Код проблемы строки | Тип | Когда |
|---|---|---|
import_external_id_required |
invalid | Не заполнен external_id |
import_field_too_long |
invalid | Значение длиннее 512 символов (loyalty.import.max-field-length) |
import_name_required |
invalid | Строгий режим: нет фамилии или имени |
import_contact_required |
invalid | Строгий режим: нет ни телефона, ни email |
invalid_phone / invalid_email |
invalid | Строгий режим: неверный формат контакта |
tag_value_invalid |
invalid | Значение тега не проходит правило значения |
unknown_tag |
invalid | Тега нет в справочнике, а у оператора нет LOYALTY_TAG_WRITE (в любом режиме проверки) |
customer_already_exists |
duplicate | Клиент с таким ID уже есть в базе |
import_duplicate_in_file |
duplicate | ID повторяется в файле |
Файл отклоняется целиком (ошибка запроса) с кодами: import_file_empty, import_no_rows,
import_missing_columns (в теле — список колонок), import_no_contact_column (строгий режим),
import_bad_encoding, import_file_binary (415), import_file_too_large (413),
import_too_many_rows, import_file_unreadable, import_file_infected (при включённой
антивирусной проверке).
Пределы импорта
Не более 10 000 строк данных (loyalty.import.max-rows; больше — отказ, а не усечение),
размер файла — до 20 МБ. Антивирусная проверка включается loyalty.import.scan.enabled.
Теги в импорте и перечень newTags описаны в разделе
Теги клиента.
Режим внешнего MDM¶
При loyalty.mdm.adapter=local (по умолчанию) каталог работает в полном объёме. При подключении
внешнего MDM профильные поля живут во внешней системе, и на сервере применяются только фильтры по
набору ID, архиву и тегам; поиск, статус, уровень, тестовый признак и период регистрации в этом
режиме не применяются, колонка «Последняя активность» не заполняется. Если MDM недоступен, список
отвечает 503 mdm_unavailable, а не страницей из одних идентификаторов.
REST API каталога¶
| Метод и путь | Роль | Назначение |
|---|---|---|
GET /v1/customers |
LOYALTY_CUSTOMER_READ |
Каталог: search, status, tier, registeredFrom, registeredTo, archived, test, tag, tagMatch, ids, externalId, page, size, sort |
POST /v1/customers |
LOYALTY_CUSTOMER_WRITE (+ LOYALTY_CUSTOMER_TAG_WRITE при тегах) |
Создать клиента |
POST /v1/customers/bulk-block, bulk-unblock |
LOYALTY_CUSTOMER_WRITE |
Заблокировать / разблокировать набор |
POST /v1/customers/bulk-archive, bulk-unarchive |
LOYALTY_CUSTOMER_WRITE |
Архивировать / разархивировать набор |
POST /v1/customers/bulk-delete |
LOYALTY_CUSTOMER_WRITE |
Обезличить и скрыть набор |
POST /v1/customers/bulk-tag-assign, bulk-tag-remove |
LOYALTY_CUSTOMER_TAG_WRITE |
Присвоить / снять теги |
POST /v1/customers/import/validate |
LOYALTY_CUSTOMER_WRITE |
Проверка файла импорта без записи |
POST /v1/customers/import |
LOYALTY_CUSTOMER_WRITE |
Импорт клиентов |
Тело статус-пакетов — {externalIds: [...]}, ответ 200 {succeeded[], errors[{externalId,
fullName, code, reason}]}. Параметры status и tier принимают несколько значений (через
запятую или повтором). Каждое обращение к каталогу фиксируется в журнале обращений к
персональным данным.
Изменение контракта (26.3.0)
Параметр фильтра по уровню — tier (список кодов). Прежний tierCode сервером не
применялся. archived=true возвращает всю базу с архивными первым блоком, а не только архивных.