> ## Documentation Index
> Fetch the complete documentation index at: https://docs.yume.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Лояльность и Wallet-дизайны

> Справочник уровней лояльности, оформление карт Apple Wallet и Google Wallet с автогенерацией уменьшенных вариантов изображений, проверки файлов и цветов, а также фоновый пересчёт уровня по сумме завершённых заказов.

Полный перечень полей — в [глоссарии](/ru/logic/user/loyalty-glossary).

Эта страница описывает подобласть, которая физически расположена в модуле «Аутентификация и пользователи», но по смыслу относится к клиентской программе лояльности: справочник уровней лояльности, оформление карт для Apple Wallet и Google Wallet (с автоматической подготовкой уменьшенных вариантов изображений), набор проверок загружаемых файлов и цветов, а также фоновый пересчёт уровня лояльности по сумме завершённых заказов.

<Info>
  Сами уровни лояльности (название, процент кэшбэка, порог суммы, лимит начисления), правило выдачи самого дешёвого уровня новому пользователю, привязка уровня к аккаунту пользователя, а также назначение карт Apple/Google Wallet уже подробно разобраны на отдельной странице. Здесь эти вещи упоминаются кратко, а раскрываются новые детали: автогенерация вариантов изображений и правила проверки файлов и цветов.

  Подробнее: [«Программа лояльности»](/ru/logic/clients-loyalty/loyalty-program).
</Info>

## Почему это живёт в модуле пользователей

«Уровень лояльности» и оба оформления карт (для Apple Wallet и Google Wallet) физически описаны рядом с моделью пользователя, в общих (глобальных) таблицах, не привязанных к компании. Причина в том, что ссылка на уровень лояльности хранится прямо в аккаунте пользователя, а фоновая задача пересчёта проходит по всем пользователям. Концептуально же это часть клиентской программы лояльности, поэтому смысловые детали (уровни, проценты, лимиты, назначение карт) описаны на странице «Программа лояльности», а на этой странице — только техническая механика, которой там нет.

## Модель данных

### Уровень лояльности

Уровень лояльности задаёт процент начисления и набор лимитов, действующих начиная с определённого порога суммы завершённых заказов.

| Поле              | Тип              | Назначение                                                     |
| ----------------- | ---------------- | -------------------------------------------------------------- |
| Название          | текст            | Необязательное человекочитаемое имя уровня                     |
| Процент           | число            | Процент начисления/кэшбэка (по умолчанию 3)                    |
| Порог (цена)      | число (2 знака)  | Сумма завершённых заказов, начиная с которой действует уровень |
| Лимит начисления  | число (2 знака)  | Максимальная сумма начисления (по умолчанию 200 000)           |
| Лимит по времени  | интервал времени | Ограничение по длительности события (по умолчанию 3 дня)       |
| Лимит на доставку | число (2 знака)  | Максимальная сумма по доставке (по умолчанию 15 000)           |

Порог активации задаётся полем «Порог (цена)»: именно по нему фоновая задача выбирает подходящий уровень для пользователя (см. раздел ниже).

### Дизайн карты Apple Wallet

Оформление карты для Apple Wallet связано с уровнем лояльности отношением один-к-одному — на каждый уровень приходится не более одной записи такого дизайна. Запись хранит цвета, тексты и изображения карты.

| Поле                    | Тип         | Назначение                                             |
| ----------------------- | ----------- | ------------------------------------------------------ |
| Уровень лояльности      | связь       | Один-к-одному с уровнем лояльности                     |
| Цвет фона               | текст (hex) | Фон карты в формате #RRGGBB (по умолчанию тёмно-синий) |
| Цвет текста             | текст (hex) | Основной цвет текста (по умолчанию белый)              |
| Цвет подписей           | текст (hex) | Цвет подписей/меток (по умолчанию светло-серый)        |
| Цвет полосы             | текст (hex) | Цвет верхней полосы, необязательный                    |
| Текст рядом с логотипом | текст       | Подпись возле логотипа                                 |
| Убрать блик на полосе   | флаг        | Отключает эффект блика на полосе                       |
| Описание                | текст       | Текстовое описание карты                               |
| Логотип (@3x)           | изображение | Исходный логотип                                       |
| Иконка (@3x)            | изображение | Исходная квадратная иконка                             |
| Полоса (@3x)            | изображение | Исходная верхняя полоса, необязательная                |

Кроме трёх исходных изображений (в разрешении @3x) в записи хранятся автоматически создаваемые уменьшенные варианты @2x и @1x для логотипа, иконки и полосы. Эти варианты недоступны для ручного редактирования — они пересобираются системой из исходников.

### Дизайн карты Google Wallet

Оформление карты для Google Wallet тоже связано с уровнем лояльности один-к-одному и хранит цвет, названия, уровни вознаграждений, изображения и дополнительные текстовые блоки.

