- Required environment.
- Python 3.7
- MongoDB 3.4 >
- clone the repo.
$ git clone git@github.com:felipe-dna/product-api.git- Install the requirements.
$ cd product-api
$ python3 -m venv venv
$ source venv/bin/activate
$ pip install -r requirements.txt
- Set environment required variables:
| variable name | description |
|---|---|
| DATABASE_NAME | The name of the database |
| DEBUG | A boolean value that define the DEBUG value for Django |
| SECRET_KEY | A key used to encrypt and decrypt some data in Django |
- If your database need authentication or the host where it is running is different from the default, pass this another variables:
| variable name | description |
|---|---|
| DATABASE_USER | The database user |
| DATABASE_PASSWORD | The database password |
| DATABASE_HOST | The database host |
| DATABASE_PORT | The database port |
- Make the migrations.
$ python manage.py makemigrations accounts kits products
$ python migrate
- Run the server.
$ python manage.py runserver
- Products table
| column | type | description | unique |
|---|---|---|---|
| id | string(UUID) | the product identifier | ✔️ |
| name | string | the product name | ❌ |
| sku | string | the product sku | ✔️ |
| cost | float | the product cost | ❌ |
| price | float | the unit price | ❌ |
| quantity | int | the quantity in stock | ❌ |
- Kit table
| column | type | description | unique |
|---|---|---|---|
| id | string(UUID) | the kit identifier | ✔️ |
| name | string | the kit name | ❌ |
| sku | string | the kit sku | ✔️ |
| products | array | a list of products | ❌ |
| price | float | the sum of all the products subtracting the discount percentage of each product in the kit | ❌ |
| cost | float | the sum of all the products that compose the kit | ❌ |
| stock | int | the quantity of possible kits in the stock based in the kit products stock | ❌ |
2.1 products
Products is a list of objects that must have the follow fields:
- sku: the product sku;
- quantity: the quantity of items in each kit;
- discount: the discount percentage from when comparing the product unit price and the kit price;
| entity | path | http method | needs authentication | internal route | Description |
|---|---|---|---|---|---|
| Users | /users | POST | ✔️ | ✔️ | Creates a new user |
| Users | /users/authenticate | POST | ❌ | ❌ | Authenticates the user |
| Products | /products | POST | ✔️ | ❌ | Creates a new product |
| Products | /products | GET | ✔️ | ❌ | Lists all the products |
| Products | /products/id | GET | ✔️ | ❌ | Retrieves a product by id |
| Products | /products/id | PATCH | ✔️ | ❌ | Updates a product |
| Products | /products/id | DELETE | ✔️ | ❌ | Deletes a product |
| Kits | /kits | POST | ✔️ | ❌ | Creates a new kit |
| Kits | /kits | GET | ✔️ | ❌ | Lists all the kits |
| Kits | /kits/id | GET | ✔️ | ❌ | Retrieves a kit by id |
| Kits | /kits/id | PATCH | ✔️ | ❌ | Updates a kit |
| Kits | /kits/id | DELETE | ✔️ | ❌ | Deletes a kit |
- Create a new user. Needs the internal key.
1.1 Path:
POST /v1/users
1.2 Needed headers:
{
"access": "<internal-api-key>"
}1.3 Body example:
{
"first-name": "jhon",
"last-name": "Doe",
"email": "john@doe.com",
"password": "something-very-secret"
}1.4 Response example:
// status-code:200
{
"id": 1,
"first-name": "jhon",
"last-name": "Doe",
"email": "john@doe.com",
"api-key": "the-created-user-api-key"
}- Authenticate in the system.
2.1 Path:
POST /v1/users/authenticate
2.2 Body example:
{
"email": "john@doe.com",
"password": "something-very-secret"
}2.3 Response example:
// status-code: 200
{
"access": "the-created-user-api-key",
"refresh": "the-key-used-to-refresh-the-api-key"
}- Create new products.
1.1 Path:
POST /v1/products
1.2 Needed headers:
{
"access": "Bearer <access-token>"
}1.3 Body example:
[
{
"name": "product 1",
"sku": "d8gasd8gasd8sagd8as",
"cost": 17.50,
"price": 30.00,
"quantity": 100
},
{
"name": "product 2",
"sku": "9dh9h9dh9hd92h9dh9hasd",
"cost": 32.50,
"price": 73.00,
"quantity": 200
}
]1.4 Response example:
// status-code: 201
[
{
"id": 1,
"name": "product 1",
"sku": "d8gasd8gasd8sagd8as",
"cost": 17.50,
"price": 30.00,
"quantity": 100
},
{
"id": 2,
"name": "product 2",
"sku": "9dh9h9dh9hd92h9dh9hasd",
"cost": 32.50,
"price": 73.00,
"quantity": 200
}
]- Read Products.
2.1 Read products by filters or not.
2.1.1 Path:
GET /v1/products
2.1.2 Needed headers:
{
"access": "Bearer <access-token>"
}2.1.3 Possible query filters:
| name | type | format | example | description |
|---|---|---|---|---|
| cost-lower-than | float | 00.00 | /v1/products?cost-lower-than=100.00 | retrieves the products with cost lower than the given value |
| cost-bigger-than | float | 00.00 | /v1/products?cost-bigger-than=100.00 | retrieves the products with cost bigger than the given value |
| price-lower-than | float | 00.00 | /v1/products?price-lower-than=100.00 | retrieves the products with price lower than the given value |
| cost-bigger-than | float | 00.00 | /v1/products?price-bigger-than=100.00 | retrieves the products with the price bigger than the given value |
| quantity-bigger-than | number | 100000 | /v1/products?quantity-bigger-than=7 | retrieves the products with stock quantity bigger than the given value |
| quantity-lower-than | number | 100000 | /v1/products?quantity-lower-than=100 | retrieves the products with stock quantity lower than given value |
| created-after | datetime | YY-mm-dd | /v1/products?crated-after=2020-09-11 | retrieves the products that was created after the given date |
| created-before | datetime | YY-mm-dd | /v1/products?created-before=2020-11-12 | retrieves the products that was created before the given date |
| created-by | string | UUID | /v1/products?created-by=9jda9dj9asdas | retrieves the products that was created by the given user |
2.1.4 Response example:
// status-code: 200
[
{
"id": 1,
"name": "product 1",
"sku": "d8gasd8gasd8sagd8as",
"cost": 17.50,
"price": 30.00,
"quantity": 100,
"created-by": {
"id": "hd9ashdashdashd9a",
"first-name": "John",
"last-name": "Doe"
},
"created-at": "2020-02-09T22:50:00Z"
},
{
"id": 2,
"name": "product 2",
"sku": "9dh9h9dh9hd92h9dh9hasd",
"cost": 32.50,
"price": 73.00,
"quantity": 200,
"created-by": {
"id": "hd9ashdashdashd9a",
"first-name": "John",
"last-name": "Doe"
},
"created-at": "2020-02-09T22:50:00Z"
}
]2.2 Read products by id.
2.2.1 Path:
GET /v1/products/:id
2.2.2 Needed headers:
{
"access": "Bearer <access-token>"
}2.2.3 Needed path parameters:
| name | type | format | example | description |
|---|---|---|---|---|
| id | string | UUID | /v1/products/jd9a9djsajd9da99a | defines the id of the product that must be retrieved |
2.2.4 Response example:
// status-code: 200
{
"id": 1,
"name": "product 1",
"sku": "d8gasd8gasd8sagd8as",
"cost": 17.50,
"price": 30.00,
"quantity": 100,
"created-by": {
"id": "hd9ashdashdashd9a",
"first-name": "John",
"last-name": "Doe"
},
"created-at": "2020-02-09T22:50:00Z"
}- Update an product.
3.1 Path:
PATCH /v1/products/:id
3.2 Needed headers:
{
"access": "Bearer <access-token>"
}3.3 Needed path parameters:
| name | type | format | example | description |
|---|---|---|---|---|
| id | string | UUID | /v1/products/jd9a9djsajd9da99a | defines the id of the product that will be updated |
3.4 Possible body parameters:
| name | type | format |
|---|---|---|
| name | string | |
| cost | float | 00.00 |
| price | float | 00.00 |
| quantity | int | 100 |
3.5 Response example:
> **status-code:** 204
> NO BODY- Delete an product.
4.1 Path:
DELETE /v1/products/:id
4.2 Needed headers:
{
"access": "Bearer <access-token>"
}4.3 Needed path parameters:
| name | type | format | example | description |
|---|---|---|---|---|
| id | string | UUID | /v1/products/jd9a9djsajd9da99a | defines the id of the product that will be deleted |
4.4 Response example:
> **status-code:** 204
> NO BODY- Create an kits.
1.1 Path:
POST /v1/kits
1.2 Needed headers:
{
"access": "Bearer <access-token>"
}1.3 Body example:
{
"name": "kit 1",
"sku": "d8gasd8gasd8sagd8as",
"products": [
{
"id": "d9sh9dsdhs9dhs9dh",
"discount": 11.5,
"quantity": 2
},
{
"id": "hd9ah9dsah9hdsada",
"discount": 0.0,
"quantity": 1
}
]
}1.4 Response example:
// status-code: 201
{
"name": "kit 1",
"sku": "d8gasd8gasd8sagd8as",
"products": [
{
"id": "d9sh9dsdhs9dhs9dh",
"name": "par de meias",
"discount": 11.5,
"quantity": 2,
},
{
"id": "hd9ah9dsah9hdsada",
"name": "tênis",
"discount": 0.0,
"quantity": 1,
}
],
"price": 30.00,
"cost": 25.00,
"stock": 10
}- Read Kits.
2.1 Read kits by filters or not.
2.1.1 Path:
GET /v1/kits
2.1.2 Needed headers:
{
"access": "Bearer <access-token>"
}2.1.3 Possible query filters:
| name | type | format | example | description |
|---|---|---|---|---|
| cost-lower-than | float | 00.00 | /v1/kits?cost-lower-than=100.00 | retrieves the kits with cost lower than the given value |
| cost-bigger-than | float | 00.00 | /v1/kits?cost-bigger-than=100.00 | retrieves the kits with cost bigger than the given value |
| price-lower-than | float | 00.00 | /v1/kits?price-lower-than=100.00 | retrieves the kits with price lower than the given value |
| cost-bigger-than | float | 00.00 | /v1/kits?price-bigger-than=100.00 | retrieves the kits with the price bigger than the given value |
| stock-bigger-than | number | 100000 | /v1/kits?stock-bigger-than=7 | retrieves the kits with stock stock bigger than the given value |
| stock-lower-than | number | 100000 | /v1/kits?stock-lower-than=100 | retrieves the kits with stock stock lower than given value |
| created-after | datetime | YY-mm-dd | /v1/kits?crated-after=2020-09-11 | retrieves the kits that was created after the given date |
| created-before | datetime | YY-mm-dd | /v1/kits?created-before=2020-11-12 | retrieves the kits that was created before the given date |
| created-by | string | UUID | /v1/kits?created-by=9jda9dj9asdas | retrieves the kits that was created by the given user |
| product-id | string | UUID | /v1/kits?product-id=hh2gd78ags8g2 | retrieves the kits that contains the given product |
2.1.4 Response example:
// status-code: 200
[
{
"name": "kit 1",
"sku": "d8gasd8gasd8sagd8as",
"products": [
{
"id": "d9sh9dsdhs9dhs9dh",
"name": "par de meias",
"discount": 11.5,
"quantity": 2,
},
{
"id": "hd9ah9dsah9hdsada",
"name": "tênis",
"discount": 0.0,
"quantity": 1,
}
],
"price": 30.00,
"cost": 25.00,
"stock": 10
},
{
"name": "kit 2",
"sku": "82g87dgg8g82",
"products": [
{
"id": "d9sh9dsdhs9dhs9dh",
"name": "par de meias rosas",
"discount": 15.00,
"quantity": 2,
},
{
"id": "hd9ah9dsah9hdsada",
"name": "tênis",
"discount": 0.0,
"quantity": 1,
}
],
"price": 30.00,
"cost": 25.00,
"stock": 10
}
]2.2 Read kits by id.
2.2.1 Path:
GET /v1/kits/:id
2.2.2 Needed headers:
{
"access": "Bearer <access-token>"
}2.2.3 Needed path parameters:
| name | type | format | example | description |
|---|---|---|---|---|
| id | string | UUID | /v1/kits/jd9a9djsajd9da99a | defines the id of the kit that must be retrieved |
2.2.4 Response example:
// status-code: 200
{
"name": "kit 1",
"sku": "d8gasd8gasd8sagd8as",
"products": [
{
"id": "d9sh9dsdhs9dhs9dh",
"name": "par de meias",
"discount": 11.5,
"quantity": 2,
},
{
"id": "hd9ah9dsah9hdsada",
"name": "tênis",
"discount": 0.0,
"quantity": 1,
}
],
"price": 30.00,
"cost": 25.00,
"stock": 10
}- Update an kit.
3.1 Path:
PATCH /v1/kits/:id
3.2 Needed headers:
{
"access": "Bearer <access-token>"
}3.3 Needed path parameters:
| name | type | format | example | description |
|---|---|---|---|---|
| id | string | UUID | /v1/kits/jd9a9djsajd9da99a | defines the id of the kit that will be updated |
3.4 Possible body parameters:
| name | type | format |
|---|---|---|
| name | string | |
| products | float | 00.00 |
3.5 Response example:
> **status-code:** 204
> NO BODY- Delete an kit.
4.1 Path:
DELETE /v1/kits/:id
4.2 Needed headers:
{
"access": "Bearer <access-token>"
}4.3 Needed path parameters:
| name | type | format | example | description |
|---|---|---|---|---|
| id | string | UUID | /v1/kits/jd9a9djsajd9da99a | defines the id of the kit that will be deleted |
4.4 Response example:
> **status-code:** 204
> NO BODY