diff --git a/maven-spring/.gitignore b/maven-spring/.gitignore
index 549e00a..9ad541b 100644
--- a/maven-spring/.gitignore
+++ b/maven-spring/.gitignore
@@ -3,6 +3,7 @@ target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
+**/.DS_Store
### STS ###
.apt_generated
diff --git a/maven-spring/pom.xml b/maven-spring/pom.xml
index 7c9c33a..2def633 100644
--- a/maven-spring/pom.xml
+++ b/maven-spring/pom.xml
@@ -11,7 +11,7 @@
com.poliveira
javaverse
- 0.0.1
+ 0.1.0
javaverse
JavaVerse macro project for mutiverse of Java
@@ -35,13 +35,13 @@
org.springframework.boot
spring-boot-starter-web
- 3.3.4
+ 3.4.4
org.springframework.boot
spring-boot-starter-data-jpa
- 3.3.4
+ 3.4.4
@@ -53,7 +53,19 @@
org.postgresql
postgresql
- 42.7.4
+ 42.7.5
+
+
+
+ org.flywaydb
+ flyway-core
+ 11.7.2
+
+
+
+ org.flywaydb
+ flyway-database-postgresql
+ 11.7.2
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/controller/.DS_Store b/maven-spring/src/main/java/com/poliveira/javaverse/controller/.DS_Store
deleted file mode 100644
index c77904a..0000000
Binary files a/maven-spring/src/main/java/com/poliveira/javaverse/controller/.DS_Store and /dev/null differ
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/controller/HelloWorld.java b/maven-spring/src/main/java/com/poliveira/javaverse/controllers/HelloWorld.java
similarity index 88%
rename from maven-spring/src/main/java/com/poliveira/javaverse/controller/HelloWorld.java
rename to maven-spring/src/main/java/com/poliveira/javaverse/controllers/HelloWorld.java
index 5210546..2c1851f 100644
--- a/maven-spring/src/main/java/com/poliveira/javaverse/controller/HelloWorld.java
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/controllers/HelloWorld.java
@@ -1,4 +1,4 @@
-package com.poliveira.javaverse.controller;
+package com.poliveira.javaverse.controllers;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/controller/TaskController.java b/maven-spring/src/main/java/com/poliveira/javaverse/controllers/TaskController.java
similarity index 78%
rename from maven-spring/src/main/java/com/poliveira/javaverse/controller/TaskController.java
rename to maven-spring/src/main/java/com/poliveira/javaverse/controllers/TaskController.java
index b6b0834..d72f1a5 100644
--- a/maven-spring/src/main/java/com/poliveira/javaverse/controller/TaskController.java
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/controllers/TaskController.java
@@ -1,12 +1,13 @@
-package com.poliveira.javaverse.controller;
+package com.poliveira.javaverse.controllers;
import static org.springframework.http.HttpStatus.CREATED;
-import com.poliveira.javaverse.model.SimpleTaskVO;
-import com.poliveira.javaverse.model.SuccessVO;
-import com.poliveira.javaverse.model.TaskVO;
-import com.poliveira.javaverse.service.TaskService;
+import com.poliveira.javaverse.models.SimpleTaskVO;
+import com.poliveira.javaverse.models.SuccessVO;
+import com.poliveira.javaverse.models.TaskVO;
+import com.poliveira.javaverse.services.TaskService;
import java.util.List;
+import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
@@ -32,17 +33,17 @@ public TaskVO createTask(@RequestBody SimpleTaskVO taskVO) {
}
@GetMapping("/{id}")
- public TaskVO readTask(@PathVariable Long id) {
+ public TaskVO readTask(@PathVariable UUID id) {
return taskService.getTaskById(id);
}
@PatchMapping("/{id}")
- public TaskVO updateTask(@PathVariable Long id, @RequestBody SimpleTaskVO taskVO) {
+ public TaskVO updateTask(@PathVariable UUID id, @RequestBody SimpleTaskVO taskVO) {
return taskService.updateTask(id, taskVO);
}
@DeleteMapping("/{id}")
- public SuccessVO deleteTask(@PathVariable Long id) {
+ public SuccessVO deleteTask(@PathVariable UUID id) {
return SuccessVO.builder()
.success(taskService.deleteTask(id))
.message("Task deleted successfully")
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/entities/StatusEntity.java b/maven-spring/src/main/java/com/poliveira/javaverse/entities/StatusEntity.java
new file mode 100644
index 0000000..fbf56cc
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/entities/StatusEntity.java
@@ -0,0 +1,30 @@
+package com.poliveira.javaverse.entities;
+
+import jakarta.persistence.*;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Entity
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "status", schema = "public")
+public class StatusEntity {
+ @Id
+ @Column(columnDefinition = "UUID")
+ private UUID id;
+
+ @Column(nullable = false)
+ private String name;
+
+ @Column(
+ name = "created_at",
+ nullable = false,
+ columnDefinition = "TIMESTAMP DEFAULT CURRENT_TIMESTAMP")
+ private LocalDateTime createdAt;
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/entities/TaskEntity.java b/maven-spring/src/main/java/com/poliveira/javaverse/entities/TaskEntity.java
new file mode 100644
index 0000000..a56adfc
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/entities/TaskEntity.java
@@ -0,0 +1,35 @@
+package com.poliveira.javaverse.entities;
+
+import jakarta.persistence.*;
+import java.time.LocalDateTime;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Entity
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "tasks")
+public class TaskEntity {
+
+ @Id @GeneratedValue private UUID id;
+
+ @Column(nullable = false)
+ private String name;
+
+ private String description;
+
+ @Column(name = "created_at", nullable = false, updatable = false)
+ private LocalDateTime createdAt;
+
+ @Column(name = "updated_at")
+ private LocalDateTime updatedAt;
+
+ @ManyToOne
+ @JoinColumn(name = "status_id")
+ private StatusEntity status;
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/model/SimpleTaskVO.java b/maven-spring/src/main/java/com/poliveira/javaverse/model/SimpleTaskVO.java
deleted file mode 100644
index e2c4f2f..0000000
--- a/maven-spring/src/main/java/com/poliveira/javaverse/model/SimpleTaskVO.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.poliveira.javaverse.model;
-
-import static jakarta.persistence.GenerationType.IDENTITY;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.Id;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@Entity
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class SimpleTaskVO {
-
- @Id
- @GeneratedValue(strategy = IDENTITY)
- private long id;
-
- private String title;
- private String description;
-}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/model/Status.java b/maven-spring/src/main/java/com/poliveira/javaverse/model/Status.java
deleted file mode 100644
index 0b2268e..0000000
--- a/maven-spring/src/main/java/com/poliveira/javaverse/model/Status.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.poliveira.javaverse.model;
-
-import static lombok.AccessLevel.PRIVATE;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-@Getter
-@RequiredArgsConstructor(access = PRIVATE)
-public enum Status {
- TODO("To Do"),
- IN_PROGRESS("In Progress"),
- DONE("Done");
-
- private final String status;
-}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/model/TaskVO.java b/maven-spring/src/main/java/com/poliveira/javaverse/model/TaskVO.java
deleted file mode 100644
index aecbf77..0000000
--- a/maven-spring/src/main/java/com/poliveira/javaverse/model/TaskVO.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.poliveira.javaverse.model;
-
-import static jakarta.persistence.GenerationType.IDENTITY;
-
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.Id;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@Entity
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class TaskVO {
-
- @Id
- @GeneratedValue(strategy = IDENTITY)
- private long id;
-
- private String title;
- private String description;
- private Status status;
- private long createdAt;
- private long updatedAt;
-}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/models/SimpleTaskVO.java b/maven-spring/src/main/java/com/poliveira/javaverse/models/SimpleTaskVO.java
new file mode 100644
index 0000000..8a4504b
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/models/SimpleTaskVO.java
@@ -0,0 +1,16 @@
+package com.poliveira.javaverse.models;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SimpleTaskVO {
+
+ private String name;
+ private String description;
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/models/Status.java b/maven-spring/src/main/java/com/poliveira/javaverse/models/Status.java
new file mode 100644
index 0000000..4fabeb2
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/models/Status.java
@@ -0,0 +1,26 @@
+package com.poliveira.javaverse.models;
+
+import static lombok.AccessLevel.PRIVATE;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+@Getter
+@RequiredArgsConstructor(access = PRIVATE)
+public enum Status {
+ OPEN("Open"),
+ IN_PROGRESS("In Progress"),
+ BLOCKED("Blocked"),
+ DONE("Done");
+
+ private final String status;
+
+ public static Status from(String status) {
+ for (Status s : Status.values()) {
+ if (s.getStatus().equalsIgnoreCase(status)) {
+ return s;
+ }
+ }
+ throw new IllegalArgumentException("Invalid status: " + status);
+ }
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/model/SuccessVO.java b/maven-spring/src/main/java/com/poliveira/javaverse/models/SuccessVO.java
similarity index 86%
rename from maven-spring/src/main/java/com/poliveira/javaverse/model/SuccessVO.java
rename to maven-spring/src/main/java/com/poliveira/javaverse/models/SuccessVO.java
index 3caca11..6feb394 100644
--- a/maven-spring/src/main/java/com/poliveira/javaverse/model/SuccessVO.java
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/models/SuccessVO.java
@@ -1,4 +1,4 @@
-package com.poliveira.javaverse.model;
+package com.poliveira.javaverse.models;
import lombok.AllArgsConstructor;
import lombok.Builder;
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/models/TaskVO.java b/maven-spring/src/main/java/com/poliveira/javaverse/models/TaskVO.java
new file mode 100644
index 0000000..34de51a
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/models/TaskVO.java
@@ -0,0 +1,21 @@
+package com.poliveira.javaverse.models;
+
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TaskVO {
+
+ private UUID id;
+ private String name;
+ private String description;
+ private Status status;
+ private long createdAt;
+ private long updatedAt;
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/processors/MappingService.java b/maven-spring/src/main/java/com/poliveira/javaverse/processors/MappingService.java
new file mode 100644
index 0000000..a42bbc0
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/processors/MappingService.java
@@ -0,0 +1,46 @@
+package com.poliveira.javaverse.processors;
+
+import com.poliveira.javaverse.entities.StatusEntity;
+import com.poliveira.javaverse.entities.TaskEntity;
+import com.poliveira.javaverse.models.Status;
+import com.poliveira.javaverse.models.TaskVO;
+import com.poliveira.javaverse.utils.TimeUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class MappingService {
+
+ private final TimeUtils timeUtils;
+
+ public Status toVO(StatusEntity statusEntity) {
+ return Status.from(statusEntity.getName());
+ }
+
+ public StatusEntity toEntity(Status status) {
+ return StatusEntity.builder().name(status.name()).build();
+ }
+
+ public TaskEntity toEntity(TaskVO taskVO) {
+ return TaskEntity.builder()
+ .id(taskVO.getId())
+ .name(taskVO.getName())
+ .description(taskVO.getDescription())
+ .createdAt(timeUtils.toLocalDateTime(taskVO.getCreatedAt()))
+ .updatedAt(timeUtils.toLocalDateTime(taskVO.getUpdatedAt()))
+ .status(toEntity(taskVO.getStatus()))
+ .build();
+ }
+
+ public TaskVO toVO(TaskEntity taskEntity) {
+ return TaskVO.builder()
+ .id(taskEntity.getId())
+ .name(taskEntity.getName())
+ .description(taskEntity.getDescription())
+ .status(toVO(taskEntity.getStatus()))
+ .createdAt(timeUtils.toEpochMilli(taskEntity.getCreatedAt()))
+ .updatedAt(timeUtils.toEpochMilli(taskEntity.getUpdatedAt()))
+ .build();
+ }
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/repositories/TaskRepository.java b/maven-spring/src/main/java/com/poliveira/javaverse/repositories/TaskRepository.java
new file mode 100644
index 0000000..61dcf3d
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/repositories/TaskRepository.java
@@ -0,0 +1,9 @@
+package com.poliveira.javaverse.repositories;
+
+import com.poliveira.javaverse.entities.TaskEntity;
+import java.util.UUID;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface TaskRepository extends JpaRepository {}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/repository/TaskRepository.java b/maven-spring/src/main/java/com/poliveira/javaverse/repository/TaskRepository.java
deleted file mode 100644
index 51fcfd4..0000000
--- a/maven-spring/src/main/java/com/poliveira/javaverse/repository/TaskRepository.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.poliveira.javaverse.repository;
-
-import com.poliveira.javaverse.model.TaskVO;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface TaskRepository extends JpaRepository {
-
- // Custom query methods can be defined here if needed
- // For example, to find tasks by status:
- // List findByStatus(Status status);
-
-}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/service/TaskService.java b/maven-spring/src/main/java/com/poliveira/javaverse/service/TaskService.java
deleted file mode 100644
index c07f9fa..0000000
--- a/maven-spring/src/main/java/com/poliveira/javaverse/service/TaskService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package com.poliveira.javaverse.service;
-
-import static com.poliveira.javaverse.model.Status.TODO;
-import static java.lang.System.currentTimeMillis;
-import static java.util.Objects.nonNull;
-
-import com.poliveira.javaverse.model.SimpleTaskVO;
-import com.poliveira.javaverse.model.TaskVO;
-import com.poliveira.javaverse.repository.TaskRepository;
-import java.util.List;
-import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
-
-@Service
-@RequiredArgsConstructor
-public class TaskService {
-
- private final TaskRepository taskRepository;
-
- public List getAllTasks() {
- return taskRepository.findAll();
- }
-
- public TaskVO getTaskById(Long id) {
- return taskRepository.findById(id).orElse(null);
- }
-
- public TaskVO createTask(SimpleTaskVO simpleTaskVO) {
- TaskVO task =
- TaskVO.builder()
- .title(simpleTaskVO.getTitle())
- .description(simpleTaskVO.getDescription())
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
- .build();
- return taskRepository.save(task);
- }
-
- public TaskVO updateTask(Long id, SimpleTaskVO task) {
- TaskVO existingTask = taskRepository.findById(id).orElse(null);
- if (nonNull(existingTask)) {
- existingTask.setTitle(task.getTitle());
- existingTask.setDescription(task.getDescription());
- existingTask.setUpdatedAt(currentTimeMillis());
- return taskRepository.save(existingTask);
- }
- return null;
- }
-
- public boolean deleteTask(Long id) {
- try {
- taskRepository.deleteById(id);
- return true;
- } catch (Exception e) {
- return false;
- }
- }
-}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/services/TaskService.java b/maven-spring/src/main/java/com/poliveira/javaverse/services/TaskService.java
new file mode 100644
index 0000000..acb08d6
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/services/TaskService.java
@@ -0,0 +1,62 @@
+package com.poliveira.javaverse.services;
+
+import static com.poliveira.javaverse.models.Status.OPEN;
+import static java.lang.System.currentTimeMillis;
+
+import com.poliveira.javaverse.entities.TaskEntity;
+import com.poliveira.javaverse.models.SimpleTaskVO;
+import com.poliveira.javaverse.models.TaskVO;
+import com.poliveira.javaverse.processors.MappingService;
+import com.poliveira.javaverse.repositories.TaskRepository;
+import java.util.List;
+import java.util.UUID;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+@Service
+@RequiredArgsConstructor
+public class TaskService {
+
+ private final TaskRepository taskRepository;
+ private final MappingService mappingService;
+
+ public List getAllTasks() {
+ return taskRepository.findAll().stream().map(mappingService::toVO).toList();
+ }
+
+ public TaskVO getTaskById(UUID id) {
+ TaskEntity taskEntity = taskRepository.findById(id).orElseThrow();
+ return mappingService.toVO(taskEntity);
+ }
+
+ public TaskVO createTask(SimpleTaskVO simpleTaskVO) {
+ TaskVO task =
+ TaskVO.builder()
+ .name(simpleTaskVO.getName())
+ .description(simpleTaskVO.getDescription())
+ .status(OPEN)
+ .createdAt(currentTimeMillis())
+ .updatedAt(currentTimeMillis())
+ .build();
+ TaskEntity taskEntity = mappingService.toEntity(task);
+ return mappingService.toVO(taskRepository.save(taskEntity));
+ }
+
+ public TaskVO updateTask(UUID id, SimpleTaskVO task) {
+ TaskEntity existingTask = taskRepository.findById(id).orElseThrow();
+ TaskVO taskVo = mappingService.toVO(existingTask);
+ taskVo.setName(task.getName());
+ taskVo.setDescription(task.getDescription());
+ taskVo.setUpdatedAt(currentTimeMillis());
+ return mappingService.toVO(taskRepository.save(mappingService.toEntity(taskVo)));
+ }
+
+ public boolean deleteTask(UUID id) {
+ try {
+ taskRepository.deleteById(id);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+}
diff --git a/maven-spring/src/main/java/com/poliveira/javaverse/utils/TimeUtils.java b/maven-spring/src/main/java/com/poliveira/javaverse/utils/TimeUtils.java
new file mode 100644
index 0000000..a61f4e9
--- /dev/null
+++ b/maven-spring/src/main/java/com/poliveira/javaverse/utils/TimeUtils.java
@@ -0,0 +1,23 @@
+package com.poliveira.javaverse.utils;
+
+import static java.lang.System.currentTimeMillis;
+import static java.time.ZoneOffset.UTC;
+
+import java.time.LocalDateTime;
+import java.util.Objects;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TimeUtils {
+ public LocalDateTime toLocalDateTime(long epochSecond) {
+ return LocalDateTime.ofEpochSecond(epochSecond / 1000, 0, UTC);
+ }
+
+ public long toEpochMilli(LocalDateTime localDateTime) {
+ if (Objects.isNull(localDateTime)) {
+ return currentTimeMillis();
+ }
+
+ return localDateTime.toEpochSecond(UTC) * 1000;
+ }
+}
diff --git a/maven-spring/src/main/resources/application-dev.yml b/maven-spring/src/main/resources/application-dev.yml
index 56d6bb7..2cc43ae 100644
--- a/maven-spring/src/main/resources/application-dev.yml
+++ b/maven-spring/src/main/resources/application-dev.yml
@@ -1,16 +1,3 @@
spring:
- application:
- name: javaverse
-
datasource:
- url: jdbc:postgresql://localhost:5432/tasks
- username: myuser
- password: mypassword
- driver-class-name: "org.postgresql.Driver"
-
- jpa:
- hibernate:
- ddl-auto: update
-
-server:
- port: 5190
+ url: jdbc:postgresql://localhost:5432/tasks
\ No newline at end of file
diff --git a/maven-spring/src/main/resources/application.yml b/maven-spring/src/main/resources/application.yml
index 9a73bc5..38a8999 100644
--- a/maven-spring/src/main/resources/application.yml
+++ b/maven-spring/src/main/resources/application.yml
@@ -12,5 +12,9 @@ spring:
hibernate:
ddl-auto: update
+ flyway:
+ enabled: true
+ baseline-on-migrate: true
+
server:
port: 5190
diff --git a/maven-spring/src/main/resources/db/migration/V1__create_tasks.sql b/maven-spring/src/main/resources/db/migration/V1__create_tasks.sql
new file mode 100644
index 0000000..83119e0
--- /dev/null
+++ b/maven-spring/src/main/resources/db/migration/V1__create_tasks.sql
@@ -0,0 +1,7 @@
+CREATE TABLE tasks
+(
+ id UUID PRIMARY KEY NOT NULL,
+ name VARCHAR(255) NOT NULL,
+ description TEXT,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
\ No newline at end of file
diff --git a/maven-spring/src/main/resources/db/migration/V2__add_status.sql b/maven-spring/src/main/resources/db/migration/V2__add_status.sql
new file mode 100644
index 0000000..4cd44fa
--- /dev/null
+++ b/maven-spring/src/main/resources/db/migration/V2__add_status.sql
@@ -0,0 +1,10 @@
+CREATE TABLE status
+(
+ id UUID PRIMARY KEY NOT NULL,
+ name VARCHAR(255) NOT NULL,
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
+);
+
+ALTER TABLE tasks
+ADD COLUMN status_id UUID,
+ADD CONSTRAINT fk_status FOREIGN KEY (status_id) REFERENCES status(id);
\ No newline at end of file
diff --git a/maven-spring/src/main/resources/db/migration/V3__insert_data.sql b/maven-spring/src/main/resources/db/migration/V3__insert_data.sql
new file mode 100644
index 0000000..c21f478
--- /dev/null
+++ b/maven-spring/src/main/resources/db/migration/V3__insert_data.sql
@@ -0,0 +1,10 @@
+INSERT INTO status (id, name)
+VALUES
+ ('D6127F26-55B6-408D-A010-322FBEC9B1B1', 'Open'),
+ ('C78BDBC7-E2D6-4C39-AF32-FDDAC2DC9004', 'In Progress'),
+ ('31BD3B30-FFCC-44C5-B24B-F169E28FC138', 'Blocked'),
+ ('9CD7D8F8-980B-4344-9A6C-44DA84A72974', 'Done');
+
+-- create new task with status in progress
+INSERT INTO tasks (id, name, description, created_at, status_id)
+VALUES ('525B5626-D373-4023-A026-FBA5642EAEF0', 'Create CLI', 'This todo list as CLI', now(), 'C78BDBC7-E2D6-4C39-AF32-FDDAC2DC9004');
\ No newline at end of file
diff --git a/maven-spring/src/test/java/com/poliveira/javaverse/TasksRepositoryTest.java b/maven-spring/src/test/java/com/poliveira/javaverse/TasksRepositoryTest.java
index 9958d5c..742818c 100644
--- a/maven-spring/src/test/java/com/poliveira/javaverse/TasksRepositoryTest.java
+++ b/maven-spring/src/test/java/com/poliveira/javaverse/TasksRepositoryTest.java
@@ -1,16 +1,18 @@
package com.poliveira.javaverse;
-import static com.poliveira.javaverse.model.Status.TODO;
import static java.lang.System.currentTimeMillis;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
-import com.poliveira.javaverse.model.TaskVO;
-import com.poliveira.javaverse.repository.TaskRepository;
+import com.poliveira.javaverse.entities.StatusEntity;
+import com.poliveira.javaverse.entities.TaskEntity;
+import com.poliveira.javaverse.repositories.TaskRepository;
+import com.poliveira.javaverse.utils.TimeUtils;
import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -22,108 +24,123 @@ public class TasksRepositoryTest {
@Mock private TaskRepository taskRepository;
+ private TimeUtils timeUtils = new TimeUtils();
+ private StatusEntity open =
+ StatusEntity.builder()
+ .id(UUID.fromString("D6127F26-55B6-408D-A010-322FBEC9B1B1"))
+ .name("Open")
+ .build();
+
@BeforeEach
public void setUp() {}
@Test
public void testCreateTask() {
- TaskVO mockTaskVO =
- TaskVO.builder()
- .id(1L)
- .title("New Task")
+ UUID taskId = UUID.randomUUID();
+ TaskEntity mockTaskEntity =
+ TaskEntity.builder()
+ .id(taskId)
+ .name("New Task")
.description("This is a new task")
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .status(open)
+ .status(open)
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
.build();
- when(taskRepository.save(any(TaskVO.class))).thenReturn(mockTaskVO);
+ when(taskRepository.save(any(TaskEntity.class))).thenReturn(mockTaskEntity);
- TaskVO taskVO = taskRepository.save(mockTaskVO);
- assertTrue(taskVO.getId() > 0);
- assertEquals(mockTaskVO.getTitle(), taskVO.getTitle());
- assertEquals(mockTaskVO.getDescription(), taskVO.getDescription());
- assertEquals(TODO, taskVO.getStatus());
+ TaskEntity taskEntity = taskRepository.save(mockTaskEntity);
+ assertEquals(taskEntity.getId(), taskId);
+ assertEquals(mockTaskEntity.getName(), taskEntity.getName());
+ assertEquals(mockTaskEntity.getDescription(), taskEntity.getDescription());
+ assertEquals(open.getId(), taskEntity.getStatus().getId());
+ assertEquals(open.getName(), taskEntity.getStatus().getName());
}
@Test
public void testFindAllTasks() {
- TaskVO task1 =
- TaskVO.builder()
- .id(1L)
- .title("Task 1")
+ UUID taskId1 = UUID.randomUUID();
+ TaskEntity task1 =
+ TaskEntity.builder()
+ .id(taskId1)
+ .name("Task 1")
.description("Description 1")
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
.build();
- TaskVO task2 =
- TaskVO.builder()
- .id(2L)
- .title("Task 2")
+ UUID taskId2 = UUID.randomUUID();
+ TaskEntity task2 =
+ TaskEntity.builder()
+ .id(taskId2)
+ .name("Task 2")
.description("Description 2")
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
.build();
when(taskRepository.findAll()).thenReturn(List.of(task1, task2));
- List tasks = taskRepository.findAll();
+ List tasks = taskRepository.findAll();
assertEquals(2, tasks.size());
- assertEquals(task1.getTitle(), tasks.get(0).getTitle());
- assertEquals(task2.getTitle(), tasks.get(1).getTitle());
+ assertEquals(task1.getName(), tasks.get(0).getName());
+ assertEquals(task2.getName(), tasks.get(1).getName());
}
@Test
public void testFindById() {
- TaskVO task1 =
- TaskVO.builder()
- .id(1L)
- .title("Task 1")
+ UUID taskId = UUID.randomUUID();
+ TaskEntity task1 =
+ TaskEntity.builder()
+ .id(taskId)
+ .name("Task 1")
.description("Description 1")
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
.build();
- when(taskRepository.findById(1L)).thenReturn(java.util.Optional.of(task1));
+ when(taskRepository.findById(taskId)).thenReturn(Optional.of(task1));
- TaskVO foundTask = taskRepository.findById(1L).orElse(null);
+ TaskEntity foundTask = taskRepository.findById(taskId).orElse(null);
assertNotNull(foundTask);
- assertEquals(task1.getTitle(), foundTask.getTitle());
+ assertEquals(task1.getName(), foundTask.getName());
assertEquals(task1.getDescription(), foundTask.getDescription());
}
@Test
public void testUpdateTask() {
- TaskVO mockTaskVO =
- TaskVO.builder()
- .id(1L)
- .title("New Task")
+ UUID taskId = UUID.randomUUID();
+ TaskEntity mockTaskEntity =
+ TaskEntity.builder()
+ .id(taskId)
+ .name("New Task")
.description("This is an new task")
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
.build();
- when(taskRepository.save(any(TaskVO.class))).thenReturn(mockTaskVO);
+ when(taskRepository.save(any(TaskEntity.class))).thenReturn(mockTaskEntity);
- TaskVO taskVO1 = taskRepository.save(mockTaskVO);
- assertTrue(taskVO1.getId() > 0);
- assertEquals(mockTaskVO.getTitle(), taskVO1.getTitle());
- assertEquals(mockTaskVO.getDescription(), taskVO1.getDescription());
- assertEquals(TODO, taskVO1.getStatus());
+ TaskEntity taskEntity1 = taskRepository.save(mockTaskEntity);
+ assertEquals(taskEntity1.getId(), taskId);
+ assertEquals(mockTaskEntity.getName(), taskEntity1.getName());
+ assertEquals(mockTaskEntity.getDescription(), taskEntity1.getDescription());
+ assertEquals(open.getId(), taskEntity1.getStatus().getId());
+ assertEquals(open.getName(), taskEntity1.getStatus().getName());
// update the task
- mockTaskVO.setTitle("Updated Task");
- when(taskRepository.save(any(TaskVO.class))).thenReturn(mockTaskVO);
-
- TaskVO taskVO2 = taskRepository.save(mockTaskVO);
- assertTrue(taskVO2.getId() > 0);
- assertEquals(mockTaskVO.getTitle(), taskVO2.getTitle());
- assertEquals(mockTaskVO.getDescription(), taskVO2.getDescription());
- assertEquals(TODO, taskVO2.getStatus());
+ mockTaskEntity.setName("Updated Task");
+ when(taskRepository.save(any(TaskEntity.class))).thenReturn(mockTaskEntity);
+
+ TaskEntity taskEntity2 = taskRepository.save(mockTaskEntity);
+ assertEquals(taskEntity2.getId(), taskId);
+ assertEquals(mockTaskEntity.getName(), taskEntity2.getName());
+ assertEquals(mockTaskEntity.getDescription(), taskEntity2.getDescription());
+ assertEquals(open.getId(), taskEntity2.getStatus().getId());
+ assertEquals(open.getName(), taskEntity2.getStatus().getName());
}
}
diff --git a/maven-spring/src/test/java/com/poliveira/javaverse/TasksServiceTest.java b/maven-spring/src/test/java/com/poliveira/javaverse/TasksServiceTest.java
index e48bd27..d94c417 100644
--- a/maven-spring/src/test/java/com/poliveira/javaverse/TasksServiceTest.java
+++ b/maven-spring/src/test/java/com/poliveira/javaverse/TasksServiceTest.java
@@ -1,18 +1,22 @@
package com.poliveira.javaverse;
-import static com.poliveira.javaverse.model.Status.TODO;
+import static com.poliveira.javaverse.models.Status.OPEN;
import static java.lang.System.currentTimeMillis;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
-import com.poliveira.javaverse.model.SimpleTaskVO;
-import com.poliveira.javaverse.model.TaskVO;
-import com.poliveira.javaverse.repository.TaskRepository;
-import com.poliveira.javaverse.service.TaskService;
+import com.poliveira.javaverse.entities.StatusEntity;
+import com.poliveira.javaverse.entities.TaskEntity;
+import com.poliveira.javaverse.models.SimpleTaskVO;
+import com.poliveira.javaverse.models.TaskVO;
+import com.poliveira.javaverse.processors.MappingService;
+import com.poliveira.javaverse.repositories.TaskRepository;
+import com.poliveira.javaverse.services.TaskService;
+import com.poliveira.javaverse.utils.TimeUtils;
import java.util.List;
import java.util.Optional;
+import java.util.UUID;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -22,79 +26,122 @@
@ExtendWith(MockitoExtension.class)
public class TasksServiceTest {
+ private final StatusEntity open =
+ StatusEntity.builder()
+ .id(UUID.fromString("D6127F26-55B6-408D-A010-322FBEC9B1B1"))
+ .name("Open")
+ .build();
+
+ @Mock private TimeUtils timeUtils;
+ @Mock private MappingService mappingService;
@Mock private TaskRepository taskRepository;
@InjectMocks private TaskService taskService;
@Test
public void testCreateTask() {
SimpleTaskVO task =
- SimpleTaskVO.builder().title("New Task").description("This is a new task").build();
+ SimpleTaskVO.builder().name("New Task").description("This is a new task").build();
+ UUID taskId = UUID.randomUUID();
+ long now = currentTimeMillis();
+ TaskEntity mockTaskEntity =
+ TaskEntity.builder()
+ .id(taskId)
+ .name("New Task")
+ .description("This is a new task")
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(now))
+ .updatedAt(timeUtils.toLocalDateTime(now))
+ .build();
TaskVO mockTaskVO =
TaskVO.builder()
- .id(1L)
- .title(task.getTitle())
- .description(task.getDescription())
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .id(taskId)
+ .name("New Task")
+ .description("This is a new task")
+ .status(OPEN)
+ .createdAt(now)
+ .updatedAt(now)
.build();
- when(taskRepository.save(any(TaskVO.class))).thenReturn(mockTaskVO);
+ when(mappingService.toVO(any(TaskEntity.class))).thenReturn(mockTaskVO);
+ when(mappingService.toEntity(any(TaskVO.class))).thenReturn(mockTaskEntity);
+ when(taskRepository.save(any(TaskEntity.class))).thenReturn(mockTaskEntity);
TaskVO taskVO = taskService.createTask(task);
- assertTrue(taskVO.getId() > 0);
- assertEquals(task.getTitle(), taskVO.getTitle());
- assertEquals(task.getDescription(), taskVO.getDescription());
- assertEquals(TODO, taskVO.getStatus());
+ assertEquals(taskVO.getId(), taskId);
+ assertEquals("New Task", taskVO.getName());
+ assertEquals("This is a new task", taskVO.getDescription());
+ assertEquals(OPEN, taskVO.getStatus());
}
@Test
public void testFindAll() {
- TaskVO task =
+ TaskVO mockTaskVO =
TaskVO.builder()
- .id(1L)
- .title("Test Task")
+ .id(UUID.randomUUID())
+ .name("Test Task")
.description("This is a test task")
- .status(TODO)
+ .status(OPEN)
.createdAt(currentTimeMillis())
.updatedAt(currentTimeMillis())
.build();
+ TaskEntity task =
+ TaskEntity.builder()
+ .id(UUID.randomUUID())
+ .name("Test Task")
+ .description("This is a test task")
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .build();
+ when(mappingService.toVO(any(TaskEntity.class))).thenReturn(mockTaskVO);
when(taskRepository.findAll()).thenReturn(List.of(task));
List tasks = taskService.getAllTasks();
assertEquals(1, tasks.size());
- assertEquals(task.getTitle(), tasks.getFirst().getTitle());
+ assertEquals(task.getName(), tasks.getFirst().getName());
}
@Test
public void testUpdateTask() {
- TaskVO mockExistingTask =
+ UUID taskId = UUID.randomUUID();
+ TaskEntity mockExistingTask =
+ TaskEntity.builder()
+ .id(taskId)
+ .name("Old Task")
+ .description("This is an old task")
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .build();
+ TaskVO mockExistingTaskVO =
TaskVO.builder()
- .id(1L)
- .title("Old Task")
+ .id(taskId)
+ .name("Old Task")
.description("This is an old task")
- .status(TODO)
+ .status(OPEN)
.createdAt(currentTimeMillis())
.updatedAt(currentTimeMillis())
.build();
- TaskVO mockUpdatedTask =
- TaskVO.builder()
- .id(1L)
- .title("Updated Task")
+ TaskEntity mockUpdatedTask =
+ TaskEntity.builder()
+ .id(taskId)
+ .name("Updated Task")
.description("This is an updated task")
- .status(TODO)
- .createdAt(currentTimeMillis())
- .updatedAt(currentTimeMillis())
+ .status(open)
+ .createdAt(timeUtils.toLocalDateTime(currentTimeMillis()))
+ .updatedAt(timeUtils.toLocalDateTime(currentTimeMillis()))
.build();
- when(taskRepository.findById(1L)).thenReturn(Optional.of(mockExistingTask));
- when(taskRepository.save(any(TaskVO.class))).thenReturn(mockUpdatedTask);
+ when(taskRepository.findById(taskId)).thenReturn(Optional.of(mockExistingTask));
+ when(mappingService.toVO(any(TaskEntity.class))).thenReturn(mockExistingTaskVO);
+ when(mappingService.toEntity(any(TaskVO.class))).thenReturn(mockUpdatedTask);
+ when(taskRepository.save(any(TaskEntity.class))).thenReturn(mockUpdatedTask);
SimpleTaskVO task =
- SimpleTaskVO.builder().title("Updated Task").description("This is an updated task").build();
- TaskVO updatedTask = taskService.updateTask(1L, task);
- assertEquals(task.getTitle(), updatedTask.getTitle());
+ SimpleTaskVO.builder().name("Updated Task").description("This is an updated task").build();
+ TaskVO updatedTask = taskService.updateTask(taskId, task);
+ assertEquals(task.getName(), updatedTask.getName());
assertEquals(task.getDescription(), updatedTask.getDescription());
}
}