1use std::sync::Arc;
2
3use axum::{
4 Extension, Json,
5 extract::{Path, State},
6 http::StatusCode,
7 response::IntoResponse,
8};
9use serde_json::json;
10use sqlx::{Row, query};
11
12use crate::{
13 AppState,
14 models::{FilteredUser, TicketCreateScheme, TicketResponse, TicketUpdateScheme},
15};
16
17pub async fn create_ticket(
37 Extension(user): Extension<FilteredUser>,
38 State(data): State<Arc<AppState>>,
39 Json(body): Json<TicketCreateScheme>,
40) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
41 let query = query(
42 r#"INSERT INTO tickets (category, description, betreff, room, user_id) VALUES ($1, $2, $3, $4, $5)"#,
43 )
44 .bind(body.category.to_string())
45 .bind(body.description.to_string())
46 .bind(body.betreff.to_string())
47 .bind(body.room)
48 .bind(user.id)
49 .execute(&data.db)
50 .await;
51
52 if let Err(err) = query {
53 return Err((
54 StatusCode::INTERNAL_SERVER_ERROR,
55 Json(json!({"status": "error", "message": format!("{:?}", err),})),
56 ));
57 }
58
59 let response_status = serde_json::json!({"status": "success"});
60 Ok(Json(response_status))
61}
62
63pub async fn delete_ticket(
76 Path(id): Path<i32>,
77 State(data): State<Arc<AppState>>,
78) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
79 let query = sqlx::query(r#"DELETE FROM tickets WHERE id = $1"#)
80 .bind(id)
81 .execute(&data.db)
82 .await
83 .map_err(|e| {
84 (
85 StatusCode::INTERNAL_SERVER_ERROR,
86 Json(json!({"status": "error", "message": format!("{:?}", e)})),
87 )
88 })?;
89
90 if query.rows_affected() == 0 {
91 let error_response = serde_json::json!({
92 "status": "error",
93 "message": format!("Ticket with ID {} not found", id)
94 });
95 return Err((StatusCode::NOT_FOUND, Json(error_response)));
96 }
97
98 Ok(StatusCode::NO_CONTENT)
99}
100
101pub async fn get_tickets(
135 State(data): State<Arc<AppState>>,
136) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
137 let tickets = sqlx::query(
139 r#"SELECT t.id, t.category, t.betreff, t.description, t.room, t.status, t.date, t.user_id, u.first_name, u.last_name
140 FROM tickets t
141 LEFT JOIN users u ON t.user_id = u.id
142 ORDER BY t.date DESC"#,
143 )
144 .fetch_all(&data.db)
145 .await
146 .map_err(|e| {
147 let error_response = serde_json::json!({
148 "status": "error",
149 "message": format!("Database error: {}", e),
150 });
151 (StatusCode::INTERNAL_SERVER_ERROR, Json(error_response))
152 })?;
153
154 let ticket_response: Vec<TicketResponse> = tickets
156 .iter()
157 .map(|row| TicketResponse {
158 id: row.get("id"),
159 category: row.get("category"),
160 betreff: row.get("betreff"),
161 description: row.get("description"),
162 room: row.get("room"),
163 status: row.get("status"),
164 date: row.get("date"),
165 user_id: row.get("user_id"),
166 user_first_name: row.get("first_name"),
167 user_last_name: row.get("last_name"),
168 })
169 .collect();
170
171 let json_response = serde_json::json!(ticket_response);
172 Ok(Json(json_response))
173}
174
175pub async fn get_ticket_by_id(
205 Path(id): Path<i32>,
206 State(data): State<Arc<AppState>>,
207) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
208 let query = sqlx::query(
209 r#"SELECT t.id, t.category, t.betreff, t.description, t.room, t.status, t.date, t.user_id, u.first_name, u.last_name
210 FROM tickets t
211 LEFT JOIN users u ON t.user_id = u.id
212 WHERE t.id = $1"#,
213 )
214 .bind(id)
215 .fetch_one(&data.db)
216 .await;
217
218 match query {
219 Ok(row) => {
220 let ticket_response = TicketResponse {
221 id: row.get("id"),
222 category: row.get("category"),
223 betreff: row.get("betreff"),
224 description: row.get("description"),
225 room: row.get("room"),
226 status: row.get("status"),
227 date: row.get("date"),
228 user_id: row.get("user_id"),
229 user_first_name: row.get("first_name"),
230 user_last_name: row.get("last_name"),
231 };
232 let response = serde_json::json!(ticket_response);
233 return Ok(Json(response));
234 }
235 Err(sqlx::Error::RowNotFound) => {
236 let error_response = serde_json::json!({
237 "status": "fail",
238 "message": format!("Ticket with ID {} not found", id)
239 });
240 return Err((StatusCode::NOT_FOUND, Json(error_response)));
241 }
242 Err(e) => {
243 return Err((
244 StatusCode::INTERNAL_SERVER_ERROR,
245 Json(json!({"status": "error", "message": format!("{:?}", e)})),
246 ));
247 }
248 };
249}
250
251pub async fn edit_ticket(
271 Path(id): Path<i32>,
272 State(data): State<Arc<AppState>>,
273 Json(body): Json<TicketUpdateScheme>,
274) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
275 let update_result = sqlx::query(r#"UPDATE tickets SET status = $1 WHERE id = $2"#)
277 .bind(body.status.to_owned())
278 .bind(id)
279 .execute(&data.db)
280 .await
281 .map_err(|e| {
282 (
283 StatusCode::INTERNAL_SERVER_ERROR,
284 Json(json!({"status": "error", "message": format!("{:?}", e)})),
285 )
286 })?;
287
288 if update_result.rows_affected() == 0 {
289 let error_response = serde_json::json!({
290 "status": "error",
291 "message": format!("Ticket with ID {} not found", id)
292 });
293 return Err((StatusCode::INTERNAL_SERVER_ERROR, Json(error_response)));
294 }
295
296 let updated_ticket = sqlx::query(
298 r#"SELECT t.id, t.category, t.betreff, t.description, t.room, t.status, t.date, t.user_id, u.first_name, u.last_name
299 FROM tickets t
300 LEFT JOIN users u ON t.user_id = u.id
301 WHERE t.id = $1"#,
302 )
303 .bind(id)
304 .fetch_one(&data.db)
305 .await
306 .map_err(|e| {
307 (
308 StatusCode::INTERNAL_SERVER_ERROR,
309 Json(json!({"status": "error", "message": format!("{:?}", e)})),
310 )
311 })?;
312
313 let ticket_response = TicketResponse {
314 id: updated_ticket.get("id"),
315 category: updated_ticket.get("category"),
316 betreff: updated_ticket.get("betreff"),
317 description: updated_ticket.get("description"),
318 room: updated_ticket.get("room"),
319 status: updated_ticket.get("status"),
320 date: updated_ticket.get("date"),
321 user_id: updated_ticket.get("user_id"),
322 user_first_name: updated_ticket.get("first_name"),
323 user_last_name: updated_ticket.get("last_name"),
324 };
325
326 let response = serde_json::json!({
327 "ticket": ticket_response,
328 "status": "success"
329 });
330
331 Ok(Json(response))
332}