diff --git a/README.md b/README.md index a3f93af..2f252b1 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,7 @@ La aplicación expone una API REST completa: |---------------------------------------|--------|----------------------- | `/api/v1/conversations` | GET | Listar conversaciones | `/api/v1/conversations` | POST | Crear conversación +| `/api/v1/conversations/{id}` | DELETE | Elimina conversación | `/api/v1/conversations/{id}/messages` | GET | Obtener mensajes | `/api/v1/conversations/{id}/messages` | POST | Enviar mensaje diff --git a/chat-api/src/main/java/com/pablotj/ai/chat/application/usecase/DeleteConversationUseCase.java b/chat-api/src/main/java/com/pablotj/ai/chat/application/usecase/DeleteConversationUseCase.java new file mode 100644 index 0000000..56ec29b --- /dev/null +++ b/chat-api/src/main/java/com/pablotj/ai/chat/application/usecase/DeleteConversationUseCase.java @@ -0,0 +1,45 @@ +package com.pablotj.ai.chat.application.usecase; + +import com.pablotj.ai.chat.domain.exception.ConversationNotFoundException; +import com.pablotj.ai.chat.domain.model.ConversationId; +import com.pablotj.ai.chat.domain.repository.ConversationRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * Use case for deleting a specific conversation. + */ +@Service +@Transactional +public class DeleteConversationUseCase { + + private static final Logger logger = LoggerFactory.getLogger(DeleteConversationUseCase.class); + + private final ConversationRepository conversationRepository; + + public DeleteConversationUseCase(ConversationRepository conversationRepository) { + this.conversationRepository = conversationRepository; + } + + /** + * Deletes the specified conversation. + * + * @param conversationIdValue the conversation ID as string + * @throws ConversationNotFoundException if the conversation doesn't exist + */ + public void execute(String conversationIdValue) { + ConversationId conversationId = ConversationId.of(conversationIdValue); + + logger.debug("Attempting to delete conversation: {}", conversationId); + + if (!conversationRepository.existsById(conversationId)) { + throw new ConversationNotFoundException(conversationId); + } + + conversationRepository.deleteById(conversationId); + + logger.info("Conversation deleted: {}", conversationId); + } +} \ No newline at end of file diff --git a/chat-api/src/main/java/com/pablotj/ai/chat/presentation/rest/ConversationController.java b/chat-api/src/main/java/com/pablotj/ai/chat/presentation/rest/ConversationController.java index 3fef7d1..723ee31 100644 --- a/chat-api/src/main/java/com/pablotj/ai/chat/presentation/rest/ConversationController.java +++ b/chat-api/src/main/java/com/pablotj/ai/chat/presentation/rest/ConversationController.java @@ -4,6 +4,7 @@ import com.pablotj.ai.chat.application.dto.ConversationDto; import com.pablotj.ai.chat.application.dto.ConversationMessageDto; import com.pablotj.ai.chat.application.dto.ConversationSummaryDto; import com.pablotj.ai.chat.application.usecase.CreateConversationUseCase; +import com.pablotj.ai.chat.application.usecase.DeleteConversationUseCase; import com.pablotj.ai.chat.application.usecase.GetConversationHistoryUseCase; import com.pablotj.ai.chat.application.usecase.GetConversationMessagesUseCase; import com.pablotj.ai.chat.application.usecase.ProcessUserMessageUseCase; @@ -23,6 +24,7 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; @@ -46,16 +48,18 @@ public class ConversationController { private final GetConversationHistoryUseCase getConversationHistoryUseCase; private final GetConversationMessagesUseCase getConversationMessagesUseCase; private final ProcessUserMessageUseCase processUserMessageUseCase; + private final DeleteConversationUseCase deleteConversationUseCase; - public ConversationController( - CreateConversationUseCase createConversationUseCase, - GetConversationHistoryUseCase getConversationHistoryUseCase, - GetConversationMessagesUseCase getConversationMessagesUseCase, - ProcessUserMessageUseCase processUserMessageUseCase) { + public ConversationController(CreateConversationUseCase createConversationUseCase, + GetConversationHistoryUseCase getConversationHistoryUseCase, + GetConversationMessagesUseCase getConversationMessagesUseCase, + ProcessUserMessageUseCase processUserMessageUseCase, + DeleteConversationUseCase deleteConversationUseCase) { this.createConversationUseCase = createConversationUseCase; this.getConversationHistoryUseCase = getConversationHistoryUseCase; this.getConversationMessagesUseCase = getConversationMessagesUseCase; this.processUserMessageUseCase = processUserMessageUseCase; + this.deleteConversationUseCase = deleteConversationUseCase; } @Operation( @@ -152,4 +156,27 @@ public class ConversationController { return ResponseEntity.ok(aiResponse); } + + @Operation( + summary = "Delete a conversation", + description = "Deletes the specified conversation by its unique identifier" + ) + @ApiResponses(value = { + @ApiResponse(responseCode = "204", description = "Conversation successfully deleted"), + @ApiResponse(responseCode = "404", description = "Conversation not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @DeleteMapping("/{conversationId}") + public ResponseEntity deleteConversation( + @Parameter(description = "Unique conversation identifier", required = true) + @PathVariable String conversationId) { + + logger.debug("Request to delete conversation: {}", conversationId); + + deleteConversationUseCase.execute(conversationId); + + logger.info("Conversation deleted: {}", conversationId); + + return ResponseEntity.noContent().build(); + } }