- api
docker-compose up
docker-compose run --rm web <your-command>
npm start
npm run build
npm run test
npm run lint
(npm run lint -- --fix
to lint automatically)npm run format
Before pushing your changes, you should:
- Lint and format your code:
npm run format
npm run lint -- --fix
- Check that the tests still pass:
npm run test:e2e
⚠️ WarningAll endpoints except authentication endpoints are protected and require authentication.
POST /auth/register
Parameters | Type | In | Description |
---|---|---|---|
string | body | [required] | |
password | string | body | [required] |
role | string | body | [required] |
POST /auth/register
{
"email":"[email protected]",
"password":"12345678",
"role":"User"
}
Status: 201 CREATED
{
"id": 1,
"uuid": "some-uuid",
"username": "test",
"email":"[email protected]"
"isActive": true,
"cards": []
}
PUT /auth/login
Parameters | Type | In | Description |
---|---|---|---|
string | body | [required] | |
password | string | body | [required] |
PUT /auth/login
{
"email":"[email protected]"
"password":"12345678"
}
Status: 200 OK
{
"status": 200,
"token": "some-jwt-token"
}
GET /user/:uuid
Parameters | Type | In | Description |
---|---|---|---|
uuid | string | query | [required] |
GET /user/some-uuid
Status: 200 OK
{
"id": 1,
"username": "test",
"email": "[email protected]",
"isActive": true,
"cards":
[
{
"id": 1,
"shopId": 1,
"userId": 1,
"startAt": "",
"endAt": "",
"isActive": true,
"shop": {
"companyName": "Bistrot123",
"activity":"Restauration",
"siren": "123456789",
"siret": "12345678901234",
"email": "[email protected]",
"zipCode": "12345",
"lat":"22.366329",
"long": "-10.137468",
"phone": "0632547698",
"address": "12 rue du bistrot",
"city": "Paris"
},
"balances": [
{
"id": 1,
"promotionId": 1,
"cardId": 1,
"counter": 0,
"isActive": true
"promotion": {
"id": 1,
"shopId": 1,
"name": "Promotion",
"description": "Promotion description",
"startAt": "2019-05-27",
"endAt": "2020-05-27",
"checkoutLimit": 10,
}
}
]
},
{
"id": 2,
"shopId": 2,
"userId": 1,
"startAt": "",
"endAt": "",
"isActive": true,
"shop": {
"companyName": "Coffee Shop",
"activity":"Restauration",
"siren": "987654321",
"siret": "98765432101234",
"email": "[email protected]",
"zipCode": "54321",
"lat": "18.365229",
"long": "-11.147119",
"phone": "0698765432",
"address": "1 rue du café",
"city": "Paris"
},
"balances": [
{
"id": 2,
"promotionId": 2,
"cardId": 2,
"counter": 5,
"isActive": true
"promotion": {
"id": 2,
"shopId": 2,
"name": "Promotion2",
"description": "Promotion2 description",
"startAt": "2019-05-27",
"endAt": "2020-05-27",
"checkoutLimit": 20,
}
}
]
}
]
}
GET /user/cards
GET /user/cards
Status: 200 OK
[
{
"id": 1,
"shopId": 1,
"userId": 1
},
{
"id": 2,
"shopId": 2,
"userId": 1
},
{
"id": 3,
"shopId": 3,
"userId": 1
}
]
PUT /user/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
username | string | body | [optional] |
string | body | [optional] | |
birthday | string | body | [optional] |
sexe | string | body | [optional] |
PUT /user/1
{
"username": "test",
"email":"[email protected]"
}
Status: 200 OK
{
"id": 1,
"username": "test",
"email":"[email protected]"
"isActive": true,
"cards": []
}
DELETE /user/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
DELETE /user/1
Status: 200 OK
{
"message": "User deleted"
}
GET /shop/
Parameters | Type | In | Description |
---|---|---|---|
distance | number | query | [required] Distance in metres |
lat | number | query | [required] Latitude |
long | number | query | [required] Longitude |
isActive | boolean | query | [required] Active |
GET /shop/?distance=3000&long=2.3690961&lat=48.8573185
Status: 200 OK
[
{
"id": 1,
"companyName": "Bistrot123",
"activity":"Restauration",
"siren": "123456789",
"siret": "12345678901234",
"email": "[email protected]",
"zipCode": "12345",
"lat": "48.8578461",
"long": "2.3685758",
"phone": "0632547698",
"address": "12 rue du bistrot",
"city": "Paris"
"isActive": true,
}
]
GET /shop/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /shop/1
Status: 200 OK
{
"id": 1,
"companyName": "Bistrot123",
"activity": "Restauration",
"siren": "123456789",
"siret": "12345678901234",
"email": "[email protected]",
"zipCode": "12345",
"lat": "22.366329",
"long": "-10.137468",
"phone": "0632547698",
"address": "12 rue du bistrot",
"city": "Paris",
"isActive": true
}
GET /shop/:id/promotion
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /shop/1/promotion
Status: 200 OK
[
{
"id": 1,
"shopId": 1,
"name": "Promotion",
"description": "Promotion description",
"startAt": "2019-05-27",
"endAt": "2020-05-27",
"checkoutLimit": 10,
"isActive": true
}
]
GET /shop/:id/cards
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /shop/1/cards
Status: 200 OK
[
{
"id": 1,
"url": "https://example.com",
"isActive": true,
"shopId": 1,
"userId": 1,
"user": {
"id": 1,
"username": "test",
"email": "[email protected]",
"isActive": true
},
"balances": []
},
{
"id": 2,
"url": "https://example.com",
"isActive": true,
"shopId": 1,
"userId": 2,
"user": {
"id": 2,
"username": "test2",
"email": "[email protected]",
"isActive": true
},
"balances": []
}
]
GET /shop/:id/campaigns
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /shop/1/campaigns
Status: 200 OK
[
{
"id": 1,
"promotionId": 1,
"shopId": 1,
"subject": "Hello",
"textData": "New promotion available at your store!",
"isActive": true
}
]
POST /shop
Parameters | Type | In | Description |
---|---|---|---|
companyName | string | body | [required] |
activity | string | body | [required] |
siren | string | body | [required] |
siret | string | body | [required] |
string | body | [required] | |
zipCode | string | body | [required] |
lat | string | body | [required] |
long | string | body | [required] |
phone | string | body | [required] |
address | string | body | [required] |
POST /shop
{
"companyName": "Bistrot123",
"activity":"Restauration",
"siren": "123456789",
"siret": "12345678901234",
"email": "[email protected]",
"zipCode": "12345",
"lat":"22.366329",
"long": "-10.137468",
"phone": "0632547698",
"address": "12 rue du bistrot",
}
Status: 201 CREATED
{
"message": "Shop created"
}
PUT /shop/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
companyName | string | body | [optional] |
activity | string | body | [optional] |
siren | string | body | [optional] |
siret | string | body | [optional] |
string | body | [optional] | |
zipCode | string | body | [optional] |
lat | string | body | [optional] |
long | string | body | [optional] |
phone | string | body | [optional] |
address | string | body | [optional] |
PUT /shop/1
{
"companyName": "Bistrot123",
"siren": "123456789",
"siret": "12345678901234",
"email": "[email protected]",
"zipCode": "12345",
"lat":"22.366329",
"long": "-10.137468",
"phone": "0632547698",
"address": "12 rue du bistrot",
}
Status: 200 OK
{
"message": "Shop updated"
}
DELETE /shop/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
DELETE /shop/1
Status: 200 OK
{
"message": "Shop deleted"
}
GET /card/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /card/1
Status: 200 OK
{
"id": 1,
"shopId": 1,
"userId": 1
}
POST /card
Parameters | Type | In | Description |
---|---|---|---|
shopId | number | body | [required] |
userId | number | body | [optional] Need to be specified if the card is created by a Fider |
isActive | boolean | body | [optional] |
POST /card
{
"shopId": 1,
}
Status: 201 CREATED
{
"message": "Card created"
}
PUT /card/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
isActive | boolean | body | [optional] |
PUT /card/1
{
"isActive": false,
}
Status: 200 OK
{
"message": "Card updated"
}
DELETE /card/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
DELETE /card/1
Status: 200 OK
{
"message": "Card deleted"
}
GET /promotion/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /promotion/1
Status: 200 OK
{
"id": 1,
"shopId": 1,
"name": "Promotion",
"description": "Promotion description",
"startAt": "2019-05-27",
"endAt": "2020-05-27",
"checkoutLimit": 10
}
POST /promotion
Parameters | Type | In | Description |
---|---|---|---|
name | string | body | [required] |
description | string | body | [optional] |
checkoutLimit | number | body | [required] |
startAt | string | body | [optional] |
endAt | string | body | [required] |
isActive | boolean | body | [optional] |
POST /promotion
{
"name": "Promotion",
"description": "Promotion description",
"startAt": "2019-05-27",
"endAt": "2020-05-27",
"checkoutLimit": 10,
}
Status: 201 CREATED
{
"message": "Promotion created"
}
PUT /promotion/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
name | string | body | [optional] |
description | string | body | [optional] |
checkoutLimit | number | body | [optional] |
endAt | string | body | [optional] |
isActive | boolean | body | [optional] |
PUT /promotion/1
{
"description": "Promotion description",
"endAt": "2020-05-27",
}
Status: 200 OK
{
"message": "Promotion updated"
}
DELETE /promotion/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
DELETE /promotion/1
Status: 200 OK
{
"message": "Promotion deleted"
}
GET /balance/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /balance/1
Status: 200 OK
{
"id": 1,
"promotionId": 1,
"cardId": 1,
"counter": 0,
"isActive": true
}
POST /balance
Parameters | Type | In | Description |
---|---|---|---|
promotionId | number | body | [required] |
cardId | number | body | [required] |
counter | number | body | [optional] Default 0 |
isActive | boolean | body | [optional] |
POST /balance
{
"promotionId": 1,
"cardId": 1,
"counter": 0,
"isActive": true
}
Status: 201 CREATED
{
"message": "Balance created"
}
PUT /balance/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
counter | number | body | [optional] |
isActive | boolean | body | [optional] |
PUT /balance/1
{
"counter": 10,
"isActive": false
}
Status: 200 OK
{
"message": "Balance updated"
}
DELETE /balance/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
DELETE /balance/1
Status: 200 OK
{
"message": "Balance deleted"
}
PUT /checkout
Parameters | Type | In | Description |
---|---|---|---|
uuid | string | body | [required] uuid of user (scanned from QR code) |
promotionId | number | body | [required] promotion id to apply |
PUT /checkout
{
"promotionId": 1,
"uuid": some-uuid
}
Status: 200 OK
{
"message": "Balance updated" // increments counter +1
}
or
Status: 200 OK
{
"message": "Promotion limit reached" // Limit is reached, customer gets prize
}
GET /campaign/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
GET /campaign/1
Status: 200 OK
{
"id": 1,
"promotionId": 1,
"shopId": 1,
"subject": "Hello",
"textData": "New promotion available at your store!",
"isActive": true
}
POST /balance
Parameters | Type | In | Description |
---|---|---|---|
promotionId | number | body | [optional] |
subject | string | body | [required] |
textData | string | body | [optional] One of textData , htmlData and templateUrl is required |
htmlData | string | body | [optional] One of textData , htmlData and templateUrl is required |
templateUrl | string | body | [optional] One of textData , htmlData and templateUrl is required |
POST /campaign
{
"promotionId": 1,
"subject": "Hello",
"textData": "New promotion available at your store!",
"isActive": true
}
Status: 201 CREATED
{
"message": "Campaign created"
}
This feature sends the campaign immediatly to the customers.
You can choose to send a new campaign by filling the parameters or send an existing one by only providing an id
.
POST /campaign/send
Parameters | Type | In | Description |
---|---|---|---|
id | number | body | [optional] If id is specified, the other parameters should be absent |
promotionId | number | body | [optional] Only if id is not specified |
subject | string | body | [required] Only if id is not specified |
textData | string | body | [optional] Only if id is not specified. One of textData , htmlData and templateUrl is required |
htmlData | string | body | [optional] Only if id is not specified. One of textData , htmlData and templateUrl is required |
templateUrl | string | body | [optional] Only if id is not specified. One of textData , htmlData and templateUrl is required |
POST /campaign/send
{
"id": 1,
}
OR
POST /campaign/send
{
"subject": "Hello",
"textData": "New promotion available at your store!",
"isActive": true
}
Status: 200 Ok
{
"status": 200
}
PUT /campaign/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
promotionId | number | body | [optional] |
subject | string | body | [optional] |
textData | string | body | [optional] |
htmlData | string | body | [optional] |
templateUrl | string | body | [optional] |
PUT /campaign/1
{
"counter": 10,
"isActive": false
}
Status: 200 OK
{
"message": "Campaign updated"
}
DELETE /campaign/:id
Parameters | Type | In | Description |
---|---|---|---|
id | number | query | [required] |
DELETE /campaign/1
Status: 200 OK
{
"message": "Campaign deleted"
}
GET /analytics/affluence?start_date=xxx&end_date=yyy
Parameters | Type | In | Description |
---|---|---|---|
start_date | string | query | [required] DateString (ISO) |
end_date | string | query | [required] DateString (ISO) |
GET /analytics/affluence?start_date=2022-06-23&end_date=2023-06-23
Status: 200 OK
{
"status": 200,
"value": 20
}
GET /analytics/clients-count?start_date=xxx&end_date=yyy
Parameters | Type | In | Description |
---|---|---|---|
start_date | string | query | [required] DateString (ISO) |
end_date | string | query | [required] DateString (ISO) |
GET /analytics/clients-count?start_date=2022-06-23&end_date=2023-06-23
Status: 200 OK
{
"status": 200,
"value": 20
}
GET /analytics/promotions-ranking?start_date=xxx&end_date=yyy
Parameters | Type | In | Description |
---|---|---|---|
start_date | string | query | [required] DateString (ISO) |
end_date | string | query | [required] DateString (ISO) |
GET /analytics/promotions-ranking?start_date=2022-06-23&end_date=2023-06-23
Status: 200 OK
{
"status": 200,
"promotionNames": ["best promotion", "second best promotion"],
"values": [55, 24]
}
GET /analytics/promotion-checkout-count/:id?start_date=xxx&end_date=yyy
Parameters | Type | In | Description |
---|---|---|---|
id | string | query | [required] Promotion id |
start_date | string | query | [required] DateString (ISO) |
end_date | string | query | [required] DateString (ISO) |
GET /analytics/promotion-checkout-count/1?start_date=2022-06-23&end_date=2023-06-23
Status: 200 OK
{
"status": 200,
"values": 55
}