96 lines
3.1 KiB
Python
96 lines
3.1 KiB
Python
"""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",
|
|
)
|