This project is REST API designed for a mock consumer application where users can earn rewards points for transactions with certain businesses and then spend those reward points.
-
A
user
can have reward points balances in their account from variouspayers
(businesses where a user transacts)- e.g.,
{"Nike": 500, "Cheesecake Factory": 1000}
- e.g.,
-
Transactions
are submitted to add or subtract points from a user's reward points balance- Payer balances in a user's account cannot go below 0
-
A user can
spend
points from their account/payer balances- User's total points cannot go below 0
- Points are spent in First-In-First-Out order based on transaction timestamp, irrespective of payer
- Python - The latest version of Python to run the program, or at least version 3.7+
- FastAPI - A modern, fast, web framework for building APIs with Python 3.6+ based on standard Python type hints
- Pydantic - Data validation and settings management using python type annotations
- Pytest - Python testing framework
-
Clone git repo to your local machine
git clone https://github.com/alexsmaldone/consumer-rewards-api.git
-
Cd into the project's root directory
cd consumer-rewards-api/
-
Install dependencies
pip install -r requirements.txt
-
Start the server
uvicorn main:app --reload
Your terminal should read:
Uvicorn running on http://127.0.0.1:8000
You can verify the server is running by visiting http://localhost:8000 in your browser, where you should see this response:
Hi! Welcome to Alex Smaldone's mock API design for a consumer app that tracks a user's transactions and allocates rewards points based on those transactions.
This service uses no database or persistent storage, so user points / payer transactions will reset every time the server is started/restarted
I recommend using a tool like Postman to test out API calls.
Request Format
{"payer": <str>, "points": <int>, "timestamp": <datetime>}
Example Request and Response
{"payer": "Nike, "points": 500, "timestamp": "2022-06-20T11:07:01.017197"}
{"Message": "Transaction Successful", "Current Balance": 500}
Example Request and Response (including previous)
{"payer": "Adidas, "points": 500, "timestamp": "2022-06-20T11:07:02.017197"}
{"Message": "Transaction Successful", "Current Balance": 1000}
Error Handling
- Preventing payer balances from going negative
- Preventing 0 points transactions
- Type checking for request body values
Request Format
{"points": <int>}
Example Request and Response
{"points": 250}
Subtracts 250 points from Nike payer balance as it is the oldest transaction.
{"payer": "Nike", "points": -250}
Error Handling
- Preventing spend that is greater than total user points
- Preventing negative spend
- Type checking for request body values
After making the above transaction and spend requests, the payer points would look like:
{
"Nike": 250, "Adidas": 500
}
You can run the tests in test_main.py
from the main directory by running:
pytest
The tests check the following:
- Returns the proper points balance
- Cannot create negative payer balances with a transaction
- Cannot add 0 point transactions
- Tests valid transaction sequences
- Tests valid spend sequences
- Spend must be greater than 0 and less than total available points