Files
peikarband/docs/handbook.md
Ehsan.Asadi a0e778f007
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/manual/woodpecker Pipeline failed
CD - Build & Deploy / build-and-push (push) Has been cancelled
CD - Build & Deploy / package-helm (push) Has been cancelled
CD - Build & Deploy / deploy-staging (push) Has been cancelled
CD - Build & Deploy / deploy-production (push) Has been cancelled
CD - Build & Deploy / release (push) Has been cancelled
CI / test (3.11) (push) Has been cancelled
CI / test (3.12) (push) Has been cancelled
CI / security (push) Has been cancelled
fix: change REFLEX_ENV from 'production' to 'prod' in Dockerfile
Reflex only accepts 'dev' or 'prod' as valid --env values.
This was causing: Error: Invalid value for '--env': 'production' is not one of 'dev', 'prod'

Changes:
- Dockerfile: REFLEX_ENV=production -> prod
- Dockerfile CMD: --env production -> prod
- docs/handbook.md: updated example command
2025-12-30 17:14:01 +03:30

23 KiB

پروژه پیکربند - Handbook جامع

نسخه: 1.0.0
آخرین بروزرسانی: 2025-01-24
نویسنده: تیم توسعه پیکربند


فهرست مطالب

  1. معرفی پروژه
  2. معماری کلی
  3. قوانین و استانداردها
  4. راه‌اندازی محیط توسعه
  5. ساختار پروژه
  6. Design Patterns
  7. Best Practices
  8. Testing Strategy
  9. Deployment Guide
  10. Troubleshooting
  11. مستندسازی تغییرات

1. معرفی پروژه

1.1 هدف

پیکربند یک پلتفرم جامع مدیریت هاستینگ و زیرساخت ابری است که شامل:

  • هاستینگ وردپرس: مدیریت حرفه‌ای سایت‌های WordPress
  • فروش دامین: ثبت و مدیریت دامین‌ها
  • سرورهای اختصاصی: VPS و Dedicated Servers
  • خدمات DevOps: مشاوره و پیاده‌سازی
  • پنل مدیریت: پنل کنترل سفارشی شبیه cPanel

1.2 تکنولوژی‌های استفاده شده

تکنولوژی نسخه کاربرد
Python 3.11+ زبان اصلی
Reflex 0.4.0 Frontend/Backend Framework
PostgreSQL 14+ Database اصلی
Redis 7+ Cache & Sessions
SQLAlchemy 2.0+ ORM
Celery 5.3+ Task Queue
pytest 7.4+ Testing

1.3 اصول طراحی

Clean Architecture

پروژه بر اساس معماری تمیز طراحی شده که شامل 4 لایه اصلی است:

  1. Domain Layer: منطق کسب‌وکار خالص
  2. Application Layer: موارد استفاده (Use Cases)
  3. Infrastructure Layer: جزئیات فنی
  4. Presentation Layer: رابط کاربری

SOLID Principles

  • Single Responsibility Principle
  • Open/Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

سایر اصول

  • DRY: Don't Repeat Yourself
  • KISS: Keep It Simple, Stupid
  • YAGNI: You Aren't Gonna Need It
  • Convention over Configuration

2. معماری کلی

2.1 نمای کلی لایه‌ها

┌─────────────────────────────────────────┐
│      Presentation Layer (Reflex UI)     │
│  ┌────────┐  ┌────────┐  ┌────────┐   │
│  │Landing │  │Dashboard│  │ Admin │   │
│  └────────┘  └────────┘  └────────┘   │
└──────────────────┬──────────────────────┘
                   │
┌──────────────────┴──────────────────────┐
│       Application Layer (Use Cases)      │
│  ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐  │
│  │ Auth │ │Billing│ │Server│ │Ticket│  │
│  └──────┘ └──────┘ └──────┘ └──────┘  │
└──────────────────┬──────────────────────┘
                   │
┌──────────────────┴──────────────────────┐
│     Domain Layer (Business Logic)        │
│  ┌────────┐ ┌────────┐ ┌────────┐     │
│  │Entities│ │ Values │ │Services│     │
│  └────────┘ └────────┘ └────────┘     │
└──────────────────┬──────────────────────┘
                   │
