Criando organization

This commit is contained in:
Gabriel Santana de Menezes 2026-05-02 21:46:34 -04:00
parent 985311211a
commit 953730fffd
50 changed files with 792 additions and 138 deletions

View file

@ -0,0 +1,44 @@
package net.beetechgroup.beetask.entities;
import java.util.List;
import net.beetechgroup.beetask.entities.organization.Organization;
public class Project {
private Long id;
private String name;
private Organization organization;
private List<User> users;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}

View file

@ -0,0 +1,31 @@
package net.beetechgroup.beetask.entities;
public class User {
private Long id;
private String name;
private String email;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View file

@ -0,0 +1,44 @@
package net.beetechgroup.beetask.entities.organization;
import java.util.List;
import net.beetechgroup.beetask.entities.Project;
public class Organization {
private Long id;
private String name;
private List<Project> projects;
private List<UserOrganization> users;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
public List<UserOrganization> getUsers() {
return users;
}
public void setUsers(List<UserOrganization> users) {
this.users = users;
}
}

View file

@ -0,0 +1,9 @@
package net.beetechgroup.beetask.entities.organization;
import net.beetechgroup.beetask.entities.User;
public class UserOrganization {
private User user;
private Organization organization;
private UserOrganizationRole role;
}

View file

@ -0,0 +1,7 @@
package net.beetechgroup.beetask.entities.organization;
public enum UserOrganizationRole {
OWNER,
ADMIN,
MEMBER
}

View file

@ -1,15 +1,17 @@
package net.beetechgroup.beetask.entities;
package net.beetechgroup.beetask.entities.task;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import net.beetechgroup.beetask.entities.Project;
public class Task {
private Long id;
private String title;
private String description;
private TaskStatus status;
private String project;
private Project project;
private List<TaskHistoryItem> history = new ArrayList<>();
public Long getId() {
@ -41,14 +43,26 @@ public class Task {
}
public void setStatus(TaskStatus status) {
if (this.status == status) return;
if (status == TaskStatus.IN_PROGRESS) {
if (!isRunning()) {
start();
}
} else if (this.status == TaskStatus.IN_PROGRESS || isRunning()) {
if (isRunning()) {
stop();
}
}
this.status = status;
}
public String getProject() {
public Project getProject() {
return project;
}
public void setProject(String project) {
public void setProject(Project project) {
this.project = project;
}

View file

@ -1,4 +1,4 @@
package net.beetechgroup.beetask.entities;
package net.beetechgroup.beetask.entities.task;
import java.time.LocalDateTime;

View file

@ -1,4 +1,4 @@
package net.beetechgroup.beetask.entities;
package net.beetechgroup.beetask.entities.task;
public enum TaskStatus {
NOT_STARTED("NOT_STARTED"),

View file

@ -0,0 +1,15 @@
package net.beetechgroup.beetask.frameworks.config;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import net.beetechgroup.beetask.usecase.organization.create.CreateOrganizationUseCase;
import net.beetechgroup.beetask.usecase.repository.OrganizationRepository;
@ApplicationScoped
public class OrganizationUseCaseConfig {
@Produces
public CreateOrganizationUseCase createOrganizationUseCase(OrganizationRepository organizationRepository) {
return new CreateOrganizationUseCase(organizationRepository);
}
}

View file

@ -0,0 +1,46 @@
package net.beetechgroup.beetask.frameworks.persistence.entities;
import java.util.List;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "organizations")
public class OrganizationEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany(mappedBy = "organization")
private List<UserOrganizationEntity> userOrganizations;
public void setUserOrganizations(List<UserOrganizationEntity> userOrganizations) {
this.userOrganizations = userOrganizations;
}
public List<UserOrganizationEntity> getUserOrganizations() {
return userOrganizations;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View file

@ -0,0 +1,62 @@
package net.beetechgroup.beetask.frameworks.persistence.entities;
import java.util.List;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToMany;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
@Entity
@Table(name = "projects")
public class ProjectEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "organization_id")
private OrganizationEntity organization;
@ManyToMany
@JoinTable(name = "project_users", joinColumns = @JoinColumn(name = "project_id"), inverseJoinColumns = @JoinColumn(name = "user_id"))
private List<UserEntity> users;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public OrganizationEntity getOrganization() {
return organization;
}
public void setOrganization(OrganizationEntity organization) {
this.organization = organization;
}
public List<UserEntity> getUsers() {
return users;
}
public void setUsers(List<UserEntity> users) {
this.users = users;
}
}

View file

@ -9,8 +9,10 @@ import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import net.beetechgroup.beetask.entities.TaskStatus;
import net.beetechgroup.beetask.entities.Project;
import net.beetechgroup.beetask.entities.task.TaskStatus;
@Entity
@Table(name = "tasks")
@ -21,7 +23,10 @@ public class TaskEntity {
private String title;
private String description;
private TaskStatus status;
private String project;
@ManyToOne
@JoinColumn(name = "project_id")
private ProjectEntity project;
@ElementCollection
@CollectionTable(name = "task_history", joinColumns = @JoinColumn(name = "task_id"))
private List<TaskHistoryItemEntity> history;
@ -66,11 +71,11 @@ public class TaskEntity {
this.status = status;
}
public String getProject() {
public ProjectEntity getProject() {
return project;
}
public void setProject(String project) {
public void setProject(ProjectEntity project) {
this.project = project;
}

View file

@ -0,0 +1,41 @@
package net.beetechgroup.beetask.frameworks.persistence.entities;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

View file

@ -0,0 +1,49 @@
package net.beetechgroup.beetask.frameworks.persistence.entities;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import net.beetechgroup.beetask.entities.organization.UserOrganizationRole;
@Entity
@Table(name = "user_organizations")
public class UserOrganizationEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "user_id")
private UserEntity user;
@ManyToOne
@JoinColumn(name = "organization_id")
private OrganizationEntity organization;
private UserOrganizationRole role;
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public OrganizationEntity getOrganization() {
return organization;
}
public void setOrganization(OrganizationEntity organization) {
this.organization = organization;
}
public UserOrganizationRole getRole() {
return role;
}
public void setRole(UserOrganizationRole role) {
this.role = role;
}
}

View file

@ -0,0 +1,22 @@
package net.beetechgroup.beetask.frameworks.persistence.mapper;
import net.beetechgroup.beetask.entities.organization.Organization;
import net.beetechgroup.beetask.frameworks.persistence.entities.OrganizationEntity;
public class OrganizationEntityMapper {
public static OrganizationEntity toEntity(Organization organization) {
OrganizationEntity entity = new OrganizationEntity();
entity.setId(organization.getId());
entity.setName(organization.getName());
return entity;
}
public static Organization toDomain(OrganizationEntity entity) {
if (entity == null) return null;
Organization organization = new Organization();
organization.setId(entity.getId());
organization.setName(entity.getName());
return organization;
}
}

View file

@ -0,0 +1,23 @@
package net.beetechgroup.beetask.frameworks.persistence.mapper;
import net.beetechgroup.beetask.entities.Project;
import net.beetechgroup.beetask.frameworks.persistence.entities.ProjectEntity;
public class ProjectEntityMapper {
public static ProjectEntity toEntity(Project project) {
ProjectEntity entity = new ProjectEntity();
entity.setId(project.getId());
entity.setName(project.getName());
return entity;
}
public static Project toDomain(ProjectEntity entity) {
if (entity == null) return null;
Project project = new Project();
project.setId(entity.getId());
project.setName(entity.getName());
return project;
}
}

View file

@ -1,10 +1,11 @@
package net.beetechgroup.beetask.frameworks.persistence.mapper;
import java.util.ArrayList;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.frameworks.persistence.entities.TaskEntity;
public class TaskMapper {
public class TaskEntityMapper {
public static TaskEntity toEntity(Task task) {
TaskEntity entity = new TaskEntity();
@ -12,7 +13,7 @@ public class TaskMapper {
entity.setTitle(task.getTitle());
entity.setDescription(task.getDescription());
entity.setStatus(task.getStatus());
entity.setProject(task.getProject());
entity.setProject(ProjectEntityMapper.toEntity(task.getProject()));
entity.setHistory(new ArrayList<>(task.getHistory().stream().map(TaskHistoryItemMapper::toEntity).toList()));
return entity;
}
@ -25,7 +26,7 @@ public class TaskMapper {
task.setTitle(entity.getTitle());
task.setDescription(entity.getDescription());
task.setStatus(entity.getStatus());
task.setProject(entity.getProject());
task.setProject(ProjectEntityMapper.toDomain(entity.getProject()));
task.setHistory(new ArrayList<>(entity.getHistory().stream().map(TaskHistoryItemMapper::toDomain).toList()));
return task;

View file

@ -1,6 +1,6 @@
package net.beetechgroup.beetask.frameworks.persistence.mapper;
import net.beetechgroup.beetask.entities.TaskHistoryItem;
import net.beetechgroup.beetask.entities.task.TaskHistoryItem;
import net.beetechgroup.beetask.frameworks.persistence.entities.TaskHistoryItemEntity;
public class TaskHistoryItemMapper {

View file

@ -0,0 +1,26 @@
package net.beetechgroup.beetask.frameworks.persistence.repository;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import net.beetechgroup.beetask.entities.organization.Organization;
import net.beetechgroup.beetask.frameworks.persistence.entities.OrganizationEntity;
import net.beetechgroup.beetask.frameworks.persistence.mapper.OrganizationEntityMapper;
import net.beetechgroup.beetask.usecase.repository.OrganizationRepository;
@ApplicationScoped
public class OrganizationRepositoryImpl implements OrganizationRepository, PanacheRepository<OrganizationEntity> {
@Override
@Transactional
public Organization saveOrganization(Organization organization) {
OrganizationEntity entity = OrganizationEntityMapper.toEntity(organization);
if (entity.getId() == null) {
persist(entity);
} else {
entity = getEntityManager().merge(entity);
}
return OrganizationEntityMapper.toDomain(entity);
}
}

View file

@ -5,9 +5,9 @@ import java.util.List;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.transaction.Transactional;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.frameworks.persistence.entities.TaskEntity;
import net.beetechgroup.beetask.frameworks.persistence.mapper.TaskMapper;
import net.beetechgroup.beetask.frameworks.persistence.mapper.TaskEntityMapper;
import net.beetechgroup.beetask.usecase.exceptions.TaskNotFoundException;
import net.beetechgroup.beetask.usecase.repository.TaskRepository;
@ -17,24 +17,24 @@ public class TaskRepositoryImpl implements TaskRepository, PanacheRepository<Tas
@Override
@Transactional
public Task saveTask(Task task) {
TaskEntity entity = TaskMapper.toEntity(task);
TaskEntity entity = TaskEntityMapper.toEntity(task);
if (entity.getId() == null) {
persist(entity);
} else {
entity = getEntityManager().merge(entity);
}
return TaskMapper.toDomain(entity);
return TaskEntityMapper.toDomain(entity);
}
@Override
public Task findTaskById(Long id) {
TaskEntity entity = find("id = ?1", id).firstResultOptional()
.orElseThrow(() -> new TaskNotFoundException(id));
return TaskMapper.toDomain(entity);
return TaskEntityMapper.toDomain(entity);
}
@Override
public List<Task> findAllTasks() {
return findAll().list().stream().map(TaskMapper::toDomain).toList();
return findAll().list().stream().map(TaskEntityMapper::toDomain).toList();
}
}

View file

@ -0,0 +1,58 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.auth;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import java.time.LocalDateTime;
import java.util.List;
@Path("/auth")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Authentication", description = "Authentication operations (Mocked)")
public class AuthController {
@Path("/login")
@POST
@Operation(summary = "Login", description = "Mocked login that returns user data")
public LoginResponse login() {
return new LoginResponse(
"Gabriel Menezes",
"gabriel@beetech.net",
"https://ui-avatars.com/api/?name=Gabriel+Menezes&background=random",
"mocked-jwt-token-abcd-1234",
"mocked-refresh-token-wxyz-5678",
3600L, // 1 hour
LocalDateTime.now().toString(),
List.of(
new LoginResponse.OrganizationDTO("BeeTech Group", List.of("ADMIN", "OWNER")),
new LoginResponse.OrganizationDTO("SkyMob Dev", List.of("DEVELOPER"))
)
);
}
@Path("/refresh")
@POST
@Operation(summary = "Refresh token", description = "Mocked token refresh")
public LoginResponse refresh() {
return new LoginResponse(
"Gabriel Menezes",
"gabriel@beetech.net",
"https://ui-avatars.com/api/?name=Gabriel+Menezes&background=random",
"refreshed-jwt-token-" + System.currentTimeMillis(),
"refreshed-refresh-token-" + System.currentTimeMillis(),
3600L,
LocalDateTime.now().toString(),
List.of(
new LoginResponse.OrganizationDTO("BeeTech Group", List.of("ADMIN", "OWNER")),
new LoginResponse.OrganizationDTO("SkyMob Dev", List.of("DEVELOPER"))
)
);
}
}

View file

@ -0,0 +1,19 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.auth;
import java.util.List;
public record LoginResponse(
String name,
String email,
String photo,
String jwt,
String refreshToken,
Long expiresIn,
String issuedAt,
List<OrganizationDTO> organizations
) {
public record OrganizationDTO(
String name,
List<String> roles
) {}
}

View file

@ -0,0 +1,5 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.organization;
public record CreateOrganizationRequest(
String name) {
}

View file

@ -0,0 +1,4 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.organization;
public record CreateOrganizationResponse(Long id, String name) {
}

View file

@ -0,0 +1,25 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.organization;
import org.eclipse.microprofile.openapi.annotations.Operation;
import jakarta.inject.Inject;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import net.beetechgroup.beetask.usecase.organization.create.CreateOrganizationInput;
import net.beetechgroup.beetask.usecase.organization.create.CreateOrganizationOutput;
import net.beetechgroup.beetask.usecase.organization.create.CreateOrganizationUseCase;
@Path("/organizations")
public class OrganizationController {
@Inject
CreateOrganizationUseCase createOrganizationUseCase;
@POST
@Operation(summary = "Create organization", description = "Creates a new organization")
public CreateOrganizationResponse createOrganization(CreateOrganizationRequest request) {
CreateOrganizationInput input = OrganizationControllerMapper.toCreateOrganizationInput(request);
CreateOrganizationOutput output = createOrganizationUseCase.execute(input);
return OrganizationControllerMapper.toCreateOrganizationResponse(output);
}
}

View file

@ -0,0 +1,14 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.organization;
import net.beetechgroup.beetask.usecase.organization.create.CreateOrganizationInput;
import net.beetechgroup.beetask.usecase.organization.create.CreateOrganizationOutput;
public class OrganizationControllerMapper {
public static CreateOrganizationInput toCreateOrganizationInput(CreateOrganizationRequest request) {
return new CreateOrganizationInput(request.name());
}
public static CreateOrganizationResponse toCreateOrganizationResponse(CreateOrganizationOutput output) {
return new CreateOrganizationResponse(output.id(), output.name());
}
}

View file

@ -0,0 +1,10 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.task;
import net.beetechgroup.beetask.entities.task.TaskStatus;
public record CreateTaskRequest(
String title,
String description,
TaskStatus status,
Long projectId) {
}

View file

@ -0,0 +1,14 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.task;
import java.util.List;
import net.beetechgroup.beetask.entities.task.TaskStatus;
public record CreateTaskResponse(
Long id,
String title,
String description,
TaskStatus status,
String project,
List<TaskHistoryItemResponse> history) {
}

View file

@ -1,4 +1,4 @@
package net.beetechgroup.beetask.interfaceadapters.controllers;
package net.beetechgroup.beetask.interfaceadapters.controllers.task;
import jakarta.inject.Inject;
import jakarta.ws.rs.Consumes;
@ -16,11 +16,11 @@ import java.util.List;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.TaskStatus;
import net.beetechgroup.beetask.interfaceadapters.dtos.TaskDTOMapper;
import net.beetechgroup.beetask.interfaceadapters.dtos.TaskRequestDTO;
import net.beetechgroup.beetask.interfaceadapters.dtos.TaskResponseDTO;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.entities.task.TaskStatus;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskInput;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskOutput;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskUseCase;
import net.beetechgroup.beetask.usecase.task.listall.ListAllTasksUseCase;
import net.beetechgroup.beetask.usecase.task.start.StartTaskUseCase;
@ -51,43 +51,44 @@ public class TaskController {
@POST
@Operation(summary = "Create a new task", description = "Creates a new task in the system")
@APIResponse(responseCode = "201", description = "Task created successfully")
public TaskResponseDTO createTask(TaskRequestDTO request) {
Task task = createTaskUseCase.execute(TaskDTOMapper.toCreateTaskInput(request));
return TaskDTOMapper.toTaskResponseDTO(task);
public CreateTaskResponse createTask(CreateTaskRequest request) {
CreateTaskInput input = TaskControllerMapper.toCreateTaskInput(request);
CreateTaskOutput output = createTaskUseCase.execute(input);
return TaskControllerMapper.toCreateTaskResponse(output);
}
@PUT
@Path("/{id}/start")
@Operation(summary = "Start a task", description = "Starts a task in the system")
@APIResponse(responseCode = "200", description = "Task started successfully")
public TaskResponseDTO startTask(@PathParam("id") Long id) {
Task task = startTaskUseCase.execute(TaskDTOMapper.toStartTaskInput(id));
return TaskDTOMapper.toTaskResponseDTO(task);
public CreateTaskResponse startTask(@PathParam("id") Long id) {
CreateTaskOutput output = startTaskUseCase.execute(TaskControllerMapper.toStartTaskInput(id));
return TaskControllerMapper.toCreateTaskResponse(output);
}
@PUT
@Path("/{id}/stop")
@Operation(summary = "Stop a task", description = "Stops a task in the system")
@APIResponse(responseCode = "200", description = "Task stopped successfully")
public TaskResponseDTO stopTask(@PathParam("id") Long id) {
Task task = stopTaskUseCase.execute(TaskDTOMapper.toStopTaskInput(id));
return TaskDTOMapper.toTaskResponseDTO(task);
public CreateTaskResponse stopTask(@PathParam("id") Long id) {
CreateTaskOutput output = stopTaskUseCase.execute(TaskControllerMapper.toStopTaskInput(id));
return TaskControllerMapper.toCreateTaskResponse(output);
}
@PATCH
@Path("/{id}/status")
@Operation(summary = "Update task status", description = "Updates the status of a task")
@APIResponse(responseCode = "200", description = "Task status updated successfully")
public TaskResponseDTO updateTaskStatus(@PathParam("id") Long id, TaskStatus status) {
Task task = updateTaskStatusUseCase.execute(id, status);
return TaskDTOMapper.toTaskResponseDTO(task);
public CreateTaskResponse updateTaskStatus(@PathParam("id") Long id, TaskStatus status) {
CreateTaskOutput output = updateTaskStatusUseCase.execute(id, status);
return TaskControllerMapper.toCreateTaskResponse(output);
}
@GET
@Operation(summary = "List all tasks", description = "Lists all tasks in the system")
@APIResponse(responseCode = "200", description = "Tasks listed successfully")
public List<TaskResponseDTO> listTasks() {
return listAllTasksUseCase.execute().stream().map(TaskDTOMapper::toTaskResponseDTO).toList();
public List<CreateTaskResponse> listTasks() {
return listAllTasksUseCase.execute().stream().map(TaskControllerMapper::toCreateTaskResponse).toList();
}
}

View file

@ -0,0 +1,37 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.task;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskInput;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskOutput;
import net.beetechgroup.beetask.usecase.task.start.StartTaskInput;
import net.beetechgroup.beetask.usecase.task.stop.StopTaskInput;
public class TaskControllerMapper {
public static CreateTaskInput toCreateTaskInput(CreateTaskRequest request) {
return new CreateTaskInput(
request.title(),
request.description(),
request.status(),
request.projectId()
);
}
public static CreateTaskResponse toCreateTaskResponse(CreateTaskOutput output) {
return new CreateTaskResponse(
output.id(),
output.title(),
output.description(),
output.status(),
output.project(),
output.history().stream().map(taskHistoryItemOutput -> new TaskHistoryItemResponse(taskHistoryItemOutput.startAt(), taskHistoryItemOutput.endAt())).toList()
);
}
public static StartTaskInput toStartTaskInput(Long id) {
return new StartTaskInput(id);
}
public static StopTaskInput toStopTaskInput(Long id) {
return new StopTaskInput(id);
}
}

View file

@ -0,0 +1,8 @@
package net.beetechgroup.beetask.interfaceadapters.controllers.task;
import java.time.LocalDateTime;
public record TaskHistoryItemResponse(
LocalDateTime startAt,
LocalDateTime endAt) {
}

View file

@ -1,42 +0,0 @@
package net.beetechgroup.beetask.interfaceadapters.dtos;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.TaskHistoryItem;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskInput;
import net.beetechgroup.beetask.usecase.task.start.StartTaskInput;
import net.beetechgroup.beetask.usecase.task.stop.StopTaskInput;
public class TaskDTOMapper {
public static CreateTaskInput toCreateTaskInput(TaskRequestDTO request) {
return new CreateTaskInput(
request.title(),
request.description(),
request.status(),
request.project()
);
}
public static TaskResponseDTO toTaskResponseDTO(Task task) {
return new TaskResponseDTO(
task.getId(),
task.getTitle(),
task.getDescription(),
task.getStatus(),
task.getProject(),
task.getHistory().stream().map(TaskDTOMapper::toTaskHistoryItemDTO).toList()
);
}
private static TaskHistoryItemDTO toTaskHistoryItemDTO(TaskHistoryItem taskHistoryItem) {
return new TaskHistoryItemDTO(taskHistoryItem.getStartAt(), taskHistoryItem.getEndAt());
}
public static StartTaskInput toStartTaskInput(Long id) {
return new StartTaskInput(id);
}
public static StopTaskInput toStopTaskInput(Long id) {
return new StopTaskInput(id);
}
}

View file

@ -1,7 +0,0 @@
package net.beetechgroup.beetask.interfaceadapters.dtos;
import java.time.LocalDateTime;
public record TaskHistoryItemDTO(LocalDateTime startAt, LocalDateTime endAt) {
}

View file

@ -1,10 +0,0 @@
package net.beetechgroup.beetask.interfaceadapters.dtos;
import net.beetechgroup.beetask.entities.TaskStatus;
public record TaskRequestDTO(
String title,
String description,
TaskStatus status,
String project) {
}

View file

@ -1,14 +0,0 @@
package net.beetechgroup.beetask.interfaceadapters.dtos;
import java.util.List;
import net.beetechgroup.beetask.entities.TaskStatus;
public record TaskResponseDTO(
Long id,
String title,
String description,
TaskStatus status,
String project,
List<TaskHistoryItemDTO> history) {
}

View file

@ -0,0 +1,4 @@
package net.beetechgroup.beetask.usecase.organization.create;
public record CreateOrganizationInput(String name) {
}

View file

@ -0,0 +1,9 @@
package net.beetechgroup.beetask.usecase.organization.create;
import net.beetechgroup.beetask.entities.organization.Organization;
public class CreateOrganizationMapper {
public static CreateOrganizationOutput toCreateOrganizationOutput(Organization organization) {
return new CreateOrganizationOutput(organization.getId(), organization.getName());
}
}

View file

@ -0,0 +1,4 @@
package net.beetechgroup.beetask.usecase.organization.create;
public record CreateOrganizationOutput(Long id, String name) {
}

View file

@ -0,0 +1,19 @@
package net.beetechgroup.beetask.usecase.organization.create;
import net.beetechgroup.beetask.entities.organization.Organization;
import net.beetechgroup.beetask.usecase.repository.OrganizationRepository;
public class CreateOrganizationUseCase {
private final OrganizationRepository organizationRepository;
public CreateOrganizationUseCase(OrganizationRepository organizationRepository) {
this.organizationRepository = organizationRepository;
}
public CreateOrganizationOutput execute(CreateOrganizationInput input) {
Organization organization = new Organization();
organization.setName(input.name());
organizationRepository.saveOrganization(organization);
return CreateOrganizationMapper.toCreateOrganizationOutput(organization);
}
}

View file

@ -0,0 +1,8 @@
package net.beetechgroup.beetask.usecase.repository;
import net.beetechgroup.beetask.entities.organization.Organization;
public interface OrganizationRepository {
Organization saveOrganization(Organization organization);
}

View file

@ -2,7 +2,7 @@ package net.beetechgroup.beetask.usecase.repository;
import java.util.List;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.task.Task;
public interface TaskRepository {
Task saveTask(Task task);

View file

@ -1,10 +1,10 @@
package net.beetechgroup.beetask.usecase.task.create;
import net.beetechgroup.beetask.entities.TaskStatus;
import net.beetechgroup.beetask.entities.task.TaskStatus;
public record CreateTaskInput(
String title,
String description,
TaskStatus status,
String project) {
Long projectId) {
}

View file

@ -0,0 +1,22 @@
package net.beetechgroup.beetask.usecase.task.create;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.entities.task.TaskHistoryItem;
public class CreateTaskMapper {
public static CreateTaskOutput toCreateTaskOutput(Task task) {
return new CreateTaskOutput(
task.getId(),
task.getTitle(),
task.getDescription(),
task.getStatus(),
task.getProject().getName(),
task.getHistory().stream().map(CreateTaskMapper::toTaskHistoryItemOutput).toList());
}
private static TaskHistoryItemOutput toTaskHistoryItemOutput(TaskHistoryItem taskHistoryItem) {
return new TaskHistoryItemOutput(
taskHistoryItem.getStartAt(),
taskHistoryItem.getEndAt());
}
}

View file

@ -1,5 +1,15 @@
package net.beetechgroup.beetask.usecase.task.create;
public class CreateTaskOutput {
import java.util.List;
import net.beetechgroup.beetask.entities.task.TaskStatus;
public record CreateTaskOutput(
Long id,
String title,
String description,
TaskStatus status,
String project,
List<TaskHistoryItemOutput> history) {
}

View file

@ -1,6 +1,7 @@
package net.beetechgroup.beetask.usecase.task.create;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.Project;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.usecase.repository.TaskRepository;
public class CreateTaskUseCase {
@ -10,12 +11,13 @@ public class CreateTaskUseCase {
this.taskRepository = taskRepository;
}
public Task execute(CreateTaskInput input) {
public CreateTaskOutput execute(CreateTaskInput input) {
Task task = new Task();
task.setTitle(input.title());
task.setDescription(input.description());
task.setStatus(input.status());
task.setProject(input.project());
return taskRepository.saveTask(task);
task.setProject(new Project());
task.getProject().setId(input.projectId());
return CreateTaskMapper.toCreateTaskOutput(taskRepository.saveTask(task));
}
}

View file

@ -0,0 +1,8 @@
package net.beetechgroup.beetask.usecase.task.create;
import java.time.LocalDateTime;
public record TaskHistoryItemOutput(
LocalDateTime startAt,
LocalDateTime endAt) {
}

View file

@ -1,7 +1,8 @@
package net.beetechgroup.beetask.usecase.task.listall;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.usecase.repository.TaskRepository;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskMapper;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskOutput;
import java.util.List;
@ -13,7 +14,7 @@ public class ListAllTasksUseCase {
this.taskRepository = taskRepository;
}
public List<Task> execute() {
return taskRepository.findAllTasks();
public List<CreateTaskOutput> execute() {
return taskRepository.findAllTasks().stream().map(CreateTaskMapper::toCreateTaskOutput).toList();
}
}

View file

@ -1,7 +1,9 @@
package net.beetechgroup.beetask.usecase.task.start;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.usecase.repository.TaskRepository;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskMapper;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskOutput;
public class StartTaskUseCase {
@ -11,9 +13,9 @@ public class StartTaskUseCase {
this.taskRepository = taskRepository;
}
public Task execute(StartTaskInput input) {
public CreateTaskOutput execute(StartTaskInput input) {
Task task = taskRepository.findTaskById(input.id());
task.start();
return taskRepository.saveTask(task);
return CreateTaskMapper.toCreateTaskOutput(taskRepository.saveTask(task));
}
}

View file

@ -1,7 +1,9 @@
package net.beetechgroup.beetask.usecase.task.stop;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.usecase.repository.TaskRepository;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskMapper;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskOutput;
public class StopTaskUseCase {
@ -11,9 +13,9 @@ public class StopTaskUseCase {
this.taskRepository = taskRepository;
}
public Task execute(StopTaskInput input) {
public CreateTaskOutput execute(StopTaskInput input) {
Task task = taskRepository.findTaskById(input.id());
task.stop();
return taskRepository.saveTask(task);
return CreateTaskMapper.toCreateTaskOutput(taskRepository.saveTask(task));
}
}

View file

@ -1,8 +1,12 @@
package net.beetechgroup.beetask.usecase.task.update;
import net.beetechgroup.beetask.entities.Task;
import net.beetechgroup.beetask.entities.TaskStatus;
import net.beetechgroup.beetask.entities.task.Task;
import net.beetechgroup.beetask.entities.task.TaskStatus;
import net.beetechgroup.beetask.usecase.repository.TaskRepository;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskMapper;
import net.beetechgroup.beetask.usecase.task.create.CreateTaskOutput;
public class UpdateTaskStatusUseCase {
@ -12,13 +16,11 @@ public class UpdateTaskStatusUseCase {
this.taskRepository = taskRepository;
}
public Task execute(Long id, TaskStatus newStatus) {
public CreateTaskOutput execute(Long id, TaskStatus newStatus) {
Task task = taskRepository.findTaskById(id);
// Simple status update
// In a more complex scenario, we might want to trigger start() or stop() logic here
task.setStatus(newStatus);
return taskRepository.saveTask(task);
return CreateTaskMapper.toCreateTaskOutput(taskRepository.saveTask(task));
}
}