"""Phase 7.5 Referral Engine validators — program status, attribution rules, transitions.""" from __future__ import annotations from uuid import UUID from shared.exceptions import AppError from app.models.types import ( ReferralAttributionStatus, ReferralCodeStatus, ReferralProgramStatus, ) def validate_referral_program_status( status: ReferralProgramStatus | str, ) -> ReferralProgramStatus: if isinstance(status, ReferralProgramStatus): return status try: return ReferralProgramStatus(status) except ValueError as exc: raise AppError( "وضعیت برنامه معرفی نامعتبر است", status_code=422, error_code="invalid_referral_program_status", ) from exc def ensure_referral_program_active(status: ReferralProgramStatus) -> None: if status != ReferralProgramStatus.ACTIVE: raise AppError( "برنامه معرفی فعال نیست", status_code=409, error_code="referral_program_not_active", ) def ensure_code_active(status: ReferralCodeStatus) -> None: if status != ReferralCodeStatus.ACTIVE: raise AppError( "کد معرفی فعال نیست", status_code=409, error_code="referral_code_not_active", ) def ensure_not_self_referral(referrer_member_id: UUID, referee_member_id: UUID) -> None: if referrer_member_id == referee_member_id: raise AppError( "معرفی خود فرد مجاز نیست", status_code=422, error_code="referral_self_referral_forbidden", ) def ensure_max_referrals_not_exceeded( current_count: int, max_referrals: int | None ) -> None: if max_referrals is not None and current_count >= max_referrals: raise AppError( "سقف تعداد معرفی‌های این عضو تکمیل شده است", status_code=409, error_code="referral_max_referrals_exceeded", ) def ensure_attribution_pending(status: ReferralAttributionStatus) -> None: if status != ReferralAttributionStatus.PENDING: raise AppError( "وضعیت معرفی برای تبدیل مناسب نیست", status_code=409, error_code="referral_not_pending", ) def ensure_attribution_converted(status: ReferralAttributionStatus) -> None: if status != ReferralAttributionStatus.CONVERTED: raise AppError( "معرفی باید ابتدا تبدیل شده باشد", status_code=409, error_code="referral_not_converted", ) def ensure_attribution_cancellable(status: ReferralAttributionStatus) -> None: if status in ( ReferralAttributionStatus.REWARDED, ReferralAttributionStatus.CANCELLED, ): raise AppError( "این معرفی قابل لغو نیست", status_code=409, error_code="referral_not_cancellable", )