┌──────────────────┴──────────────────────┐
│   Infrastructure Layer (Technical)       │
│  ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐      │
│  │ DB  │ │Cache│ │ API │ │Tasks│      │
│  └─────┘ └─────┘ └─────┘ └─────┘      │
└─────────────────────────────────────────┘

2.2 جریان داده

User Request → Presentation → Application → Domain
                                            ↓
Infrastructure ← Application ← Domain Logic
                ↓
          External APIs

2.3 Layer های جزئی

Domain Layer

  • Entities: موجودیت‌های اصلی (User, Service, Invoice, etc.)
  • Value Objects: اشیاء ارزشی (Email, Money, Phone)
  • Domain Services: منطق پیچیده دامین
  • Enums: مقادیر ثابت
  • Exceptions: خطاهای دامین

Application Layer

  • Use Cases: موارد استفاده سیستم
  • DTOs: Data Transfer Objects
  • Interfaces: تعریف رابط‌های سرویس‌ها
  • Validators: اعتبارسنجی ورودی‌ها

Infrastructure Layer

  • Database: Models و Repositories
  • Cache: Redis implementation
  • External: API های خارجی
  • Tasks: Background jobs
  • Security: Authentication & Authorization
  • Logging: Structured logging

Presentation Layer

  • Web: Reflex components و pages
  • API: REST endpoints (optional)
  • State: Reflex state management

3. قوانین و استانداردها

3.1 Python Code Style (PEP 8)

Naming Conventions

# Classes: PascalCase
class UserService:
    pass

class PaymentGateway:
    pass

# Functions & Methods: snake_case
def create_user(email: str) -> User:
    pass

def process_payment(amount: Decimal) -> PaymentResult:
    pass

# Constants: UPPER_SNAKE_CASE
MAX_LOGIN_ATTEMPTS = 3
DEFAULT_TIMEOUT = 30
API_VERSION = "v1"

# Private methods: _leading_underscore
def _internal_helper():
    pass

# Protected: __double_underscore (name mangling)
class BaseClass:
    def __private_method(self):
        pass

# Variables: snake_case
user_email = "test@example.com"
total_amount = Decimal("100.00")

3.2 Type Hints (الزامی)

from typing import Optional, List, Dict, Any, Union
from decimal import Decimal

# Function signatures
def get_user_by_id(user_id: int) -> Optional[User]:
    pass

def create_invoice(
    user_id: int,
    amount: Decimal,
    items: List[InvoiceItem]
) -> Invoice:
    pass

# Return types
def get_users(limit: int = 10) -> List[User]:
    pass

def find_service(service_id: int) -> Optional[Service]:
    pass

# Complex types
def process_config(config: Dict[str, Any]) -> bool:
    pass

UserOrNone = Optional[User]
ServiceList = List[Service]

3.3 Docstrings (Google Style - الزامی)

def create_user(
    email: str,
    password: str,
    full_name: str,
    phone: Optional[str] = None
) -> User:
    """Create a new user account.
    
    This function creates a new user in the system with the provided
    information. Password is automatically hashed before storage.
    
    Args:
        email: User's email address (must be unique)
        password: Plain text password (will be hashed)
        full_name: User's full name
        phone: Optional phone number
        
    Returns:
        User: Created user object
        
    Raises:
        EmailAlreadyExistsException: If email is already registered
        InvalidEmailException: If email format is invalid
        WeakPasswordException: If password doesn't meet requirements
        
    Example:
        >>> user = create_user(
        ...     email="test@example.com",
        ...     password="SecurePass123!",
        ...     full_name="John Doe",
        ...     phone="+989123456789"
        ... )
        >>> print(user.id)
        1
    """
    pass

3.4 Import Order (با isort)

# 1. Standard library imports
import os
import sys
from typing import Optional, List
from decimal import Decimal
from datetime import datetime

# 2. Third-party imports
import redis
from sqlalchemy import Column, Integer, String
from pydantic import BaseModel

# 3. Local application imports
from src.config.settings import settings
from src.core.domain.entities.user import User
from src.infrastructure.database.repositories.user_repository import UserRepository

3.5 Error Handling

