Skip to content

Commit b35e436

Browse files
committed
update readme file
1 parent 661d3c8 commit b35e436

9 files changed

Lines changed: 340 additions & 2 deletions

File tree

README.md

Lines changed: 247 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,248 @@
1-
# Marketplace
1+
# 🛒 Marketplace — Modern E‑Commerce Backend Platform
22

3-
> E-commerce application in FastAPI
3+
**Marketplace** is a high‑performance, scalable, and modular e‑commerce backend built with **FastAPI**. It provides a fully structured architecture that covers every essential part of an online marketplace: user authentication, product catalog, carts, orders, delivery logistics, image upload system, and review management.
4+
5+
Designed following **clean architecture principles**, the project is maintainable, extendable, and production‑ready.
6+
7+
# 🧰 Used Technologies
8+
9+
Below is the list of core technologies and dependencies used in this project, based on the project configuration:
10+
11+
### 🔧 Runtime & Frameworks
12+
13+
* **Python 3.12+**[https://www.python.org/](https://www.python.org/)
14+
* **FastAPI**[https://fastapi.tiangolo.com/](https://fastapi.tiangolo.com/)
15+
* **Uvicorn**[https://www.uvicorn.org/](https://www.uvicorn.org/)
16+
* **SQLAlchemy 2.0**[https://docs.sqlalchemy.org/](https://docs.sqlalchemy.org/)
17+
* **Alembic**[https://alembic.sqlalchemy.org/](https://alembic.sqlalchemy.org/)
18+
19+
### 📦 Async & Utilities
20+
21+
* **aiofiles**[https://github.com/Tinche/aiofiles](https://github.com/Tinche/aiofiles)
22+
* **httpx**[https://www.python-httpx.org/](https://www.python-httpx.org/)
23+
* **orjson**[https://github.com/ijl/orjson](https://github.com/ijl/orjson)
24+
* **argon2-cffi**[https://argon2-cffi.readthedocs.io/](https://argon2-cffi.readthedocs.io/)
25+
* **passlib[bcrypt]**[https://passlib.readthedocs.io/](https://passlib.readthedocs.io/)
26+
* **python-jose**[https://github.com/mpdavis/python-jose](https://github.com/mpdavis/python-jose)
27+
* **python-multipart**[https://andrew-d.github.io/python-multipart/](https://andrew-d.github.io/python-multipart/)
28+
* **pydantic-settings**[https://docs.pydantic.dev/](https://docs.pydantic.dev/)
29+
* **python-dotenv**[https://github.com/theskumar/python-dotenv](https://github.com/theskumar/python-dotenv)
30+
31+
### 📨 Email & Background Tasks
32+
33+
* **FastAPI-Mail**[https://sabuhish.github.io/fastapi-mail/](https://sabuhish.github.io/fastapi-mail/)
34+
* **Celery**[https://docs.celeryq.dev/](https://docs.celeryq.dev/)
35+
* **Flower (Celery Monitoring)**[https://flower.readthedocs.io/](https://flower.readthedocs.io/)
36+
37+
### 🧪 Testing
38+
39+
* **pytest**[https://docs.pytest.org/](https://docs.pytest.org/)
40+
* **pytest-asyncio**[https://github.com/pytest-dev/pytest-asyncio](https://github.com/pytest-dev/pytest-asyncio)
41+
* **pytest-cov**[https://github.com/pytest-dev/pytest-cov](https://github.com/pytest-dev/pytest-cov)
42+
43+
### 🛠 Development Tools
44+
45+
* **black**[https://github.com/psf/black](https://github.com/psf/black)
46+
* **isort**[https://pycqa.github.io/isort/](https://pycqa.github.io/isort/)
47+
* **ruff**[https://docs.astral.sh/ruff/](https://docs.astral.sh/ruff/)
48+
* **mypy**[https://mypy-lang.org/](https://mypy-lang.org/)
49+
* **pre-commit**[https://pre-commit.com/](https://pre-commit.com/)
50+
* **loguru**[https://github.com/Delgan/loguru](https://github.com/Delgan/loguru)
51+
52+
---
53+
54+
## 🚀 Features
55+
56+
### 👤 Users & Authentication
57+
58+
* User registration & login
59+
* Logout and token revocation
60+
* Refresh token workflow
61+
* Password recovery via email
62+
* Secure JWT‑based authentication (access + refresh tokens)
63+
* Role system with permissions:
64+
65+
* **Buyer**
66+
* **Seller**
67+
* **Courier**
68+
* **Admin**
69+
70+
---
71+
72+
## 🔐 Security
73+
74+
* Password hashing with **bcrypt**
75+
* Revoked token tracking (logout / logout_all)
76+
* Role‑based access control
77+
* Strict Pydantic validation for all input/output data
78+
* Secure and isolated file upload handling
79+
80+
---
81+
82+
## 💾 Tech Stack
83+
84+
| Layer | Technologies |
85+
| ---------------------- | ---------------------------------------- |
86+
| **Backend** | FastAPI, SQLAlchemy 2.0, Alembic |
87+
| **Database** | PostgreSQL |
88+
| **Async** | asyncpg, aiofiles |
89+
| **Authentication** | OAuth2, JWT (Access & Refresh) |
90+
| **Caching (optional)** | Redis |
91+
| **File Storage** | `/media` directory with hashed filenames |
92+
| **Testing** | Pytest |
93+
| **DevOps (optional)** | GitHub Actions |
94+
95+
---
96+
97+
## 🗄️ Database SQL Diagram
98+
![](/docs/media/diagram.png)
99+
> Project SQL diagram overview
100+
101+
### Core Tables
102+
103+
* **users**
104+
* **sellers**
105+
* **couriers**
106+
* **delivery_addresses**
107+
* **deliveries**
108+
* **product_variants**
109+
* **products**
110+
* **product_images**
111+
* **orders**
112+
* **order_items**
113+
* **brands**
114+
* **categories**
115+
* **carts**
116+
* **cart_items**
117+
* **promo_codes**
118+
119+
---
120+
121+
## 📂 Project Structure
122+
123+
```bash
124+
src/
125+
├── api/
126+
│ └── v1/
127+
│ ├── auth/
128+
│ ├── users/
129+
│ ├── products/
130+
│ ├── categories/
131+
│ ├── seller/
132+
│ ├── courier/
133+
│ ├── orders/
134+
│ └── delivery/
135+
├── core/
136+
│ ├── config.py
137+
│ └── security.py
138+
├── db/
139+
│ ├── session.py
140+
│ ├── base.py
141+
│ └── models/
142+
│ ├── users.py
143+
│ ├── products.py
144+
│ ├── categories.py
145+
│ ├── brands.py
146+
│ ├── cart.py
147+
│ ├── orders.py
148+
│ ├── delivery.py
149+
│ ├── seller_profile.py
150+
│ ├── courier_profile.py
151+
│ └── review.py
152+
├── services/
153+
└── media/
154+
```
155+
156+
---
157+
158+
## 🧠 Architecture
159+
160+
### ✔ Clean Architecture
161+
162+
* Clear separation between API, services, repositories, and database models
163+
* Easy to extend and maintain
164+
165+
### ✔ Modular & Scalable
166+
167+
* Each domain (products, orders, delivery, etc.) is fully isolated
168+
* Can be easily split into microservices (catalog, delivery, payments, etc.)
169+
170+
### ✔ Async‑first Design
171+
172+
* High throughput thanks to async stack
173+
* Perfect for real‑time tasks such as courier tracking
174+
175+
---
176+
177+
## ⚙️ Environment Variables Example (`.env-example`)
178+
179+
```env
180+
# Use this file to configure your development environment
181+
# Copy it to .env and fill your credentials
182+
```
183+
184+
## ▶️ Getting Started (Without Docker)
185+
186+
### 1. Clone Repository
187+
188+
```bash
189+
git clone https://github.com/RustamovAkrom/Marketplace-FastAPI.git
190+
cd Marketplace-FastAPI
191+
```
192+
193+
### 2. Create `.env` File
194+
195+
```env
196+
DATABASE_URL=postgresql+asyncpg://user:pass@localhost/db
197+
SECRET_KEY=your-secret-key
198+
DEBUG=true
199+
```
200+
201+
### 3. Install Dependencies
202+
203+
```bash
204+
python -m venv venv
205+
source venv/bin/activate # Linux/Mac
206+
venv\Scripts\activate # Windows
207+
pip install -r requirements.txt
208+
```
209+
210+
### 4. Run Migrations
211+
212+
```bash
213+
alembic upgrade head
214+
```
215+
216+
### 5. Start Server
217+
218+
```bash
219+
uvicorn src.main:app --reload --host 0.0.0.0 --port 8000
220+
```
221+
222+
### 6. Open API Docs
223+
224+
```
225+
http://localhost:8000/docs
226+
```
227+
228+
---
229+
230+
## 🧪 Tests
231+
232+
Run all tests using:
233+
234+
```bash
235+
pytest -vv
236+
```
237+
238+
---
239+
240+
## 👨‍💻 Author
241+
242+
**Akrom** — Backend developer passionate about scalable architecture, clean code, and modern engineering practices. Building a production‑ready e‑commerce backend for real-world use and portfolio purposes.
243+
244+
---
245+
246+
## 📄 License
247+
248+
MIT License.

docs/media/diagram.png

894 KB
Loading

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ description = "Add your description here"
55
readme = "README.md"
66
requires-python = ">=3.12"
77
dependencies = [
8+
"aiofiles>=25.1.0",
89
"aiosqlite>=0.21.0",
910
"alembic>=1.17.2",
1011
"argon2-cffi>=25.1.0",
@@ -28,6 +29,7 @@ dependencies = [
2829
"pytest-cov>=7.0.0",
2930
"python-dotenv>=1.2.1",
3031
"python-jose[cryptography]>=3.5.0",
32+
"python-multipart>=0.0.20",
3133
"ruff>=0.14.7",
3234
"types-python-jose>=3.5.0.20250531",
3335
"uvicorn[standard]>=0.38.0",

src/core/config.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
BASE_DIR = Path(__file__).resolve().parent.parent.parent
77

8+
MEDIA_ROOT = BASE_DIR / "media"
9+
MEDIA_URL = "/media/"
10+
811

912
class BaseAppSettings(BaseSettings):
1013
# ENVIRONMENT

src/db/crud/base.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# src/api/v1/upload.py
2+
from fastapi import APIRouter, Depends, HTTPException, UploadFile
3+
from sqlalchemy.ext.asyncio import AsyncSession
4+
5+
from core import config
6+
from db.crud.base import get_crud_for_model # универсальная функция для CRUD
7+
from db.dependencies.sessions import get_db_session
8+
from services.file_service import save_file
9+
10+
router = APIRouter(prefix="/upload", tags=["Upload"])
11+
12+
13+
@router.post("/{model_name}/{instance_id}/{field_name}")
14+
async def upload_file(
15+
model_name: str,
16+
instance_id: int,
17+
field_name: str,
18+
file: UploadFile,
19+
filetype: str = "image",
20+
db: AsyncSession = Depends(get_db_session),
21+
):
22+
"""
23+
Универсальный upload endpoint.
24+
model_name: имя модели в lower_case
25+
instance_id: ID объекта
26+
field_name: имя поля модели для сохранения пути
27+
"""
28+
# Получаем CRUD для модели
29+
crud = get_crud_for_model(model_name, db)
30+
if not crud:
31+
raise HTTPException(
32+
status_code=400, detail=f"Model '{model_name}' not supported"
33+
)
34+
35+
# Получаем объект
36+
instance = await crud.get_by_id(instance_id)
37+
if not instance:
38+
raise HTTPException(
39+
status_code=404, detail=f"{model_name.capitalize()} not found"
40+
)
41+
42+
# Сохраняем файл
43+
relative_path = await save_file(file, model_name, instance_id, filetype)
44+
45+
# Обновляем поле модели
46+
current_value = getattr(instance, field_name, None)
47+
if isinstance(current_value, list):
48+
# для множественных файлов
49+
current_value.append(relative_path)
50+
setattr(instance, field_name, current_value)
51+
else:
52+
# одно поле
53+
setattr(instance, field_name, relative_path)
54+
55+
db.add(instance)
56+
await db.commit()
57+
await db.refresh(instance)
58+
59+
return {"url": f"{config.MEDIA_URL}{relative_path}", "field": field_name}

src/utils/__init__.py

Whitespace-only changes.

src/utils/file_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import uuid
2+
3+
4+
def generate_filename(original_name: str) -> str:
5+
ext = original_name.split(".")[-1]
6+
return f"{uuid.uuid4().hex}.{ext}"

src/utils/sms_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
def generate_random_code(): ...

0 commit comments

Comments
 (0)