diff --git a/src/main/java/smartpot/com/api/Commands/Controller/CommandController.java b/src/main/java/smartpot/com/api/Commands/Controller/CommandController.java
index 535b6de..7ac1d11 100644
--- a/src/main/java/smartpot/com/api/Commands/Controller/CommandController.java
+++ b/src/main/java/smartpot/com/api/Commands/Controller/CommandController.java
@@ -11,7 +11,6 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import smartpot.com.api.Commands.Model.DTO.CommandDTO;
-import smartpot.com.api.Commands.Model.Entity.Command;
import smartpot.com.api.Commands.Service.SCommandI;
import smartpot.com.api.Crops.Model.DTO.CropDTO;
import smartpot.com.api.Responses.DeleteResponse;
@@ -104,22 +103,8 @@ public ResponseEntity> getUserById(@PathVariable String id) {
content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)))
})
public ResponseEntity> executeCommand(@PathVariable String id, @PathVariable String response) {
- /*
- Command command = serviceCommand.getCommandById(id);
- if (command != null) {
- command.setStatus("EXECUTED");
- command.setDateExecuted(new Date());
- command.setResponse("SUCCESSFUL");
- Command updatedCommand = serviceCommand.updateCommand(id, command);
- return ResponseEntity.ok(updatedCommand);
- } else {
- return ResponseEntity.notFound().build();
- }
-
- */
-
try {
- return new ResponseEntity<>(serviceCommand.excuteCommand(id, response), HttpStatus.OK);
+ return new ResponseEntity<>(serviceCommand.executeCommand(id, response), HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(new ErrorResponse("Error al actualizar el comando con ID '" + id + "' [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND);
}
@@ -146,8 +131,23 @@ public ResponseEntity> deleteCommand(@Parameter(description = "ID único del c
}
@PutMapping("/Update/{id}")
- public Command updateCommand(@PathVariable String id, @RequestBody Command updatedCommad) throws Exception {
- return serviceCommand.updateCommand(id, updatedCommad);
+ @Operation(summary = "Eliminar un comando",
+ description = "Elimina un comando existente utilizando su ID. "
+ + "Si el comando no existe o hay un error en el proceso, se devolverá un error con el código HTTP 404.",
+ responses = {
+ @ApiResponse(description = "Comando eliminado",
+ responseCode = "204",
+ content = @Content(mediaType = "application/json")),
+ @ApiResponse(responseCode = "404",
+ description = "Comando no encontrado o error en la eliminación.",
+ content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class)))
+ })
+ public ResponseEntity> updateCommand(@PathVariable String id, @RequestBody CommandDTO updatedCommand) {
+ try {
+ return new ResponseEntity<>(new DeleteResponse("Se ha eliminado un recurso [" + serviceCommand.updateCommand(id, updatedCommand) + "]"), HttpStatus.OK);
+ } catch (Exception e) {
+ return new ResponseEntity<>(new ErrorResponse("Error al actualizar el comando con ID '" + id + "' [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND);
+ }
}
}
diff --git a/src/main/java/smartpot/com/api/Commands/Service/SCommand.java b/src/main/java/smartpot/com/api/Commands/Service/SCommand.java
index 444c679..56fcaab 100644
--- a/src/main/java/smartpot/com/api/Commands/Service/SCommand.java
+++ b/src/main/java/smartpot/com/api/Commands/Service/SCommand.java
@@ -7,21 +7,60 @@
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
-import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import smartpot.com.api.Commands.Mapper.MCommand;
import smartpot.com.api.Commands.Model.DTO.CommandDTO;
-import smartpot.com.api.Commands.Model.Entity.Command;
import smartpot.com.api.Commands.Repository.RCommand;
import smartpot.com.api.Crops.Service.SCropI;
-import smartpot.com.api.Exception.ApiException;
-import smartpot.com.api.Exception.ApiResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
-
+import java.util.stream.Collectors;
+
+/**
+ * Service implementation for managing commands.
+ *
+ *
+ * This class provides the business logic for managing commands, including
+ * CRUD operations and execution logic. It interacts with the repository,
+ * a mapper, and additional services to fulfill its responsibilities.
+ *
+ *
+ * Annotations:
+ *
+ * - {@code @Data} - Generates boilerplate code such as getters, setters, and toString.
+ * - {@code @Builder} - Enables the builder pattern for constructing instances of this class.
+ * - {@code @Service} - Marks this class as a Spring-managed service component.
+ *
+ *
+ * Dependencies:
+ *
+ * - {@code RCommand} - Repository for accessing and persisting command entities.
+ * - {@code SCropI} - Service for managing crops, used for operations involving crop data.
+ * - {@code MCommand} - Mapper for converting between entity and DTO representations of commands.
+ *
+ *
+ * Responsibilities:
+ *
+ * - Provides methods for creating, retrieving, updating, and deleting commands.
+ * - Implements caching for frequently accessed commands to improve performance.
+ * - Validates and processes business logic for commands before interacting with the repository.
+ *
+ *
+ * Usage:
+ *
+ * This service is typically used by controllers to handle HTTP requests related to commands,
+ * or by other services that depend on command-related operations.
+ *
+ *
+ * @see SCommandI
+ * @see RCommand
+ * @see SCropI
+ * @see MCommand
+ */
@Data
@Builder
@Service
@@ -31,6 +70,13 @@ public class SCommand implements SCommandI {
private final SCropI serviceCrop;
private final MCommand mapperCommand;
+ /**
+ * Constructs an instance of {@code SCommand} with the required dependencies.
+ *
+ * @param repositoryCommand the repository for command-related database operations
+ * @param serviceCrop the service responsible for crop-related logic
+ * @param mapperCommand the mapper for converting entities to DTOs and vice versa
+ */
@Autowired
public SCommand(RCommand repositoryCommand, SCropI serviceCrop, MCommand mapperCommand) {
this.repositoryCommand = repositoryCommand;
@@ -38,11 +84,38 @@ public SCommand(RCommand repositoryCommand, SCropI serviceCrop, MCommand mapperC
this.mapperCommand = mapperCommand;
}
+ /**
+ * Retrieves all commands from the repository and maps them to DTOs.
+ *
+ * This method is cached to improve performance when retrieving the list of commands.
+ * The cache is identified by the key 'all_commands' under the 'commands' cache.
+ *
+ *
+ * @return a list of {@code CommandDTO} objects representing all commands
+ * @throws Exception if no commands exist in the repository
+ */
@Override
- public List getAllCommands() {
- return repositoryCommand.findAll();
+ @Cacheable(value = "commands", key = "'all_commands'")
+ public List getAllCommands() throws Exception {
+ return Optional.of(repositoryCommand.findAll())
+ .filter(commands -> !commands.isEmpty())
+ .map(crops -> crops.stream()
+ .map(mapperCommand::toDTO)
+ .collect(Collectors.toList()))
+ .orElseThrow(() -> new Exception("No existe ningún comando"));
}
+ /**
+ * Retrieves a command by its unique identifier and maps it to a DTO.
+ *
+ * This method is cached to improve performance for retrieving individual commands.
+ * The cache is identified by the key pattern 'id_{id}' under the 'commands' cache.
+ *
+ *
+ * @param id the unique identifier of the command to retrieve
+ * @return a {@code CommandDTO} representing the command with the specified ID
+ * @throws Exception if the command with the specified ID does not exist
+ */
@Override
@Cacheable(value = "commands", key = "'id_'+#id")
public CommandDTO getCommandById(String id) throws Exception {
@@ -55,7 +128,21 @@ public CommandDTO getCommandById(String id) throws Exception {
.orElseThrow(() -> new Exception("El Comando no existe"));
}
+ /**
+ * Creates a new command based on the provided DTO, sets its creation date and status,
+ * and persists it in the repository.
+ *
+ *
+ * This method assigns a default status of "PENDING" and records the current timestamp
+ * as the creation date in the format "yyyy-MM-dd HH:mm:ss".
+ *
+ *
+ * @param commandDTO the {@code CommandDTO} containing the details of the command to create
+ * @return a {@code CommandDTO} representing the created command
+ * @throws IllegalStateException if a command with the same details already exists
+ */
@Override
+ @Transactional
public CommandDTO createCommand(CommandDTO commandDTO) throws IllegalStateException {
return Optional.of(commandDTO)
.map(dto -> {
@@ -70,84 +157,22 @@ public CommandDTO createCommand(CommandDTO commandDTO) throws IllegalStateExcept
.orElseThrow(() -> new IllegalStateException("El Comando ya existe"));
}
- @Override
- public Command updateCommand(String id, Command upCommand) throws Exception {
- if (!ObjectId.isValid(id)) {
- throw new ApiException(new ApiResponse(
- "El ID '" + id + "' no es válido. Asegúrate de que tiene 24 caracteres y solo incluye dÃgitos hexadecimales (0-9, a-f, A-F).",
- HttpStatus.BAD_REQUEST.value()
- ));
- }
- Command exCommand = repositoryCommand.findById(new ObjectId(id)).orElseThrow(() -> new ApiException(
- new ApiResponse("El Comando con ID '" + id + "' no fue encontrado.",
- HttpStatus.NOT_FOUND.value())
- ));
-
- if (upCommand == null) {
- throw new IllegalArgumentException("El comando de actualización no puede ser nulo");
- }
-
- if (upCommand.getCrop() == null && serviceCrop.getCropById(upCommand.getCrop().toString()) != null) {
- throw new IllegalArgumentException("El campo 'crop' no puede ser nulo");
- }
-
- if (upCommand.getDateCreated() == null) {
- throw new IllegalArgumentException("El campo 'dateCreated' no puede ser nulo");
- }
-
- // Validar y convertir commandType a mayúsculas
- if (upCommand.getCommandType() == null || upCommand.getCommandType().isEmpty()) {
- throw new IllegalArgumentException("El campo 'commandType' no puede estar vacÃo");
- } else {
- exCommand.setCommandType(upCommand.getCommandType().toUpperCase());
- }
-
- // Validar y convertir status a mayúsculas
- if (upCommand.getStatus() == null || upCommand.getStatus().isEmpty()) {
- throw new IllegalArgumentException("El campo 'status' no puede estar vacÃo");
- } else {
- exCommand.setStatus(upCommand.getStatus().toUpperCase());
- }
-
- // Si se cumplen todas las validaciones, se procede a actualizar el comando
- if (exCommand != null) {
- exCommand.setCrop(upCommand.getCrop());
- exCommand.setResponse(upCommand.getResponse());
- exCommand.setDateCreated(upCommand.getDateCreated());
- return repositoryCommand.save(exCommand);
- } else {
- return null;
- }
- /*
-
-
- if (!upCommand.getCommandType().matches(exCommand.getCommandType())) {
- throw new Exception(new ErrorResponse(
- "El nombre '" + upCommand.getCommandType() + "' no es válido.",
- HttpStatus.BAD_REQUEST.value()
- ));
- }
- if (!upCommand.ge) {
- }
- */
-
-
- }
-
- @Override
- @CacheEvict(value = "commands", key = "'id_'+#id")
- public String deleteCommand(String id) throws Exception {
- return Optional.of(getCommandById(id))
- .map(command -> {
- repositoryCommand.deleteById(new ObjectId(command.getId()));
- return "El Comando con ID '" + id + "' fue eliminado.";
- })
- .orElseThrow(() -> new Exception("El Comando no existe."));
- }
-
+ /**
+ * Executes a command by updating its status to "EXECUTED" and setting a response message.
+ *
+ *
+ * This method updates the specified command with the current timestamp, sets its status to
+ * "EXECUTED", and records the provided response message.
+ *
+ *
+ * @param id the ID of the command to execute
+ * @param response the response message to associate with the executed command
+ * @return a {@code CommandDTO} representing the updated command
+ * @throws Exception if the command cannot be found or updated
+ */
@Override
@CachePut(value = "commands", key = "'id:'+#id")
- public CommandDTO excuteCommand(String id, String response) throws Exception {
+ public CommandDTO executeCommand(String id, String response) throws Exception {
return Optional.of(getCommandById(id))
.map(commandDTO -> {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@@ -162,31 +187,59 @@ public CommandDTO excuteCommand(String id, String response) throws Exception {
.orElseThrow(() -> new Exception("El Comando no se pudo actualizar"));
}
-/*
-
-
-
-
- public Command executeCommand(String id, String response) {
- Command command = repositoryCommand.findById(id).orElse(null);
- if (command != null) {
- command.setStatus("EXECUTED");
- command.setDateExecuted(new Date());
- command.setResponse(response);
- return repositoryCommand.save(command);
- }
- return null;
+ /**
+ * Updates the specified command with new details provided in the update DTO.
+ *
+ *
+ * This method updates fields in the command only if the corresponding fields in the
+ * update DTO are non-null. The existing values are retained for fields that are null in the update DTO.
+ *
+ *
+ * @param id the ID of the command to update
+ * @param updateCommand the {@code CommandDTO} containing the updated details
+ * @return a {@code CommandDTO} representing the updated command
+ * @throws Exception if the command cannot be found or updated
+ */
+ @Override
+ @Transactional
+ @CachePut(value = "commands", key = "'id_'+#id")
+ public CommandDTO updateCommand(String id, CommandDTO updateCommand) throws Exception {
+ CommandDTO existingCommand = getCommandById(id);
+ return Optional.of(updateCommand)
+ .map(dto -> {
+ existingCommand.setId(dto.getCommandType() != null ? dto.getCommandType() : existingCommand.getCommandType());
+ existingCommand.setResponse(dto.getResponse() != null ? dto.getResponse() : existingCommand.getResponse());
+ existingCommand.setCrop(dto.getCrop() != null ? dto.getCrop() : existingCommand.getCrop());
+ return existingCommand;
+ })
+ .map(mapperCommand::toEntity)
+ .map(repositoryCommand::save)
+ .map(mapperCommand::toDTO)
+ .orElseThrow(() -> new Exception("El Comando no se pudo actualizar"));
}
-
-
- public List getCommandsByStatus(String status) {
- return repositoryCommand.findByStatus(status);
+ /**
+ * Deletes the specified command by its ID.
+ *
+ *
+ * This method removes the command from the repository and evicts the corresponding cache entry.
+ *
+ *
+ * @param id the ID of the command to delete
+ * @return a confirmation message indicating the successful deletion
+ * @throws Exception if the command cannot be found
+ */
+ @Override
+ @Transactional
+ @CacheEvict(value = "commands", key = "'id_'+#id")
+ public String deleteCommand(String id) throws Exception {
+ return Optional.of(getCommandById(id))
+ .map(command -> {
+ repositoryCommand.deleteById(new ObjectId(command.getId()));
+ return "El Comando con ID '" + id + "' fue eliminado.";
+ })
+ .orElseThrow(() -> new Exception("El Comando no existe."));
}
- public List getCommandsByCropId(String cropId) {
- return repositoryCommand.findByCrop_Id(cropId);
- }
- */
}
diff --git a/src/main/java/smartpot/com/api/Commands/Service/SCommandI.java b/src/main/java/smartpot/com/api/Commands/Service/SCommandI.java
index 5a54198..d0ad4bb 100644
--- a/src/main/java/smartpot/com/api/Commands/Service/SCommandI.java
+++ b/src/main/java/smartpot/com/api/Commands/Service/SCommandI.java
@@ -1,20 +1,100 @@
package smartpot.com.api.Commands.Service;
import smartpot.com.api.Commands.Model.DTO.CommandDTO;
-import smartpot.com.api.Commands.Model.Entity.Command;
import java.util.List;
+/**
+ * Interface for the Command Service.
+ *
+ *
+ * Defines the contract for managing command-related operations, including
+ * CRUD operations and execution logic. Implementations of this interface
+ * are expected to provide the core functionality for working with commands.
+ *
+ *
+ * Responsibilities:
+ *
+ * - Retrieve all commands from the data source.
+ * - Retrieve a specific command by its ID.
+ * - Create a new command with specified details.
+ * - Update the details of an existing command.
+ * - Delete a command by its ID.
+ * - Execute a command and record its response.
+ *
+ *
+ * Methods:
+ *
+ * - {@link #getAllCommands()} - Fetches all available commands.
+ * - {@link #getCommandById(String)} - Retrieves a command by its unique ID.
+ * - {@link #createCommand(CommandDTO)} - Creates a new command in the system.
+ * - {@link #updateCommand(String, CommandDTO)} - Updates the details of a command.
+ * - {@link #deleteCommand(String)} - Deletes a command by its ID.
+ * - {@link #executeCommand(String, String)} - Executes a command and logs its response.
+ *
+ *
+ * Usage:
+ *
+ * This interface is typically implemented by a service class, such as {@code SCommand},
+ * to provide the actual logic for managing commands. It is used by controllers
+ * or other services to interact with command-related functionality.
+ *
+ *
+ * @see SCommand
+ * @see CommandDTO
+ */
public interface SCommandI {
- List getAllCommands();
+ /**
+ * Retrieves all commands available in the system.
+ *
+ * @return a list of {@link CommandDTO} representing all commands.
+ * @throws Exception if an error occurs during retrieval or if no commands exist.
+ */
+ List getAllCommands() throws Exception;
+ /**
+ * Retrieves a specific command by its ID.
+ *
+ * @param id the unique identifier of the command.
+ * @return the {@link CommandDTO} representing the command.
+ * @throws Exception if the command does not exist or retrieval fails.
+ */
CommandDTO getCommandById(String id) throws Exception;
+ /**
+ * Creates a new command in the system.
+ *
+ * @param newCommand the {@link CommandDTO} containing the command details.
+ * @return the created {@link CommandDTO}.
+ */
CommandDTO createCommand(CommandDTO newCommand);
- Command updateCommand(String id, Command upCommand) throws Exception;
+ /**
+ * Updates the details of an existing command.
+ *
+ * @param id the unique identifier of the command to update.
+ * @param updateCommand the {@link CommandDTO} containing updated details.
+ * @return the updated {@link CommandDTO}.
+ * @throws Exception if the command does not exist or the update fails.
+ */
+ CommandDTO updateCommand(String id, CommandDTO updateCommand) throws Exception;
+ /**
+ * Deletes a command by its unique ID.
+ *
+ * @param id the unique identifier of the command to delete.
+ * @return a message confirming the deletion.
+ * @throws Exception if the command does not exist or the deletion fails.
+ */
String deleteCommand(String id) throws Exception;
- CommandDTO excuteCommand(String id, String reponse) throws Exception;
+ /**
+ * Executes a command and records its response.
+ *
+ * @param id the unique identifier of the command to execute.
+ * @param response the response or result of the command execution.
+ * @return the updated {@link CommandDTO} reflecting the execution details.
+ * @throws Exception if the command does not exist or execution fails.
+ */
+ CommandDTO executeCommand(String id, String response) throws Exception;
}
diff --git a/src/main/java/smartpot/com/api/Crops/Service/SCrop.java b/src/main/java/smartpot/com/api/Crops/Service/SCrop.java
index ff6dbc5..f6ae2da 100644
--- a/src/main/java/smartpot/com/api/Crops/Service/SCrop.java
+++ b/src/main/java/smartpot/com/api/Crops/Service/SCrop.java
@@ -10,6 +10,7 @@
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import smartpot.com.api.Crops.Mapper.MCrop;
import smartpot.com.api.Crops.Model.DTO.CropDTO;
import smartpot.com.api.Crops.Model.Entity.CropStatus;
@@ -85,6 +86,7 @@ public SCrop(RCrop repositoryCrop, SUserI serviceUser, MCrop mapperCrop, VCropI
* @see MCrop
*/
@Override
+ @Transactional
@CachePut(value = "crops", key = "#cropDTO.id")
public CropDTO createCrop(CropDTO cropDTO) throws Exception {
return Optional.of(cropDTO)
@@ -369,6 +371,7 @@ public List getAllStatus() throws Exception {
* @see MCrop
*/
@Override
+ @Transactional
@CachePut(value = "crops", key = "'id_'+#id")
public CropDTO updatedCrop(String id, CropDTO updateCrop) throws Exception {
CropDTO existingCrop = getCropById(id);
@@ -415,6 +418,7 @@ public CropDTO updatedCrop(String id, CropDTO updateCrop) throws Exception {
* @see RCrop
*/
@Override
+ @Transactional
@CacheEvict(value = "crops", key = "'id_'+#id")
public String deleteCrop(String id) throws Exception {
return Optional.of(getCropById(id))
diff --git a/src/main/java/smartpot/com/api/DataInitializer.java b/src/main/java/smartpot/com/api/DataInitializer.java
deleted file mode 100644
index 1fe1f33..0000000
--- a/src/main/java/smartpot/com/api/DataInitializer.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package smartpot.com.api;
-
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.stereotype.Component;
-
-@Component
-public class DataInitializer implements CommandLineRunner {
- @Override
- public void run(String... args) throws Exception {
-
- }
-
- /* @Autowired
- private RUser userRepository;
-
- @Autowired
- private RSession sessionRepository;
-
- @Autowired
- private RCrop cropRepository;
-
- @Autowired
- private RHistory historyRepository;
-
- @Override
- public void run(String... args) throws Exception {
- /*
- ObjectMapper mapper = new ObjectMapper();
- InputStream inputStream = TypeReference.class.getResourceAsStream("/import.json");
-
- Map data = mapper.readValue(inputStream, new TypeReference