TorbatYar/backend/services/healthcare/app/validators/foundation.py
Mortezakoohjani 625275e55b feat(healthcare): add backend service and finalize frontend build
Add the Healthcare platform backend (phases 13.0–13.7) with Alembic migration revision fix, production deploy script, validation reports, shared UI exports, and loyalty list page client directives so Next.js build succeeds.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-27 11:38:31 +03:30

56 lines
1.7 KiB
Python

"""Reusable validators for Delivery foundation."""
from __future__ import annotations
import re
from typing import Any
from shared.exceptions import AppError
CODE_RE = re.compile(r"^[a-zA-Z0-9][a-zA-Z0-9_\-]{1,49}$")
class ValidationError(AppError):
def __init__(self, message: str, details: dict[str, Any] | None = None):
super().__init__(
message=message,
error_code="validation_error",
status_code=422,
details=details or {},
)
def validate_non_empty(value: str | None, field: str) -> str:
if value is None or not str(value).strip():
raise ValidationError(f"{field} الزامی است", {"field": field})
return str(value).strip()
def validate_code(code: str) -> str:
code = validate_non_empty(code, "code")
if not CODE_RE.match(code):
raise ValidationError(
"کد نامعتبر است",
{"field": "code", "pattern": CODE_RE.pattern},
)
return code
def validate_currency_code(code: str) -> str:
code = validate_non_empty(code, "currency_code").upper()
if len(code) != 3:
raise ValidationError("currency_code باید ۳ حرفی باشد", {"field": "currency_code"})
return code
def ensure_optimistic_version(entity: Any, expected: int) -> None:
current = getattr(entity, "version", None)
if current is None:
return
if current != expected:
raise AppError(
"نسخه موجودیت هم‌خوان نیست",
error_code="version_conflict",
status_code=409,
details={"expected": expected, "actual": current},
)