Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"java.configuration.updateBuildConfiguration": "automatic"
}
12 changes: 12 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
version: '3.1'

services:
tasks_db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: "mysql"
MYSQL_DATABASE: "tasks_db"
ports:
- "3306:3306"
volumes:
- ./script.sql:/docker-entrypoint-initdb.d/init.sql
25 changes: 23 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
Expand Down Expand Up @@ -66,6 +67,15 @@
<version>${version.junit}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>


<!-- Other dependencies -->
<dependency>
<groupId>org.projectlombok</groupId>
Expand All @@ -78,6 +88,17 @@
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>


<dependency>
<groupId>io.skullabs.kikaha</groupId>
<artifactId>kikaha-db</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version> <!-- Você pode usar a versão mais recente -->
</dependency>
</dependencies>

<build>
Expand Down Expand Up @@ -111,4 +132,4 @@
</plugin>
</plugins>
</build>
</project>
</project>
7 changes: 7 additions & 0 deletions resources/conf/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,10 @@ server:
health-check:
enabled: true
url: "/api/internal/health-check"

db:
datasources:
default:
jdbc-url: "jdbc:mysql://localhost:3306/tasks_db"
username: "root"
password: "mysql"
11 changes: 11 additions & 0 deletions script.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
USE tasks_db;

CREATE TABLE IF NOT EXISTS tasks (
id CHAR(36) NOT NULL DEFAULT (UUID()),
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
progress INT NOT NULL DEFAULT 0,
status ENUM('PROGRESS', 'COMPLETE') NOT NULL DEFAULT 'PROGRESS',
createdAt TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
31 changes: 31 additions & 0 deletions source/backend/challenge/modules/task/config/UUIDConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package backend.challenge.modules.task.config;

import java.util.UUID;

import javax.enterprise.inject.Typed;
import javax.inject.Singleton;

import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import java.util.UUID;
import kikaha.urouting.api.AbstractConverter;
import kikaha.urouting.api.ConversionException;

/**
* UUIDConverter
*/
@Singleton
@Typed(AbstractConverter.class)
public class UUIDConverter extends AbstractConverter<UUID>{

@Override
public UUID convert(String value) throws ConversionException {

try {
return UUID.fromString(value);
} catch (Exception e) {
throw new RuntimeException("Falha ao converter " + value + " para UUID");
}
}


}
2 changes: 0 additions & 2 deletions source/backend/challenge/modules/task/dtos/TaskDTO.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import lombok.Setter;
import lombok.experimental.Accessors;

import java.util.Date;

@Getter
@Setter
@Accessors(chain = true)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package backend.challenge.modules.task.dtos;

import java.util.UUID;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
Expand All @@ -11,7 +13,7 @@
@NoArgsConstructor(staticName = "create")
public class TaskProgressDTO {

private Long id;
private UUID id;
private int progress;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package backend.challenge.modules.task.exceptions;

public class ProgressTaskUpdateNotAvailable extends RuntimeException{
public ProgressTaskUpdateNotAvailable(){
super("O progresso deve estar entre 0 e 100.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package backend.challenge.modules.task.exceptions;

public class TaskAlterationNotAvailable extends RuntimeException{
public TaskAlterationNotAvailable() {
super("É apenas possível alterar o Título e Descrição nesta operação.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package backend.challenge.modules.task.exceptions;

public class TaskNotFound extends RuntimeException {

public TaskNotFound() {
super("Tarefa não encontrda.");
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package backend.challenge.modules.task.infra.http.controllers;

import backend.challenge.modules.task.dtos.TaskDTO;
import backend.challenge.modules.task.exceptions.TaskAlterationNotAvailable;
import backend.challenge.modules.task.exceptions.TaskNotFound;
import backend.challenge.modules.task.infra.http.views.TaskView;
import backend.challenge.modules.task.models.Task;
import backend.challenge.modules.task.services.*;
import kikaha.urouting.api.*;

import java.util.UUID;
import javax.inject.Inject;
import javax.inject.Singleton;

Expand All @@ -20,56 +23,75 @@ public class TaskController {

@Inject
public TaskController(
final ICreateTaskService createTaskService,
final IDeleteTaskService deleteTaskService,
final IRetrieveAllTasksService retrieveAllTasksService
) {
final ICreateTaskService createTaskService,
final IDeleteTaskService deleteTaskService,
final IRetrieveAllTasksService retrieveAllTasksService,
final IRetrieveTaskByIdService retrieveTaskByIdService,
final IUpdateTaskService iUpdateTaskService) {
this.createTaskService = createTaskService;
this.deleteTaskService = deleteTaskService;
this.retrieveAllTasksService = retrieveAllTasksService;
this.retrieveTaskByIdService = null;
this.updateTaskService = null;
this.retrieveTaskByIdService = retrieveTaskByIdService;
this.updateTaskService = iUpdateTaskService;
}

@GET
public Response show() {
// TODO: Rota que lista todas as tarefas

return DefaultResponse.ok().entity("Hello world");
return DefaultResponse.ok().entity(retrieveAllTasksService.execute());
}

@GET
@Path("single/{taskId}")
public Response index(@PathParam("taskId") Long taskId) {
// TODO: A rota deve retornar somente a tarefa a qual o id corresponder
public Response index(@PathParam("taskId") UUID taskId) {

try {
Task taskOpt = this.retrieveTaskByIdService.execute(taskId);
return DefaultResponse.ok().entity(taskOpt);

} catch (TaskNotFound e) {
return DefaultResponse.badRequest().entity(e.getMessage());
}

return DefaultResponse.ok().entity("Hello world");
}

@POST
public Response create(TaskView task) {
// TODO: A rota deve receber title e description, sendo o `title` o título da tarefa e `description` uma descrição da tarefa.
public Response create(TaskView taskView) {

TaskDTO taskDto = TaskDTO.create().setTitle(taskView.getTitle()).setDescription(taskView.getDescription());
this.createTaskService.execute(taskDto);

return DefaultResponse.ok().entity("Hello world");
return DefaultResponse.created();
}

@PUT
@Path("single/{taskId}")
public Response update(@PathParam("taskId") Long taskId, Task task) {
/*
TODO: A rota deve alterar apenas o title e description da tarefa
que possua o id igual ao id correspondente nos parâmetros da rota.
*/
public Response update(@PathParam("taskId") UUID taskId, TaskDTO taskDto) {

try {
Task task = new Task();
task.setId(taskId);
task.setDescription(taskDto.getDescription());
task.setTitle(taskDto.getTitle());
this.updateTaskService.execute(task);
return DefaultResponse.ok();
} catch (TaskAlterationNotAvailable| TaskNotFound e) {

return DefaultResponse.badRequest().entity(e.getMessage());
} catch (Exception e) {
return DefaultResponse.serverError();
}

return DefaultResponse.ok().entity("Hello world");
}

@DELETE
@Path("single/{taskId}")
public Response delete(@PathParam("taskId") Long taskId) {
// TODO: A rota deve deletar a tarefa com o id correspondente nos parâmetros da rota

return DefaultResponse.ok().entity("Hello world");
public Response delete(@PathParam("taskId") UUID taskId) {
try {
this.deleteTaskService.execute(taskId);
return DefaultResponse.ok();
} catch (TaskNotFound e) {
return DefaultResponse.badRequest().entity(e.getMessage());
}
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package backend.challenge.modules.task.infra.http.controllers;

import backend.challenge.modules.task.dtos.TaskProgressDTO;
import backend.challenge.modules.task.exceptions.ProgressTaskUpdateNotAvailable;
import backend.challenge.modules.task.exceptions.TaskAlterationNotAvailable;
import backend.challenge.modules.task.exceptions.TaskNotFound;
import backend.challenge.modules.task.infra.http.views.TaskProgressView;
import backend.challenge.modules.task.models.Task;
import backend.challenge.modules.task.services.*;
import kikaha.urouting.api.*;

import java.util.UUID;
import javax.inject.Inject;
import javax.inject.Singleton;

Expand All @@ -21,15 +24,18 @@ public TaskProgressController(final IUpdateTaskProgressService updateTaskProgres

@PUT
@Path("single/{taskId}")
public Response updateProgress(@PathParam("taskId") Long taskId, TaskProgressView taskProgressView) {
/*
TODO: A rota deve alterar apenas o progresso da tarefa que possua o id igual ao id correspondente
nos parâmetros da rota.
O `progress` pode ter o valor máximo de 100, e quando ele atingi o máximo,
o `status` deve ser alterado para `COMPLETE`
*/

return DefaultResponse.ok().entity("Hello world");
public Response updateProgress(@PathParam("taskId") UUID taskId, TaskProgressView taskProgressView) {
TaskProgressDTO progressDTO = TaskProgressDTO.create().setId(taskId)
.setProgress(taskProgressView.getProgress());

try {
this.updateTaskProgressService.execute(progressDTO);
return DefaultResponse.ok();

} catch (ProgressTaskUpdateNotAvailable | TaskNotFound e) {
return DefaultResponse.badRequest().entity(e.getMessage());
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

@Getter
@Setter

public class TaskProgressView {

private int progress;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import lombok.Getter;
import lombok.Setter;

import java.util.Date;

@Getter
@Setter
Expand Down
16 changes: 14 additions & 2 deletions source/backend/challenge/modules/task/models/Task.java
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
package backend.challenge.modules.task.models;

import backend.challenge.modules.task.enums.TaskStatus;
import lombok.AllArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.UUID;

import javax.xml.crypto.Data;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Task {

private Long id;
private UUID id;
private String title;
private String description;
private int progress;
private TaskStatus status;
private Date createdAt;
private LocalDate createdAt;

}
Loading