discount/README.md
2024-03-20 19:57:35 +00:00

12 KiB
Raw Permalink Blame History

accruals-service

Микросервис для создания скидок и формирования цен из реализованных скидок

Branch Pipeline Code coverage
main pipeline status coverage report
staging pipeline status coverage report
dev pipeline status coverage report

Переменные окружения приложения

GRPC_HOST                   - хост прослушивания приложения (gRPC)
GPRC_PORT                   - порт прослушивания приложения (gRPC)
HTTP_PORT                   - порт прослушивания приложения (HTTP)

MONGO_HOST                  - хост базы данных
MONGO_PORT                  - порт базы данных
MONGO_USER                  - имя пользователя базы данных для авторизации
MONGO_PASSWORD              - пароль пользователя базы данных для авторизации
MONGO_AUTH                  - название базы данных для авторизации
MONGO_DATABASE_NAME         - название базы данных, к которой будет идти подключение

Пример переменных окружения:

GRPC_HOST=0.0.0.0
GPRC_PORT=9001
HTTP_PORT=8001

MONGO_HOST=localhost
MONGO_PORT=27017
MONGO_USER=test
MONGO_PASSWORD=test
MONGO_AUTH=admin

Команды для работы с приложением:

make help                   - вывести список доступных команд с описанием
make install                - устанавливает все необходимые зависимости и инструменты
make generate               - генерирует proto файлы gRPC сервиса
make test                   - запускает unit и интеграционные тесты
make test.unit              - запуск unit тестов
make test.integration       - запуск интеграционных тестов (поднятие и завершение окружения)
make test.integration.up    - поднятие тестового окружения
make test.integration.start - запуск интеграционных тестов
make test.integration.down  - завершение тестового окружения
make run                    - запуск приложения

Текущая логика рассчёта скидки

  • Получаем на вход состояние пользователя и список тарифов

Общая логика вычисления скидки это:

  • Подготовить данные для выбора скидок(Подготовка)
  • Найти все подходящие скидки(Фильтрация)
  • Выбор максимальных скидок(Макс)
  • Применение скидок(Применение)

В вычислении скидок есть 4 слоя применения, в каждом слое есть все перечисленные пункты

Слой 1: Подготовка - если у привилегии в тарифе есть ненулевой price, то берём его в качестве цены. если нет - умножаем стоимость привилегии на amount этой привилегии в рамках тарифа. создаём map с ключем - айдишником привилегии, значением - суммарным количеством всех amount привилегий с таким же айдишником. это надо потому что в корзине может быть много тарифов с одной и той же привилегией, но разным количеством оной, а скидка применяется к общему количеству этой привилегии в корзине

Фильтрация - если userType == nko - выбираем единственную скидку за nko. Иначе - выбираем все скидки у которых layer 1 и Term <= amount привилегии

Макс - если выбрана nko, то этот пункт пропускаем. Иначе - для каждой привилегии выбираем скидку с максимальным Term

Применение - умножаем стоимость каждой привилегии на Factor соответствующей скидки. если выбрана скидка nko, то суммируем все стоимости привилегий, умножаем на Factor скидки за nko и прерываем рассчёт скидки, ибо остальные слои в случае nko не принимаются

Слой 2:

Подготовка - суммируем список привилегий с их стоимостями после применения скидок первого слоя, формируя map с ключём - serviceKey, а значением - стоимостью всех привилегий по этому сервису

Фильтрация - выбираем скидки где layer == 2, group == ключ подготовленной map, PriceFrom <= значение подготовленной map

Mакс - оставляем скидки с максимальным PriceFrom в рамках group.

Применение - умножаем значение подготовленной map на Factor соответствущей скидки

Слой 3:

Подготовка - суммируем map подготовленную на прошлом слое, после применения всех скидок. Это размер корзины

Фильтрация - выбираем скидки где layer == 3, CartPurchasesAmount <= полученное значение после суммирования

Макс - выбираем скидку с максимальным значением CartPurchasesAmount

Применение - умножаем на Factor из найденной скидки

Слой 4:

Подготовка - никакой, всё сделано на прошлом слое

Фильтрация - выбираем скидки где layer == 4, purchasesAmount <= значение после применения скидки предыдущего слоя

Макс - выбираем скидку с максимальным значением purchasesAmount

Применения - умножаем на Factor выбранной скидки

Общая формула вычисления стоимости корзины: (F1-n - множитель скидки, A1-n - количество привилегии, P1-n - стоимость кокретной привилегии, S1-n - стоимость конкретного сервиса в рамках корзины)

Cart = (S1 * F1 + S2 * F2 + ... + Sn * Fn) * Fкорзина * Fлояльность

Si = A1 * P1 * F1 + A2 * P2 * F2 + ... + An * Pn * Fn

Новая логика рассчёта скидки

  • вычисляем количество привилегий во всей корзине - создаём map[Product]amount
  • вычисляем стоимость каждой привилегии в корзине - создаём map[Product]price
  • вычисляем стоимость каждой привилегии в корзине - создаём map[Product]serviceKey
  • если в CommonConditions есть UserType == "nko", то ищем скидку за nko, суммируем ассоциативный массив цен за привилегии, умножаем на эту скидку и возвращаем
  • иначе, выбираем скидки за 1 Слой. убедись, что запрос способен получать скидки с Condition.User. если не способен - можешь получить скидки на юзера отдельным запросом в самом начале расчета - это всё равно всегда одна скидка
  • проходимся по ассоциативному массиву цен, ищем в списке скидок скидки за этот продукт. если есть скидка на этого юзера с layer == 1, то применяем её вместо скидки, которую нашли по getLayer. если есть скидка на этого юзера слоя 2 на этот сервис, не применяем никакой скидк(вернее применяем никакую скидку). что значит примеменить скидку - умножить стоимость этой привилегии на фактор скидки и добавить к текущему значению в ассоциативном массиве цен за сервис
  • выбираем 2 Слой
  • проходимся по ассоциативному массиву стоимости сервисов. если есть скидка на юзера со слоем 2 и на этот сервис - применяем её. иначе применяем скидку на этот сервис. т.е. умножаем стоимости сервиса на фактор скидки и обновляем значение в самом ассоциативном массиве
  • суммируем ассоциативный массив стоимости сервисов
  • выбираем 3 Слой с учетом просуммированной стоимости корзины на прошлом этапе
  • применяем эту скидку ко всем стоимостям сервисов по отдельности, кроме того, на который есть скидка 2 уровня у этого юзера
  • выбираем 4 Слой
  • применяем эту скидку ко всем стоимостям сервисов по отдельности, кроме того, на который есть скидка 2 уровня у этого юзера
  • суммируем и возвращаем