TorbatYar/backend/services/communication/app/api/v1/contacts.py
Mortezakoohjani e41ecfad4c Sync platform docs, infra, and module services with Accounting integration.
Include Loyalty/Communication/Sports Center backends and registry updates alongside production nginx and compose wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-25 22:35:23 +03:30

104 lines
3.0 KiB
Python

from uuid import UUID
from fastapi import APIRouter, Depends
from pydantic import BaseModel
from app.api.deps import AsyncSession, CurrentUser, get_current_user, get_db, require_tenant
from app.schemas.common import (
ContactCreate,
ContactOut,
ContactSourceCreate,
ContactSourceOut,
)
from app.services.contact_service import ContactService
router = APIRouter()
class CSVImportBody(BaseModel):
csv_text: str
class ResolveBody(BaseModel):
source_id: UUID | None = None
query: dict | None = None
channel: str = "sms"
@router.get("/manual", response_model=list[ContactOut])
async def list_manual_contacts(
tenant_id: UUID = Depends(require_tenant),
session: AsyncSession = Depends(get_db),
_: CurrentUser = Depends(get_current_user),
):
return await ContactService(session).list_manual(tenant_id)
@router.post("/manual", response_model=ContactOut, status_code=201)
async def create_manual_contact(
body: ContactCreate,
tenant_id: UUID = Depends(require_tenant),
session: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await ContactService(session).create_manual(
tenant_id, body.model_dump(), actor_id=user.user_id
)
@router.post("/manual/import-csv", response_model=list[ContactOut], status_code=201)
async def import_csv(
body: CSVImportBody,
tenant_id: UUID = Depends(require_tenant),
session: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await ContactService(session).import_csv(
tenant_id, body.csv_text, actor_id=user.user_id
)
@router.get("/sources", response_model=list[ContactSourceOut])
async def list_sources(
tenant_id: UUID = Depends(require_tenant),
session: AsyncSession = Depends(get_db),
_: CurrentUser = Depends(get_current_user),
):
return await ContactService(session).list_sources(tenant_id)
@router.post("/sources", response_model=ContactSourceOut, status_code=201)
async def create_source(
body: ContactSourceCreate,
tenant_id: UUID = Depends(require_tenant),
session: AsyncSession = Depends(get_db),
user: CurrentUser = Depends(get_current_user),
):
return await ContactService(session).create_source(
tenant_id, body.model_dump(), actor_id=user.user_id
)
@router.post("/resolve")
async def resolve_contacts(
body: ResolveBody,
tenant_id: UUID = Depends(require_tenant),
session: AsyncSession = Depends(get_db),
_: CurrentUser = Depends(get_current_user),
):
resolved = await ContactService(session).resolve(
tenant_id,
source_id=body.source_id,
query=body.query,
channel=body.channel,
)
return [
{
"address": r.address,
"display_name": r.display_name,
"external_ref": r.external_ref,
"source_type": r.source_type,
}
for r in resolved
]