From 2b41085865c7a1809bb598f362e65860bafd3456 Mon Sep 17 00:00:00 2001
From: dDogge <douglasfjallrud@gmail.com>
Date: Tue, 19 Mar 2024 19:04:45 +0100
Subject: [PATCH] Added GetWeeklyReportsUser function and handler, also
 corresponding tests to both GetWeeklyReportsUser and handler added

---
 backend/internal/database/db.go               | 31 +++++++++++++++
 backend/internal/database/db_test.go          | 39 +++++++++++++++++++
 backend/internal/handlers/global_state.go     |  1 +
 .../handlers/handlers_report_related.go       | 19 +++++++++
 backend/internal/types/WeeklyReport.go        | 21 ++++++++++
 backend/main.go                               |  2 +
 testing.py                                    | 18 +++++++++
 7 files changed, 131 insertions(+)

diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go
index bc6e1e8..574557a 100644
--- a/backend/internal/database/db.go
+++ b/backend/internal/database/db.go
@@ -32,6 +32,7 @@ type Database interface {
 	GetProject(projectId int) (types.Project, error)
 	GetUserRole(username string, projectname string) (string, error)
 	GetWeeklyReport(username string, projectName string, week int) (types.WeeklyReport, error)
+	GetWeeklyReportsUser(username string, projectname string) ([]types.WeeklyReportList, error)
 	SignWeeklyReport(reportId int, projectManagerId int) error
 	IsSiteAdmin(username string) (bool, error)
 }
@@ -402,6 +403,36 @@ func (d *Db) Migrate() error {
 	return nil
 }
 
+// GetWeeklyReportsUser retrieves weekly reports for a specific user and project.
+func (d *Db) GetWeeklyReportsUser(username string, projectName string) ([]types.WeeklyReportList, error) {
+	query := `
+		SELECT
+			wr.week,
+			wr.development_time,
+			wr.meeting_time,
+			wr.admin_time,
+			wr.own_work_time,
+			wr.study_time,
+			wr.testing_time,
+			wr.signed_by
+		FROM
+			weekly_reports wr
+		INNER JOIN
+			users u ON wr.user_id = u.id
+		INNER JOIN
+			projects p ON wr.project_id = p.id
+		WHERE
+			u.username = ? AND p.name = ?
+	`
+
+	var reports []types.WeeklyReportList
+	if err := d.Select(&reports, query, username, projectName); err != nil {
+		return nil, err
+	}
+
+	return reports, nil
+}
+
 // MigrateSampleData applies sample data to the database.
 func (d *Db) MigrateSampleData() error {
 	// Insert sample data
diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go
index a7f3878..a6009cf 100644
--- a/backend/internal/database/db_test.go
+++ b/backend/internal/database/db_test.go
@@ -566,3 +566,42 @@ func TestGetProject(t *testing.T) {
 		t.Errorf("Expected Name to be testproject, got %s", project.Name)
 	}
 }
