diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index 6ee275a..b5170b3 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -46,6 +46,7 @@ type Database interface { RemoveProject(projectname string) error GetUserName(id int) (string, error) UnsignWeeklyReport(reportId int, projectManagerId int) error + DeleteReport(reportID int) error } // This struct is a wrapper type that holds the database connection @@ -654,3 +655,8 @@ func (d *Db) GetUserName(id int) (string, error) { err := d.Get(&username, "SELECT username FROM users WHERE id = ?", id) return username, err } + +func (d *Db) DeleteReport(reportID int) error { + _, err := d.Exec("DELETE FROM weekly_reports WHERE report_id = ?", reportID) + return err +} diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 1c93baf..b5a598c 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -1052,3 +1052,41 @@ func TestRemoveProject(t *testing.T) { } } + +func TestDeleteReport(t *testing.T) { + db, err := setupAdvancedState() + if err != nil { + t.Error("setupState failed:", err) + } + + // Promote user to Admin + err = db.PromoteToAdmin("demouser") + if err != nil { + t.Error("PromoteToAdmin failed:", err) + } + + // create a weekly report + err = db.AddWeeklyReport("projecttest", "demouser", 16, 1, 1, 1, 1, 1, 1) + if err != nil { + t.Error("AddWeeklyReport failed:", err) + } + + // Check if the report was added + report, err := db.GetWeeklyReport("demouser", "projecttest", 16) + if err != nil { + t.Error("GetWeeklyReport failed:", err) + } + + // Remove report + err = db.DeleteReport(report.ReportId,) + if err != nil { + t.Error("RemoveReport failed:", err) + } + + // Check if the report was removed + report, err = db.GetWeeklyReport("demouser", "projecttest", 16) + if err == nil { + t.Error("RemoveReport failed: report not removed") + } + +} diff --git a/backend/internal/handlers/reports/DeleteReport.go b/backend/internal/handlers/reports/DeleteReport.go new file mode 100644 index 0000000..b3ae7de --- /dev/null +++ b/backend/internal/handlers/reports/DeleteReport.go @@ -0,0 +1,22 @@ +package reports + +import ( + "strconv" + db "ttime/internal/database" + + "github.com/gofiber/fiber/v2" +) + +func DeleteReport(c *fiber.Ctx) error { + reportID := c.Params("reportID") + reportIDInt, err := strconv.Atoi(reportID) + if err != nil { + return c.Status(400).SendString("Invalid report ID") + } + + if err := db.GetDb(c).DeleteReport(reportIDInt); err != nil { + return c.Status(500).SendString((err.Error())) + } + + return c.Status(200).SendString("Weekly report deleted") +} diff --git a/backend/main.go b/backend/main.go index 8fe7d1d..dbf5151 100644 --- a/backend/main.go +++ b/backend/main.go @@ -136,6 +136,7 @@ func main() { api.Put("/signReport/:reportId", reports.SignReport) api.Put("/updateWeeklyReport", reports.UpdateWeeklyReport) api.Put("/unsignReport/:reportId", reports.UnsignReport) + api.Delete("/deleteReport/:reportId", reports.DeleteReport) // Announce the port we are listening on and start the server err = server.Listen(fmt.Sprintf(":%d", conf.Port)) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 64bfd2e..de5f19d 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -248,6 +248,16 @@ interface API { * @param {string} token Your token */ getUsername(id: number, token: string): Promise>; + + /** + * Deletes a WeeklyReport from the database + * @param {number} reportId The id of the report to delete + * @param {string} token The authentication token + */ + deleteWeeklyReport( + reportId: number, + token: string, + ): Promise>; } /** An instance of the API */ @@ -929,4 +939,27 @@ export const api: API = { return { success: false, message: "Failed to get username" }; } }, + + async deleteWeeklyReport( + reportId: number, + token: string, + ): Promise> { + try { + const response = await fetch(`/api/deleteReport/${reportId}`, { + method: "DELETE", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + }); + + if (!response.ok) { + return { success: false, message: "Failed to delete report" }; + } else { + return { success: true, message: "Report deleted" }; + } + } catch (e) { + return { success: false, message: "Failed to delete report" }; + } + }, }; diff --git a/testing/helpers.py b/testing/helpers.py index 6436922..7269260 100644 --- a/testing/helpers.py +++ b/testing/helpers.py @@ -35,6 +35,7 @@ getUpdateWeeklyReportPath = base_url + "/api/updateWeeklyReport" removeProjectPath = base_url + "/api/removeProject" promoteToPmPath = base_url + "/api/promoteToPm" unsignReportPath = base_url + "/api/unsignReport" +deleteReportPath = base_url + "/api/deleteReport" debug_output = False @@ -156,3 +157,8 @@ def unsignReport(project_manager_token: string, report_id: int): unsignReportPath + "/" + str(report_id), headers={"Authorization": "Bearer " + project_manager_token}, ) + +def deleteReport(report_id: int): + return requests.delete( + deleteReportPath + "/" + str(report_id), + ) diff --git a/testing/testing.py b/testing/testing.py index c3c987c..5eedc28 100644 --- a/testing/testing.py +++ b/testing/testing.py @@ -557,8 +557,74 @@ def test_promote_to_manager(): response = promoteToManager(pm_token, member_user, project_name) assert response.status_code == 200, "Promote to manager failed" +def test_delete_report(): + # Create admin + admin_username = randomString() + admin_password = "admin_password2" + dprint( + "Registering with username: ", admin_username, " and password: ", admin_password + ) + response = requests.post( + registerPath, json={"username": admin_username, "password": admin_password} + ) + dprint(response.text) + + # Log in as the admin + admin_token = login(admin_username, admin_password).json()["token"] + response = requests.post( + promoteToAdminPath, + json={"username": admin_username}, + headers={"Authorization": "Bearer " + admin_token}, + ) + + # Create a new project + new_project = randomString() + response = requests.post( + addProjectPath, + json={"name": new_project, "description": "This is a project"}, + headers={"Authorization": "Bearer " + admin_token}, + ) + assert response.status_code == 200, "Add project failed" + + # Create a new report + new_report = { + "projectName": new_project, + "week": 1, + "developmentTime": 10, + "meetingTime": 5, + "adminTime": 5, + "ownWorkTime": 10, + "studyTime": 10, + "testingTime": 10, + } + response = submitReport(admin_token, new_report); + assert response.status_code == 200, "Submit report failed" + + # Get the report ID + report_id = getReport(admin_token, admin_username, new_project)["reportId"] + assert report_id != None, "Get report failed" + + # Delete the report + response = requests.delete( + deleteReportPath + "/" + str(report_id), + headers={"Authorization": "Bearer " + admin_token}, + ) + assert response.status_code == 200, "Delete report failed" + + # Check if the report was deleted + response = requests.get( + getWeeklyReportPath, + headers={"Authorization": "Bearer " + admin_token}, + params={"username": admin_username, "projectName": new_project, "week": 1}, + ) + assert response.status_code == 500, "Report was not deleted" + + gprint("test_delete_report successful") + + if __name__ == "__main__": + test_delete_report() test_unsign_report() test_promote_to_manager() test_remove_project()