"""Create post use case. This module implements the use case for creating new blog posts. Handles slug generation, duplicate checking, and entity persistence. """ from app.application.dtos.post import CreatePostDTO, PostResponseDTO from app.application.interfaces import TransactionManager from app.domain.entities import Post from app.domain.exceptions import AlreadyExistsException from app.domain.repositories import PostRepository class CreatePostUseCase: """Use case for creating a new blog post. Encapsulates the business logic for creating posts including slug generation from title and duplicate slug detection. Attributes: _post_repo: Repository for post data access. _tx_manager: Transaction manager for commit control. Example: >>> use_case = CreatePostUseCase(post_repo, tx_manager) >>> result = await use_case.execute(dto) """ def __init__( self, post_repo: PostRepository, tx_manager: TransactionManager, ) -> None: """Initialize use case with dependencies. Args: post_repo: Repository for post operations. tx_manager: Transaction manager instance. """ self._post_repo = post_repo self._tx_manager = tx_manager async def execute(self, dto: CreatePostDTO) -> PostResponseDTO: """Execute the use case to create a new post. Args: dto: Data transfer object containing post creation data including title, content, author ID, and optional tags. Returns: PostResponseDTO with created post data including generated ID and slug. Raises: AlreadyExistsException: If a post with the same slug exists. Note: Slug is automatically generated from the title. """ from app.domain.value_objects import Slug slug = Slug.from_title(dto.title) if await self._post_repo.slug_exists(slug.value): raise AlreadyExistsException(f"Post with slug '{slug.value}' already exists") post = Post.create( title_str=dto.title, content_str=dto.content, author_id=dto.author_id, tags=dto.tags or [], ) await self._post_repo.add(post) await self._tx_manager.commit() return self._map_to_dto(post) def _map_to_dto(self, post: Post) -> PostResponseDTO: """Map domain entity to response DTO. Args: post: Domain post entity. Returns: PostResponseDTO with all post attributes. """ return PostResponseDTO( id=post.id, title=post.title.value, content=post.content.value, slug=post.slug.value, author_id=post.author_id, published=post.published, like_count=post.like_count, tags=post.tags.copy(), created_at=post.created_at, updated_at=post.updated_at, )