use argon2::Params; use axum::{extract::{ws::{close_code::STATUS, Message}, Path, State}, http::StatusCode, response::IntoResponse}; use rusqlite::params; use serde::Serialize; use serde_json::json; use crate::utils::{auth::AuthClaims, db_pool::AppState}; pub async fn create_inventory_item( State(state): State, Path((item_name, item_amount)): Path<(String, i32)>, AuthClaims{ user_id, hotel_id}: AuthClaims, ) -> impl IntoResponse { let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get(){ Ok(conn) => conn, Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("couldn't open the connection")) }; let result = conn.execute( "INSERT INTO inventory (item_name, amount, user_id) VALUES (?1, ?2, ?3)", params![&item_name,&item_amount,&user_id] ); match result { Ok(rows) => (StatusCode::OK, format!("inserted item {item_name}, with {item_amount} amount")), Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("couldn't add the new item, err: {}", err )) } } #[derive(Serialize)] pub struct InventoryItems { id: i32, amount: i32, name: String, user_id: i32, updated_at: String, } pub async fn update_inventory_item( State(state): State, Path((item_id, item_amount)): Path<(i32, i32)>, AuthClaims { user_id, hotel_id }: AuthClaims, ) -> impl IntoResponse { //TODO: make better error handling : // if wrong param collumn targeted, // if missing path param let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get(){ Ok(conn) => conn, Err(err) => return (StatusCode::INTERNAL_SERVER_ERROR, format!("Pool error: {err}")), }; let result: Result = conn.query_row( "UPDATE inventory SET amount = ?1, user_id=?3 WHERE id = ?2 RETURNING item_name", params![&item_amount, &item_id, &user_id], |row| row.get(0), ); match result { Ok(item_name) => { if let Err(err) = conn.execute( "INSERT INTO inventory_history (item_id, amount, item_name, user_id) VALUES (?1,?2,?3,?4)", params![&item_id,&item_amount,&item_name, &user_id] ){ return (StatusCode::INTERNAL_SERVER_ERROR, format!("failed to update inventory history")); } if let Some(hotel_users) = state.ws_map.get(&hotel_id) { let update_msg = json!({ "event_type": "item_update", "item_id": item_id, "number": item_amount, "updated_by": user_id, }) .to_string(); for entry in hotel_users.iter() { let sender = entry.value(); // ignore errors (client disconnected) let _ = sender.send(Message::Text(update_msg.clone().into())); } } (StatusCode::OK, format!("updated item history")) } Ok(_) => (StatusCode::NOT_FOUND, "No item found, err : {_}".to_string()), Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("Error from DB: {err}")), } /* match result { Ok(row) => (StatusCode::OK, format!("Items updated")), Ok(_) => (StatusCode::NOT_FOUND, format!("No item with this id exist")), Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, format!("error updating the item with id :{} with amount: {}", item_id, item_amount)) } */ } pub async fn get_inventory_item( State(state): State, AuthClaims { user_id, hotel_id }: AuthClaims, ) -> impl IntoResponse { let pool = state.hotel_pools.get_pool(hotel_id); let conn = match pool.get() { Ok(c) => c, Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Pool error".to_string()), }; let mut stmt = match conn.prepare("SELECT id, amount, item_name, user_id, updated_at FROM inventory") { Ok(s) => s, Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Statement error".to_string()), }; let mut query_result = match stmt.query([]) { Ok(r) => r, Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Query error".to_string()), }; let mut items = Vec::new(); while let Ok(Some(row)) = query_result.next() { let item = InventoryItems { id: row.get("id").unwrap_or_default(), amount: row.get("amount").unwrap_or_default(), name: row.get("item_name").unwrap_or_default(), user_id: row.get("user_id").unwrap_or_default(), updated_at: row.get("updated_at").unwrap_or_default(), }; items.push(item); } // Serialize to JSON let json = match serde_json::to_string(&items) { Ok(j) => j, Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, "Serialization error".to_string()), }; (StatusCode::OK, json) }