Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/hesabixAPI/build/lib/adapters/api/v1/schemas.py
2026-04-14 19:34:55 +03:30

339 lines
15 KiB
Python
Executable file

from typing import Any, List, Optional, Union, Generic, TypeVar
from pydantic import BaseModel, EmailStr, Field
from enum import Enum
from datetime import datetime, date
T = TypeVar('T')
class FilterItem(BaseModel):
property: str = Field(..., description="نام فیلد مورد نظر برای اعمال فیلتر")
operator: str = Field(..., description="نوع عملگر: =, >, >=, <, <=, !=, *, ?*, *?, in")
value: Any = Field(..., description="مقدار مورد نظر")
class QueryInfo(BaseModel):
sort_by: Optional[str] = Field(default=None, description="نام فیلد مورد نظر برای مرتب سازی")
sort_desc: bool = Field(default=False, description="false = مرتب سازی صعودی، true = مرتب سازی نزولی")
take: int = Field(default=10, ge=1, le=1000, description="حداکثر تعداد رکورد بازگشتی")
skip: int = Field(default=0, ge=0, description="تعداد رکوردی که از ابتدای لیست صرف نظر می شود")
search: Optional[str] = Field(default=None, description="عبارت جستجو")
search_fields: Optional[List[str]] = Field(default=None, description="آرایه ای از فیلدهایی که جستجو در آن انجام می گیرد")
filters: Optional[List[FilterItem]] = Field(default=None, description="آرایه ای از اشیا برای اعمال فیلتر بر روی لیست")
class CaptchaSolve(BaseModel):
captcha_id: str = Field(..., min_length=8)
captcha_code: str = Field(..., min_length=3, max_length=8)
class RegisterRequest(CaptchaSolve):
first_name: Optional[str] = Field(default=None, max_length=100)
last_name: Optional[str] = Field(default=None, max_length=100)
email: Optional[EmailStr] = None
mobile: Optional[str] = Field(default=None, max_length=32)
password: str = Field(..., min_length=8, max_length=128)
device_id: Optional[str] = Field(default=None, max_length=100)
referrer_code: Optional[str] = Field(default=None, min_length=4, max_length=32)
class LoginRequest(CaptchaSolve):
identifier: str = Field(..., min_length=3, max_length=255)
password: str = Field(..., min_length=8, max_length=128)
device_id: Optional[str] = Field(default=None, max_length=100)
class ForgotPasswordRequest(CaptchaSolve):
identifier: str = Field(..., min_length=3, max_length=255)
class ResetPasswordRequest(CaptchaSolve):
token: str = Field(..., min_length=16)
new_password: str = Field(..., min_length=8, max_length=128)
class ChangePasswordRequest(BaseModel):
current_password: str = Field(..., min_length=8, max_length=128)
new_password: str = Field(..., min_length=8, max_length=128)
confirm_password: str = Field(..., min_length=8, max_length=128)
class CreateApiKeyRequest(BaseModel):
name: Optional[str] = Field(default=None, max_length=100)
scopes: Optional[str] = Field(default=None, max_length=500)
expires_at: Optional[str] = None # ISO string; parse server-side if provided
# Response Models
class SuccessResponse(BaseModel):
success: bool = Field(default=True, description="وضعیت موفقیت عملیات")
message: Optional[str] = Field(default=None, description="پیام توضیحی")
data: Optional[Union[dict, list]] = Field(default=None, description="داده‌های بازگشتی")
class ErrorResponse(BaseModel):
success: bool = Field(default=False, description="وضعیت موفقیت عملیات")
message: str = Field(..., description="پیام خطا")
error_code: Optional[str] = Field(default=None, description="کد خطا")
details: Optional[dict] = Field(default=None, description="جزئیات خطا")
class UserResponse(BaseModel):
id: int = Field(..., description="شناسه کاربر")
email: Optional[str] = Field(default=None, description="ایمیل کاربر")
mobile: Optional[str] = Field(default=None, description="شماره موبایل")
first_name: Optional[str] = Field(default=None, description="نام")
last_name: Optional[str] = Field(default=None, description="نام خانوادگی")
is_active: bool = Field(..., description="وضعیت فعال بودن")
referral_code: str = Field(..., description="کد معرفی")
referred_by_user_id: Optional[int] = Field(default=None, description="شناسه کاربر معرف")
app_permissions: Optional[dict] = Field(default=None, description="مجوزهای اپلیکیشن")
created_at: str = Field(..., description="تاریخ ایجاد")
updated_at: str = Field(..., description="تاریخ آخرین بروزرسانی")
class CaptchaResponse(BaseModel):
captcha_id: str = Field(..., description="شناسه کپچا")
image_base64: str = Field(..., description="تصویر کپچا به صورت base64")
ttl_seconds: int = Field(..., description="زمان انقضا به ثانیه")
class LoginResponse(BaseModel):
api_key: str = Field(..., description="کلید API")
expires_at: Optional[str] = Field(default=None, description="تاریخ انقضا")
user: UserResponse = Field(..., description="اطلاعات کاربر")
class ApiKeyResponse(BaseModel):
id: int = Field(..., description="شناسه کلید")
name: Optional[str] = Field(default=None, description="نام کلید")
scopes: Optional[str] = Field(default=None, description="محدوده دسترسی")
device_id: Optional[str] = Field(default=None, description="شناسه دستگاه")
user_agent: Optional[str] = Field(default=None, description="اطلاعات مرورگر")
ip: Optional[str] = Field(default=None, description="آدرس IP")
expires_at: Optional[str] = Field(default=None, description="تاریخ انقضا")
last_used_at: Optional[str] = Field(default=None, description="آخرین استفاده")
created_at: str = Field(..., description="تاریخ ایجاد")
class ReferralStatsResponse(BaseModel):
total_referrals: int = Field(..., description="تعداد کل معرفی‌ها")
active_referrals: int = Field(..., description="تعداد معرفی‌های فعال")
recent_referrals: int = Field(..., description="تعداد معرفی‌های اخیر")
referral_rate: float = Field(..., description="نرخ معرفی")
class PaginationInfo(BaseModel):
total: int = Field(..., description="تعداد کل رکوردها")
page: int = Field(..., description="شماره صفحه فعلی")
per_page: int = Field(..., description="تعداد رکورد در هر صفحه")
total_pages: int = Field(..., description="تعداد کل صفحات")
has_next: bool = Field(..., description="آیا صفحه بعدی وجود دارد")
has_prev: bool = Field(..., description="آیا صفحه قبلی وجود دارد")
class UsersListResponse(BaseModel):
items: List[UserResponse] = Field(..., description="لیست کاربران")
pagination: PaginationInfo = Field(..., description="اطلاعات صفحه‌بندی")
query_info: dict = Field(..., description="اطلاعات جستجو و فیلتر")
class UsersSummaryResponse(BaseModel):
total_users: int = Field(..., description="تعداد کل کاربران")
active_users: int = Field(..., description="تعداد کاربران فعال")
inactive_users: int = Field(..., description="تعداد کاربران غیرفعال")
active_percentage: float = Field(..., description="درصد کاربران فعال")
# Business Schemas
class BusinessType(str, Enum):
COMPANY = "شرکت"
SHOP = "مغازه"
STORE = "فروشگاه"
UNION = "اتحادیه"
CLUB = "باشگاه"
INSTITUTE = "موسسه"
INDIVIDUAL = "شخصی"
class BusinessField(str, Enum):
MANUFACTURING = "تولیدی"
COMMERCIAL = "بازرگانی"
SERVICE = "خدماتی"
OTHER = "سایر"
class BusinessCreateRequest(BaseModel):
name: str = Field(..., min_length=1, max_length=255, description="نام کسب و کار")
business_type: BusinessType = Field(..., description="نوع کسب و کار")
business_field: BusinessField = Field(..., description="زمینه فعالیت")
address: Optional[str] = Field(default=None, max_length=1000, description="آدرس")
phone: Optional[str] = Field(default=None, max_length=20, description="تلفن ثابت")
mobile: Optional[str] = Field(default=None, max_length=20, description="موبایل")
national_id: Optional[str] = Field(default=None, max_length=20, description="کد ملی")
registration_number: Optional[str] = Field(default=None, max_length=50, description="شماره ثبت")
economic_id: Optional[str] = Field(default=None, max_length=50, description="شناسه اقتصادی")
country: Optional[str] = Field(default=None, max_length=100, description="کشور")
province: Optional[str] = Field(default=None, max_length=100, description="استان")
city: Optional[str] = Field(default=None, max_length=100, description="شهر")
postal_code: Optional[str] = Field(default=None, max_length=20, description="کد پستی")
fiscal_years: Optional[List["FiscalYearCreate"]] = Field(default=None, description="آرایه سال‌های مالی برای ایجاد اولیه")
default_currency_id: Optional[int] = Field(default=None, description="شناسه ارز پیشفرض")
currency_ids: Optional[List[int]] = Field(default=None, description="لیست شناسه ارزهای قابل استفاده")
class BusinessUpdateRequest(BaseModel):
name: Optional[str] = Field(default=None, min_length=1, max_length=255, description="نام کسب و کار")
business_type: Optional[BusinessType] = Field(default=None, description="نوع کسب و کار")
business_field: Optional[BusinessField] = Field(default=None, description="زمینه فعالیت")
address: Optional[str] = Field(default=None, max_length=1000, description="آدرس")
phone: Optional[str] = Field(default=None, max_length=20, description="تلفن ثابت")
mobile: Optional[str] = Field(default=None, max_length=20, description="موبایل")
national_id: Optional[str] = Field(default=None, max_length=20, description="کد ملی")
registration_number: Optional[str] = Field(default=None, max_length=50, description="شماره ثبت")
economic_id: Optional[str] = Field(default=None, max_length=50, description="شناسه اقتصادی")
country: Optional[str] = Field(default=None, max_length=100, description="کشور")
province: Optional[str] = Field(default=None, max_length=100, description="استان")
city: Optional[str] = Field(default=None, max_length=100, description="شهر")
postal_code: Optional[str] = Field(default=None, max_length=20, description="کد پستی")
class BusinessResponse(BaseModel):
id: int = Field(..., description="شناسه کسب و کار")
name: str = Field(..., description="نام کسب و کار")
business_type: str = Field(..., description="نوع کسب و کار")
business_field: str = Field(..., description="زمینه فعالیت")
owner_id: int = Field(..., description="شناسه مالک")
address: Optional[str] = Field(default=None, description="آدرس")
phone: Optional[str] = Field(default=None, description="تلفن ثابت")
mobile: Optional[str] = Field(default=None, description="موبایل")
national_id: Optional[str] = Field(default=None, description="کد ملی")
registration_number: Optional[str] = Field(default=None, description="شماره ثبت")
economic_id: Optional[str] = Field(default=None, description="شناسه اقتصادی")
country: Optional[str] = Field(default=None, description="کشور")
province: Optional[str] = Field(default=None, description="استان")
city: Optional[str] = Field(default=None, description="شهر")
postal_code: Optional[str] = Field(default=None, description="کد پستی")
created_at: str = Field(..., description="تاریخ ایجاد")
updated_at: str = Field(..., description="تاریخ آخرین بروزرسانی")
default_currency: Optional[dict] = Field(default=None, description="ارز پیشفرض")
currencies: Optional[List[dict]] = Field(default=None, description="ارزهای فعال کسب‌وکار")
class BusinessListResponse(BaseModel):
items: List[BusinessResponse] = Field(..., description="لیست کسب و کارها")
pagination: PaginationInfo = Field(..., description="اطلاعات صفحه‌بندی")
query_info: dict = Field(..., description="اطلاعات جستجو و فیلتر")
class BusinessSummaryResponse(BaseModel):
total_businesses: int = Field(..., description="تعداد کل کسب و کارها")
by_type: dict = Field(..., description="تعداد بر اساس نوع")
by_field: dict = Field(..., description="تعداد بر اساس زمینه فعالیت")
class PaginatedResponse(BaseModel, Generic[T]):
"""پاسخ صفحه‌بندی شده برای لیست‌ها"""
items: List[T] = Field(..., description="آیتم‌های صفحه")
total: int = Field(..., description="تعداد کل آیتم‌ها")
page: int = Field(..., description="شماره صفحه فعلی")
limit: int = Field(..., description="تعداد آیتم در هر صفحه")
total_pages: int = Field(..., description="تعداد کل صفحات")
@classmethod
def create(cls, items: List[T], total: int, page: int, limit: int) -> 'PaginatedResponse[T]':
"""ایجاد پاسخ صفحه‌بندی شده"""
total_pages = (total + limit - 1) // limit
return cls(
items=items,
total=total,
page=page,
limit=limit,
total_pages=total_pages
)
# Fiscal Year Schemas
class FiscalYearCreate(BaseModel):
title: str = Field(..., min_length=1, max_length=255, description="عنوان سال مالی")
start_date: date = Field(..., description="تاریخ شروع سال مالی")
end_date: date = Field(..., description="تاریخ پایان سال مالی")
is_last: bool = Field(default=True, description="آیا آخرین سال مالی فعال است؟")
# Business User Schemas
class BusinessUserSchema(BaseModel):
id: int
business_id: int
user_id: int
user_name: str
user_email: str
user_phone: Optional[str] = None
role: str
status: str
added_at: datetime
last_active: Optional[datetime] = None
permissions: dict
class Config:
from_attributes = True
class AddUserRequest(BaseModel):
email_or_phone: str
class Config:
json_schema_extra = {
"example": {
"email_or_phone": "user@example.com"
}
}
class AddUserResponse(BaseModel):
success: bool
message: str
user: Optional[BusinessUserSchema] = None
class UpdatePermissionsRequest(BaseModel):
permissions: dict
class Config:
json_schema_extra = {
"example": {
"permissions": {
"sales": {
"read": True,
"write": True,
"delete": False
},
"reports": {
"read": True,
"export": True
},
"settings": {
"manage_users": True
}
}
}
}
class UpdatePermissionsResponse(BaseModel):
success: bool
message: str
class RemoveUserResponse(BaseModel):
success: bool
message: str
class BusinessUsersListResponse(BaseModel):
success: bool
message: str
data: dict
calendar_type: Optional[str] = None