Simple Inventory + Billing CRUD API built with Python, FastAPI, and MongoDB.
- CRUD operations for 5 MongoDB collections:
suppliers,products,customers,invoices,invoice_items - Billing endpoint to create an invoice from product line items
- Automatic stock deduction during billing
- Basic duplicate protections with MongoDB indexes
- Python
- FastAPI
- PyMongo
- MongoDB
.
├── app
│ ├── __init__.py
│ ├── config.py
│ ├── database.py
│ ├── main.py
│ ├── schemas.py
│ └── utils.py
├── .env.example
├── .gitignore
├── README.md
└── requirements.txt
- Create and activate a virtual environment:
python3 -m venv .venv
source .venv/bin/activate- Install dependencies:
pip install -r requirements.txt- Copy environment file and edit values if needed:
cp .env.example .env- Ensure MongoDB is running (default URI in
.env.example):
mongodb://localhost:27017
- Run API server:
uvicorn app.main:app --reload- Open docs:
- Swagger UI:
http://127.0.0.1:8000/docs - ReDoc:
http://127.0.0.1:8000/redoc
POST /suppliersGET /suppliersGET /suppliers/{supplier_id}PUT /suppliers/{supplier_id}DELETE /suppliers/{supplier_id}
POST /productsGET /productsGET /products/{product_id}PUT /products/{product_id}DELETE /products/{product_id}
POST /customersGET /customersGET /customers/{customer_id}PUT /customers/{customer_id}DELETE /customers/{customer_id}
POST /invoicesGET /invoicesGET /invoices/{invoice_id}PUT /invoices/{invoice_id}DELETE /invoices/{invoice_id}
POST /invoice-itemsGET /invoice-itemsGET /invoice-items/{invoice_item_id}PUT /invoice-items/{invoice_item_id}DELETE /invoice-items/{invoice_item_id}
POST /billing/invoices
Creates an invoice from product lines, inserts invoice items, and decreases stock.
curl -X POST "http://127.0.0.1:8000/billing/invoices" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "CUSTOMER_OBJECT_ID",
"tax_rate": 0.05,
"items": [
{"product_id": "PRODUCT_OBJECT_ID_1", "quantity": 2},
{"product_id": "PRODUCT_OBJECT_ID_2", "quantity": 1}
]
}'- MongoDB uses collections, which are the equivalent of SQL tables.
- This project is intentionally simple and does not implement auth.