Skip to content

abdukhafiz/systemio-test

Repository files navigation

Написать Symfony REST приложение для расчета цены продукта и проведения оплаты

Проект написан на Laravel!

  • Клонировать проект
  • Установить зависимости через composer
  • Запустить миграцию через команду php artisan migrate
  • Запустить сидер через команду php artisan db:seed

Первый эндпоинт

URL (POST): http://localhost/api/v1/calculate-price Тело запроса:

{
    "product": id из таблицы products,
    "taxNumber": tax_format из таблицы countries,
    "couponCode": code из таблицы coupons
}

Второй эндпоинт

URL (POST): http://localhost/api/v1/purchase Тело запроса:

{
    "product": id из таблицы products,
    "taxNumber": tax_format из таблицы countries,
    "couponCode": code из таблицы coupons
    "paymentProcessor": "paypal" ИЛИ "stripe"
}

Необходимо написать 2 эндпоинта:

  1. POST: для расчёта цены

http://127.0.0.1:80/calculate-price

Пример json тела запроса:

{
    "product": 1,
    "taxNumber": "DE123456789",
    "couponCode": "D15"
}
  1. POST: для выполнения покупки

http://127.0.0.1:80/purchase

Пример json тела запроса:

{
    "product": 1,
    "taxNumber": "IT12345678900",
    "couponCode": "D15",
    "paymentProcessor": "paypal"
}

При успешном выполнении запроса вернуть HTTP ответ с кодом 200.

При неверных входных данных или ошибках оплаты вернуть HTTP ответ с кодом 400 и json объект с ошибками.

Продукты

Предполагается, что продукты хранятся в БД, для примера можно взять 3 продукта:

  • Iphone (100 евро)
  • Наушники (20 евро)
  • Чехол (10 евро)

Купоны

При наличии купона покупатель может применить его к покупке.

Купон может быть двух типов:

  • фиксированная сумма скидки
  • процент от суммы покупки

Мы подразумеваем, что купоны создаются продавцом и где-то хранятся (ну или захардкодены, на ваше усмотрение)

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

Например, при наличии (в БД или в виде хардкода) купонов P10 (скидка 10%) и P100 (скидка 100%) у покупателя не должно быть возможности применить купон P50, если он не хранится явным образом.

Код купона не обязательно должен соответствовать какому-либо формату. Вы можете выбрать его на своё усмотрение.

Расчет налога

При покупке продукта получатель сверх цены продукта должен уплатить налог, относительно страны налогового номера:

  • Германии - 19%
  • Италии - 22%
  • Франции - 20%
  • Греции - 24%

В итоге для покупателя Iphone из Греции цена составляет 124 евро (цена продукта 100 евро + налог 24%).
Если у покупателя есть купон на 6% скидку на покупку, то цена будет 116.56 евро (цена продукта 100 евро - 6% скидка + налог 24%).

Формат налогового номера

DEXXXXXXXXX - для жителей Германии,

ITXXXXXXXXXXX - для жителей Италии,

GRXXXXXXXXX - для жителей Греции,

FRYYXXXXXXXXX - для жителей Франции

где:

  • первые два символа - это код страны,
  • X - любая цифра от 0 до 9,
  • Y - любая буква

Обратите внимание, что длина налогового номера разная для разных стран.
Форматы налоговых номеров могут меняться, что случается редко. (Это зависит от законодательства.)

Детали

При выполнении задания нужно:

  • реализовать валидацию всех полей (в том числе корректность tax номера согласно формату) в теле запросов, используя Symfony validator
  • рассчитать итоговую цену покупки вместе с купоном (если указан) и налогом
  • использовать для проведения платежа PaypalPaymentProcessor::pay() или StripePaymentProcessor::processPayment()
    Эти классы представлены в этом проекте, использовать следует именно их. В методах оплаты они принимают цену как в разных юнитах (как в центах, так и в долларах).
    • ИЛИ скопируйте их себе в проект. Для простоты представьте, что эти два класса входят в два разных сторонних SDK, и у вас нет возможности править эти классы или какую-либо логику внутри них.
    • ИЛИ добавьте systemeio/test-for-candidates как зависимость через Composer.
  • приложить в README.md примеры HTTP-запросов к двум эндпоинтам: path и тело запроса (для ручного тестирования) в формате curl команды

CRUD для сущностей писать не нужно, будем считать что он "есть" и данные в БД валидны, т.е. проверок в сервисах, что процентная скидка по купону больше 0, меньше 1000 и прочих подобных делать не нужно.

При написании тестового используйте git, после выполнения пришлите ссылку на репозиторий.

Необходимо учесть возможность добавления новых PaymentProcessors.

Если вы чувствуете, что определённая часть задания требует у вас много времени на выполнение, вы можете выбрать наиболее простое решение и комментарием указать возможные варианты реализации, которые вы рассматриваете

Будет плюсом

  • использование контейнеризации для php, postgres/mysql
  • наличие PHPUnit tests
  • соответствие кода принципам SOLID (без фанатизма)
  • покоммитное оформление этапов реализации приветствуется
  • продемонстрированное умение НЕ! использовать подходы вроде onion-based/DDD/CQS/гексагональной архитектуры при выполнении задания: мы куда больше ценим его корректность и полноту; такие сложные концепции в нашем задании скорее не уместны

Мы не ограничиваем вас по срокам выполнения задания, но при этом ожидаем, что в тестовом задании вы раскроете принципы, которых придерживаетесь в работе.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published