Files
hotel_api/src/inventory/handler.rs

158 lines
5.0 KiB
Rust

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<AppState>,
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<AppState>,
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<String, rusqlite::Error> = 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<AppState>,
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)
}