Keep a single README and remove extra markdown docs

EOF

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Shayan Azadi
2026-07-16 17:32:04 +03:30
parent 50c9cf613f
commit 97127d5772
3 changed files with 2 additions and 813 deletions

View File

@@ -1,584 +0,0 @@
<div dir="rtl" lang="fa">
# مستندات API (Zoneco ORG)
این سند نحوهٔ کارکرد APIهای بک‌اند پروژه Zoneco ORG را به زبان فارسی توضیح می‌دهد.
---
## وضعیت تست‌ها
```
Ran 31 tests — OK (0 failures)
```
| تعداد تست | گروه |
|-----------|------|
| ۷ تست | Admin Login |
| ۶ تست | Contact Us |
| ۱۱ تست | Compositions |
| ۷ تست | Campaigns |
اجرای تست‌ها:
```bash
cd backend
python manage.py test api -v 2
```
---
## اطلاعات پایه
| مقدار | مورد |
|--------|------|
| `{{base_url}}` | آدرس پایه |
| `/api/` | پیشوند API |
| JSON | فرمت پاسخ |
| ۲۰ آیتم در هر صفحه | صفحه‌بندی |
| `/admin/` | پنل ادمین |
### متغیر Postman
در فایل Postman از متغیر `{{base_url}}` استفاده شده است.
مقدار آن را مطابق محیط اجرا (لوکال، سرور تست یا پروداکشن) تنظیم کنید.
**نمونهٔ آدرس کامل یک endpoint:**
```
{{base_url}}/api/contact-us/
```
---
## سطح دسترسی
| دسترسی | عملیات |
|--------|--------|
| عمومی — بدون نیاز به ورود | لیست و جزئیات (متد `GET`) |
| عمومی — بدون نیاز به ورود | ایجاد (متد `POST`) |
| فقط ادمین — نیاز به توکن | ویرایش و حذف (متدهای `PUT`، `PATCH`، `DELETE`) |
---
## ۰. ورود ادمین (Admin Login)
| مقدار | مورد |
|--------|------|
| `{{admin_username}}` از env (`ADMIN_USERNAME`) | نام کاربری |
| `{{admin_password}}` از env (`ADMIN_PASSWORD`) | رمز عبور |
| `{{base_url}}/admin/` | پنل جنگو ادمین |
| `POST {{base_url}}/api/admin/login/` | ورود از طریق API |
> نام کاربری و رمز در کد هاردکد نمی‌شوند. روی سرور در فایل `.env` تنظیم کنید.
### ورود و دریافت توکن
```
POST {{base_url}}/api/admin/login/
Content-Type: application/json
```
```json
{
"username": "{{admin_username}}",
"password": "{{admin_password}}"
}
```
**پاسخ نمونه:**
```json
{
"token": "<token>",
"user": {
"id": 1,
"username": "<admin_username>",
"is_staff": true,
"is_superuser": true
}
}
```
در درخواست‌های محافظت‌شده این هدر را بفرستید:
```
Authorization: Token <token>
```
### اطلاعات ادمین فعلی
```
GET {{base_url}}/api/admin/me/
Authorization: Token <token>
```
### خروج (حذف توکن)
```
POST {{base_url}}/api/admin/logout/
Authorization: Token <token>
```
برای درخواست‌های ادمین در Postman، ابتدا login کنید، سپس توکن را در متغیر `admin_token` بگذارید.
---
## ۱. تماس با ما (Contact Us)
**مسیر پایه:**
```
/api/contact-us/
```
### فیلدها
| توضیح | الزامی | نوع | فیلد |
|-------|--------|-----|------|
| نام و نام خانوادگی | بله | string | `name` |
| ایمیل یا شماره تماس | بله | string | `email_or_phone` |
| متن پیام | بله | string | `description` |
| دسته‌بندی | بله | string | `category` |
**مقادیر مجاز برای `category`:**
- همکاری
- فروش
- پشتیبانی
- درخواست مشاور
- سایر
---
### دریافت لیست تماس‌ها
```
GET {{base_url}}/api/contact-us/
```
**پاسخ نمونه:**
```json
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"name": "احمد محمدی",
"email_or_phone": "ahmad@example.com",
"description": "سلام، سوالی دارم.",
"category": "پشتیبانی",
"created_at": "2025-12-17T12:00:00Z",
"updated_at": "2025-12-17T12:00:00Z"
}
]
}
```
---
### دریافت یک تماس
```
GET {{base_url}}/api/contact-us/{id}/
```
---
### ثبت تماس جدید
```
POST {{base_url}}/api/contact-us/
Content-Type: application/json
```
**بدنه درخواست:**
```json
{
"name": "احمد محمدی",
"email_or_phone": "09121234567",
"description": "می‌خواهم در مورد محصولات اطلاعات بگیرم.",
"category": "فروش"
}
```
**کد پاسخ:** `201 Created`
---
### فیلتر بر اساس دسته‌بندی
```
GET {{base_url}}/api/contact-us/by_category/?category=پشتیبانی
```
| توضیح | الزامی | پارامتر |
|-------|--------|---------|
| یکی از دسته‌های مجاز | بله | `category` |
اگر پارامتر `category` ارسال نشود، خطای `400` برمی‌گردد.
---
### ویرایش و حذف (ادمین)
```
PUT {{base_url}}/api/contact-us/{id}/
PATCH {{base_url}}/api/contact-us/{id}/
DELETE {{base_url}}/api/contact-us/{id}/
```
نیاز به احراز هویت ادمین دارد.
---
## ۲. ترکیبات (Compositions)
**مسیر پایه:**
```
/api/compositions/
```
هر ترکیب می‌تواند **چند تصویر** داشته باشد.
یکی از تصاویر با فیلد `is_main: true` به‌عنوان **تصویر اصلی** مشخص می‌شود.
### فیلدها
| توضیح | الزامی | نوع | فیلد |
|-------|--------|-----|------|
| نام ترکیب | بله | string | `name` |
| توضیحات | بله | string | `description` |
| یک یا چند فایل تصویر (فقط در ایجاد/ویرایش) | خیر | file[] | `uploaded_images` |
| ایندکس تصویر اصلی (شمارش از ۰) | خیر | integer | `main_image_index` |
### محدودیت تصاویر
- فرمت‌های مجاز: JPEG، PNG، WebP، GIF
- حداکثر حجم هر فایل: **۵ مگابایت**
- مسیر ذخیره: `media/compositions/`
---
### دریافت لیست ترکیبات
```
GET {{base_url}}/api/compositions/
```
---
### دریافت یک ترکیب
```
GET {{base_url}}/api/compositions/{id}/
```
**پاسخ نمونه:**
```json
{
"id": 1,
"name": "ترکیب A",
"description": "توضیحات ترکیب",
"image": null,
"image_url": null,
"images": [
{
"id": 2,
"image": "/media/compositions/img2.jpg",
"image_url": "{{base_url}}/media/compositions/img2.jpg",
"is_main": true,
"created_at": "2025-12-17T12:00:00Z"
},
{
"id": 1,
"image": "/media/compositions/img1.jpg",
"image_url": "{{base_url}}/media/compositions/img1.jpg",
"is_main": false,
"created_at": "2025-12-17T11:00:00Z"
}
],
"main_image": {
"id": 2,
"image_url": "{{base_url}}/media/compositions/img2.jpg",
"is_main": true,
"created_at": "2025-12-17T12:00:00Z"
},
"created_at": "2025-12-17T10:00:00Z",
"updated_at": "2025-12-17T12:00:00Z"
}
```
---
### فیلتر بر اساس تاریخ ایجاد
```
GET {{base_url}}/api/compositions/by-created-at/?from=2026-06-01T00:00:00Z&to=2026-06-30T23:59:59Z
```
| توضیح | الزامی | پارامتر |
|-------|--------|---------|
| برگشت ترکیب‌هایی که `created_at >= from` | حداقل یکی | `from` |
| برگشت ترکیب‌هایی که `created_at <= to` | حداقل یکی | `to` |
فرمت تاریخ: ISO 8601 — مثال: `2026-06-01T00:00:00Z`
اگر هیچ پارامتری ارسال نشود، خطای `400` برمی‌گردد.
---
### ایجاد ترکیب (بدون تصویر)
```
POST {{base_url}}/api/compositions/
Content-Type: application/json
```
```json
{
"name": "ترکیب تست",
"description": "توضیحات ترکیب"
}
```
---
### ایجاد ترکیب با چند تصویر
```
POST {{base_url}}/api/compositions/
Content-Type: multipart/form-data
```
| مقدار نمونه | نوع | فیلد |
|-------------|-----|------|
| ترکیب A | text | `name` |
| توضیحات | text | `description` |
| image1.jpg | file | `uploaded_images` |
| image2.jpg | file | `uploaded_images` |
| 1 | text | `main_image_index` |
**نکته:** فیلد `uploaded_images` را برای هر تصویر یک‌بار تکرار کنید.
**نکته:** اگر `main_image_index` ارسال نشود، **اولین تصویر** به‌عنوان تصویر اصلی انتخاب می‌شود.
---
### افزودن تصویر به ترکیب موجود (ادمین)
```
POST {{base_url}}/api/compositions/{id}/add-images/
Content-Type: multipart/form-data
```
| نوع | فیلد |
|-----|------|
| file (یک یا چند فایل) | `uploaded_images` |
| text (اختیاری) | `main_image_index` |
---
### تنظیم تصویر اصلی (ادمین)
```
POST {{base_url}}/api/compositions/{id}/set-main-image/
Content-Type: application/json
```
```json
{
"image_id": 3
}
```
---
### حذف یک تصویر (ادمین)
```
DELETE {{base_url}}/api/compositions/{id}/images/{image_id}/
```
**کد پاسخ:** `204 No Content`
---
### ویرایش و حذف ترکیب (ادمین)
```
PUT {{base_url}}/api/compositions/{id}/
PATCH {{base_url}}/api/compositions/{id}/
DELETE {{base_url}}/api/compositions/{id}/
```
---
## ۳. کمپین‌ها (Campaigns)
**مسیر پایه:**
```
/api/campaigns/
```
### فیلدها
| توضیح | الزامی | نوع | فیلد |
|-------|--------|-----|------|
| نام کمپین | بله | string | `name` |
| توضیحات | بله | string | `description` |
| زمان شروع (ISO 8601) | بله | datetime | `start_time` |
| زمان پایان (باید بعد از `start_time` باشد) | بله | datetime | `end_time` |
| تصویر کمپین | خیر | file | `image` |
### فیلدهای محاسباتی (فقط خواندنی)
| توضیح | فیلد |
|-------|------|
| آیا کمپین الان فعال است | `is_active` |
| آیا کمپین هنوز شروع نشده | `is_upcoming` |
| آیا کمپین تمام شده | `is_ended` |
---
### دریافت لیست کمپین‌ها
```
GET {{base_url}}/api/campaigns/
```
---
### دریافت یک کمپین
```
GET {{base_url}}/api/campaigns/{id}/
```
---
### ایجاد کمپین
```
POST {{base_url}}/api/campaigns/
Content-Type: application/json
```
```json
{
"name": "کمپین نوروز",
"description": "تخفیف ویژه نوروز",
"start_time": "2026-03-01T00:00:00Z",
"end_time": "2026-03-31T23:59:59Z"
}
```
---
### کمپین‌های فعال
```
GET {{base_url}}/api/campaigns/active/
```
کمپین‌هایی که زمان فعلی بین `start_time` و `end_time` قرار دارد.
---
### کمپین‌های آینده
```
GET {{base_url}}/api/campaigns/upcoming/
```
کمپین‌هایی که هنوز شروع نشده‌اند.
---
### کمپین‌های پایان‌یافته
```
GET {{base_url}}/api/campaigns/ended/
```
---
### ویرایش و حذف (ادمین)
```
PUT {{base_url}}/api/campaigns/{id}/
PATCH {{base_url}}/api/campaigns/{id}/
DELETE {{base_url}}/api/campaigns/{id}/
```
---
## کدهای وضعیت HTTP
| معنی | کد |
|------|-----|
| موفق | `200` |
| ایجاد شد | `201` |
| حذف شد (بدون بدنه) | `204` |
| داده نامعتبر | `400` |
| دسترسی ندارید | `403` |
| یافت نشد | `404` |
---
## فایل Postman
مجموعه Postman در مسیر زیر قرار دارد:
```
backend/Zoneco_ORG_API.postman_collection.json
```
### نحوه import
1. Postman را باز کنید
2. گزینه **Import** را بزنید
3. فایل `Zoneco_ORG_API.postman_collection.json` را انتخاب کنید
4. متغیر `{{base_url}}` را مطابق محیط خود تنظیم کنید
5. برای درخواست‌های ادمین، در تب **Authorization** گزینه **Basic Auth** را فعال کنید
---
## خلاصه endpointها
| دسترسی | Endpoint | Method | # |
|--------|----------|--------|---|
| عمومی | `/api/admin/login/` | POST | 1 |
| ادمین | `/api/admin/logout/` | POST | 2 |
| ادمین | `/api/admin/me/` | GET | 3 |
| عمومی | `/api/contact-us/` | GET | 4 |
| عمومی | `/api/contact-us/` | POST | 5 |
| عمومی | `/api/contact-us/{id}/` | GET | 6 |
| عمومی | `/api/contact-us/by_category/?category=...` | GET | 7 |
| ادمین | `/api/contact-us/{id}/` | PUT/PATCH/DELETE | 8 |
| عمومی | `/api/compositions/` | GET | 9 |
| عمومی | `/api/compositions/` | POST | 10 |
| عمومی | `/api/compositions/{id}/` | GET | 11 |
| عمومی | `/api/compositions/by-created-at/?from=...&to=...` | GET | 12 |
| ادمین | `/api/compositions/{id}/add-images/` | POST | 13 |
| ادمین | `/api/compositions/{id}/set-main-image/` | POST | 14 |
| ادمین | `/api/compositions/{id}/images/{image_id}/` | DELETE | 15 |
| ادمین | `/api/compositions/{id}/` | PUT/PATCH/DELETE | 16 |
| عمومی | `/api/campaigns/` | GET | 17 |
| عمومی | `/api/campaigns/` | POST | 18 |
| عمومی | `/api/campaigns/{id}/` | GET | 19 |
| عمومی | `/api/campaigns/active/` | GET | 20 |
| عمومی | `/api/campaigns/upcoming/` | GET | 21 |
| عمومی | `/api/campaigns/ended/` | GET | 22 |
| ادمین | `/api/campaigns/{id}/` | PUT/PATCH/DELETE | 23 |
> **توجه:** در Postman قبل از هر مسیر، مقدار `{{base_url}}` را قرار دهید.
> مثال: `{{base_url}}/api/campaigns/active/`
</div>

