466 lines
10 KiB
Markdown
466 lines
10 KiB
Markdown
# LaTiendaCOOP backend
|
|
|
|
This README aims to document functionality of backend as well as required steps to get it up and running.
|
|
|
|
## Table of Contents
|
|
|
|
- [First Steps](#first-steps)
|
|
- [Load location data](#load-location-data)
|
|
- [Load taxonomy data](#load-taxonomy-data)
|
|
- [Social Auth](#social-auth)
|
|
- [Company Endpoints](#company-endpoints)
|
|
- [Product Endpoints](#product-endpoints)
|
|
- [Core Endpoints](#core-endpoints)
|
|
- [History Endpoints](#history-endpoints)
|
|
- [Stats Endpoints](#stats-endpoints)
|
|
- [Shop Integrations](#shop-integrations)
|
|
- [WooCommerce](#woocommerce)
|
|
- [Product Search](#product-search)
|
|
- [Massive Data Load Endpoints](#massive-data-load-endpoints)
|
|
- [COOP and Managing User Data Load](#coop-and-managing-user-data-load)
|
|
- [Product Data Load](#product-data-load)
|
|
- [GeoIP Setup](#geoip-setup)
|
|
- [Tags](#tags)
|
|
- [Development Utils](#development-utils)
|
|
- [Fake product data generation](#fake-product-data-generation)
|
|
|
|
## First Steps
|
|
|
|
- Clone repository:
|
|
`git clone git@bitbucket.org:enreda/back-latienda.git`
|
|
|
|
- Use docker image for Postgis
|
|
|
|
```
|
|
docker run --name postgis -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -d -p 5432:5432 postgis/postgis
|
|
```
|
|
|
|
If you are in ARM64 use the image `imresamu/postgis:17-3.5.2-alpine3.21`
|
|
|
|
- Create file `.env` from `example.env` and populate fields correctly
|
|
|
|
From inside the project's folder:
|
|
|
|
- Make migrations:
|
|
|
|
```
|
|
python manage.py makemigrations core geo companies products history stats
|
|
python manage.py migrate
|
|
```
|
|
|
|
- Start server in development mode: `python manage.py runserver`
|
|
|
|
### Load Location Data
|
|
|
|
To load initial location data use: `python manage.py loadgisdata`
|
|
|
|
### Load Taxonomy Data
|
|
|
|
This data serves as initial Tags
|
|
|
|
To load initial set of tags: `python manage.py addtaxonomy`
|
|
|
|
## Social Auth
|
|
|
|
Use your credentials from social media network to create acount and log in.
|
|
|
|
Backend must be registered with every service that we want to use it with.
|
|
|
|
During registration, provide a `Callback URL`, where the app can receive requests.
|
|
You are given `client key` and `client secret` tokens, used to validate login requests.
|
|
|
|
### Facebook
|
|
|
|
- Go to `developers.facebook.com/`
|
|
- click on `My Apps`
|
|
- On `Add a New App`, click on `Website`
|
|
- Click on `Create App ID`
|
|
- On the next screen click on `Skip Quick Start`
|
|
- grab the `App ID` and `App Secret`
|
|
- in `Settings / Basic`, click on the button `+ Add Platform` and add a website, and other info
|
|
|
|
## Company Endpoints
|
|
|
|
### CompanyViewSet
|
|
|
|
Queryset: validated Company instances only
|
|
|
|
Permissions:
|
|
|
|
- anon user: safe methods
|
|
- auth user: full access where user is company creator
|
|
|
|
### MyCompanyViewSet
|
|
|
|
Queryset: Company instances where user is creator
|
|
|
|
Permissions:
|
|
|
|
- anon user: no access
|
|
- auth user: full access
|
|
|
|
### AdminCompanyViewSet
|
|
|
|
Queryset: all Company instances, validated or not
|
|
|
|
Permissions: only accesible to authenticated users with role `SITE_ADMIN`
|
|
|
|
### random_company_sample
|
|
|
|
Method view that returns a randome sample of companies
|
|
|
|
By default it returns 6 instances, but can be customized through parameter `size`
|
|
|
|
## Product Endpoints
|
|
|
|
### ProductViewSet
|
|
|
|
Endpoint url: `/api/v1/products/`
|
|
|
|
Queryset: active Product instances only
|
|
|
|
Permissions:
|
|
|
|
- anon user: safe methods
|
|
- auth user: full access where user is product creator
|
|
|
|
### MyProductsViewSet
|
|
|
|
Endpoint url: `/api/v1/my_products/`
|
|
|
|
Queryset: Product instances where user is creator
|
|
|
|
Permissions:
|
|
|
|
- anon user: no access
|
|
- auth user: full access
|
|
|
|
### AdminProductsViewSet
|
|
|
|
Endpoint url: `/api/v1/admin_products/`
|
|
|
|
Queryset: all Product instances, acgtive or not
|
|
|
|
Permissions: only accesible to authenticated users with role `SITE_ADMIN`
|
|
|
|
### load_coop_products [POST]
|
|
|
|
Endpoint url: `/api/v1/load_products/`
|
|
|
|
Method view that reads a CSV file.
|
|
|
|
### product_search [GET]
|
|
|
|
Endpoint url: `/api/v1/search_products/`
|
|
|
|
Allows searching of Products to all users
|
|
|
|
Parameters:
|
|
|
|
- q: used for search [MANDATORY]
|
|
- limit: max number of returned instances [OPTIONAL]
|
|
- offset: where to start counting results [OPTIONAL]
|
|
- shipping_cost: true/false
|
|
- discount: true/false
|
|
- category: string
|
|
- tags: string
|
|
- order: string (newest/oldest)
|
|
- price_min: int
|
|
- price_max: int
|
|
|
|
### purchase_email [POST]
|
|
|
|
Endpoint url: `/api/v1/purchase_email/`
|
|
|
|
Sends email to company manager about the product that the user wants to purchase, and sends confirmation email to user.
|
|
|
|
Parameters:
|
|
|
|
- email: mandatory for anonymous users
|
|
- telephone
|
|
- company
|
|
- product
|
|
- comment
|
|
|
|
## Core Endpoints
|
|
|
|
### CustomUserViewSet
|
|
|
|
Endpoint url: `/api/v1/users/`
|
|
|
|
Queryset: all CustomUser instances
|
|
|
|
Permissions:
|
|
|
|
- anon user: only POST to register new user
|
|
- auth user: no access
|
|
- admin user: full access
|
|
|
|
### ChangeUserPasswordView
|
|
|
|
Ednpoint url: `/api/v1/user/change_password/<int:pk>/`
|
|
|
|
Permissions: only accessible for your own user instance
|
|
|
|
### UpdateUserView
|
|
|
|
Endpoint url: `/api/v1/user/update/`
|
|
|
|
Permissions: only accessible for your own user instance
|
|
|
|
### create_company_user [POST]
|
|
|
|
Edndpoint: `/api/v1/create_company_user/`
|
|
|
|
Simultaneously create a company and its related user
|
|
|
|
NOT WORKING!!!
|
|
|
|
### my_user [GET]
|
|
|
|
Endpoint url: `/api/v1/my_user/`
|
|
|
|
Returns instance of authenticated user
|
|
|
|
### load_coop_managers [POST]
|
|
|
|
Ednpoint url: `/api/v1/load_coops/`
|
|
|
|
For each row it creates a Company instance, and a user instance linked to the company, with role `COOP_MANAGER`
|
|
|
|
### activate_user
|
|
|
|
Endpoint: `/activate/<uidb64>/<token>/`
|
|
|
|
This endpoint is reached from the URL sent to the user after their registration
|
|
|
|
### User Management
|
|
|
|
Creation:
|
|
|
|
- endpoint: `/api/v1/users/`
|
|
- method: GET
|
|
- payload:
|
|
|
|
```json
|
|
{
|
|
"email": "test@email.com",
|
|
"full_name": "TEST NAME",
|
|
"password": "VENTILADOR2ES1234499.89"
|
|
}
|
|
```
|
|
|
|
Change password:
|
|
|
|
- endpoint: api/v1/user/change_password/{user.pk}/
|
|
- method: POST
|
|
- payload:
|
|
|
|
```json
|
|
{
|
|
"old_password": "my_old_password",
|
|
"password": "SUPERSECRETNEWPASSWORD",
|
|
"password2": "SUPERSECRETNEWPASSWORD"
|
|
}
|
|
```
|
|
|
|
Update user profile:
|
|
|
|
- endpoint: api/v1/users/<int:pk>/
|
|
- method: PUT
|
|
- payload:
|
|
|
|
```json
|
|
{
|
|
"email": "new_user@email.com",
|
|
"full_name": "Mr. TEST NAME"
|
|
}
|
|
```
|
|
|
|
### Authentication
|
|
|
|
Implemented using `djangorestframework-simplejwt`
|
|
|
|
New token pair endpoint: `/api/v1/token/`
|
|
|
|
Response:
|
|
|
|
```json
|
|
{
|
|
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYxMjI3MTcwNSwianRpIjoiZDU4YTgzYzFkYzFkNDI5MTljMGQ0NzcxNzljNzUxYTQiLCJ1c2VyX2lkIjo4fQ.yln80W5lONSyHwwqF4qBBHteqLuRfdLLWuaQANr_vxc",
|
|
"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjEyMTg4OTA1LCJqdGkiOiIzNGIxMzM3NmU4MWI0OWY5YjU3ZmUxM2M5NThmZWZkYiIsInVzZXJfaWQiOjh9.aRDCUvKj7LCvixjPLC9ghy0h7rfRwR6Lo3A7HX4kSHE"
|
|
}
|
|
```
|
|
|
|
Refresh expired token endpoint: `/api/v1/token/refresh/`
|
|
|
|
### Users
|
|
|
|
Endpoint url: `/api/v1/users/`
|
|
|
|
To get info on authenticated user: `/api/v1/my_user/`
|
|
|
|
Authenticated users cannot create new users
|
|
|
|
User are active by default
|
|
|
|
To create user:
|
|
|
|
```json
|
|
{
|
|
"email": "test_user23@mail.com",
|
|
"full_name": "Mr Test User",
|
|
"password": "wqertewqr32qrewqr",
|
|
"provider": "TWITTER"
|
|
}
|
|
```
|
|
|
|
## History Endpoints
|
|
|
|
Endpoint url: `/api/v1/history/`:
|
|
|
|
Historical records about product importation
|
|
|
|
## Stats Endpoints
|
|
|
|
Endpoint url: `/api/v1/stats/`
|
|
|
|
logs about user interaction with products links
|
|
|
|
## Location Endpoints
|
|
|
|
Location ednpoints:
|
|
|
|
- `/api/v1/countries/`
|
|
- `/api/v1/regions/`
|
|
- `/api/v1/provinces/`
|
|
- `/api/v1/cities/`
|
|
|
|
Tables filled with data from `datasets/gadm36_ESP.gpkg` with `loadgisdata` command.
|
|
|
|
## Shop Integrations
|
|
|
|
We provide integrations with online shop platforms
|
|
|
|
It requires the json field `Company.credentials` to have the appropiate format and values
|
|
|
|
Endoint: `/api/v1/companies/{PK}/import_products/`
|
|
|
|
The software to handle different platform imports can be found in `utils`
|
|
|
|
### WooCommerce
|
|
|
|
Credential format:
|
|
|
|
```json
|
|
{
|
|
"key": "qwerweqr",
|
|
"secret": "asdfsa"
|
|
}
|
|
```
|
|
|
|
Method: `utils.woocommerce.migrate_shop_products`
|
|
|
|
## Product Search
|
|
|
|
Endpoint: `/api/v1/product_search/`
|
|
|
|
Query parameters:
|
|
|
|
- `q`: text from the search input box
|
|
|
|
Response format:
|
|
|
|
```json
|
|
{
|
|
"filters": {
|
|
"tags": {
|
|
"singles": ["tag1", "tag2"], // for tags that aren't nested
|
|
"entry_1": ["subtag_1", "subtag_2"], // for tree tags like entry_1/subtag_1
|
|
"entry_2": ["subtag_1", "subtag_2"] // one per penultimate tag in tree
|
|
},
|
|
"attributes": {
|
|
"singles": ["tag1", "tag2"], // for tags that aren't nested
|
|
"entry_1": ["subtag_1", "subtag_2"], // for tree tags like entry_1/subtag_1
|
|
"entry_2": ["subtag_1", "subtag_2"] // one per penultimate tag in tree
|
|
}
|
|
},
|
|
"products": [] // list of serialized instances, in order of relevancy
|
|
}
|
|
```
|
|
|
|
Available query parameters:
|
|
|
|
- q: used for search [MANDATORY]
|
|
- limit: max number of returned instances [OPTIONAL]
|
|
- offset: where to start counting results [OPTIONAL]
|
|
- shipping_cost: true/false
|
|
- discount: true/false
|
|
- category: string
|
|
- tags: string
|
|
- order: string (newest/oldest)
|
|
|
|
Check out `products.tests.ProductSearchTest` for a practical case.
|
|
|
|
## Massive Data Load Endpoints
|
|
|
|
### COOP and Managing User Data Load
|
|
|
|
For massive load of data from COOPs and the managing user.
|
|
|
|
CSV headers: `email,cif,nombre-coop,nombre-corto,url,es-tienda`
|
|
|
|
Only admin users have access to endoint
|
|
|
|
### Product Data Load
|
|
|
|
Endpoint: `/api/v1/load_products/`
|
|
|
|
Only functional for users with a related company instance
|
|
|
|
For massive load of product data.
|
|
|
|
CSV headers: `sku,nombre-producto,descripcion,imagen,url,precio,gastos-envio,cond-envio,descuento,stock,tags,categoria,identificadores`
|
|
|
|
Number fields must not include other symbols (like currency)
|
|
|
|
## GeoIP Setup
|
|
|
|
Module: `geoip2`
|
|
|
|
- Download the `GeoLite2 City` and `GeoLite2 Country` binary datasets from maxmind.com
|
|
- Unzip files into `datasets/` folder
|
|
- Set `settings.GEOIP_PATH` to datasets folder
|
|
|
|
Optional:
|
|
|
|
- install `libmaxminddb` C library for improved performance:
|
|
|
|
`sudo apt install libmaxminddb0 libmaxminddb-dev mmdb-bin`
|
|
|
|
## Tags
|
|
|
|
Both `Company` and `Product` models make use of tags.
|
|
|
|
### Load shopping taxonomy
|
|
|
|
To create the initial set of tags, we can use the `addtaxonomy` management command.
|
|
Reads the data from `datasets/shop-taxonomy.es-ES.txt` which is from google shopping
|
|
|
|
### Top-level tags
|
|
|
|
In order to extract the top level tags for use as categories, we can use the `extractparenttas` management command.
|
|
It saves the results to `datasets/top_tags.txt`
|
|
|
|
## Development Utils
|
|
|
|
### Fake product data generation
|
|
|
|
To create a dataset of fake companies and products:
|
|
|
|
`python manage.py addtestdata`
|
|
|
|
Creates 10 Companies, with 10 products each.
|
|
|
|
WARNING: the script deletes existing instances of both Company and Product
|