| Поле                               | Тип         | Назначение                                             |
| ---------------------------------- | ----------- | ------------------------------------------------------ |
| Уровень лояльности                 | связь       | Один-к-одному с уровнем лояльности                     |
| Цвет фона                          | текст (hex) | Фон карты в формате #RRGGBB (по умолчанию тёмно-синий) |
| Название программы                 | текст       | Название программы лояльности                          |
| Уровень вознаграждения             | текст       | Значение уровня вознаграждения                         |
| Подпись уровня вознаграждения      | текст       | Подпись к уровню вознаграждения                        |
| Доп. уровень вознаграждения        | текст       | Вторичное значение уровня вознаграждения               |
| Подпись доп. уровня вознаграждения | текст       | Подпись к вторичному уровню                            |
| Подпись ID аккаунта                | текст       | Подпись к идентификатору аккаунта                      |
| Подпись имени аккаунта             | текст       | Подпись к имени аккаунта                               |
| Логотип программы                  | изображение | Логотип программы                                      |
| Баннер                             | изображение | Широкое изображение-баннер, необязательное             |
| Текстовые модули                   | список      | Дополнительные текстовые блоки                         |
| Модуль ссылок                      | структура   | Ссылки, отображаемые на карте                          |

<Note>
  В отличие от карты Apple Wallet, оформление для Google Wallet не создаёт автоматически уменьшенных вариантов изображений — Google принимает исходные изображения и масштабирует их на своей стороне. Поэтому здесь хранятся только исходный логотип и баннер.
</Note>

## Проверки загружаемых данных

Перед сохранением цвета и изображения проходят набор проверок. Они одинаково применяются и в админке, и при программном сохранении.

### Проверка цветов

* Обязательные цвета проверяются на строгий формат `#RRGGBB` (решётка и ровно шесть шестнадцатеричных символов). Значение вне этого формата отклоняется.
* Необязательные цвета (например, цвет верхней полосы на карте Apple Wallet) допускают пустое значение; если значение задано — оно проверяется по тому же формату.

### Проверка файлов изображений

* **Расширение.** Принимаются только файлы PNG или JPEG; файлы других форматов отклоняются.
* **Минимальный размер.** Каждое исходное изображение проверяется на минимальные размеры в пикселях, соответствующие эталонному разрешению @3x. Если ширина или высота меньше требуемой, файл отклоняется с сообщением, в котором указаны требуемый и фактический размеры.

Минимальные размеры исходных изображений:

| Изображение                     | Минимальный размер |
| ------------------------------- | ------------------ |
| Логотип карты Apple Wallet      | 160 × 50 px        |
| Иконка карты Apple Wallet       | 87 × 87 px         |
| Полоса карты Apple Wallet       | 1125 × 432 px      |
| Логотип программы Google Wallet | 660 × 660 px       |
| Баннер Google Wallet            | 1032 × 336 px      |

<Tip>
  Размеры при проверке читаются так, чтобы не сбить позицию в файле: указатель чтения возвращается на исходное место, а само изображение открывается из отдельной копии в памяти. Это позволяет затем сохранить и обработать тот же файл без повторной загрузки.
</Tip>

## Автогенерация вариантов изображений Apple Wallet

Apple Wallet ожидает изображения в трёх плотностях (@3x, @2x, @1x). Пользователь загружает только исходное изображение @3x, а варианты @2x и @1x система готовит сама при сохранении оформления карты.

### Когда варианты пересобираются

При каждом сохранении оформления система сначала определяет, какие из трёх исходных изображений (логотип, иконка, полоса) изменились с момента последнего чтения из базы:

* Для новой записи изменившимися считаются все непустые исходные изображения.
* Для существующей записи текущие значения сравниваются с тем, что сейчас хранится в базе; в набор изменившихся попадают только реально заменённые или очищенные изображения.

Варианты пересобираются только для изменившихся исходников — неизменные изображения не трогаются, лишняя обработка не выполняется.

### Что происходит с каждым изменившимся изображением

* **Если исходник заменён** — старые варианты @2x и @1x удаляются, из нового исходника генерируются свежие варианты и сохраняются.
* **Если исходник очищен** (загруженное ранее изображение убрали) — оба варианта тоже удаляются и обнуляются.

Целевые размеры вариантов:

| Изображение | Способ                             | Вариант @2x     | Вариант @1x     |
| ----------- | ---------------------------------- | --------------- | --------------- |
| Иконка      | квадрат по центру                  | 58 × 58 px      | 29 × 29 px      |
| Логотип     | вписывание с сохранением пропорций | до 320 × 100 px | до 160 × 50 px  |
| Полоса      | вписывание с сохранением пропорций | до 750 × 288 px | до 375 × 144 px |

