api/routes/modules/assignments/delete.rs
1//! Assignment deletion routes.
2//!
3//! Provides endpoints for deleting single or multiple assignments within a module.
4//!
5//! - `DELETE /api/modules/{module_id}/assignments/{assignment_id}`
6//! Deletes a single assignment along with its associated files and folder.
7//!
8//! - `DELETE /api/modules/{module_id}/assignments/bulk`
9//! Deletes multiple assignments in a module using a JSON array of assignment IDs.
10//!
11//! **Access Control:** Only lecturers or admins assigned to the module can perform deletions.
12//!
13//! **Responses:** JSON-wrapped `ApiResponse` indicating success, number of deletions, or detailed errors.
14
15use axum::{
16 extract::{State, Path},
17 http::StatusCode,
18 response::IntoResponse,
19 Json,
20};
21use sqlx::types::JsonValue;
22use serde_json::json;
23use db::models::assignment;
24use util::state::AppState;
25use crate::response::ApiResponse;
26use super::common::BulkDeleteRequest;
27
28/// DELETE /api/modules/:module_id/assignments/:assignment_id
29///
30/// Delete a specific assignment and its associated files and folder.
31/// Only accessible by lecturers or admins assigned to the module.
32///
33/// ### Path Parameters
34/// - `module_id` (i64): The ID of the module containing the assignment
35/// - `assignment_id` (i64): The ID of the assignment to delete
36///
37/// ### Responses
38///
39/// - `200 OK`
40/// ```json
41/// {
42/// "success": true,
43/// "message": "Assignment 123 deleted successfully"
44/// }
45/// ```
46///
47/// - `404 Not Found`
48/// ```json
49/// {
50/// "success": false,
51/// "message": "No assignment found with ID 123 in module 456"
52/// }
53/// ```
54///
55/// - `500 Internal Server Error`
56/// ```json
57/// {
58/// "success": false,
59/// "message": "Database error details"
60/// }
61/// ```
62pub async fn delete_assignment(
63 State(app_state): State<AppState>,
64 Path((module_id, assignment_id)): Path<(i64, i64)>,
65) -> impl IntoResponse {
66 let db = app_state.db();
67
68 match assignment::Model::delete(db, assignment_id as i32, module_id as i32).await {
69 Ok(()) => (
70 StatusCode::OK,
71 Json(json!({
72 "success": true,
73 "message": format!("Assignment {} deleted successfully", assignment_id),
74 })),
75 ),
76 Err(e) => (
77 StatusCode::INTERNAL_SERVER_ERROR,
78 Json(json!({
79 "success": false,
80 "message": e.to_string(),
81 })),
82 ),
83 }
84}
85
86/// DELETE /api/modules/:module_id/assignments/bulk
87///
88/// Bulk delete multiple assignments by ID within a module.
89/// Only accessible by lecturers or admins assigned to the module.
90///
91/// ### Path Parameters
92/// - `module_id` (i64): The ID of the module containing the assignments
93///
94/// ### Request Body (JSON)
95/// ```json
96/// {
97/// "assignment_ids": [123, 124, 125]
98/// }
99/// ```
100///
101/// ### Success Response (200 OK)
102/// ```json
103/// {
104/// "success": true,
105/// "data": {
106/// "deleted": 2,
107/// "failed": [
108/// { "id": 125, "error": "Assignment 125 in module 1 not found" }
109/// ]
110/// },
111/// "message": "Deleted 2/3 assignments"
112/// }
113/// ```
114pub async fn bulk_delete_assignments(
115 State(app_state): State<AppState>,
116 Path(module_id): Path<i64>,
117 Json(req): Json<BulkDeleteRequest>,
118) -> impl IntoResponse {
119 let db = app_state.db();
120
121 if req.assignment_ids.is_empty() {
122 return (
123 StatusCode::BAD_REQUEST,
124 Json(ApiResponse::<JsonValue>::error("No assignment IDs provided")),
125 );
126 }
127
128 let mut deleted_count = 0;
129 let mut failed: Vec<JsonValue> = Vec::new();
130
131 for &id in &req.assignment_ids {
132 match assignment::Model::delete(db, id as i32, module_id as i32).await {
133 Ok(_) => deleted_count += 1,
134 Err(e) => {
135 failed.push(json!({
136 "id": id,
137 "error": e.to_string()
138 }));
139 }
140 }
141 }
142
143 let message = format!(
144 "Deleted {}/{} assignments",
145 deleted_count,
146 req.assignment_ids.len()
147 );
148
149 let data = json!({
150 "deleted": deleted_count,
151 "failed": failed
152 });
153
154 let response = ApiResponse::success(data, message);
155
156 (
157 StatusCode::OK,
158 Json(response),
159 )
160}