+
+func TestGetWeeklyReportsUser(t *testing.T) {
+	db, err := setupState()
+	if err != nil {
+		t.Error("setupState failed:", err)
+	}
+
+	err = db.AddUser("testuser", "password")
+	if err != nil {
+		t.Error("AddUser failed:", err)
+	}
+
+	err = db.AddProject("testproject", "description", "testuser")
+	if err != nil {
+		t.Error("AddProject failed:", err)
+	}
+
+	err = db.AddWeeklyReport("testproject", "testuser", 1, 1, 1, 1, 1, 1, 1)
+	if err != nil {
+		t.Error("AddWeeklyReport failed:", err)
+	}
+
+	err = db.AddWeeklyReport("testproject", "testuser", 2, 1, 1, 1, 1, 1, 1)
+	if err != nil {
+		t.Error("AddWeeklyReport failed:", err)
+	}
+
+	reports, err := db.GetWeeklyReportsUser("testuser", "testproject")
+	if err != nil {
+		t.Error("GetWeeklyReportsUser failed:", err)
+	}
+
+	// Check if the retrieved reports match the expected values
+	if len(reports) != 2 {
+		t.Errorf("Expected 1 report, got %d", len(reports))
+	}
+
+	// You can add further checks here if needed
+}
diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go
index 932451d..0d041b0 100644
--- a/backend/internal/handlers/global_state.go
+++ b/backend/internal/handlers/global_state.go
@@ -20,6 +20,7 @@ type GlobalState interface {
 	GetProject(c *fiber.Ctx) error
 	AddUserToProjectHandler(c *fiber.Ctx) error
 	PromoteToAdmin(c *fiber.Ctx) error
+	GetWeeklyReportsUserHandler(c *fiber.Ctx) error
 	// GetProject(c *fiber.Ctx) error           // To get a specific project
 	// UpdateProject(c *fiber.Ctx) error        // To update a project
 	// DeleteProject(c *fiber.Ctx) error        // To delete a project
diff --git a/backend/internal/handlers/handlers_report_related.go b/backend/internal/handlers/handlers_report_related.go
index 85eb6e2..b745400 100644
--- a/backend/internal/handlers/handlers_report_related.go
+++ b/backend/internal/handlers/handlers_report_related.go
@@ -114,3 +114,22 @@ func (gs *GState) SignReport(c *fiber.Ctx) error {
 
 	return c.Status(200).SendString("Weekly report signed successfully")
 }
+
+// GetWeeklyReportsUserHandler retrieves all weekly reports for a user in a specific project
+func (gs *GState) GetWeeklyReportsUserHandler(c *fiber.Ctx) error {
+	// Extract necessary parameters from the request
+	username := c.Params("username")
+	projectName := c.Params("projectName")
+
+	// Retrieve weekly reports for the user in the project from the database
+	reports, err := gs.Db.GetWeeklyReportsUser(username, projectName)
+	if err != nil {
+		log.Info("Error getting weekly reports for user:", err)
+		return c.Status(500).SendString(err.Error())
+	}
+
+	log.Info("Returning weekly reports for user:", username, "in project:", projectName)
+
+	// Return the list of reports as JSON
+	return c.JSON(reports)
+}
diff --git a/backend/internal/types/WeeklyReport.go b/backend/internal/types/WeeklyReport.go
index 299395a..8d22b6a 100644
--- a/backend/internal/types/WeeklyReport.go
+++ b/backend/internal/types/WeeklyReport.go
@@ -20,6 +20,27 @@ type NewWeeklyReport struct {
 	TestingTime int `json:"testingTime"`
 }
 
+type WeeklyReportList struct {
+	// The name of the project, as it appears in the database
+	ProjectName string `json:"projectName" db:"project_name"`
+	// The week number
+	Week int `json:"week" db:"week"`
+	// Total time spent on development
+	DevelopmentTime int `json:"developmentTime" db:"development_time"`
+	// Total time spent in meetings
+	MeetingTime int `json:"meetingTime" db:"meeting_time"`
+	// Total time spent on administrative tasks
+	AdminTime int `json:"adminTime" db:"admin_time"`
+	// Total time spent on personal projects
+	OwnWorkTime int `json:"ownWorkTime" db:"own_work_time"`
+	// Total time spent on studying
+	StudyTime int `json:"studyTime" db:"study_time"`
+	// Total time spent on testing
+	TestingTime int `json:"testingTime" db:"testing_time"`
+	// The project manager who signed it
+	SignedBy *int `json:"signedBy" db:"signed_by"`
+}
+
 type WeeklyReport struct {
 	// The ID of the report
 	ReportId int `json:"reportId" db:"report_id"`
diff --git a/backend/main.go b/backend/main.go
index e578c52..900e1bd 100644
--- a/backend/main.go
+++ b/backend/main.go
@@ -94,6 +94,8 @@ func main() {
 	server.Put("/api/addUserToProject", gs.AddUserToProjectHandler)
 	server.Post("/api/promoteToAdmin", gs.PromoteToAdmin)
 	server.Get("/api/users/all", gs.ListAllUsers)
+	server.Get("/api/getWeeklyReportsUser", gs.GetWeeklyReportsUserHandler)
+
 	// Announce the port we are listening on and start the server
 	err = server.Listen(fmt.Sprintf(":%d", conf.Port))
 	if err != nil {
diff --git a/testing.py b/testing.py
index a3de715..6b262fe 100644
--- a/testing.py
+++ b/testing.py
@@ -37,6 +37,7 @@ signReportPath = base_url + "/api/signReport"
 addUserToProjectPath = base_url + "/api/addUserToProject"
 promoteToAdminPath = base_url + "/api/promoteToAdmin"
 getUserProjectsPath = base_url + "/api/getUserProjects"
+getWeeklyReportsUserPath = base_url + "/api/getWeeklyReportsUser"
 
 
 def test_get_user_projects():
@@ -275,6 +276,22 @@ def test_sign_report():
     dprint(response.text)
     gprint("test_sign_report successful")
 
+# Test function to get weekly reports for a user in a project
+def test_get_weekly_reports_user():
+    # Log in as the user
+    token = login(username, "always_same").json()["token"]
+
+    # Get weekly reports for the user in the project
+    response = requests.get(
+        getWeeklyReportsUserPath,
+        headers={"Authorization": "Bearer " + token},
+        params={"username": username, "projectName": projectName},
+    )
+    
+    dprint(response.text)
+    assert response.status_code == 200, "Get weekly reports for user failed"
+    gprint("test_get_weekly_reports_user successful")
+
 
 if __name__ == "__main__":
     test_get_user_projects()
@@ -286,3 +303,4 @@ if __name__ == "__main__":
     test_get_project()
     test_sign_report()
     test_add_user_to_project()
+    test_get_weekly_reports_user()