From a75d6bcb802e8093d73d0f80b8015a9434dd7ce7 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Mon, 27 Oct 2025 10:23:00 -0500 Subject: [PATCH 01/18] Template --- .../Controller/ActuatorController.java | 19 ++++++++ .../api/Actuators/Model/DTO/ActuatorDTO.java | 26 +++++++++++ .../api/Actuators/Model/Entity/Actuator.java | 45 +++++++++++++++++++ .../Actuators/Model/Entity/ActuatorType.java | 5 +++ .../api/Actuators/Repository/RActuator.java | 24 ++++++++++ .../com/api/Actuators/Service/SActuator.java | 23 ++++++++++ .../com/api/Actuators/Service/SActuatorI.java | 14 ++++++ 7 files changed, 156 insertions(+) create mode 100644 src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Service/SActuator.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java diff --git a/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java new file mode 100644 index 0000000..2a9a456 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java @@ -0,0 +1,19 @@ +package smartpot.com.api.Actuators.Controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import smartpot.com.api.Actuators.Service.SActuator; + +@RestController +@RequestMapping("Actuators") +public class ActuatorController { + + private final SActuator serviceActuator; + + @Autowired + public ActuatorController(SActuator serviceActuator) { + this.serviceActuator = serviceActuator; + } + +} diff --git a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java new file mode 100644 index 0000000..470e928 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java @@ -0,0 +1,26 @@ +package smartpot.com.api.Actuators.Model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import smartpot.com.api.Actuators.Model.Entity.ActuatorType; + +public class ActuatorDTO { + @Schema(description = "ID único de la instrucción del actuador, generado automáticamente por la base de datos.", + example = "676ae2a9b909de5f9607fcb6", hidden = true) + private String id = null; + + @Schema(description = "La fecha donde se activara el sensor. Si es nulo se asume que se activa al instante", + example = "2024-12-24 11:34:49") + private String actingDate = null; + + @Schema(description = "Tiempo de actuación en segundos.", + example = "300") + private int performanceTime; + + @Schema(description = "Identificador del cultivo asociado.", + example = "") + private String crop; + + @Schema(description = "Tipo de actuador que se desea activar.", + example = "WATER_PUMP") + private ActuatorType type; +} diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java b/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java new file mode 100644 index 0000000..61143f5 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java @@ -0,0 +1,45 @@ +package smartpot.com.api.Actuators.Model.Entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +import java.util.Date; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Document(collection = "actuadores") +public class Actuator { + @Id + @Field("_id") + private ObjectId id; + + // Si no se pone acting date, se asumira que se inicia la ejecucion apenas llege la peticion + @FutureOrPresent(message = "La fecha de actuacion debe ser hoy o en el futuro") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") + @Field("actingDate") + private Date actingDate; + + // segundos + @NotNull(message = "El tiempo de actuacion no puede estar vacio") + @Field("performanceTime") + private int performanceTime; + + @NotNull(message = "El registro debe estar asociado a un cultivo") + @Field("crop") + private ObjectId crop; + + @NotNull(message = "El tipo de actuador no puede ser nulo") + @Field("type") + private ActuatorType type; +} diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java b/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java new file mode 100644 index 0000000..03e309d --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java @@ -0,0 +1,5 @@ +package smartpot.com.api.Actuators.Model.Entity; + +public enum ActuatorType { + UV_LIGHT, WATER_PUMP, HUMIDIFIER +} diff --git a/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java b/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java new file mode 100644 index 0000000..b1cf7f7 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java @@ -0,0 +1,24 @@ +package smartpot.com.api.Actuators.Repository; + +import jakarta.validation.constraints.NotNull; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.mongodb.repository.Query; +import org.springframework.stereotype.Repository; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface RActuator extends MongoRepository { + + @Query("{'_id': ?0}") + Optional findById( + @NotNull(message = "Se necesita el id del actuador") + ObjectId id); + + List findByCrop( + @NotNull(message = "El registro debe estar asociado a un cultivo") + ObjectId crop); +} diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java new file mode 100644 index 0000000..d6f0cf0 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -0,0 +1,23 @@ +package smartpot.com.api.Actuators.Service; + +import org.bson.types.ObjectId; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +import java.util.List; + +public class SActuator implements SActuatorI { + @Override + public List getAllActuators() { + return List.of(); + } + + @Override + public Actuator getActuatorById(ObjectId id) { + return null; + } + + @Override + public List getActuatorsByCrop(ObjectId crop) { + return List.of(); + } +} diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java new file mode 100644 index 0000000..f07927a --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java @@ -0,0 +1,14 @@ +package smartpot.com.api.Actuators.Service; + +import org.bson.types.ObjectId; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +import java.util.List; + +public interface SActuatorI { + List getAllActuators(); + + Actuator getActuatorById(ObjectId id); + + List getActuatorsByCrop(ObjectId crop); +} From ef79e6d251cc9f1b58f4913d0a915dc40ff48875 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Mon, 27 Oct 2025 10:23:00 -0500 Subject: [PATCH 02/18] Template --- .../Controller/ActuatorController.java | 19 ++++++++ .../api/Actuators/Model/DTO/ActuatorDTO.java | 26 +++++++++++ .../api/Actuators/Model/Entity/Actuator.java | 45 +++++++++++++++++++ .../Actuators/Model/Entity/ActuatorType.java | 5 +++ .../api/Actuators/Repository/RActuator.java | 24 ++++++++++ .../com/api/Actuators/Service/SActuator.java | 23 ++++++++++ .../com/api/Actuators/Service/SActuatorI.java | 14 ++++++ 7 files changed, 156 insertions(+) create mode 100644 src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Service/SActuator.java create mode 100644 src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java diff --git a/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java new file mode 100644 index 0000000..2a9a456 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java @@ -0,0 +1,19 @@ +package smartpot.com.api.Actuators.Controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import smartpot.com.api.Actuators.Service.SActuator; + +@RestController +@RequestMapping("Actuators") +public class ActuatorController { + + private final SActuator serviceActuator; + + @Autowired + public ActuatorController(SActuator serviceActuator) { + this.serviceActuator = serviceActuator; + } + +} diff --git a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java new file mode 100644 index 0000000..470e928 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java @@ -0,0 +1,26 @@ +package smartpot.com.api.Actuators.Model.DTO; + +import io.swagger.v3.oas.annotations.media.Schema; +import smartpot.com.api.Actuators.Model.Entity.ActuatorType; + +public class ActuatorDTO { + @Schema(description = "ID único de la instrucción del actuador, generado automáticamente por la base de datos.", + example = "676ae2a9b909de5f9607fcb6", hidden = true) + private String id = null; + + @Schema(description = "La fecha donde se activara el sensor. Si es nulo se asume que se activa al instante", + example = "2024-12-24 11:34:49") + private String actingDate = null; + + @Schema(description = "Tiempo de actuación en segundos.", + example = "300") + private int performanceTime; + + @Schema(description = "Identificador del cultivo asociado.", + example = "") + private String crop; + + @Schema(description = "Tipo de actuador que se desea activar.", + example = "WATER_PUMP") + private ActuatorType type; +} diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java b/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java new file mode 100644 index 0000000..61143f5 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java @@ -0,0 +1,45 @@ +package smartpot.com.api.Actuators.Model.Entity; + +import com.fasterxml.jackson.annotation.JsonFormat; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.bson.types.ObjectId; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; +import org.springframework.data.mongodb.core.mapping.Field; + +import java.util.Date; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Document(collection = "actuadores") +public class Actuator { + @Id + @Field("_id") + private ObjectId id; + + // Si no se pone acting date, se asumira que se inicia la ejecucion apenas llege la peticion + @FutureOrPresent(message = "La fecha de actuacion debe ser hoy o en el futuro") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") + @Field("actingDate") + private Date actingDate; + + // segundos + @NotNull(message = "El tiempo de actuacion no puede estar vacio") + @Field("performanceTime") + private int performanceTime; + + @NotNull(message = "El registro debe estar asociado a un cultivo") + @Field("crop") + private ObjectId crop; + + @NotNull(message = "El tipo de actuador no puede ser nulo") + @Field("type") + private ActuatorType type; +} diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java b/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java new file mode 100644 index 0000000..03e309d --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java @@ -0,0 +1,5 @@ +package smartpot.com.api.Actuators.Model.Entity; + +public enum ActuatorType { + UV_LIGHT, WATER_PUMP, HUMIDIFIER +} diff --git a/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java b/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java new file mode 100644 index 0000000..b1cf7f7 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java @@ -0,0 +1,24 @@ +package smartpot.com.api.Actuators.Repository; + +import jakarta.validation.constraints.NotNull; +import org.bson.types.ObjectId; +import org.springframework.data.mongodb.repository.MongoRepository; +import org.springframework.data.mongodb.repository.Query; +import org.springframework.stereotype.Repository; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface RActuator extends MongoRepository { + + @Query("{'_id': ?0}") + Optional findById( + @NotNull(message = "Se necesita el id del actuador") + ObjectId id); + + List findByCrop( + @NotNull(message = "El registro debe estar asociado a un cultivo") + ObjectId crop); +} diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java new file mode 100644 index 0000000..d6f0cf0 --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -0,0 +1,23 @@ +package smartpot.com.api.Actuators.Service; + +import org.bson.types.ObjectId; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +import java.util.List; + +public class SActuator implements SActuatorI { + @Override + public List getAllActuators() { + return List.of(); + } + + @Override + public Actuator getActuatorById(ObjectId id) { + return null; + } + + @Override + public List getActuatorsByCrop(ObjectId crop) { + return List.of(); + } +} diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java new file mode 100644 index 0000000..f07927a --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java @@ -0,0 +1,14 @@ +package smartpot.com.api.Actuators.Service; + +import org.bson.types.ObjectId; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +import java.util.List; + +public interface SActuatorI { + List getAllActuators(); + + Actuator getActuatorById(ObjectId id); + + List getActuatorsByCrop(ObjectId crop); +} From c49109dd7521dd0b7f136e7171ffb5aa16de07db Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 10:28:37 -0500 Subject: [PATCH 03/18] Actuator basic endpoints --- .../Controller/ActuatorController.java | 46 +++++++++++++++++-- .../com/api/Actuators/Service/SActuator.java | 13 +++++- .../com/api/Actuators/Service/SActuatorI.java | 5 +- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java index 2a9a456..6125b57 100644 --- a/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java +++ b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java @@ -1,19 +1,57 @@ package smartpot.com.api.Actuators.Controller; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import smartpot.com.api.Actuators.Service.SActuator; +import smartpot.com.api.Actuators.Model.Entity.Actuator; +import smartpot.com.api.Actuators.Service.SActuatorI; + +import java.util.List; @RestController -@RequestMapping("Actuators") +@RequestMapping("/Actuators") public class ActuatorController { - private final SActuator serviceActuator; + private final SActuatorI serviceActuator; @Autowired - public ActuatorController(SActuator serviceActuator) { + public ActuatorController(SActuatorI serviceActuator) { this.serviceActuator = serviceActuator; } + + /** + * Obtiene todos los actuadores almacenados en el sistema. + * + * @return Lista de todos los actuadores existentes + */ + @GetMapping("/All") + public List getAllActuators() { + return serviceActuator.getAllActuators(); + } + + /** + * Obtiene el actuadores con el identificador proporcionado. + * + * @param id Es el identificador del la instruccion del actuador + * @return Lista de todos los actuadores existentes + */ + @GetMapping("/{id}") + public Actuator getActuatorById(@PathVariable String id) { + return serviceActuator.getActuatorById(id); + } + + /** + * Obtiene todos los actuadores almacenados en el sistema para un cultivo espesificado. + * + * @param id Es el identificador del cultivo + * @return Lista de todos los actuadores existentes + */ + @GetMapping("/crop/{id}") + public List getActuatorByCrop(@PathVariable String id) { + return serviceActuator.getActuatorsByCrop(id); + } + } diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java index d6f0cf0..1599fce 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -1,10 +1,18 @@ package smartpot.com.api.Actuators.Service; +import lombok.Builder; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; +import org.springframework.stereotype.Service; import smartpot.com.api.Actuators.Model.Entity.Actuator; import java.util.List; +@Slf4j +@Data +@Builder +@Service public class SActuator implements SActuatorI { @Override public List getAllActuators() { @@ -12,12 +20,13 @@ public List getAllActuators() { } @Override - public Actuator getActuatorById(ObjectId id) { + public Actuator getActuatorById(String id) { return null; } @Override - public List getActuatorsByCrop(ObjectId crop) { + public List getActuatorsByCrop(String crop) { return List.of(); } + } diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java index f07927a..e0d2df6 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java @@ -1,6 +1,5 @@ package smartpot.com.api.Actuators.Service; -import org.bson.types.ObjectId; import smartpot.com.api.Actuators.Model.Entity.Actuator; import java.util.List; @@ -8,7 +7,7 @@ public interface SActuatorI { List getAllActuators(); - Actuator getActuatorById(ObjectId id); + Actuator getActuatorById(String id); - List getActuatorsByCrop(ObjectId crop); + List getActuatorsByCrop(String crop); } From e1eb81cd9931d9f0b7ed495fe037e4112e253743 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 10:33:47 -0500 Subject: [PATCH 04/18] SActuatorI Crud Op --- .../smartpot/com/api/Actuators/Service/SActuatorI.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java index e0d2df6..5152a63 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java @@ -1,6 +1,8 @@ package smartpot.com.api.Actuators.Service; +import org.springframework.http.ResponseEntity; import smartpot.com.api.Actuators.Model.Entity.Actuator; +import smartpot.com.api.Exception.ApiResponse; import java.util.List; @@ -10,4 +12,12 @@ public interface SActuatorI { Actuator getActuatorById(String id); List getActuatorsByCrop(String crop); + + Actuator CreateActuator(Actuator actuator); + + Actuator UpdateActuator(Actuator actuator); + + Actuator DeleteActuatorById(String id); + + ResponseEntity DeleteActuators(List ids); } From ccbf6e49f50a166b243f10d0b4f2a2f2d92b8ee2 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 10:34:29 -0500 Subject: [PATCH 05/18] Raw override on SActuator --- .../com/api/Actuators/Service/SActuator.java | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java index 1599fce..6cc3a41 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -4,8 +4,10 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import smartpot.com.api.Actuators.Model.Entity.Actuator; +import smartpot.com.api.Exception.ApiResponse; import java.util.List; @@ -14,6 +16,7 @@ @Builder @Service public class SActuator implements SActuatorI { + @Override public List getAllActuators() { return List.of(); @@ -29,4 +32,23 @@ public List getActuatorsByCrop(String crop) { return List.of(); } + @Override + public Actuator CreateActuator(Actuator actuator) { + return null; + } + + @Override + public Actuator UpdateActuator(Actuator actuator) { + return null; + } + + @Override + public Actuator DeleteActuatorById(String id) { + return null; + } + + @Override + public ResponseEntity DeleteActuators(List ids) { + return null; + } } From 69812e99c134b880e9bf91ceafbf342e974fe594 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 10:52:43 -0500 Subject: [PATCH 06/18] Basic implementations in service --- .../api/Actuators/Repository/RActuator.java | 12 +++++ .../com/api/Actuators/Service/SActuator.java | 49 ++++++++++++++++--- .../com/api/Actuators/Service/SActuatorI.java | 5 +- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java b/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java index b1cf7f7..072126d 100644 --- a/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Repository/RActuator.java @@ -13,11 +13,23 @@ @Repository public interface RActuator extends MongoRepository { + /** + * Busca el registro de actuador con la id espesificada + * + * @param id El identificado del registro del actuador. + * @return Devuelve el actuador, en caso de ser encontrado. + */ @Query("{'_id': ?0}") Optional findById( @NotNull(message = "Se necesita el id del actuador") ObjectId id); + /** + * Busca los registros de actuadorres con el identificador del cultivo espesificado + * + * @param crop El identificado del cultivo relacionado a registros del actuadores. + * @return Devuelve una lista de actuadores. + */ List findByCrop( @NotNull(message = "El registro debe estar asociado a un cultivo") ObjectId crop); diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java index 6cc3a41..bf020f8 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -4,9 +4,14 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; import smartpot.com.api.Actuators.Model.Entity.Actuator; +import smartpot.com.api.Actuators.Repository.RActuator; +import smartpot.com.api.Exception.ApiException; import smartpot.com.api.Exception.ApiResponse; import java.util.List; @@ -17,28 +22,60 @@ @Service public class SActuator implements SActuatorI { + private final RActuator actuatorRepository; + + @Autowired + public SActuator(RActuator actuatorRepository) { + this.actuatorRepository = actuatorRepository; + } + @Override public List getAllActuators() { - return List.of(); + List actuators = actuatorRepository.findAll(); + if (actuators.isEmpty()) { + throw new ApiException(new ApiResponse( + "No se encontró ningún actuador en el sistema", + HttpStatus.NOT_FOUND.value() + )); + } + return actuators; } @Override public Actuator getActuatorById(String id) { - return null; + 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() + )); + } + return actuatorRepository.findById(new ObjectId(id)) + .orElseThrow(() -> new ApiException( + new ApiResponse("El Actuador con id '" + id + "' no fue encontrado.", + HttpStatus.NOT_FOUND.value()) + )); } @Override public List getActuatorsByCrop(String crop) { - return List.of(); + if (!ObjectId.isValid(crop)) { + throw new ApiException(new ApiResponse( + "El id de cultivo '" + crop + "' 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() + )); + } + return actuatorRepository.findByCrop(new ObjectId(crop)); } @Override - public Actuator CreateActuator(Actuator actuator) { - return null; + public Actuator CreateActuator(ActuatorDTO actuator) { + //Actuator act = new Actuator(); + //return actuatorRepository.save(actuator); + return null } @Override - public Actuator UpdateActuator(Actuator actuator) { + public Actuator UpdateActuator(ActuatorDTO actuator) { return null; } diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java index 5152a63..b511ddb 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java @@ -1,6 +1,7 @@ package smartpot.com.api.Actuators.Service; import org.springframework.http.ResponseEntity; +import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; import smartpot.com.api.Actuators.Model.Entity.Actuator; import smartpot.com.api.Exception.ApiResponse; @@ -13,9 +14,9 @@ public interface SActuatorI { List getActuatorsByCrop(String crop); - Actuator CreateActuator(Actuator actuator); + Actuator CreateActuator(ActuatorDTO actuator); - Actuator UpdateActuator(Actuator actuator); + Actuator UpdateActuator(ActuatorDTO actuator); Actuator DeleteActuatorById(String id); From 88d2808e89661f63d0a441dea146b15e907dce84 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 10:53:07 -0500 Subject: [PATCH 07/18] fix --- src/main/java/smartpot/com/api/Actuators/Service/SActuator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java index bf020f8..58dc57c 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -71,7 +71,7 @@ public List getActuatorsByCrop(String crop) { public Actuator CreateActuator(ActuatorDTO actuator) { //Actuator act = new Actuator(); //return actuatorRepository.save(actuator); - return null + return null; } @Override From 631eca4cbc756ab839d02867bdfe9f8de43575a1 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 11:00:02 -0500 Subject: [PATCH 08/18] Mapper for Actuator's entity and DTO --- .../com/api/Actuators/Mapper/MActuators.java | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java diff --git a/src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java b/src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java new file mode 100644 index 0000000..428dddc --- /dev/null +++ b/src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java @@ -0,0 +1,31 @@ +package smartpot.com.api.Actuators.Mapper; + +import org.bson.types.ObjectId; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.factory.Mappers; +import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; +import smartpot.com.api.Actuators.Model.Entity.Actuator; + +@Mapper(componentModel = "spring") +public interface MActuators { + MActuators INSTANCE = Mappers.getMapper(MActuators.class); + + @Mapping(source = "id", target = "id", qualifiedByName = "stringToObjectId") + @Mapping(source = "crop", target = "crop", qualifiedByName = "stringToObjectId") + Actuator toEntity(ActuatorDTO recordDTO); + + @Mapping(source = "id", target = "id", qualifiedByName = "objectIdToString") + @Mapping(source = "crop", target = "crop", qualifiedByName = "objectIdToString") + ActuatorDTO toDTO(Actuator history); + + @org.mapstruct.Named("objectIdToString") + default String objectIdToString(ObjectId objectId) { + return objectId != null ? objectId.toHexString() : null; + } + + @org.mapstruct.Named("stringToObjectId") + default ObjectId stringToObjectId(String id) { + return id != null ? new ObjectId(id) : null; + } +} From ce6bf5e43488fa6dd9abce0d759d10722ee0c053 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 1 Nov 2025 11:20:11 -0500 Subject: [PATCH 09/18] Basic controller implemented (no tested) --- .../Controller/ActuatorController.java | 23 ++++++-- .../api/Actuators/Model/DTO/ActuatorDTO.java | 2 + .../com/api/Actuators/Service/SActuator.java | 52 ++++++++++++++----- .../com/api/Actuators/Service/SActuatorI.java | 8 +-- 4 files changed, 64 insertions(+), 21 deletions(-) diff --git a/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java index 6125b57..30e0406 100644 --- a/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java +++ b/src/main/java/smartpot/com/api/Actuators/Controller/ActuatorController.java @@ -1,12 +1,12 @@ package smartpot.com.api.Actuators.Controller; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; import smartpot.com.api.Actuators.Model.Entity.Actuator; import smartpot.com.api.Actuators.Service.SActuatorI; +import smartpot.com.api.Exception.ApiResponse; import java.util.List; @@ -54,4 +54,19 @@ public List getActuatorByCrop(@PathVariable String id) { return serviceActuator.getActuatorsByCrop(id); } + @PostMapping("/Create") + public Actuator createActuator(@RequestBody ActuatorDTO actuator) throws Exception { + return serviceActuator.createActuator(actuator); + } + + @PutMapping("/Update/{id}") + public Actuator updateActuator(@PathVariable String id, @RequestBody ActuatorDTO actuator) throws Exception { + return serviceActuator.updateActuator(serviceActuator.getActuatorById(id), actuator); + } + + @DeleteMapping("/Delete/{id}") + public ResponseEntity deleteActuator(@PathVariable String id) throws Exception { + return serviceActuator.deleteActuatorById(serviceActuator.getActuatorById(id)); + } + } diff --git a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java index 470e928..eb78085 100644 --- a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java +++ b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java @@ -1,8 +1,10 @@ package smartpot.com.api.Actuators.Model.DTO; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; import smartpot.com.api.Actuators.Model.Entity.ActuatorType; +@Data public class ActuatorDTO { @Schema(description = "ID único de la instrucción del actuador, generado automáticamente por la base de datos.", example = "676ae2a9b909de5f9607fcb6", hidden = true) diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java index 58dc57c..da530a9 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java @@ -8,9 +8,11 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; +import smartpot.com.api.Actuators.Mapper.MActuators; import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; import smartpot.com.api.Actuators.Model.Entity.Actuator; import smartpot.com.api.Actuators.Repository.RActuator; +import smartpot.com.api.Crops.Service.SCropI; import smartpot.com.api.Exception.ApiException; import smartpot.com.api.Exception.ApiResponse; @@ -23,10 +25,12 @@ public class SActuator implements SActuatorI { private final RActuator actuatorRepository; + private final SCropI serviceCrop; @Autowired - public SActuator(RActuator actuatorRepository) { + public SActuator(RActuator actuatorRepository, SCropI serviceCrop) { this.actuatorRepository = actuatorRepository; + this.serviceCrop = serviceCrop; } @Override @@ -68,24 +72,46 @@ public List getActuatorsByCrop(String crop) { } @Override - public Actuator CreateActuator(ActuatorDTO actuator) { - //Actuator act = new Actuator(); - //return actuatorRepository.save(actuator); - return null; + public Actuator createActuator(ActuatorDTO actuator) throws Exception { + serviceCrop.getCropById(actuator.getCrop()); + Actuator act = MActuators.INSTANCE.toEntity(actuator); + return actuatorRepository.save(act); } @Override - public Actuator UpdateActuator(ActuatorDTO actuator) { - return null; - } + public Actuator updateActuator(Actuator existingActuator, ActuatorDTO actuator) { + if (actuator.getId() != null && actuator.getCrop() != null) { + existingActuator = MActuators.INSTANCE.toEntity(actuator); + } - @Override - public Actuator DeleteActuatorById(String id) { - return null; + try { + return actuatorRepository.save(existingActuator); + } catch (Exception e) { + log.error("e: ", e); + throw new ApiException( + new ApiResponse("No se pudo actualizar el actuador con ID '" + existingActuator.getId() + "'.", + HttpStatus.INTERNAL_SERVER_ERROR.value())); + } } @Override - public ResponseEntity DeleteActuators(List ids) { - return null; + public ResponseEntity deleteActuatorById(Actuator actuator) { + try { + actuatorRepository.deleteById(actuator.getId()); + return ResponseEntity.status(HttpStatus.OK.value()).body( + new ApiResponse("El Actuador con ID '" + actuator.getId() + "' fue eliminado.", + HttpStatus.OK.value()) + ); + } catch (Exception e) { + log.error("e: ", e); + throw new ApiException( + new ApiResponse("No se pudo eliminar el Actuador con ID '" + actuator.getId() + "'.", + HttpStatus.INTERNAL_SERVER_ERROR.value())); + } } + + //@Override + //public ResponseEntity deleteActuators(List ids) { + // return null; + //} } diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java index b511ddb..585e3b8 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java +++ b/src/main/java/smartpot/com/api/Actuators/Service/SActuatorI.java @@ -14,11 +14,11 @@ public interface SActuatorI { List getActuatorsByCrop(String crop); - Actuator CreateActuator(ActuatorDTO actuator); + Actuator createActuator(ActuatorDTO actuator) throws Exception; - Actuator UpdateActuator(ActuatorDTO actuator); + Actuator updateActuator(Actuator existingActuator , ActuatorDTO actuator); - Actuator DeleteActuatorById(String id); + ResponseEntity deleteActuatorById(Actuator actuator); - ResponseEntity DeleteActuators(List ids); + //ResponseEntity deleteActuators(List ids); } From 2962603d3e2976c9d82cd06fd9d7308d0aacf766 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Fri, 14 Nov 2025 17:55:33 -0500 Subject: [PATCH 10/18] actuator and command wip --- .../api/Actuators/Model/DTO/ActuatorDTO.java | 8 ----- .../api/Actuators/Model/Entity/Actuator.java | 11 ------- .../Controller/CommandController.java | 23 ++++++++++++++- .../com/api/Commands/Mapper/MCommand.java | 2 ++ .../api/Commands/Model/DTO/CommandDTO.java | 4 ++- .../api/Commands/Model/Entity/Command.java | 9 ++++-- .../Commands/Model/Entity/CommandStatus.java | 5 ++++ .../com/api/Commands/Service/SCommand.java | 29 +++++++++++++++++-- .../com/api/Commands/Service/SCommandI.java | 9 ++++++ 9 files changed, 74 insertions(+), 26 deletions(-) create mode 100644 src/main/java/smartpot/com/api/Commands/Model/Entity/CommandStatus.java diff --git a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java index eb78085..739778d 100644 --- a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java +++ b/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java @@ -10,14 +10,6 @@ public class ActuatorDTO { example = "676ae2a9b909de5f9607fcb6", hidden = true) private String id = null; - @Schema(description = "La fecha donde se activara el sensor. Si es nulo se asume que se activa al instante", - example = "2024-12-24 11:34:49") - private String actingDate = null; - - @Schema(description = "Tiempo de actuación en segundos.", - example = "300") - private int performanceTime; - @Schema(description = "Identificador del cultivo asociado.", example = "") private String crop; diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java b/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java index 61143f5..9a9fef1 100644 --- a/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java +++ b/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java @@ -24,17 +24,6 @@ public class Actuator { @Field("_id") private ObjectId id; - // Si no se pone acting date, se asumira que se inicia la ejecucion apenas llege la peticion - @FutureOrPresent(message = "La fecha de actuacion debe ser hoy o en el futuro") - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ") - @Field("actingDate") - private Date actingDate; - - // segundos - @NotNull(message = "El tiempo de actuacion no puede estar vacio") - @Field("performanceTime") - private int performanceTime; - @NotNull(message = "El registro debe estar asociado a un cultivo") @Field("crop") private ObjectId crop; 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 7ac1d11..3e4177d 100644 --- a/src/main/java/smartpot/com/api/Commands/Controller/CommandController.java +++ b/src/main/java/smartpot/com/api/Commands/Controller/CommandController.java @@ -17,7 +17,7 @@ import smartpot.com.api.Responses.ErrorResponse; @RestController -@RequestMapping("/Comandos") +@RequestMapping("/Commands") public class CommandController { private final SCommandI serviceCommand; @@ -70,6 +70,27 @@ public ResponseEntity getAllCommand() { } } + @GetMapping("/crop/{crop}") + @Operation(summary = "Obtener todos los comandos de un cultivo", + description = "Recupera todos los comandos asociados a un cultivo en el sistema. " + + "En caso de no haber comandos, se devolverá una excepción.", + responses = { + @ApiResponse(description = "Comandos encontrados", + responseCode = "200", + content = @Content(mediaType = "application/json", + array = @ArraySchema(schema = @Schema(implementation = CommandDTO.class)))), + @ApiResponse(responseCode = "404", + description = "No se encontraron Comandos registrados.", + content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))) + }) + public ResponseEntity getCommandsByCrop(@PathVariable String crop) { + try { + return new ResponseEntity<>(serviceCommand.getCommandsByCrop(crop), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al obtener los comandos [" + e.getMessage() + "]", HttpStatus.INTERNAL_SERVER_ERROR.value()), HttpStatus.INTERNAL_SERVER_ERROR); + } + } + @GetMapping("/id/{id}") @Operation(summary = "Buscar comando por ID", description = "Recupera un comando utilizando su ID único. " diff --git a/src/main/java/smartpot/com/api/Commands/Mapper/MCommand.java b/src/main/java/smartpot/com/api/Commands/Mapper/MCommand.java index b5531ea..87e1ea6 100644 --- a/src/main/java/smartpot/com/api/Commands/Mapper/MCommand.java +++ b/src/main/java/smartpot/com/api/Commands/Mapper/MCommand.java @@ -13,10 +13,12 @@ public interface MCommand { @Mapping(source = "id", target = "id", qualifiedByName = "stringToObjectId") @Mapping(source = "crop", target = "crop", qualifiedByName = "stringToObjectId") + @Mapping(source = "actuator", target = "actuator", qualifiedByName = "stringToObjectId") Command toEntity(CommandDTO commandDTO); @Mapping(source = "id", target = "id", qualifiedByName = "objectIdToString") @Mapping(source = "crop", target = "crop", qualifiedByName = "objectIdToString") + @Mapping(source = "actuator", target = "actuator", qualifiedByName = "objectIdToString") CommandDTO toDTO(Command command); @org.mapstruct.Named("objectIdToString") diff --git a/src/main/java/smartpot/com/api/Commands/Model/DTO/CommandDTO.java b/src/main/java/smartpot/com/api/Commands/Model/DTO/CommandDTO.java index 929c382..d0c0e08 100644 --- a/src/main/java/smartpot/com/api/Commands/Model/DTO/CommandDTO.java +++ b/src/main/java/smartpot/com/api/Commands/Model/DTO/CommandDTO.java @@ -1,6 +1,7 @@ package smartpot.com.api.Commands.Model.DTO; import lombok.Data; +import smartpot.com.api.Commands.Model.Entity.CommandStatus; import java.io.Serializable; @@ -8,7 +9,8 @@ public class CommandDTO implements Serializable { private String id; private String commandType; - private String status; + private String actuator; + private CommandStatus status; private String dateCreated; private String dateExecuted; private String response; diff --git a/src/main/java/smartpot/com/api/Commands/Model/Entity/Command.java b/src/main/java/smartpot/com/api/Commands/Model/Entity/Command.java index d344099..ff23301 100644 --- a/src/main/java/smartpot/com/api/Commands/Model/Entity/Command.java +++ b/src/main/java/smartpot/com/api/Commands/Model/Entity/Command.java @@ -36,8 +36,12 @@ public class Command { @Field("commandType") private String commandType; + @NotNull + @Field("actuator") + private ObjectId actuator; + @Field("status") - private String status; + private CommandStatus status; @NotNull(message = "La fecha de creación no puede estar vacía") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX") @@ -48,15 +52,14 @@ public class Command { @Field("dateExecuted") private Date dateExecuted; - @Field("response") private String response; @NotNull(message = "El comando debe ejecutarse en un cultivo") + //@DBRef @Field("crop") private ObjectId crop; - } /* diff --git a/src/main/java/smartpot/com/api/Commands/Model/Entity/CommandStatus.java b/src/main/java/smartpot/com/api/Commands/Model/Entity/CommandStatus.java new file mode 100644 index 0000000..92c25bb --- /dev/null +++ b/src/main/java/smartpot/com/api/Commands/Model/Entity/CommandStatus.java @@ -0,0 +1,5 @@ +package smartpot.com.api.Commands.Model.Entity; + +public enum CommandStatus { + EXECUTED, PENDING, FAILED, ABORTED +} 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 56fcaab..d72f974 100644 --- a/src/main/java/smartpot/com/api/Commands/Service/SCommand.java +++ b/src/main/java/smartpot/com/api/Commands/Service/SCommand.java @@ -11,6 +11,7 @@ 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.CommandStatus; import smartpot.com.api.Commands.Repository.RCommand; import smartpot.com.api.Crops.Service.SCropI; @@ -105,6 +106,30 @@ public List getAllCommands() throws Exception { .orElseThrow(() -> new Exception("No existe ningún comando")); } + /** + * Retrieves all commands for a crop 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 'crop_' under the 'commands' cache. + *

+ * + * @param crop the unique identifier of the crop to retrieve the commands + * @return a list of {@code CommandDTO} objects representing all commands + * @throws Exception if no commands exist in the repository + */ + @Override + @Cacheable(value = "commands", key = "'crop_'+#crop") + public List getCommandsByCrop(String crop) throws Exception { + return Optional.of(crop) + .map(ObjectId::new) + .map(repositoryCommand::findByCropId) + .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. *

@@ -148,7 +173,7 @@ public CommandDTO createCommand(CommandDTO commandDTO) throws IllegalStateExcept .map(dto -> { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dto.setDateCreated(formatter.format(new Date())); - dto.setStatus("PENDING"); + dto.setStatus(CommandStatus.PENDING); return dto; }) .map(mapperCommand::toEntity) @@ -177,7 +202,7 @@ public CommandDTO executeCommand(String id, String response) throws Exception { .map(commandDTO -> { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); commandDTO.setDateCreated(formatter.format(new Date())); - commandDTO.setStatus("EXECUTED"); + commandDTO.setStatus(CommandStatus.EXECUTED); commandDTO.setResponse(response); return commandDTO; }) 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 d0ad4bb..89c857f 100644 --- a/src/main/java/smartpot/com/api/Commands/Service/SCommandI.java +++ b/src/main/java/smartpot/com/api/Commands/Service/SCommandI.java @@ -52,6 +52,15 @@ public interface SCommandI { */ List getAllCommands() throws Exception; + /** + * Retrieves all commands for a crop in the system. + * + * @param crop the unique identifier of the crop + * @return a list of {@link CommandDTO} representing all commands. + * @throws Exception if an error occurs during retrieval or if no commands exist. + */ + List getCommandsByCrop(String crop) throws Exception; + /** * Retrieves a specific command by its ID. * From 1e121665d27bc95fc9c5383dd73d8139d33608c1 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 15:06:19 -0500 Subject: [PATCH 11/18] package update and rename --- .../api/actuators/mapper/ActuatorMapper.java} | 10 +++++----- .../api/actuators/model/dto}/ActuatorDTO.java | 4 ++-- .../api/actuators/model/entity}/Actuator.java | 6 +----- .../actuators/model/entity}/ActuatorType.java | 2 +- .../service/ServiceActuatorImpl.java} | 20 +++++++++---------- 5 files changed, 19 insertions(+), 23 deletions(-) rename src/main/java/{smartpot/com/api/Actuators/Mapper/MActuators.java => app/smartpot/api/actuators/mapper/ActuatorMapper.java} (77%) rename src/main/java/{smartpot/com/api/Actuators/Model/DTO => app/smartpot/api/actuators/model/dto}/ActuatorDTO.java (84%) rename src/main/java/{smartpot/com/api/Actuators/Model/Entity => app/smartpot/api/actuators/model/entity}/Actuator.java (80%) rename src/main/java/{smartpot/com/api/Actuators/Model/Entity => app/smartpot/api/actuators/model/entity}/ActuatorType.java (57%) rename src/main/java/{smartpot/com/api/Actuators/Service/SActuator.java => app/smartpot/api/actuators/service/ServiceActuatorImpl.java} (85%) diff --git a/src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java b/src/main/java/app/smartpot/api/actuators/mapper/ActuatorMapper.java similarity index 77% rename from src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java rename to src/main/java/app/smartpot/api/actuators/mapper/ActuatorMapper.java index 428dddc..3de202a 100644 --- a/src/main/java/smartpot/com/api/Actuators/Mapper/MActuators.java +++ b/src/main/java/app/smartpot/api/actuators/mapper/ActuatorMapper.java @@ -1,15 +1,15 @@ -package smartpot.com.api.Actuators.Mapper; +package app.smartpot.api.actuators.mapper; import org.bson.types.ObjectId; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; -import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; -import smartpot.com.api.Actuators.Model.Entity.Actuator; +import app.smartpot.api.actuators.model.dto.ActuatorDTO; +import app.smartpot.api.actuators.model.entity.Actuator; @Mapper(componentModel = "spring") -public interface MActuators { - MActuators INSTANCE = Mappers.getMapper(MActuators.class); +public interface ActuatorMapper { + ActuatorMapper INSTANCE = Mappers.getMapper(ActuatorMapper.class); @Mapping(source = "id", target = "id", qualifiedByName = "stringToObjectId") @Mapping(source = "crop", target = "crop", qualifiedByName = "stringToObjectId") diff --git a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java b/src/main/java/app/smartpot/api/actuators/model/dto/ActuatorDTO.java similarity index 84% rename from src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java rename to src/main/java/app/smartpot/api/actuators/model/dto/ActuatorDTO.java index 739778d..29656cf 100644 --- a/src/main/java/smartpot/com/api/Actuators/Model/DTO/ActuatorDTO.java +++ b/src/main/java/app/smartpot/api/actuators/model/dto/ActuatorDTO.java @@ -1,8 +1,8 @@ -package smartpot.com.api.Actuators.Model.DTO; +package app.smartpot.api.actuators.model.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import smartpot.com.api.Actuators.Model.Entity.ActuatorType; +import app.smartpot.api.actuators.model.entity.ActuatorType; @Data public class ActuatorDTO { diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java b/src/main/java/app/smartpot/api/actuators/model/entity/Actuator.java similarity index 80% rename from src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java rename to src/main/java/app/smartpot/api/actuators/model/entity/Actuator.java index 9a9fef1..1b0b8da 100644 --- a/src/main/java/smartpot/com/api/Actuators/Model/Entity/Actuator.java +++ b/src/main/java/app/smartpot/api/actuators/model/entity/Actuator.java @@ -1,7 +1,5 @@ -package smartpot.com.api.Actuators.Model.Entity; +package app.smartpot.api.actuators.model.entity; -import com.fasterxml.jackson.annotation.JsonFormat; -import jakarta.validation.constraints.FutureOrPresent; import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Builder; @@ -12,8 +10,6 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; -import java.util.Date; - @Data @Builder @NoArgsConstructor diff --git a/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java b/src/main/java/app/smartpot/api/actuators/model/entity/ActuatorType.java similarity index 57% rename from src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java rename to src/main/java/app/smartpot/api/actuators/model/entity/ActuatorType.java index 03e309d..0c06962 100644 --- a/src/main/java/smartpot/com/api/Actuators/Model/Entity/ActuatorType.java +++ b/src/main/java/app/smartpot/api/actuators/model/entity/ActuatorType.java @@ -1,4 +1,4 @@ -package smartpot.com.api.Actuators.Model.Entity; +package app.smartpot.api.actuators.model.entity; public enum ActuatorType { UV_LIGHT, WATER_PUMP, HUMIDIFIER diff --git a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java b/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java similarity index 85% rename from src/main/java/smartpot/com/api/Actuators/Service/SActuator.java rename to src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java index da530a9..9476974 100644 --- a/src/main/java/smartpot/com/api/Actuators/Service/SActuator.java +++ b/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java @@ -1,4 +1,4 @@ -package smartpot.com.api.Actuators.Service; +package app.smartpot.api.actuators.service; import lombok.Builder; import lombok.Data; @@ -8,10 +8,10 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; -import smartpot.com.api.Actuators.Mapper.MActuators; -import smartpot.com.api.Actuators.Model.DTO.ActuatorDTO; -import smartpot.com.api.Actuators.Model.Entity.Actuator; -import smartpot.com.api.Actuators.Repository.RActuator; +import app.smartpot.api.actuators.mapper.ActuatorMapper; +import app.smartpot.api.actuators.model.dto.ActuatorDTO; +import app.smartpot.api.actuators.model.entity.Actuator; +import app.smartpot.api.actuators.repository.ActuatorRepository; import smartpot.com.api.Crops.Service.SCropI; import smartpot.com.api.Exception.ApiException; import smartpot.com.api.Exception.ApiResponse; @@ -22,13 +22,13 @@ @Data @Builder @Service -public class SActuator implements SActuatorI { +public class ServiceActuatorImpl implements ServiceActuator { - private final RActuator actuatorRepository; + private final ActuatorRepository actuatorRepository; private final SCropI serviceCrop; @Autowired - public SActuator(RActuator actuatorRepository, SCropI serviceCrop) { + public ServiceActuatorImpl(ActuatorRepository actuatorRepository, SCropI serviceCrop) { this.actuatorRepository = actuatorRepository; this.serviceCrop = serviceCrop; } @@ -74,14 +74,14 @@ public List getActuatorsByCrop(String crop) { @Override public Actuator createActuator(ActuatorDTO actuator) throws Exception { serviceCrop.getCropById(actuator.getCrop()); - Actuator act = MActuators.INSTANCE.toEntity(actuator); + Actuator act = ActuatorMapper.INSTANCE.toEntity(actuator); return actuatorRepository.save(act); } @Override public Actuator updateActuator(Actuator existingActuator, ActuatorDTO actuator) { if (actuator.getId() != null && actuator.getCrop() != null) { - existingActuator = MActuators.INSTANCE.toEntity(actuator); + existingActuator = ActuatorMapper.INSTANCE.toEntity(actuator); } try { From 4eea0275ac2fdc4d367526a8788b09e351770002 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 15:09:48 -0500 Subject: [PATCH 12/18] package update and rename 2 --- .../api/actuators/controller/ActuatorController.java | 2 +- .../api/actuators/service/ServiceActuator.java | 2 +- .../api/actuators/service/ServiceActuatorImpl.java | 10 +++++----- .../api/commands/controller/CommandController.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java index d30be05..51e73c9 100644 --- a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java +++ b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java @@ -6,7 +6,7 @@ import app.smartpot.api.actuators.model.dto.ActuatorDTO; import app.smartpot.api.actuators.model.entity.Actuator; import app.smartpot.api.actuators.service.ServiceActuator; -import smartpot.com.api.Exception.ApiResponse; +import app.smartpot.api.exception.ApiResponse; import java.util.List; diff --git a/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java b/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java index 1d17583..c9639cc 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java +++ b/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java @@ -3,7 +3,7 @@ import org.springframework.http.ResponseEntity; import app.smartpot.api.actuators.model.dto.ActuatorDTO; import app.smartpot.api.actuators.model.entity.Actuator; -import smartpot.com.api.Exception.ApiResponse; +import app.smartpot.api.exception.ApiResponse; import java.util.List; diff --git a/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java b/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java index 9476974..1cea81c 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java +++ b/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java @@ -12,9 +12,9 @@ import app.smartpot.api.actuators.model.dto.ActuatorDTO; import app.smartpot.api.actuators.model.entity.Actuator; import app.smartpot.api.actuators.repository.ActuatorRepository; -import smartpot.com.api.Crops.Service.SCropI; -import smartpot.com.api.Exception.ApiException; -import smartpot.com.api.Exception.ApiResponse; +import app.smartpot.api.crops.service.CropService; +import app.smartpot.api.exception.ApiException; +import app.smartpot.api.exception.ApiResponse; import java.util.List; @@ -25,10 +25,10 @@ public class ServiceActuatorImpl implements ServiceActuator { private final ActuatorRepository actuatorRepository; - private final SCropI serviceCrop; + private final CropService serviceCrop; @Autowired - public ServiceActuatorImpl(ActuatorRepository actuatorRepository, SCropI serviceCrop) { + public ServiceActuatorImpl(ActuatorRepository actuatorRepository, CropService serviceCrop) { this.actuatorRepository = actuatorRepository; this.serviceCrop = serviceCrop; } diff --git a/src/main/java/app/smartpot/api/commands/controller/CommandController.java b/src/main/java/app/smartpot/api/commands/controller/CommandController.java index 986f3c8..0dc4138 100644 --- a/src/main/java/app/smartpot/api/commands/controller/CommandController.java +++ b/src/main/java/app/smartpot/api/commands/controller/CommandController.java @@ -85,7 +85,7 @@ public ResponseEntity getAllCommand() { }) public ResponseEntity getCommandsByCrop(@PathVariable String crop) { try { - return new ResponseEntity<>(serviceCommand.getCommandsByCrop(crop), HttpStatus.OK); + return new ResponseEntity<>(commandService.getCommandsByCrop(crop), HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>(new ErrorResponse("Error al obtener los comandos [" + e.getMessage() + "]", HttpStatus.INTERNAL_SERVER_ERROR.value()), HttpStatus.INTERNAL_SERVER_ERROR); } From fdfe65f99095ba853f7f1108a7cb2fcb4823e6da Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 16:15:58 -0500 Subject: [PATCH 13/18] Controller now returns a ResponseEntity --- .../controller/ActuatorController.java | 61 ++++++++++++++----- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java index 51e73c9..8e94366 100644 --- a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java +++ b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java @@ -1,6 +1,8 @@ package app.smartpot.api.actuators.controller; +import app.smartpot.api.responses.ErrorResponse; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import app.smartpot.api.actuators.model.dto.ActuatorDTO; @@ -14,6 +16,8 @@ @RequestMapping("/Actuators") public class ActuatorController { + // TODO: Documentar mejor, por ejemplo como en UserController + private final ServiceActuator serviceActuator; @Autowired @@ -28,45 +32,70 @@ public ActuatorController(ServiceActuator serviceActuator) { * @return Lista de todos los actuadores existentes */ @GetMapping("/All") - public List getAllActuators() { - return serviceActuator.getAllActuators(); + public ResponseEntity getAllActuators() { + try { + return new ResponseEntity<>(serviceActuator.getAllActuators(), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al buscar los actuadores [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); + } } /** - * Obtiene el actuadores con el identificador proporcionado. + * Obtiene el actuador con el identificador proporcionado. * - * @param id Es el identificador del la instruccion del actuador - * @return Lista de todos los actuadores existentes + * @param id Es el identificador del actuador + * @return El actuador que tenga la id suministrada */ @GetMapping("/{id}") - public Actuator getActuatorById(@PathVariable String id) { - return serviceActuator.getActuatorById(id); + public ResponseEntity getActuatorById(@PathVariable String id) { + try { + return new ResponseEntity<>(serviceActuator.getActuatorById(id), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al buscar los actuadores [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); + } } /** - * Obtiene todos los actuadores almacenados en el sistema para un cultivo espesificado. + * Obtiene todos los actuadores almacenados en el sistema para un cultivo especificado. * * @param id Es el identificador del cultivo * @return Lista de todos los actuadores existentes */ @GetMapping("/crop/{id}") - public List getActuatorByCrop(@PathVariable String id) { - return serviceActuator.getActuatorsByCrop(id); + public ResponseEntity getActuatorByCrop(@PathVariable String id) { + try { + return new ResponseEntity<>(serviceActuator.getActuatorsByCrop(id), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al buscar el actuadores [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); + } + } @PostMapping("/Create") - public Actuator createActuator(@RequestBody ActuatorDTO actuator) throws Exception { - return serviceActuator.createActuator(actuator); + public ResponseEntity createActuator(@RequestBody ActuatorDTO actuator) { + try { + return new ResponseEntity<>(serviceActuator.createActuator(actuator), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al crear el actuador [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); + } } @PutMapping("/Update/{id}") - public Actuator updateActuator(@PathVariable String id, @RequestBody ActuatorDTO actuator) throws Exception { - return serviceActuator.updateActuator(serviceActuator.getActuatorById(id), actuator); + public ResponseEntity updateActuator(@PathVariable String id, @RequestBody ActuatorDTO actuator) { + try { + return new ResponseEntity<>(serviceActuator.updateActuator(serviceActuator.getActuatorById(id), actuator), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al actualizar el actuador [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); + } } @DeleteMapping("/Delete/{id}") - public ResponseEntity deleteActuator(@PathVariable String id) throws Exception { - return serviceActuator.deleteActuatorById(serviceActuator.getActuatorById(id)); + public ResponseEntity deleteActuator(@PathVariable String id) { + try { + return new ResponseEntity<>(serviceActuator.deleteActuatorById(serviceActuator.getActuatorById(id).getId()), HttpStatus.OK); + } catch (Exception e) { + return new ResponseEntity<>(new ErrorResponse("Error al eliminar el actuador [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); + } } } From 3e28aa6f9f4c27f58428992dff9ff6c4bab47bb5 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 19:25:34 -0500 Subject: [PATCH 14/18] Controller method name updated --- .../app/smartpot/api/commands/controller/CommandController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/app/smartpot/api/commands/controller/CommandController.java b/src/main/java/app/smartpot/api/commands/controller/CommandController.java index 0dc4138..cf54b85 100644 --- a/src/main/java/app/smartpot/api/commands/controller/CommandController.java +++ b/src/main/java/app/smartpot/api/commands/controller/CommandController.java @@ -103,7 +103,7 @@ public ResponseEntity getCommandsByCrop(@PathVariable String crop) { description = "Comando no encontrado con el ID especificado.", content = @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))) }) - public ResponseEntity getUserById(@PathVariable String id) { + public ResponseEntity getCommandById(@PathVariable String id) { try { return new ResponseEntity<>(commandService.getCommandById(id), HttpStatus.OK); } catch (Exception e) { From b048b2a427dbe618f56e245b80c96fca815cff27 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 20:03:50 -0500 Subject: [PATCH 15/18] ActuatorController update to responseEntity and DTO format --- .../api/actuators/controller/ActuatorController.java | 9 ++++----- .../api/commands/service/CommandServiceImpl.java | 12 ++++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java index 8e94366..763eeeb 100644 --- a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java +++ b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java @@ -1,17 +1,15 @@ package app.smartpot.api.actuators.controller; import app.smartpot.api.responses.ErrorResponse; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import app.smartpot.api.actuators.model.dto.ActuatorDTO; -import app.smartpot.api.actuators.model.entity.Actuator; import app.smartpot.api.actuators.service.ServiceActuator; -import app.smartpot.api.exception.ApiResponse; - -import java.util.List; +@Slf4j @RestController @RequestMapping("/Actuators") public class ActuatorController { @@ -83,7 +81,8 @@ public ResponseEntity createActuator(@RequestBody ActuatorDTO actuator) { @PutMapping("/Update/{id}") public ResponseEntity updateActuator(@PathVariable String id, @RequestBody ActuatorDTO actuator) { try { - return new ResponseEntity<>(serviceActuator.updateActuator(serviceActuator.getActuatorById(id), actuator), HttpStatus.OK); + log.debug("CONTROLLER................."); + return new ResponseEntity<>(serviceActuator.updateActuator(serviceActuator.getActuatorById(id).getId(), actuator), HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>(new ErrorResponse("Error al actualizar el actuador [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); } diff --git a/src/main/java/app/smartpot/api/commands/service/CommandServiceImpl.java b/src/main/java/app/smartpot/api/commands/service/CommandServiceImpl.java index 0793da7..4e0e5cd 100644 --- a/src/main/java/app/smartpot/api/commands/service/CommandServiceImpl.java +++ b/src/main/java/app/smartpot/api/commands/service/CommandServiceImpl.java @@ -5,6 +5,7 @@ import app.smartpot.api.commands.model.entity.CommandStatus; import app.smartpot.api.commands.repository.CommandRepository; import app.smartpot.api.crops.service.CropService; +import jakarta.validation.ValidationException; import lombok.Builder; import lombok.Data; import org.bson.types.ObjectId; @@ -18,6 +19,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -170,6 +172,16 @@ public CommandDTO getCommandById(String id) throws Exception { @Transactional public CommandDTO createCommand(CommandDTO commandDTO) throws IllegalStateException { return Optional.of(commandDTO) + .map(valid -> { + try { + if (!Objects.equals(cropService.getCropById(commandDTO.getCrop()).getId(), commandDTO.getCrop())) { + throw new ValidationException("Actuator crop is different to Command Crop"); + } + return commandDTO; + } catch (Exception e) { + throw new RuntimeException(e); + } + }) .map(dto -> { SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); dto.setDateCreated(formatter.format(new Date())); From 8063d7b385589b577f78551343c5ca6b94ed5a16 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 20:04:52 -0500 Subject: [PATCH 16/18] ServiceActuator update to responseEntity and DTO format --- .../actuators/service/ServiceActuator.java | 13 +- .../service/ServiceActuatorImpl.java | 135 +++++++++--------- 2 files changed, 72 insertions(+), 76 deletions(-) diff --git a/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java b/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java index c9639cc..de70761 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java +++ b/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java @@ -2,23 +2,22 @@ import org.springframework.http.ResponseEntity; import app.smartpot.api.actuators.model.dto.ActuatorDTO; -import app.smartpot.api.actuators.model.entity.Actuator; import app.smartpot.api.exception.ApiResponse; import java.util.List; public interface ServiceActuator { - List getAllActuators(); + List getAllActuators() throws Exception; - Actuator getActuatorById(String id); + ActuatorDTO getActuatorById(String id) throws Exception; - List getActuatorsByCrop(String crop); + List getActuatorsByCrop(String crop) throws Exception; - Actuator createActuator(ActuatorDTO actuator) throws Exception; + ActuatorDTO createActuator(ActuatorDTO actuator) throws Exception; - Actuator updateActuator(Actuator existingActuator , ActuatorDTO actuator); + ActuatorDTO updateActuator(String id , ActuatorDTO actuator) throws Exception; - ResponseEntity deleteActuatorById(Actuator actuator); + String deleteActuatorById(String id) throws Exception; //ResponseEntity deleteActuators(List ids); } diff --git a/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java b/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java index 1cea81c..9921355 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java +++ b/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java @@ -1,22 +1,20 @@ package app.smartpot.api.actuators.service; +import jakarta.validation.ValidationException; import lombok.Builder; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import app.smartpot.api.actuators.mapper.ActuatorMapper; import app.smartpot.api.actuators.model.dto.ActuatorDTO; -import app.smartpot.api.actuators.model.entity.Actuator; import app.smartpot.api.actuators.repository.ActuatorRepository; import app.smartpot.api.crops.service.CropService; -import app.smartpot.api.exception.ApiException; -import app.smartpot.api.exception.ApiResponse; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; @Slf4j @Data @@ -26,92 +24,91 @@ public class ServiceActuatorImpl implements ServiceActuator { private final ActuatorRepository actuatorRepository; private final CropService serviceCrop; + private final ActuatorMapper actuatorMapper; @Autowired - public ServiceActuatorImpl(ActuatorRepository actuatorRepository, CropService serviceCrop) { + public ServiceActuatorImpl(ActuatorRepository actuatorRepository, CropService serviceCrop, ActuatorMapper actuatorMapper) { this.actuatorRepository = actuatorRepository; this.serviceCrop = serviceCrop; + this.actuatorMapper = actuatorMapper; } @Override - public List getAllActuators() { - List actuators = actuatorRepository.findAll(); - if (actuators.isEmpty()) { - throw new ApiException(new ApiResponse( - "No se encontró ningún actuador en el sistema", - HttpStatus.NOT_FOUND.value() - )); - } - return actuators; + public List getAllActuators() throws Exception { + return Optional.of(actuatorRepository.findAll()) + .filter(actuators -> !actuators.isEmpty()) + .map(actuators -> actuators.stream() + .map(actuatorMapper::toDTO) + .collect(Collectors.toList())) + .orElseThrow(() -> new Exception("No existe ningún actuador")); } @Override - public Actuator getActuatorById(String id) { - 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() - )); - } - return actuatorRepository.findById(new ObjectId(id)) - .orElseThrow(() -> new ApiException( - new ApiResponse("El Actuador con id '" + id + "' no fue encontrado.", - HttpStatus.NOT_FOUND.value()) - )); + public ActuatorDTO getActuatorById(String id) throws Exception { + return Optional.of(id) + .map(ValidId -> { + if (!ObjectId.isValid(id)) { + throw new ValidationException("Id invalido"); + } + return new ObjectId(ValidId); + }) + .map(actuatorRepository::findById) + .filter(Optional::isPresent) + .map(Optional::get) + .map(actuatorMapper::toDTO) + .orElseThrow(() -> new Exception("El Actuador no existe")); } @Override - public List getActuatorsByCrop(String crop) { - if (!ObjectId.isValid(crop)) { - throw new ApiException(new ApiResponse( - "El id de cultivo '" + crop + "' 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() - )); - } - return actuatorRepository.findByCrop(new ObjectId(crop)); + public List getActuatorsByCrop(String crop) throws Exception { + return Optional.of(crop) + .map(id -> { + if (!ObjectId.isValid(id)) { + throw new ValidationException("Id de crop invalido"); + } + return new ObjectId(id); + }) + .map(actuatorRepository::findByCrop) + .filter(users -> !users.isEmpty()) + .map(actuators -> actuators.stream() + .map(actuatorMapper::toDTO) + .collect(Collectors.toList()) + ) + .orElseThrow(() -> new Exception("El actuador no existe")); } @Override - public Actuator createActuator(ActuatorDTO actuator) throws Exception { - serviceCrop.getCropById(actuator.getCrop()); - Actuator act = ActuatorMapper.INSTANCE.toEntity(actuator); - return actuatorRepository.save(act); + public ActuatorDTO createActuator(ActuatorDTO actuator) throws Exception { + return Optional.of(actuator) + .map(actuatorMapper::toEntity) + .map(actuatorRepository::save) + .map(actuatorMapper::toDTO) + .orElseThrow(() -> new IllegalStateException("El Usuario ya existe")); } @Override - public Actuator updateActuator(Actuator existingActuator, ActuatorDTO actuator) { - if (actuator.getId() != null && actuator.getCrop() != null) { - existingActuator = ActuatorMapper.INSTANCE.toEntity(actuator); - } - - try { - return actuatorRepository.save(existingActuator); - } catch (Exception e) { - log.error("e: ", e); - throw new ApiException( - new ApiResponse("No se pudo actualizar el actuador con ID '" + existingActuator.getId() + "'.", - HttpStatus.INTERNAL_SERVER_ERROR.value())); - } + public ActuatorDTO updateActuator(String id, ActuatorDTO actuator) throws Exception { + ActuatorDTO existingActuator = getActuatorById(id); + log.debug("UPDATING......................"); + return Optional.of(actuator) + .map(updated -> { + existingActuator.setType(updated.getType()); + return existingActuator; + }) + .map(actuatorMapper::toEntity) + .map(actuatorRepository::save) + .map(actuatorMapper::toDTO) + .orElseThrow(() -> new Exception("El usuario no se pudo actualizar")); } @Override - public ResponseEntity deleteActuatorById(Actuator actuator) { - try { - actuatorRepository.deleteById(actuator.getId()); - return ResponseEntity.status(HttpStatus.OK.value()).body( - new ApiResponse("El Actuador con ID '" + actuator.getId() + "' fue eliminado.", - HttpStatus.OK.value()) - ); - } catch (Exception e) { - log.error("e: ", e); - throw new ApiException( - new ApiResponse("No se pudo eliminar el Actuador con ID '" + actuator.getId() + "'.", - HttpStatus.INTERNAL_SERVER_ERROR.value())); - } + public String deleteActuatorById(String id) throws Exception { + return Optional.of(getActuatorById(id)) + .map(user -> { + actuatorRepository.deleteById(new ObjectId(user.getId())); + return "El Usuario con ID '" + id + "' fue eliminado."; + }) + .orElseThrow(() -> new Exception("El Usuario no existe.")); } - //@Override - //public ResponseEntity deleteActuators(List ids) { - // return null; - //} } From 1d797ac22af9c16329d1c9ae9e3e0136da24ec05 Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 20:05:54 -0500 Subject: [PATCH 17/18] ServiceActuator refactor to ActuatorService --- .../api/actuators/controller/ActuatorController.java | 6 +++--- .../service/{ServiceActuator.java => ActuatorService.java} | 4 +--- .../{ServiceActuatorImpl.java => ActuatorServiceImpl.java} | 4 ++-- 3 files changed, 6 insertions(+), 8 deletions(-) rename src/main/java/app/smartpot/api/actuators/service/{ServiceActuator.java => ActuatorService.java} (82%) rename src/main/java/app/smartpot/api/actuators/service/{ServiceActuatorImpl.java => ActuatorServiceImpl.java} (97%) diff --git a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java index 763eeeb..0224a36 100644 --- a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java +++ b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java @@ -7,7 +7,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import app.smartpot.api.actuators.model.dto.ActuatorDTO; -import app.smartpot.api.actuators.service.ServiceActuator; +import app.smartpot.api.actuators.service.ActuatorService; @Slf4j @RestController @@ -16,10 +16,10 @@ public class ActuatorController { // TODO: Documentar mejor, por ejemplo como en UserController - private final ServiceActuator serviceActuator; + private final ActuatorService serviceActuator; @Autowired - public ActuatorController(ServiceActuator serviceActuator) { + public ActuatorController(ActuatorService serviceActuator) { this.serviceActuator = serviceActuator; } diff --git a/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java b/src/main/java/app/smartpot/api/actuators/service/ActuatorService.java similarity index 82% rename from src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java rename to src/main/java/app/smartpot/api/actuators/service/ActuatorService.java index de70761..4b657ff 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ServiceActuator.java +++ b/src/main/java/app/smartpot/api/actuators/service/ActuatorService.java @@ -1,12 +1,10 @@ package app.smartpot.api.actuators.service; -import org.springframework.http.ResponseEntity; import app.smartpot.api.actuators.model.dto.ActuatorDTO; -import app.smartpot.api.exception.ApiResponse; import java.util.List; -public interface ServiceActuator { +public interface ActuatorService { List getAllActuators() throws Exception; ActuatorDTO getActuatorById(String id) throws Exception; diff --git a/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java b/src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java similarity index 97% rename from src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java rename to src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java index 9921355..e8b3278 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ServiceActuatorImpl.java +++ b/src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java @@ -20,14 +20,14 @@ @Data @Builder @Service -public class ServiceActuatorImpl implements ServiceActuator { +public class ActuatorServiceImpl implements ActuatorService { private final ActuatorRepository actuatorRepository; private final CropService serviceCrop; private final ActuatorMapper actuatorMapper; @Autowired - public ServiceActuatorImpl(ActuatorRepository actuatorRepository, CropService serviceCrop, ActuatorMapper actuatorMapper) { + public ActuatorServiceImpl(ActuatorRepository actuatorRepository, CropService serviceCrop, ActuatorMapper actuatorMapper) { this.actuatorRepository = actuatorRepository; this.serviceCrop = serviceCrop; this.actuatorMapper = actuatorMapper; From 140d29539f3b58f2c103dc6ebdd60c45a1db753d Mon Sep 17 00:00:00 2001 From: andres2204 Date: Sat, 15 Nov 2025 20:14:51 -0500 Subject: [PATCH 18/18] Remove log trace --- .../smartpot/api/actuators/controller/ActuatorController.java | 3 --- .../smartpot/api/actuators/service/ActuatorServiceImpl.java | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java index 0224a36..fc3413c 100644 --- a/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java +++ b/src/main/java/app/smartpot/api/actuators/controller/ActuatorController.java @@ -1,7 +1,6 @@ package app.smartpot.api.actuators.controller; import app.smartpot.api.responses.ErrorResponse; -import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -9,7 +8,6 @@ import app.smartpot.api.actuators.model.dto.ActuatorDTO; import app.smartpot.api.actuators.service.ActuatorService; -@Slf4j @RestController @RequestMapping("/Actuators") public class ActuatorController { @@ -81,7 +79,6 @@ public ResponseEntity createActuator(@RequestBody ActuatorDTO actuator) { @PutMapping("/Update/{id}") public ResponseEntity updateActuator(@PathVariable String id, @RequestBody ActuatorDTO actuator) { try { - log.debug("CONTROLLER................."); return new ResponseEntity<>(serviceActuator.updateActuator(serviceActuator.getActuatorById(id).getId(), actuator), HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>(new ErrorResponse("Error al actualizar el actuador [" + e.getMessage() + "]", HttpStatus.NOT_FOUND.value()), HttpStatus.NOT_FOUND); diff --git a/src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java b/src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java index e8b3278..9d37b46 100644 --- a/src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java +++ b/src/main/java/app/smartpot/api/actuators/service/ActuatorServiceImpl.java @@ -3,7 +3,6 @@ import jakarta.validation.ValidationException; import lombok.Builder; import lombok.Data; -import lombok.extern.slf4j.Slf4j; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -16,7 +15,6 @@ import java.util.Optional; import java.util.stream.Collectors; -@Slf4j @Data @Builder @Service @@ -89,7 +87,6 @@ public ActuatorDTO createActuator(ActuatorDTO actuator) throws Exception { @Override public ActuatorDTO updateActuator(String id, ActuatorDTO actuator) throws Exception { ActuatorDTO existingActuator = getActuatorById(id); - log.debug("UPDATING......................"); return Optional.of(actuator) .map(updated -> { existingActuator.setType(updated.getType());