This system represents a PoC for end-to-end supply chain monitoring for pharmaceuticals. The implementation is guided by the US and EU regulations for pharmaceutical supply chain security.
docker-compose up
The Docker setup will automatically create a track-trace
database with users
, products
, and incidents
collections in it.
These collections will be filled with dummy-data by the dbseed
service. You now can interact with our API on the admin level through the user (username: admin, password: SuperSecret)
.
Note: To reset the database (this will delete all data), remove the Docker volume backend_mongodata
. As long as this volume is present, initialization scripts will have no impact.
To force an image rebuild on docker compose, run:
docker compose up --build
- 0: Wholesaler, can checkin, checkout, and view associated products
- 1: Consumer, can checkin, terminate, and view associated products
- 2: Manufacturer, can create, checkout, and view associated products
- 3: Authorities, can signup users and view everything
- 4: Admin, has admin access
- GETs interactive documentation web page
- generates session and refresh token
POST (x-www-form-urlencoded):
{
username: str
password: str
}
Response:
{
"access_token": "str",
"refresh_token": "str",
"token_type": "str",
"access_lvl": "int"
}
- generates new session token
Header:
{
"refresh_token": "str"
}
GET:
{ }
Response:
{
"access_token": "str",
"token_type": "str",
"access_lvl": "int"
}
- enpoint to report an incident manually
- access_lvl: all
Header:
{
"access_token": "str"
}
POST:
{
"type": "str",
"serial_number": "str"
}
Response:
{
"acknowledged": "bool"
}
- returns data for incident heatmap for countries worldwide
- access_lvl: 3 & 4
Header:
{
"access_token": "str"
}
GET:
{ }
Response:
{
"heatmap_data": "[ …, { 'DE': 'int', 'addresses': [ 'str' ] }, … ]"
}
- checks if username exists
- access_lvl: 3 & 4
Header:
{
"access_token": "str"
}
GET:
{
"username": "str"
}
Response:
{
"is_username": "bool"
}
- signups new user
- access_lvl: 3 & 4
Header:
{
"access_token": "str"
}
POST:
{
"username": "str",
"password": "str",
"company": "str",
"country": "str",
"address": "str",
"access_lvl": "int"
}
Response:
{
"acknowledged": "bool"
}
- returns results of POSTed search
- access_lvl: 3 & 4
Header:
{
"access_token": "str"
}
POST:
{
MongoDB_query
}
Response:
[
MongoDB_result
]
- inserts new product into database
- access_lvl: 2 & 4
Header:
{
"access_token": "str"
}
POST:
{
"name": "str",
"common_name": "Any",
"form": "str",
"strength": "str",
"drug_code": "Any",
"pack_size": "int",
"pack_type": "Any",
"serial_number": "str",
"reimbursment_number": "Any",
"containers": "Any",
"batch_number": "str",
"expiry_date": "str",
"coding": "Any",
"marketed_states": "Any",
"manufacturer_name": "Any",
"manufacturer_adress": "Any",
"marketing_holder_name": "Any",
"marketing_holder_adress": "Any",
"wholesaler": "Any"
}
Response:
{
"acknowledged": "bool"
}
- updates product history to "in transport to…"
- access_lvl: 0, 2, & 4
Header:
{
"access_token": "str"
}
POST:
{
"serial_number": "str",
"transaction_date": "str",
"shipment_date": "str",
"owner": "str",
"owner_address": "str",
"f_owner": "str",
"f_owner_address": "str"
}
Response:
{
"acknowledged": "bool"
}
- updates product history to "arrived at…"
- access_lvl: 0, 1, & 4
Header:
{
"access_token": "str"
}
POST:
{
"serial_number": "str",
"transaction_date": "str",
"shipment_date": "str",
"prev_owner": "str",
"prev_owner_address": "str",
"owner": "str",
"owner_address": "str"
}
Response:
{
"acknowledged": "bool"
}
- updates product history to "has been used"
- access_lvl: 1 & 4
Header:
{
"access_token": "str"
}
POST:
{
"serial_number": "str"
}
Response:
{
"acknowledged": "bool"
}
- testing endpoint, modify as you please
Header:
{
"access_token": "str"
}
GET:
{
"id": "str"
}
Response:
{
"username": "str",
"password": "str | None = None",
"company": "str | None = None",
"address": "str | None = None",
"access_lvl": "int"
}
Replace the SECRET_KEY
in src/constants.py
with your own, using the following command:
openssl rand -hex 32
Change the password
property (and other properties if you want to) in dbseed/init-admin.json
, by aquiring a new password using the following command:
from passlib.context import CryptContext
CryptContext(schemes=["bcrypt"], deprecated="auto").hash("respective_password")