"""Service for bulk-transferring ownership of records between users.""" from __future__ import annotations import logging import uuid from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession from app.core.audit import log_audit logger = logging.getLogger(__name__) # Mapping of entity_type -> database table name ENTITY_TABLES: dict[str, str] = { "contacts": "contacts", "addresses": "addresses", "attachments": "attachments", "bank_accounts": "bank_accounts", "workflows": "workflows", "sequences": "sequences", "saved_filters": "saved_filters", "saved_views": "saved_views", "webhooks": "webhooks", "notifications": "notifications", "ai_conversations": "ai_conversations", } async def transfer_ownership( db: AsyncSession, tenant_id: uuid.UUID, from_user_id: uuid.UUID, to_user_id: uuid.UUID, entity_types: list[str] | None = None, ) -> dict[str, int]: """Bulk-transfer all records from one user to another for the given entity types. Args: db: Database session. tenant_id: Tenant scope. from_user_id: Current owner whose records will be transferred. to_user_id: New owner for the records. entity_types: List of entity types to transfer. If None, all known types. Returns: Dict mapping entity_type -> number of records transferred. """ if entity_types is None: entity_types = list(ENTITY_TABLES.keys()) results: dict[str, int] = {} for entity_type in entity_types: table = ENTITY_TABLES.get(entity_type) if table is None: logger.warning("Unknown entity_type=%s, skipping", entity_type) continue # Build and execute the UPDATE stmt = text( f"UPDATE {table} SET owner_id = :to_user_id " f"WHERE owner_id = :from_user_id AND tenant_id = :tenant_id" ) stmt = stmt.bindparams( to_user_id=str(to_user_id), from_user_id=str(from_user_id), tenant_id=str(tenant_id), ) result = await db.execute(stmt) count = result.rowcount results[entity_type] = count if count is not None else 0 if count and count > 0: logger.info( "Transferred %d %s from user %s to user %s (tenant %s)", count, entity_type, from_user_id, to_user_id, tenant_id, ) # Log the transfer in audit log await log_audit( db, tenant_id, to_user_id, "transfer_ownership", "ownership", changes={ "from_user_id": str(from_user_id), "to_user_id": str(to_user_id), "entity_types": entity_types, "results": results, }, ) return results