Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
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;
import app.smartpot.api.actuators.service.ActuatorService;

@RestController
@RequestMapping("/Actuators")
public class ActuatorController {

// TODO: Documentar mejor, por ejemplo como en UserController

private final ActuatorService serviceActuator;

@Autowired
public ActuatorController(ActuatorService serviceActuator) {
this.serviceActuator = serviceActuator;
}


/**
* Obtiene todos los actuadores almacenados en el sistema.
*
* @return Lista de todos los actuadores existentes
*/
@GetMapping("/All")
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 actuador con el identificador proporcionado.
*
* @param id Es el identificador del actuador
* @return El actuador que tenga la id suministrada
*/
@GetMapping("/{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 especificado.
*
* @param id Es el identificador del cultivo
* @return Lista de todos los actuadores existentes
*/
@GetMapping("/crop/{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 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 ResponseEntity<?> updateActuator(@PathVariable String id, @RequestBody ActuatorDTO actuator) {
try {
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);
}
}

@DeleteMapping("/Delete/{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);
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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 app.smartpot.api.actuators.model.dto.ActuatorDTO;
import app.smartpot.api.actuators.model.entity.Actuator;

@Mapper(componentModel = "spring")
public interface ActuatorMapper {
ActuatorMapper INSTANCE = Mappers.getMapper(ActuatorMapper.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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package app.smartpot.api.actuators.model.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import app.smartpot.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)
private String id = null;

@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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package app.smartpot.api.actuators.model.entity;

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;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Document(collection = "actuadores")
public class Actuator {
@Id
@Field("_id")
private ObjectId id;

@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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package app.smartpot.api.actuators.model.entity;

public enum ActuatorType {
UV_LIGHT, WATER_PUMP, HUMIDIFIER
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package app.smartpot.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 app.smartpot.api.actuators.model.entity.Actuator;

import java.util.List;
import java.util.Optional;

@Repository
public interface ActuatorRepository extends MongoRepository<Actuator, ObjectId> {

/**
* 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<Actuator> 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<Actuator> findByCrop(
@NotNull(message = "El registro debe estar asociado a un cultivo")
ObjectId crop);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package app.smartpot.api.actuators.service;

import app.smartpot.api.actuators.model.dto.ActuatorDTO;

import java.util.List;

public interface ActuatorService {
List<ActuatorDTO> getAllActuators() throws Exception;

ActuatorDTO getActuatorById(String id) throws Exception;

List<ActuatorDTO> getActuatorsByCrop(String crop) throws Exception;

ActuatorDTO createActuator(ActuatorDTO actuator) throws Exception;

ActuatorDTO updateActuator(String id , ActuatorDTO actuator) throws Exception;

String deleteActuatorById(String id) throws Exception;

//ResponseEntity<ApiResponse> deleteActuators(List<String> ids);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package app.smartpot.api.actuators.service;

import jakarta.validation.ValidationException;
import lombok.Builder;
import lombok.Data;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
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.repository.ActuatorRepository;
import app.smartpot.api.crops.service.CropService;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Data
@Builder
@Service
public class ActuatorServiceImpl implements ActuatorService {

private final ActuatorRepository actuatorRepository;
private final CropService serviceCrop;
private final ActuatorMapper actuatorMapper;

@Autowired
public ActuatorServiceImpl(ActuatorRepository actuatorRepository, CropService serviceCrop, ActuatorMapper actuatorMapper) {
this.actuatorRepository = actuatorRepository;
this.serviceCrop = serviceCrop;
this.actuatorMapper = actuatorMapper;
}

@Override
public List<ActuatorDTO> 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 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<ActuatorDTO> 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 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 ActuatorDTO updateActuator(String id, ActuatorDTO actuator) throws Exception {
ActuatorDTO existingActuator = getActuatorById(id);
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 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."));
}

}
Loading
Loading