- CRM_USE_STUB: local runs no longer reach the live CRM. With only the Checkbox stub, a stub receipt would still move the real order to PACKED. Refused in production, same as CHECKBOX_USE_STUB. - scripts/deploy.sh: backup, fast-forward main, build, health check and code rollback on failure. scripts/backup.sh: pg_dump with verification and 14-day rotation (used by cron and deploy.sh). - Gitea Actions CI: ruff + pytest, oxlint + build. - DEPLOY.md runbook; CLAUDE.md rules for safe local development. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.1 KiB
Python
35 lines
1.1 KiB
Python
"""Protocol клиента CRM — позволяет подменять реализацию в тестах (`StubCrmClient`)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from functools import lru_cache
|
|
from typing import Protocol
|
|
|
|
from app.core.config import settings
|
|
from app.schemas.orders import OrderOut
|
|
|
|
|
|
class CrmError(Exception):
|
|
"""CRM ответила `status: ERROR` (см. поле `errors` в ответе API)."""
|
|
|
|
|
|
class CrmClient(Protocol):
|
|
async def get_orders(self, *, status: str) -> list[OrderOut]: ...
|
|
|
|
async def set_status(self, *, order_id: str, status: str) -> None: ...
|
|
|
|
|
|
@lru_cache
|
|
def get_crm_client() -> CrmClient:
|
|
"""Один экземпляр на процесс: стаб копит выставленные статусы в памяти."""
|
|
if settings.crm_use_stub:
|
|
if settings.is_production:
|
|
raise RuntimeError("CRM_USE_STUB=true заборонено в production")
|
|
from app.services.crm.stub_client import StubCrmClient
|
|
|
|
return StubCrmClient()
|
|
|
|
from app.services.crm.exo_client import ExoCrmClient
|
|
|
|
return ExoCrmClient(settings)
|