# ✅ GOOD: Specific exceptions
try:
    user = user_repository.get_by_id(user_id)
    if not user:
        raise UserNotFoundException(f"User {user_id} not found")
except DatabaseException as e:
    logger.error("database_error", error=str(e), user_id=user_id)
    raise
except Exception as e:
    logger.critical("unexpected_error", error=str(e))
    raise InfrastructureException("Internal server error") from e

# ❌ BAD: Generic exceptions
try:
    # code
except:  # Never do this!
    pass

# ❌ BAD: Too broad
try:
    # code
except Exception:
    pass

3.6 Logging Best Practices

import structlog

logger = structlog.get_logger(__name__)

# ✅ GOOD: Structured logging with context
logger.info(
    "user_created",
    user_id=user.id,
    email=user.email,
    registration_source="web",
    ip_address=request.ip
)

logger.error(
    "payment_failed",
    user_id=user.id,
    invoice_id=invoice.id,
    amount=str(invoice.amount),
    gateway="zarinpal",
    error_code=response.code,
    error_message=response.message
)

# ❌ BAD: String concatenation
logger.info("User " + str(user.id) + " created")

4. راه‌اندازی محیط توسعه

4.1 پیش‌نیازها

# Check Python version (3.11+)
python --version

# Check PostgreSQL (14+)
psql --version

# Check Redis (7+)
redis-cli --version

# Check Node.js (18+)
node --version

4.2 نصب وابستگی‌ها

# Clone repository
git clone https://github.com/yourusername/peikarband.git
cd peikarband

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt

# Install pre-commit hooks
pre-commit install

4.3 تنظیم Environment Variables

# Copy example env file
cp .env.example .env

# Edit .env file
nano .env

# Required variables:
# - DATABASE_URL
# - REDIS_URL
# - SECRET_KEY
# - JWT_SECRET_KEY

4.4 راه‌اندازی دیتابیس

# Create database
createdb peikarband

# Or using psql
psql -U postgres
CREATE DATABASE peikarband;
\q

# Run migrations
alembic upgrade head

# (Optional) Seed database
python scripts/seed_database.py

4.5 اجرای پروژه

# Development mode
python -m reflex run

# With auto-reload
python -m reflex run --reload

# Production mode
python -m reflex run --env prod

5. ساختار پروژه

5.1 نمای کلی

peikarband/
├── docs/                    # Documentation
├── src/                     # Source code
├── tests/                   # Tests
├── scripts/                 # Utility scripts
├── .github/workflows/       # CI/CD
└── [config files]           # Configuration

5.2 src/ Structure

src/
├── config/                  # Configuration
│   ├── settings.py         # Main settings
│   ├── database.py         # DB config
│   ├── cache.py            # Redis config
│   └── logging.py          # Log config
│
├── core/                    # Core business logic
│   ├── domain/             # Domain layer
│   │   ├── entities/       # Business entities
│   │   ├── value_objects/  # Value objects
│   │   ├── enums/          # Enumerations
│   │   └── exceptions/     # Domain exceptions
│   │
│   ├── application/        # Application layer
│   │   ├── use_cases/      # Use cases
│   │   ├── dto/            # DTOs
│   │   ├── interfaces/     # Service interfaces
│   │   └── validators/     # Validators
│   │
│   └── utils/              # Core utilities
│
├── infrastructure/         # Infrastructure layer
│   ├── database/          # Database implementation
│   ├── cache/             # Cache implementation
│   ├── external/          # External APIs
│   ├── tasks/             # Background tasks
│   ├── security/          # Security utilities
│   └── logging/           # Logging setup
│
├── presentation/          # Presentation layer
│   ├── web/              # Reflex web app
│   │   ├── pages/        # Pages
│   │   ├── components/   # Components
│   │   ├── state/        # State management
│   │   └── styles/       # Styling
│   │
│   └── api/              # REST API (optional)
│
└── shared/               # Shared code
    ├── events/           # Domain events
    └── messaging/        # Event bus

6. Design Patterns

6.1 Repository Pattern

from abc import ABC, abstractmethod
from typing import Optional, List

