"""استثناهای مشترک دامنه (Domain Exceptions). این استثناها مستقل از فریم‌ورک هستند تا در همه سرویس‌ها قابل استفاده باشند. لایه API هر سرویس آن‌ها را به پاسخ HTTP مناسب تبدیل می‌کند. """ from __future__ import annotations from typing import Any class AppError(Exception): """پایه همه خطاهای دامنه‌ای برنامه.""" status_code: int = 500 error_code: str = "internal_error" def __init__( self, message: str | None = None, *, error_code: str | None = None, status_code: int | None = None, details: Any | None = None, ) -> None: self.message = message or self.__class__.__doc__ or "Application error" if error_code is not None: self.error_code = error_code if status_code is not None: self.status_code = status_code self.details = details super().__init__(self.message) class NotFoundError(AppError): """منبع درخواستی یافت نشد.""" status_code = 404 error_code = "not_found" class ConflictError(AppError): """تعارض داده (مثلاً مقدار تکراری).""" status_code = 409 error_code = "conflict" class ValidationAppError(AppError): """داده ورودی نامعتبر است.""" status_code = 422 error_code = "validation_error" class UnauthorizedError(AppError): """احراز هویت انجام نشده است.""" status_code = 401 error_code = "unauthorized" class ForbiddenError(AppError): """دسترسی مجاز نیست.""" status_code = 403 error_code = "forbidden" class TenantNotResolvedError(AppError): """tenant قابل تشخیص نبود در حالی که endpoint نیازمند tenant است.""" status_code = 400 error_code = "tenant_not_resolved" class FeatureAccessDeniedError(ForbiddenError): """tenant به این قابلیت دسترسی ندارد.""" error_code = "feature_access_denied"