feat: patch tasks done

issue #46
This commit is contained in:
Ricardo Campos
2024-09-18 10:57:51 -03:00
parent 67940048fe
commit 0bdb68c7e2
13 changed files with 146 additions and 32 deletions
@@ -1,17 +1,20 @@
package br.com.tasknoteapp.java_api.controller;
import br.com.tasknoteapp.java_api.entity.TaskEntity;
import br.com.tasknoteapp.java_api.request.TaskPatchRequest;
import br.com.tasknoteapp.java_api.request.TaskRequest;
import br.com.tasknoteapp.java_api.response.TaskResponse;
import br.com.tasknoteapp.java_api.service.TaskService;
import jakarta.validation.Valid;
import java.util.List;
import lombok.AllArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -24,13 +27,15 @@ public class TaskController {
private final TaskService taskService;
@GetMapping
public String tasks() {
return "Tasks";
public List<TaskResponse> getAllTasks() {
return taskService.getAllTasks();
}
// https://restfulapi.net/rest-put-vs-post/
@PutMapping
public void putTask() {}
@PatchMapping("/{id}")
public ResponseEntity<TaskResponse> putTask(
@PathVariable Long id, @RequestBody @Valid TaskPatchRequest taskRequest) {
return ResponseEntity.ok(taskService.patchTask(id, taskRequest));
}
// https://restfulapi.net/rest-put-vs-post/
@PostMapping
@@ -33,6 +33,6 @@ public class TaskEntity {
@ManyToOne(fetch = FetchType.LAZY)
private UserEntity user;
@OneToMany(mappedBy = "task")
@OneToMany(mappedBy = "task", fetch = FetchType.LAZY)
private List<TaskUrlEntity> urls;
}
@@ -15,7 +15,7 @@ import lombok.ToString;
@Data
@Entity
@ToString
@Table(name = "task_links")
@Table(name = "task_url")
@EqualsAndHashCode
public class TaskUrlEntity {
@@ -0,0 +1,13 @@
package br.com.tasknoteapp.java_api.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.server.ResponseStatusException;
@ResponseStatus(code = HttpStatus.NOT_FOUND)
public class TaskNotFoundException extends ResponseStatusException {
public TaskNotFoundException() {
super(HttpStatus.NOT_FOUND, "Task not found");
}
}
@@ -8,5 +8,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
public interface TaskRepository extends JpaRepository<TaskEntity, Long> {
List<TaskEntity> findAllByUserId(Long userId);
List<TaskEntity> findAllByUser_id(Long userId);
}
@@ -0,0 +1,10 @@
package br.com.tasknoteapp.java_api.repository;
import br.com.tasknoteapp.java_api.entity.TaskUrlEntity;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
public interface TaskUrlRepository extends JpaRepository<TaskUrlEntity, Long> {
void deleteAllByIdIn(List<Long> ids);
}
@@ -0,0 +1,5 @@
package br.com.tasknoteapp.java_api.request;
import java.util.List;
public record TaskPatchRequest(String description, Boolean done, List<TaskUrlPatchRequest> urls) {}
@@ -0,0 +1,3 @@
package br.com.tasknoteapp.java_api.request;
public record TaskUrlPatchRequest(Long id, String url) {}
@@ -2,21 +2,25 @@ package br.com.tasknoteapp.java_api.response;
import br.com.tasknoteapp.java_api.entity.TaskEntity;
import br.com.tasknoteapp.java_api.entity.TaskUrlEntity;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public record TaskResponse(Long id, String description, Boolean done, List<String> urls) {
public record TaskResponse(Long id, String description, Boolean done, List<TaskUrlResponse> urls) {
public static TaskResponse fromEntity(TaskEntity entity) {
List<TaskUrlEntity> urls = entity.getUrls();
List<TaskUrlResponse> urlsResponse = new ArrayList<>();
if (Objects.isNull(urls)) {
urls = List.of();
} else {
for (TaskUrlEntity url : urls) {
TaskUrlResponse urlResponse = new TaskUrlResponse(url.getId(), url.getUrl());
urlsResponse.add(urlResponse);
}
}
return new TaskResponse(
entity.getId(),
entity.getDescription(),
entity.getDone(),
urls.stream().map(TaskUrlEntity::getUrl).toList());
entity.getId(), entity.getDescription(), entity.getDone(), urlsResponse);
}
}
@@ -0,0 +1,3 @@
package br.com.tasknoteapp.java_api.response;
public record TaskUrlResponse(Long id, String url) {}
@@ -1,17 +1,18 @@
package br.com.tasknoteapp.java_api.service;
import br.com.tasknoteapp.java_api.entity.TaskEntity;
import br.com.tasknoteapp.java_api.request.TaskPatchRequest;
import br.com.tasknoteapp.java_api.request.TaskRequest;
import br.com.tasknoteapp.java_api.response.TaskResponse;
import java.util.List;
public interface TaskService {
public List<TaskResponse> getAllTasks(Long userId);
public List<TaskResponse> getAllTasks();
public TaskEntity createTask(TaskRequest taskRequest);
public void updateTask(TaskRequest taskRequest);
public TaskResponse patchTask(Long taskId, TaskPatchRequest taskRequest);
public void updateTaskDone(Long taskId);
@@ -93,7 +93,7 @@ class AuthServiceImpl implements AuthService {
*/
@Override
public String signin(LoginRequest login) {
log.info("Creating user! {}", login.email());
log.info("Signing in user! {}", login.email());
Optional<UserEntity> user = findByEmail(login.email());
if (user.isEmpty()) {
@@ -1,14 +1,22 @@
package br.com.tasknoteapp.java_api.service.impl;
import br.com.tasknoteapp.java_api.entity.TaskEntity;
import br.com.tasknoteapp.java_api.entity.TaskUrlEntity;
import br.com.tasknoteapp.java_api.entity.UserEntity;
import br.com.tasknoteapp.java_api.exception.TaskNotFoundException;
import br.com.tasknoteapp.java_api.repository.TaskRepository;
import br.com.tasknoteapp.java_api.repository.TaskUrlRepository;
import br.com.tasknoteapp.java_api.request.TaskPatchRequest;
import br.com.tasknoteapp.java_api.request.TaskRequest;
import br.com.tasknoteapp.java_api.request.TaskUrlPatchRequest;
import br.com.tasknoteapp.java_api.response.TaskResponse;
import br.com.tasknoteapp.java_api.service.AuthService;
import br.com.tasknoteapp.java_api.service.TaskService;
import br.com.tasknoteapp.java_api.util.AuthUtil;
import jakarta.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -25,11 +33,15 @@ class TaskServiceImpl implements TaskService {
private final AuthUtil authUtil;
@Override
public List<TaskResponse> getAllTasks(Long userId) {
log.info("Get all tasks to user {}", userId);
private final TaskUrlRepository taskUrlRepository;
List<TaskEntity> tasks = taskRepository.findAllByUserId(userId);
@Override
public List<TaskResponse> getAllTasks() {
UserEntity user = getCurrentUser();
log.info("Get all tasks to user {}", user.getId());
List<TaskEntity> tasks = taskRepository.findAllByUser_id(user.getId());
log.info("{} tasks found!", tasks.size());
return tasks.stream().map(TaskResponse::fromEntity).toList();
@@ -37,15 +49,9 @@ class TaskServiceImpl implements TaskService {
@Override
public TaskEntity createTask(TaskRequest taskRequest) {
log.info("Creating task {}", taskRequest);
UserEntity user = getCurrentUser();
// get user
Optional<String> currentUserEmail = authUtil.getCurrentUserEmail();
String email = currentUserEmail.orElseThrow();
UserEntity user = authService.findByEmail(email).orElseThrow();
// create task
log.info("Creating task to user {}", user.getId());
TaskEntity task = new TaskEntity();
task.setDescription(taskRequest.description());
@@ -53,14 +59,57 @@ class TaskServiceImpl implements TaskService {
task.setUser(user);
TaskEntity created = taskRepository.save(task);
if (Objects.isNull(taskRequest.urls())) {
List<TaskUrlEntity> urls = saveUrls(task, taskRequest.urls());
task.setUrls(urls);
}
log.info("Task created! Id {}", created.getId());
return created;
}
@Transactional
@Override
public void updateTask(TaskRequest taskRequest) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'updateTask'");
public TaskResponse patchTask(Long taskId, TaskPatchRequest patch) {
UserEntity user = getCurrentUser();
log.info("Patching task {} to user {}", taskId, user.getId());
Optional<TaskEntity> task = taskRepository.findById(taskId);
if (task.isEmpty()) {
throw new TaskNotFoundException();
}
TaskEntity taskEntity = task.get();
if (!Objects.isNull(patch.description()) && !patch.description().isBlank()) {
taskEntity.setDescription(patch.description());
}
if (!Objects.isNull(patch.done())) {
taskEntity.setDone(patch.done());
}
if (!Objects.isNull(patch.urls())) {
List<Long> urlIds =
patch.urls().stream().filter(p -> p.id() != null).map(TaskUrlPatchRequest::id).toList();
if (!urlIds.isEmpty()) {
taskUrlRepository.deleteAllByIdIn(urlIds);
log.info("Deleted {} urls from task {}", urlIds.size(), taskId);
} else {
log.info("No urls to patch for task {}", taskId);
}
List<String> urlsList =
patch.urls().stream().filter(p -> p.id() == null).map(TaskUrlPatchRequest::url).toList();
List<TaskUrlEntity> urls = saveUrls(taskEntity, urlsList);
taskEntity.setUrls(urls);
}
TaskEntity patchedTask = taskRepository.save(taskEntity);
log.info("Task patched! Id {}", patchedTask.getId());
return TaskResponse.fromEntity(patchedTask);
}
@Override
@@ -74,4 +123,25 @@ class TaskServiceImpl implements TaskService {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'deleteTask'");
}
private UserEntity getCurrentUser() {
Optional<String> currentUserEmail = authUtil.getCurrentUserEmail();
String email = currentUserEmail.orElseThrow();
return authService.findByEmail(email).orElseThrow();
}
private List<TaskUrlEntity> saveUrls(TaskEntity taskEntity, List<String> urls) {
List<TaskUrlEntity> tasksUrl = new ArrayList<>();
for (String url : urls) {
TaskUrlEntity taskUrl = new TaskUrlEntity();
taskUrl.setUrl(url);
taskUrl.setTask(taskEntity);
tasksUrl.add(taskUrl);
}
List<TaskUrlEntity> savedUrls = taskUrlRepository.saveAll(tasksUrl);
log.info("Saved {} urls to task {}", savedUrls.size(), taskEntity.getId());
return savedUrls;
}
}