# Interface (in core/application/interfaces/repositories/)
class IUserRepository(ABC):
    @abstractmethod
    def get_by_id(self, user_id: int) -> Optional[User]:
        """Get user by ID."""
        pass
    
    @abstractmethod
    def get_by_email(self, email: str) -> Optional[User]:
        """Get user by email."""
        pass
    
    @abstractmethod
    def save(self, user: User) -> User:
        """Save or update user."""
        pass
    
    @abstractmethod
    def delete(self, user_id: int) -> bool:
        """Delete user."""
        pass

# Implementation (in infrastructure/database/repositories/)
class UserRepository(IUserRepository):
    def __init__(self, session: Session):
        self._session = session
    
    def get_by_id(self, user_id: int) -> Optional[User]:
        model = self._session.query(UserModel).filter_by(id=user_id).first()
        return self._to_entity(model) if model else None
    
    def save(self, user: User) -> User:
        model = self._to_model(user)
        self._session.add(model)
        self._session.commit()
        self._session.refresh(model)
        return self._to_entity(model)

6.2 Unit of Work Pattern

from contextlib import contextmanager

class UnitOfWork:
    """Manages database transactions."""
    
    def __init__(self, session_factory):
        self.session_factory = session_factory
        self._session = None
    
    def __enter__(self):
        self._session = self.session_factory()
        self.users = UserRepository(self._session)
        self.services = ServiceRepository(self._session)
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            self._session.rollback()
        else:
            self._session.commit()
        self._session.close()

# Usage
with UnitOfWork(SessionLocal) as uow:
    user = uow.users.get_by_id(1)
    user.email = "new@email.com"
    uow.users.save(user)
    # Automatically commits on success

6.3 Factory Pattern

from abc import ABC, abstractmethod

class ICloudProvider(ABC):
    @abstractmethod
    def create_server(self, config: ServerConfig) -> Server:
        pass

class DigitalOceanProvider(ICloudProvider):
    def create_server(self, config: ServerConfig) -> Server:
        # Implementation
        pass

class HetznerProvider(ICloudProvider):
    def create_server(self, config: ServerConfig) -> Server:
        # Implementation
        pass

class CloudProviderFactory:
    @staticmethod
    def create(provider_type: str) -> ICloudProvider:
        providers = {
            "digitalocean": DigitalOceanProvider,
            "hetzner": HetznerProvider,
            "ovh": OVHProvider,
        }
        
        provider_class = providers.get(provider_type)
        if not provider_class:
            raise ValueError(f"Unknown provider: {provider_type}")
        
        return provider_class()

# Usage
provider = CloudProviderFactory.create("digitalocean")
server = provider.create_server(config)

6.4 Strategy Pattern

class PaymentStrategy(ABC):
    @abstractmethod
    def pay(self, amount: Decimal) -> PaymentResult:
        pass

class ZarinpalPayment(PaymentStrategy):
    def pay(self, amount: Decimal) -> PaymentResult:
        # Zarinpal implementation
        pass

class IdPayPayment(PaymentStrategy):
    def pay(self, amount: Decimal) -> PaymentResult:
        # IdPay implementation
        pass

class PaymentProcessor:
    def __init__(self, strategy: PaymentStrategy):
        self._strategy = strategy
    
    def process(self, amount: Decimal) -> PaymentResult:
        return self._strategy.pay(amount)

# Usage
processor = PaymentProcessor(ZarinpalPayment())
result = processor.process(Decimal("100.00"))

7. Best Practices

7.1 کد تمیز

# ✅ GOOD: Clear and simple
def calculate_total_price(items: List[Item]) -> Decimal:
    """Calculate total price of items."""
    return sum(item.price * item.quantity for item in items)

# ❌ BAD: Too complex
def calc(i):
    t = 0
    for x in i:
        t += x[0] * x[1]
    return t

7.2 Don't Repeat Yourself (DRY)

# ❌ BAD: Repetition
def get_user_name(user_id: int) -> str:
    session = SessionLocal()
    user = session.query(User).filter_by(id=user_id).first()
    session.close()
    return user.name

def get_user_email(user_id: int) -> str:
    session = SessionLocal()
    user = session.query(User).filter_by(id=user_id).first()
    session.close()
    return user.email

# ✅ GOOD: Reusable
def get_user(user_id: int) -> User:
    with get_db_context() as session:
        return session.query(User).filter_by(id=user_id).first()

