diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index fd8297f..f871755 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -40,8 +40,7 @@ type Database interface { IsSiteAdmin(username string) (bool, error) IsProjectManager(username string, projectname string) (bool, error) GetProjectTimes(projectName string) (map[string]int, error) - - + UpdateWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error } // This struct is a wrapper type that holds the database connection @@ -454,6 +453,26 @@ func (d *Db) IsProjectManager(username string, projectname string) (bool, error) return manager, err } +func (d *Db) UpdateWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error { + query := ` + UPDATE weekly_reports + SET + development_time = ?, + meeting_time = ?, + admin_time = ?, + own_work_time = ?, + study_time = ?, + testing_time = ? + WHERE + user_id = (SELECT id FROM users WHERE username = ?) + AND project_id = (SELECT id FROM projects WHERE name = ?) + AND week = ? + ` + + _, err := d.Exec(query, developmentTime, meetingTime, adminTime, ownWorkTime, studyTime, testingTime, userName, projectName, week) + return err +} + // MigrateSampleData applies sample data to the database. func (d *Db) MigrateSampleData() error { // Insert sample data @@ -495,34 +514,34 @@ func (d *Db) MigrateSampleData() error { // GetProjectTimes retrieves a map with times per "Activity" for a given project func (d *Db) GetProjectTimes(projectName string) (map[string]int, error) { - query := ` + query := ` SELECT development_time, meeting_time, admin_time, own_work_time, study_time, testing_time FROM weekly_reports JOIN projects ON weekly_reports.project_id = projects.id WHERE projects.name = ? ` - rows, err := d.DB.Query(query, projectName) - if err != nil { - return nil, err - } - defer rows.Close() + rows, err := d.DB.Query(query, projectName) + if err != nil { + return nil, err + } + defer rows.Close() totalTime := make(map[string]int) - for rows.Next() { - var developmentTime, meetingTime, adminTime, ownWorkTime, studyTime, testingTime int - if err := rows.Scan(&developmentTime, &meetingTime, &adminTime, &ownWorkTime, &studyTime, &testingTime); err != nil { - return nil, err - } + for rows.Next() { + var developmentTime, meetingTime, adminTime, ownWorkTime, studyTime, testingTime int + if err := rows.Scan(&developmentTime, &meetingTime, &adminTime, &ownWorkTime, &studyTime, &testingTime); err != nil { + return nil, err + } - totalTime["development"] += developmentTime - totalTime["meeting"] += meetingTime - totalTime["admin"] += adminTime - totalTime["own_work"] += ownWorkTime - totalTime["study"] += studyTime - totalTime["testing"] += testingTime - } + totalTime["development"] += developmentTime + totalTime["meeting"] += meetingTime + totalTime["admin"] += adminTime + totalTime["own_work"] += ownWorkTime + totalTime["study"] += studyTime + totalTime["testing"] += testingTime + } if err := rows.Err(); err != nil { return nil, err diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 442bf91..b68d446 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -729,90 +729,89 @@ func TestIsProjectManager(t *testing.T) { } } - func TestGetProjectTimes(t *testing.T) { - // Initialize - db, err := setupState() - if err != nil { - t.Error("setupState failed:", err) - return - } + // Initialize + db, err := setupState() + if err != nil { + t.Error("setupState failed:", err) + return + } - // Create a user - user := "TeaUser" - password := "Vanilla" - err = db.AddUser(user, password) - if err != nil { - t.Error("AddUser failed:", err) - return - } + // Create a user + user := "TeaUser" + password := "Vanilla" + err = db.AddUser(user, password) + if err != nil { + t.Error("AddUser failed:", err) + return + } - // Create a project - projectName := "ProjectVanilla" - projectDescription := "When tea tastes its best" - err = db.AddProject(projectName, projectDescription, user) // Fix the variable name here - if err != nil { - t.Error("AddProject failed:", err) - return - } + // Create a project + projectName := "ProjectVanilla" + projectDescription := "When tea tastes its best" + err = db.AddProject(projectName, projectDescription, user) // Fix the variable name here + if err != nil { + t.Error("AddProject failed:", err) + return + } - // Tests the func in db.go - totalTime, err := db.GetProjectTimes(projectName) - if err != nil { - t.Error("GetTotalTimePerActivity failed:", err) - return - } + // Tests the func in db.go + totalTime, err := db.GetProjectTimes(projectName) + if err != nil { + t.Error("GetTotalTimePerActivity failed:", err) + return + } - // Check if the totalTime map is not nil - if totalTime == nil { - t.Error("Expected non-nil totalTime map, got nil") - return - } + // Check if the totalTime map is not nil + if totalTime == nil { + t.Error("Expected non-nil totalTime map, got nil") + return + } - // Define the expected valeus - expectedTotalTime := map[string]int{ - "development": 0, - "meeting": 0, - "admin": 0, - "own_work": 0, - "study": 0, - "testing": 0, - } + // Define the expected valeus + expectedTotalTime := map[string]int{ + "development": 0, + "meeting": 0, + "admin": 0, + "own_work": 0, + "study": 0, + "testing": 0, + } - // Compare the expectedTotalTime with the totalTime retrieved from the database - for activity, expectedTime := range expectedTotalTime { - if totalTime[activity] != expectedTime { - t.Errorf("Expected %s time to be %d, got %d", activity, expectedTime, totalTime[activity]) - } - } + // Compare the expectedTotalTime with the totalTime retrieved from the database + for activity, expectedTime := range expectedTotalTime { + if totalTime[activity] != expectedTime { + t.Errorf("Expected %s time to be %d, got %d", activity, expectedTime, totalTime[activity]) + } + } - // Insert some data into the database for different activities - err = db.AddWeeklyReport(projectName, user, 1, 1, 3, 2, 1, 4, 5) - if err != nil { - t.Error("Failed to insert data into the database:", err) - return - } + // Insert some data into the database for different activities + err = db.AddWeeklyReport(projectName, user, 1, 1, 3, 2, 1, 4, 5) + if err != nil { + t.Error("Failed to insert data into the database:", err) + return + } newTotalTime, err := db.GetProjectTimes(projectName) - if err != nil { - t.Error("GetTotalTimePerActivity failed:", err) - return - } + if err != nil { + t.Error("GetTotalTimePerActivity failed:", err) + return + } newExpectedTotalTime := map[string]int{ - "development": 1, - "meeting": 3, - "admin": 2, - "own_work": 1, - "study": 4, - "testing": 5, - } + "development": 1, + "meeting": 3, + "admin": 2, + "own_work": 1, + "study": 4, + "testing": 5, + } for activity, newExpectedTime := range newExpectedTotalTime { - if newTotalTime[activity] != newExpectedTime { - t.Errorf("Expected %s time to be %d, got %d", activity, newExpectedTime, newTotalTime[activity]) - } - } + if newTotalTime[activity] != newExpectedTime { + t.Errorf("Expected %s time to be %d, got %d", activity, newExpectedTime, newTotalTime[activity]) + } + } } func TestEnsureManagerOfCreatedProject(t *testing.T) { db, err := setupState() @@ -847,3 +846,51 @@ func TestEnsureManagerOfCreatedProject(t *testing.T) { t.Error("Expected testuser to be a project manager, but it's not.") } } + +// TestUpdateWeeklyReport tests the UpdateWeeklyReport function of the database +func TestUpdateWeeklyReport(t *testing.T) { + db, err := setupState() + if err != nil { + t.Error("setupState failed:", err) + } + + // Add a user + err = db.AddUser("testuser", "password") + if err != nil { + t.Error("AddUser failed:", err) + } + + // Add a project + err = db.AddProject("testproject", "description", "testuser") + if err != nil { + t.Error("AddProject failed:", err) + } + + // Add a weekly report + err = db.AddWeeklyReport("testproject", "testuser", 1, 1, 1, 1, 1, 1, 1) + if err != nil { + t.Error("AddWeeklyReport failed:", err) + } + + // Update the weekly report + err = db.UpdateWeeklyReport("testproject", "testuser", 1, 2, 2, 2, 2, 2, 2) + if err != nil { + t.Error("UpdateWeeklyReport failed:", err) + } + + // Retrieve the updated report + updatedReport, err := db.GetWeeklyReport("testuser", "testproject", 1) + if err != nil { + t.Error("GetWeeklyReport failed:", err) + } + + // Check if the report was updated correctly + if updatedReport.DevelopmentTime != 2 || + updatedReport.MeetingTime != 2 || + updatedReport.AdminTime != 2 || + updatedReport.OwnWorkTime != 2 || + updatedReport.StudyTime != 2 || + updatedReport.TestingTime != 2 { + t.Error("UpdateWeeklyReport failed: report not updated correctly") + } +} diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index b88bdcd..49c8c09 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -28,6 +28,7 @@ type GlobalState interface { ProjectRoleChange(c *fiber.Ctx) error // To change a users role in a project ChangeUserName(c *fiber.Ctx) error // WIP GetAllUsersProject(c *fiber.Ctx) error // WIP + UpdateWeeklyReport(c *fiber.Ctx) error } // "Constructor" diff --git a/backend/internal/handlers/handlers_report_related.go b/backend/internal/handlers/handlers_report_related.go index fcba523..0e72ead 100644 --- a/backend/internal/handlers/handlers_report_related.go +++ b/backend/internal/handlers/handlers_report_related.go @@ -141,3 +141,37 @@ func (gs *GState) GetWeeklyReportsUserHandler(c *fiber.Ctx) error { // Return the list of reports as JSON return c.JSON(reports) } + +func (gs *GState) UpdateWeeklyReport(c *fiber.Ctx) error { + // Extract the necessary parameters from the token + user := c.Locals("user").(*jwt.Token) + claims := user.Claims.(jwt.MapClaims) + username := claims["name"].(string) + + // Parse the request body into an UpdateWeeklyReport struct + var updateReport types.UpdateWeeklyReport + if err := c.BodyParser(&updateReport); err != nil { + log.Info("Error parsing weekly report") + return c.Status(400).SendString(err.Error()) + } + + // Make sure all the fields of the report are valid + if updateReport.Week < 1 || updateReport.Week > 52 { + log.Info("Invalid week number") + return c.Status(400).SendString("Invalid week number") + } + + if updateReport.DevelopmentTime < 0 || updateReport.MeetingTime < 0 || updateReport.AdminTime < 0 || updateReport.OwnWorkTime < 0 || updateReport.StudyTime < 0 || updateReport.TestingTime < 0 { + log.Info("Invalid time report") + return c.Status(400).SendString("Invalid time report") + } + + // Update the weekly report in the database + if err := gs.Db.UpdateWeeklyReport(updateReport.ProjectName, username, updateReport.Week, updateReport.DevelopmentTime, updateReport.MeetingTime, updateReport.AdminTime, updateReport.OwnWorkTime, updateReport.StudyTime, updateReport.TestingTime); err != nil { + log.Info("Error updating weekly report in db:", err) + return c.Status(500).SendString(err.Error()) + } + + log.Info("Weekly report updated") + return c.Status(200).SendString("Weekly report updated") +} diff --git a/backend/internal/types/WeeklyReport.go b/backend/internal/types/WeeklyReport.go index 8d22b6a..234781b 100644 --- a/backend/internal/types/WeeklyReport.go +++ b/backend/internal/types/WeeklyReport.go @@ -65,3 +65,24 @@ type WeeklyReport struct { // The project manager who signed it SignedBy *int `json:"signedBy" db:"signed_by"` } + +type UpdateWeeklyReport struct { + // The name of the project, as it appears in the database + ProjectName string `json:"projectName"` + // The name of the user + UserName string `json:"userName"` + // The week number + Week int `json:"week"` + // Total time spent on development + DevelopmentTime int `json:"developmentTime"` + // Total time spent in meetings + MeetingTime int `json:"meetingTime"` + // Total time spent on administrative tasks + AdminTime int `json:"adminTime"` + // Total time spent on personal projects + OwnWorkTime int `json:"ownWorkTime"` + // Total time spent on studying + StudyTime int `json:"studyTime"` + // Total time spent on testing + TestingTime int `json:"testingTime"` +} diff --git a/backend/main.go b/backend/main.go index ff6b94e..b42bcab 100644 --- a/backend/main.go +++ b/backend/main.go @@ -101,6 +101,7 @@ func main() { server.Get("/api/checkIfProjectManager/:projectName", gs.IsProjectManagerHandler) server.Post("/api/ProjectRoleChange", gs.ProjectRoleChange) server.Get("/api/getUsersProject/:projectName", gs.ListAllUsersProject) + server.Put("/api/updateWeeklyReport", gs.UpdateWeeklyReport) // Announce the port we are listening on and start the server err = server.Listen(fmt.Sprintf(":%d", conf.Port)) diff --git a/testing.py b/testing.py index 6abd21d..3515720 100644 --- a/testing.py +++ b/testing.py @@ -42,6 +42,7 @@ checkIfProjectManagerPath = base_url + "/api/checkIfProjectManager" ProjectRoleChangePath = base_url + "/api/ProjectRoleChange" getUsersProjectPath = base_url + "/api/getUsersProject" getChangeUserNamePath = base_url + "/api/changeUserName" +getUpdateWeeklyReportPath = base_url + "/api/updateWeeklyReport" #ta bort auth i handlern för att få testet att gå igenom def test_ProjectRoleChange(): @@ -433,6 +434,34 @@ def test_list_all_users_project(): assert response.status_code == 200, "List all users project failed" gprint("test_list_all_users_project sucessful") +def test_update_weekly_report(): + # Log in as the user + token = login(username, "always_same").json()["token"] + + # Prepare the JSON data for updating the weekly report + update_data = { + "projectName": projectName, + "userName": username, + "week": 1, + "developmentTime": 8, + "meetingTime": 6, + "adminTime": 4, + "ownWorkTime": 11, + "studyTime": 8, + "testingTime": 18, + } + + # Send a request to update the weekly report + response = requests.put( + getUpdateWeeklyReportPath, + json=update_data, + headers={"Authorization": "Bearer " + token}, + ) + + # Check if the update was successful + assert response.status_code == 200, "Update weekly report failed" + gprint("test_update_weekly_report successful") + if __name__ == "__main__": test_get_user_projects() test_create_user() @@ -449,3 +478,4 @@ if __name__ == "__main__": test_ensure_manager_of_created_project() test_list_all_users_project() test_change_user_name() + test_update_weekly_report() \ No newline at end of file