This project aims to reproduce a simple cash register that supports business rules like buy-one-get-one-free when adding a product to cart.
- Buy X get Y free - Buy X products and get Y items of same product.
- Buy X or more items and pays a fixed price per item.
- Buy X or more items and receives a discount in percentage per item.
This app was develop on top of a modular Sinatra application and has the following requirements:
ruby 3.2.2
and
bundler 2.4.22
To run the app, after installing the requirements, one can simply:
- Clone the repository
- Navigate to project's folder
- Run
bundle
to install dependencies - Run
bundle exec rake db:create && bundle exec rake db:migrate
to setup databases - Run
bundle exec rake db:seed
to populate the database with initial data - Start the server/application by running
bundle exec rackup config.ru
To interact with the app, we should use it as an API, we can use Postman to make requests and check the responses
- GET
/products
- index of all products in the DB - GET
/cart
- Current User's cart items - PATCH
/cart/add_product
- Add product to Current User's cartRequest body: { "product_id": <id_of_product_to_add>, "qty_to_add": <units_to_be_added> }
- DELETE
/cart/clean_cart
- Remove all products from current user's cart - DELETE
/cart/remove_product
- Remove specific product from current user's cartRequest body: { "product_id": <id_of_product_to_delete>, "qty_to_delete": <units_to_be_removed_from_cart> }
Currently, all the rules are created in the db/seeds.rb
file, but the architecture is simple and flexible enough to allow it to be created from an endpoint (to be created).
The rules
database has the following columns:
trigger_product_id
: (Integer that stores the value of the product that will trigger the rule - it allows empty values for rules that check for any product in the cart)trigger_amount
: (Decimal that stores the value amount that will trigger the rule)trigger_amount_type
: (String that stores the type of the trigger amount, it can be 'unit', 'cents' or 'percentage')trigger_amount_operator
: (String that stores the logical operator that the rule will use to compare and see if it should be triggered, it allows:'GTE' (>=)
'LTE' (<=)
'EQ' (==)
'LT' (<)
'GT' (>)
rule_type_id
: (Integer that stores the id of theRuleType
record that the rule belongs_totarget_product_id
: (Integer that stores the value of the product that will be the target of the rule - will be added to the card or will receive a discount)target_amount
: (Decimal that stores the value amount for the target item - discount to be given, units to add, price to set, etc.)target_amount_type
: (String that stores the type of the target amount, it can be 'unit', 'cents' or 'percentage')
![Screenshot 2023-12-11 at 02 36 21](https://private-user-images.githubusercontent.com/87980712/289435577-d08f4450-6f3c-4ac4-95ab-f4940ccb868e.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjQwMDEwMzEsIm5iZiI6MTcyNDAwMDczMSwicGF0aCI6Ii84Nzk4MDcxMi8yODk0MzU1NzctZDA4ZjQ0NTAtNmYzYy00YWM0LTk1YWItZjQ5NDBjY2I4NjhlLnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA4MTglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwODE4VDE3MDUzMVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTNmZWZiMDAyMjgyMmUxZWMyZjRkZDMzZGIzOGJkZDc0MjhmM2MwZTE2MWQ2ZjI3NTY2NWU1MmVlZmU2ZTVhMTEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.2wlW5drtiSdGI3ilVW_tgIgRH7ZWgUyGt5YoiMKiNVY)
- Revert the rules when removing product from cart
- Fix endpoint responses to follow API patterns properly
- Improve specs
- Add User Interface / Front-end
- Improve support for different RuleTypes