def get_user_name(user_id: int) -> str:
    user = get_user(user_id)
    return user.name if user else None

7.3 Single Responsibility

# ❌ BAD: Multiple responsibilities
class User:
    def save(self):
        # Saves to database
        pass
    
    def send_email(self):
        # Sends email
        pass
    
    def calculate_discount(self):
        # Business logic
        pass

# ✅ GOOD: Separated
class User:
    # Just entity
    pass

class UserRepository:
    def save(self, user: User):
        pass

class EmailService:
    def send_welcome_email(self, user: User):
        pass

class DiscountService:
    def calculate_user_discount(self, user: User):
        pass

8. Testing Strategy

8.1 Test Pyramid

     /\
    /E2E\      10% - End-to-End Tests
   /------\
  /Integr-\    20% - Integration Tests
 /----------\
/   Unit     \  70% - Unit Tests

8.2 Unit Test Example

import pytest
from decimal import Decimal

class TestInvoiceCalculation:
    def test_calculate_total_with_items(self):
        # Arrange
        items = [
            InvoiceItem(name="Item 1", price=Decimal("10.00"), quantity=2),
            InvoiceItem(name="Item 2", price=Decimal("5.00"), quantity=3),
        ]
        invoice = Invoice(items=items)
        
        # Act
        total = invoice.calculate_total()
        
        # Assert
        assert total == Decimal("35.00")
    
    def test_calculate_total_empty(self):
        invoice = Invoice(items=[])
        assert invoice.calculate_total() == Decimal("0.00")

8.3 Integration Test Example

@pytest.mark.integration
class TestUserRepository:
    def test_save_and_retrieve_user(self, db_session):
        # Arrange
        repository = UserRepository(db_session)
        user = User(email="test@example.com", name="Test User")
        
        # Act
        saved_user = repository.save(user)
        retrieved_user = repository.get_by_id(saved_user.id)
        
        # Assert
        assert retrieved_user is not None
        assert retrieved_user.email == "test@example.com"

9. Deployment Guide

9.1 Production Checklist

  • همه تست‌ها pass شدند
  • Code coverage بالای 80%
  • Security audit انجام شد
  • Environment variables set شدند
  • Database migrations اجرا شدند
  • Monitoring setup شد
  • Backup strategy تعریف شد
  • SSL certificates نصب شدند
  • Firewall rules تنظیم شدند

10. Troubleshooting

10.1 مشکلات رایج

Database Connection Error

Problem: sqlalchemy.exc.OperationalError

Solution:

  1. Check DATABASE_URL in .env
  2. Verify PostgreSQL is running
  3. Check firewall rules
  4. Test connection: psql $DATABASE_URL

Redis Connection Error

Problem: redis.exceptions.ConnectionError

Solution:

  1. Check REDIS_URL in .env
  2. Verify Redis is running: redis-cli ping
  3. Check Redis password if set

11. مستندسازی تغییرات

11.1 Commit Message Format

<type>(<scope>): <subject>

<body>

<footer>

Types:

  • feat: ویژگی جدید
  • fix: رفع باگ
  • docs: تغییرات مستندات
  • style: فرمت‌بندی
  • refactor: بازنویسی
  • test: اضافه کردن تست
  • chore: کارهای نگهداری

Example:

feat(auth): add two-factor authentication

- Implement TOTP-based 2FA
- Add QR code generation for authenticator apps
- Add backup codes feature

Closes #123

11.2 CHANGELOG.md

تمام تغییرات باید در CHANGELOG.md ثبت شود:

# Changelog

## [Unreleased]

## [1.0.0] - 2025-01-24

### Added
- User authentication system
- Two-factor authentication
- Password reset functionality

### Changed
- Improved database schema
- Updated UI components

### Fixed
- Payment gateway timeout issue
- Email verification bug

پیوست‌ها

A. فایل‌های مهم

  • docs/architecture/: معماری سیستم
  • docs/development/: راهنمای توسعه
  • docs/changelog/: تاریخچه تغییرات
  • docs/api/: مستندات API

B. لینک‌های مفید


این handbook باید همیشه به‌روز نگه داشته شود.