Skip to content

abdallah-zaghloul/4sale-task

Repository files navigation

Laravel Logo

4Sale Task

Live Demo

Please watch this video 👇

Live Demo

Task Description

Challenge Idea
------------------------------

For Backend Application (Senior Backend)
We have two providers collect data from them in json les we need to read
and make some filter operations on them to get the result
• DataProviderX data is stored in [DataProviderX.json]
• DataProviderY data is stored in [DataProviderY.json]

DataProviderX schema is
{
    parentAmount:200,   
    Currency:'USD',
    parentEmail:'parent1@parent.eu',
    statusCode:1,
    registerationDate: '2018-11-30',
    parentIdentification: 'd3d29d70-1d25-11e3-8591-034165a3a613'
}

we have three status for DataProviderX
• authorised which will have statusCode 1
• decline which will have statusCode 2
• refunded which will have statusCode 3
DataProviderY schema is
{
    balance:300,
    currency:'AED',
    email:'parent2@parent.eu',
    status:100,
    created_at: '22/12/2018',
    id: '4fc2-a8d1'
}

we have three status for DataProviderY
• authorised which will have statusCode 100
• decline which will have statusCode 200
• refunded which will have statusCode 300

Acceptance Criteria
-----------------------------------

Using PHP Laravel, implement this API endpoint:
• it should list all users which combine transactions
from all the available providerDataProviderX and DataProviderY)

• it should be able to filter result by payment providers 
for example /api/v1/users?provider=DataProviderX it should return users from DataProviderX

• it should be able to filter result three statusCode
(authorised, decline, refunded) for example /api/v1/users?statusCode=authorised 
it should return all users from all providers that
have status code authorised

• it should be able to ler by amount range 
for example /api/v1/users?balanceMin=10&balanceMax=100 
it should return result between 10 and 100 including 10 and 100

• it should be able to filter by currency
• it should be able to combine all this filters together

The Evaluation

Task will be evaluated based on
1. Code quality
2. Application performance in reading large les
3. Code scalability : ability to add DataProviderZ by small changes
4. Unit tests coverage
5. Docker

Project Infra Structure

  • The Project is a Decoupled Modular Monolithic App : HMVC Modules (you can turn on/off each module and republish/reuse it at another project)

  • Module Structure (Repository Design Pattern)

  • Separated/Attached Tests

Solution Implementation

Database Choice (PostgreSQL):
PostgreSQL MySQL MariaDB
UUID datatype Built-in Not supported Supported at last version
JSON datatype JSONB JSON Long Text
ENUMs Checks & Enums Enums Enums
  PostgreSQL: is the most suitable for this situation because of :
  - UUID Support as PK as a built-in datatype instead of :
     * MySQL: deals with it as string or string-to-binary conversion Bad Performance
     * MariaDB: support UUID data-type at last version only with no support for JSON
  - JSONB (JSON Binary): support processing on JSON and array indexes (if needed later on)
  - Checks (Check Constrains) : is the best to be used for Scalability because :
    * better than multiple Joins
    * no needs/risks to alter schema as with ENUM
    * scalable - more performant

How to Query ?

  • Repository Design Pattern => for complex queries
  • skip invalid query params
  • query run acc to count of params ex : (1 => where, +1 =>whereIn)
  • rely on Checks (described above) for well-defined values as currency, provider status, providers
  • separated Query layer called (Criteria) => single responsibility & re-usability & remove tight coupling
  • use eloquent builder instead of ORM
  • use Joins instead of whereHas('run exists query')
  • use cursorPagination (rely on PHP generators) => can afford large database streaming & avoid memory leak
  • cache can be enabled and disabled
  • finally : we should use elastic search => I will learn it with your team

Separated Unit/Feature tests

  • tested at about 10 million records (users/transactions) using laravel Benchmark

  • implement both feature/unit tests

Docker

  • app is dockerized using laravel sail

Bonuses

  • implement search for multiple comma query params for the same param ex : statusCode=authorised,200,refunded
  • skip invalid query params
  • control pagination count (max=1000) ex : paginationCount=200

Criteria Benefits

  • scalable: you can add any filter at anytime on the same query

  • maintainable & re-usable

  • fluent builder design pattern for easy chaning

  • you can skip it and call another one

  • it can be passed from module to another

  • can be extended for another API ex: show user that have the current transactions by ID

How To Run The Project Locally

Requirements (all can be installed automatically using docker desktop):
---------------
- PHP 8.2
- Run Docker Desktop
- PostgreSQL
- SQL lite PHP Extension
  • you will find the postman collection at the project root files: 4Sale-task.postman_collection.json

Run the following at the project root dir Terminal ---------------
  • Download Vendor folder composer install
  • Make Sail alias alias sail='[ -f sail ] && sh sail || sh vendor/bin/sail'
  • Generate .env file from .env.decrypted: php artisan env:decrypt --key=base64:PtOlApk/cv8f9pSWmmasyCmKJ+nAkvUrIKeAGNAl0HQ=
  • Laravel Sail install php artisan sail:install
  • Run Your local server up: sail up -d
  • Run Your local server down: sail down
  • To Run Unit/Feature Tests but configure your test with xdebug sail php artisan test --testsuite={Modules or ModuleName}

if you have an issue you can see Laravel Sail

About

Search User Transactions

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published