View File

@@ -1,221 +0,0 @@
# Docker Setup for Zoneco ORG Backend
This document provides instructions for running the Zoneco ORG backend using Docker and Docker Compose.
## Prerequisites
- Docker Engine 20.10 or higher
- Docker Compose 2.0 or higher
## Quick Start
1. **Navigate to the backend directory:**
```bash
cd backend
```
2. **Create a `.env` file** (copy from the template below):
```bash
# Copy and modify as needed
SECRET_KEY=your-secret-key-here-change-in-production
DEBUG=False
ALLOWED_HOSTS=localhost,127.0.0.1,YOUR_SERVER_IP
POSTGRES_DB=Zoneco_ORG
POSTGRES_USER=postgres
POSTGRES_PASSWORD=change-me
POSTGRES_HOST=db
POSTGRES_PORT=5432
DJANGO_PORT=8000
ADMIN_USERNAME=your-admin-username
ADMIN_PASSWORD=your-admin-password
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://localhost:3000,http://YOUR_SERVER_IP:9123
```
3. **Build and start the containers:**
```bash
docker-compose up --build
```
4. **The application will be available at:**
- API: `http://localhost:8000/api/`
- Admin: `http://localhost:8000/admin/`
## Docker Commands
### Start services
```bash
docker-compose up
```
### Start services in detached mode
```bash
docker-compose up -d
```
### Stop services
```bash
docker-compose down
```
### Stop services and remove volumes (⚠️ deletes database data)
```bash
docker-compose down -v
```
### View logs
```bash
docker-compose logs -f
```
### View logs for specific service
```bash
docker-compose logs -f web
docker-compose logs -f db
```
### Rebuild containers
```bash
docker-compose build --no-cache
```
### Execute commands in running container
```bash
# Django shell
docker-compose exec web python manage.py shell
# Create superuser
docker-compose exec web python manage.py createsuperuser
# Run migrations manually
docker-compose exec web python manage.py migrate
# Collect static files
docker-compose exec web python manage.py collectstatic --noinput
```
## Architecture
The Docker setup consists of:
1. **Web Service** (`web`):
- Django application running with Gunicorn
- Multi-stage Dockerfile for optimized image size
- Non-root user for security
- Automatic migrations and static file collection on startup
- Health checks enabled
2. **Database Service** (`db`):
- PostgreSQL 15 Alpine (lightweight)
- Persistent data volume
- Health checks to ensure readiness
## Features
### Security Best Practices
- ✅ Multi-stage build for smaller image size
- ✅ Non-root user execution
- ✅ Environment variable configuration
- ✅ No hardcoded secrets
- ✅ Health checks for both services
### Production Ready
- ✅ Gunicorn WSGI server
- ✅ Automatic database migrations
- ✅ Static file collection
- ✅ Database connection retry logic
- ✅ Proper logging
### Development Friendly
- ✅ Volume mounts for media and static files
- ✅ Hot-reload capability (with proper setup)
- ✅ Easy access to Django management commands
## Environment Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `SECRET_KEY` | Django secret key | (required in production) |
| `DEBUG` | Enable debug mode | `False` |
| `ALLOWED_HOSTS` | Comma-separated allowed hosts | `localhost,127.0.0.1` |
| `POSTGRES_DB` | Database name | `Zoneco_ORG` |
| `POSTGRES_USER` | Database user | `postgres` |
| `POSTGRES_PASSWORD` | Database password | `postgres` |
| `POSTGRES_HOST` | Database host | `db` |
| `POSTGRES_PORT` | Database port | `5432` |
| `DJANGO_PORT` | Django application port | `8000` |
| `CORS_ALLOWED_ORIGINS` | Comma-separated CORS origins | (see .env.example) |
## Volumes
- `postgres_data`: Persistent PostgreSQL data
- `./media`: Media files (images, uploads)
- `./staticfiles`: Collected static files
## Troubleshooting
### Database connection errors
```bash
# Check if database is healthy
docker-compose ps
# Check database logs
docker-compose logs db
# Restart services
docker-compose restart
```
### Permission issues
```bash
# Fix media/staticfiles permissions
sudo chown -R $USER:$USER media staticfiles
```
### Port already in use
```bash
# Change port in .env file
DJANGO_PORT=8001
# Then update docker-compose.yml or restart
```
### Clear everything and start fresh
```bash
docker-compose down -v
docker-compose build --no-cache
docker-compose up
```
## Production Deployment
For production deployment:
1. **Set strong SECRET_KEY:**
```bash
python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())"
```
2. **Set DEBUG=False** in `.env`
3. **Configure proper ALLOWED_HOSTS**
4. **Use strong database passwords**
5. **Consider using:**
- Reverse proxy (nginx)
- SSL/TLS certificates
- Separate database server
- Backup strategy
- Monitoring and logging
## File Structure
```
backend/
├── Dockerfile # Multi-stage production Dockerfile
├── docker-compose.yml # Service orchestration
├── .dockerignore # Files to exclude from build
├── entrypoint.sh # Startup script
├── requirements.txt # Python dependencies
└── DOCKER_README.md # This file
```

View File

@@ -299,15 +299,9 @@ DB constraint: only one `is_main=True` per composition.
## Postman Collection
Import `backend/Zoneco_ORG_API.postman_collection.json` into Postman.
Import `Zoneco_ORG_API.postman_collection.json` into Postman.
Set the `base_url` collection variable to your server address.
---
## Persian Documentation
Full Persian API documentation: `backend/API_DOCS_FA.md`
Set collection variables: `base_url`, `admin_username`, `admin_password`.
---