use actix_web::{HttpResponse, Responder, Result, get, web}; use crate::{ app::App, storage::sql::product::{Product, ProductId, ProductIdStub}, }; /// Get Product by id #[utoipa::path( responses( (status = OK, description = "Product found from database", body = Product), (status = NOT_FOUND, description = "Product not found in database"), (status = INTERNAL_SERVER_ERROR, description = "Server encountered error", body = String) ), params( ("id" = ProductId, description = "Product id" ), ) )] #[get("/product/by-id/{id}")] pub(crate) async fn product_by_id( app: web::Data, id: web::Path, ) -> Result { let id = id.into_inner(); match Product::from_id(&app, id.into()).await? { Some(product) => Ok(HttpResponse::Ok().json(product)), None => Ok(HttpResponse::NotFound().finish()), } } /// Get Product by name #[utoipa::path( responses( (status = OK, description = "Product found from database", body = Product), (status = NOT_FOUND, description = "Product not found in database"), (status = INTERNAL_SERVER_ERROR, description = "Server encountered error", body = String) ), params( ("name" = String, description = "Name of the product" ), ) )] // TODO: Html decode the name, before use. Otherwise `Milk 2` will not work, as it is send as // `Milk+2` <2025-10-21> #[get("/product/by-name/{name}")] pub(crate) async fn product_by_name( app: web::Data, name: web::Path, ) -> Result { let name = name.into_inner(); match Product::from_name(&app, name).await? { Some(product) => Ok(HttpResponse::Ok().json(product)), None => Ok(HttpResponse::NotFound().finish()), } } /// Get Product suggestion by name #[utoipa::path( responses( (status = OK, description = "Product suggestions found from database", body = Vec), (status = INTERNAL_SERVER_ERROR, description = "Server encountered error", body = String) ), params( ("name" = String, description = "Partial name of a product" ), ) )] #[get("/product/by-part-name/{name}")] pub(crate) async fn product_suggestion_by_name( app: web::Data, name: web::Path, ) -> Result { let name = name.into_inner(); let all = Product::get_all(&app).await?; let matching = all .into_iter() .filter(|product| product.name.starts_with(name.as_str())) .collect::>(); Ok(HttpResponse::Ok().json(matching)) } /// Return all registered products #[utoipa::path( responses( (status = OK, description = "All products founds", body = Vec), (status = INTERNAL_SERVER_ERROR, description = "Server encountered error", body = String) ), )] #[get("/products/")] pub(crate) async fn products(app: web::Data) -> Result { let all = Product::get_all(&app).await?; Ok(HttpResponse::Ok().json(all)) }