From 1bee9174a57435fd398bb48e028bcc4e52d90bd1 Mon Sep 17 00:00:00 2001 From: Shadi Date: Tue, 16 Jun 2026 22:14:10 +0200 Subject: [PATCH] Implement project summary endpoint --- .../TicketTrackingSystemApplication.java | 2 +- .../controller/ProjectController.java | 23 +++++++++++ .../dto/response/ProjectSummaryResponse.java | 10 +++++ .../repository/ProjectRepository.java | 40 +++++++++++++++++++ .../service/ProjectService.java | 19 +++++++++ src/main/resources/db/schema.sql | 10 ++--- 6 files changed, 98 insertions(+), 6 deletions(-) create mode 100644 src/main/java/net/hackyourfuture/tickettrackingsystem/controller/ProjectController.java create mode 100644 src/main/java/net/hackyourfuture/tickettrackingsystem/dto/response/ProjectSummaryResponse.java create mode 100644 src/main/java/net/hackyourfuture/tickettrackingsystem/repository/ProjectRepository.java create mode 100644 src/main/java/net/hackyourfuture/tickettrackingsystem/service/ProjectService.java diff --git a/src/main/java/net/hackyourfuture/tickettrackingsystem/TicketTrackingSystemApplication.java b/src/main/java/net/hackyourfuture/tickettrackingsystem/TicketTrackingSystemApplication.java index 7f31a27..b70982c 100644 --- a/src/main/java/net/hackyourfuture/tickettrackingsystem/TicketTrackingSystemApplication.java +++ b/src/main/java/net/hackyourfuture/tickettrackingsystem/TicketTrackingSystemApplication.java @@ -6,7 +6,7 @@ @SpringBootApplication public class TicketTrackingSystemApplication { - public static void main(String[] args) { + static void main(String[] args) { SpringApplication.run(TicketTrackingSystemApplication.class, args); } diff --git a/src/main/java/net/hackyourfuture/tickettrackingsystem/controller/ProjectController.java b/src/main/java/net/hackyourfuture/tickettrackingsystem/controller/ProjectController.java new file mode 100644 index 0000000..bf29d58 --- /dev/null +++ b/src/main/java/net/hackyourfuture/tickettrackingsystem/controller/ProjectController.java @@ -0,0 +1,23 @@ +package net.hackyourfuture.tickettrackingsystem.controller; + +import lombok.RequiredArgsConstructor; +import net.hackyourfuture.tickettrackingsystem.dto.response.ProjectSummaryResponse; +import net.hackyourfuture.tickettrackingsystem.service.ProjectService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/projects") +public class ProjectController { + + private final ProjectService projectService; + + @GetMapping + public List getAllProjects() { + return projectService.getAllProjects(); + } +} \ No newline at end of file diff --git a/src/main/java/net/hackyourfuture/tickettrackingsystem/dto/response/ProjectSummaryResponse.java b/src/main/java/net/hackyourfuture/tickettrackingsystem/dto/response/ProjectSummaryResponse.java new file mode 100644 index 0000000..6510cb6 --- /dev/null +++ b/src/main/java/net/hackyourfuture/tickettrackingsystem/dto/response/ProjectSummaryResponse.java @@ -0,0 +1,10 @@ +package net.hackyourfuture.tickettrackingsystem.dto.response; + +public record ProjectSummaryResponse( + Long id, + String name, + int openTickets, + int inProgressTickets, + int closedTickets +) { +} \ No newline at end of file diff --git a/src/main/java/net/hackyourfuture/tickettrackingsystem/repository/ProjectRepository.java b/src/main/java/net/hackyourfuture/tickettrackingsystem/repository/ProjectRepository.java new file mode 100644 index 0000000..800c8a7 --- /dev/null +++ b/src/main/java/net/hackyourfuture/tickettrackingsystem/repository/ProjectRepository.java @@ -0,0 +1,40 @@ +package net.hackyourfuture.tickettrackingsystem.repository; + +import lombok.RequiredArgsConstructor; +import net.hackyourfuture.tickettrackingsystem.dto.response.ProjectSummaryResponse; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class ProjectRepository { + private final JdbcTemplate jdbcTemplate; + + public List findAllProjectSummaries(){ + String sql = """ + SELECT + p.id, + p.name, + COUNT(*) FILTER (WHERE t.status = 'OPEN') AS open_tickets, + COUNT(*) FILTER (WHERE t.status = 'IN_PROGRESS') AS in_progress_tickets, + COUNT(*) FILTER (WHERE t.status = 'CLOSED') AS closed_tickets + FROM projects p + LEFT JOIN tickets t ON p.id = t.project_id + GROUP BY p.id, p.name + ORDER BY p.name + """; + return jdbcTemplate.query(sql, projectSummaryResponseRowMapper); + } + + private final RowMapper projectSummaryResponseRowMapper = + (rs, rowNum) -> new ProjectSummaryResponse( + rs.getLong("id"), + rs.getString("name"), + rs.getInt("open_tickets"), + rs.getInt("in_progress_tickets"), + rs.getInt("closed_tickets") + ); +} diff --git a/src/main/java/net/hackyourfuture/tickettrackingsystem/service/ProjectService.java b/src/main/java/net/hackyourfuture/tickettrackingsystem/service/ProjectService.java new file mode 100644 index 0000000..40dab49 --- /dev/null +++ b/src/main/java/net/hackyourfuture/tickettrackingsystem/service/ProjectService.java @@ -0,0 +1,19 @@ +package net.hackyourfuture.tickettrackingsystem.service; + +import lombok.RequiredArgsConstructor; +import net.hackyourfuture.tickettrackingsystem.dto.response.ProjectSummaryResponse; +import net.hackyourfuture.tickettrackingsystem.repository.ProjectRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@RequiredArgsConstructor +public class ProjectService { + + private final ProjectRepository projectRepository; + + public List getAllProjects() { + return projectRepository.findAllProjectSummaries(); + } +} \ No newline at end of file diff --git a/src/main/resources/db/schema.sql b/src/main/resources/db/schema.sql index 317d08b..a0c4a2f 100644 --- a/src/main/resources/db/schema.sql +++ b/src/main/resources/db/schema.sql @@ -9,7 +9,7 @@ CREATE TABLE users ( ); CREATE TABLE projects ( id bigserial primary key , - name varchar(255) not null,CHECK (char_length(name) >= 3) + name varchar(255) not null CHECK (char_length(name) >= 3) ); CREATE TABLE tickets ( id bigserial primary key , @@ -21,7 +21,7 @@ CREATE TABLE tickets ( update_date TIMESTAMP, CONSTRAINT fk_ticket_project FOREIGN KEY (project_id) - REFERENCES project(id) + REFERENCES projects(id) ); @@ -37,15 +37,15 @@ CREATE TABLE user_ticket ( ON DELETE CASCADE, CONSTRAINT fk_user_ticket_ticket FOREIGN KEY (ticket_id) - REFERENCES ticket(id) + REFERENCES tickets(id) ON DELETE CASCADE ); CREATE INDEX idx_tickets_status - ON ticket(status); + ON tickets(status); CREATE INDEX idx_tickets_project_id - ON ticket(project_id); + ON tickets(project_id); CREATE INDEX idx_user_ticket_user_id ON user_ticket(user_id); \ No newline at end of file