* **Квадратный вариант** (для иконки): изображение уменьшается с сохранением пропорций и вписывается по центру в прозрачный квадрат заданного размера. Итог — всегда квадратная картинка нужной стороны, даже если исходник был не строго квадратным.
* **Вариант с сохранением пропорций** (для логотипа и полосы): изображение уменьшается так, чтобы уместиться в заданные габариты, пропорции сохраняются, лишнего поля не добавляется.

<Note>
  Все сгенерированные варианты сохраняются в формате PNG с прозрачностью, независимо от формата исходного файла. То есть даже если загрузить логотип в JPEG, варианты @2x/@1x будут PNG. Имя файла варианта — случайное.
</Note>

### Порядок сохранения

Сохранение оформления Apple Wallet выполняется в два прохода: сначала запись сохраняется целиком (чтобы у неё был идентификатор и исходные изображения были записаны), затем при необходимости отдельно дозаписываются только поля вариантов. Второй проход выполняется лишь тогда, когда варианты действительно пересобирались.

## Фоновый пересчёт уровня лояльности

Уровень лояльности пользователя пересчитывается фоновой задачей на основе суммы его завершённых заказов.

### Как считается уровень

1. Для каждого пользователя суммируются суммы (со скидкой) по его заказам в статусе «Завершён». Заказы связываются с пользователем через привязанного к заказу клиента.
2. По полученной сумме подбирается подходящий уровень лояльности — берётся уровень с наибольшим порогом, который не превышает эту сумму (то есть самый «высокий» из доступных пользователю).
3. Обновляются только те пользователи, у которых подобранный уровень отличается от текущего. Строки без изменений не переписываются. При этом, если для пользователя подходящий уровень подобрать не удалось (пустое значение), его строка не обновляется вовсе — текущий уровень сохраняется.

Вся операция выполняется одной пакетной командой в базе внутри транзакции — задача не загружает объекты пользователей в память по одному.

<Warning>
  Пересчёт учитывает только заказы в статусе «Завершён». Незавершённые заказы в сумму не входят, поэтому уровень пользователя отражает лишь фактически закрытые сделки.
</Warning>

## Как это используется

* При создании нового пользователя ему сразу присваивается самый дешёвый (с наименьшим порогом) уровень лояльности — стартовый уровень программы.
* По мере накопления завершённых заказов фоновый пересчёт поднимает пользователя на более высокий уровень, как только сумма достигает соответствующего порога.
* Оформление карт (цвета, тексты, изображения) задаётся отдельно для каждого уровня и используется при генерации карт Apple Wallet и Google Wallet. Подробнее о самих картах — на странице [«Программа лояльности»](/ru/logic/clients-loyalty/loyalty-program).

## Связанные страницы

<CardGroup cols={2}>
  <Card title="Глоссарий: Лояльность и Wallet-дизайны" icon="book" href="/ru/logic/user/loyalty-glossary">
    Полный перечень полей уровня лояльности и обоих оформлений карт.
  </Card>

  <Card title="Пользователи и доступ" icon="user-lock" href="/ru/logic/user">
    Обзорная страница раздела: аккаунт, участие в компании, роли и права.
  </Card>

  <Card title="Проблемы и логические ошибки" icon="bug" href="/ru/logic/user/issues">
    Сводный разбор известных багов и логических нюансов всего модуля.
  </Card>

  <Card title="Аккаунт и участие в компании" icon="user" href="/ru/logic/user/model">
    Как аккаунт связан с телефоном, как устроено участие в компаниях и откуда берутся роли.
  </Card>

  <Card title="Вход в систему" icon="right-to-bracket" href="/ru/logic/user/login">
    По каким данным можно войти — телефон, логин или адрес почты — и откуда берутся права.
  </Card>

  <Card title="Сессии и срок действия входа" icon="key" href="/ru/logic/user/sessions">
    Сколько живёт вход, как он продлевается и когда потребуется войти заново.
  </Card>

  <Card title="Как система определяет вашу компанию" icon="route" href="/ru/logic/user/active-company">
    Определение компании по адресу сайта или по аккаунту и что делать, если компании ещё нет.
  </Card>

  <Card title="Профиль и управление сотрудниками" icon="id-card" href="/ru/logic/user/profile">
    Редактирование своего профиля, добавление сотрудников и назначение им ролей.
  </Card>

  <Card title="Сброс пароля по коду" icon="unlock-keyhole" href="/ru/logic/user/password-reset">
    Восстановление доступа по коду из письма, с ограничением частоты запросов.
  </Card>

  <Card title="Вход через Google" icon="google" href="/ru/logic/user/google-login">
    Вход по аккаунту Google и связывание его с существующим профилем.
  </Card>
</CardGroup>
