use actix_web::{HttpResponse, Responder, Result, post, web}; use serde::Deserialize; use utoipa::ToSchema; use crate::{ app::App, storage::sql::{ barcode::Barcode, insert::Operations, product::{Product, ProductId, ProductIdStub}, unit::Unit, }, }; #[derive(Deserialize, ToSchema)] struct ProductStub { name: String, description: Option, parent: Option, } /// Register a product #[utoipa::path( responses( ( status = 200, description = "Product successfully registered in database", body = ProductId, ), ( status = INTERNAL_SERVER_ERROR, description = "Server encountered error", body = String, ) ), request_body = ProductStub, )] #[post("/product/new")] pub(crate) async fn register_product( app: web::Data, product_stub: web::Json, ) -> Result { let mut ops = Operations::new("register product"); let product = Product::register( product_stub.name.clone(), product_stub.description.clone(), product_stub.parent, &mut ops, ); ops.apply(&app).await?; Ok(HttpResponse::Ok().json(product.id)) } /// Associate a barcode with a product #[utoipa::path( responses( ( status = OK, description = "Barcode successfully associated with product", ), ( status = NOT_FOUND, description = "Product id not found in database", ), ( status = FORBIDDEN, description = "Unit used in request has not been registered yet", body = String, ), ( status = INTERNAL_SERVER_ERROR, description = "Server encountered error", body = String, ) ), params ( ("id" = ProductId, description = "The id of the product to associated the barcode with"), ), request_body = Barcode, )] #[post("/product/{id}/associate")] pub(crate) async fn associate_barcode( app: web::Data, id: web::Path, barcode: web::Json, ) -> Result { let mut ops = Operations::new("associated barcode with product"); { let units = Unit::get_all(&app).await?; if !units.into_iter().any(|unit| unit.id == barcode.amount.unit) { return Ok(HttpResponse::Forbidden() .body("The used unit has not been registered; it cannot be used.\n")); } } match Product::from_id(&app, id.into_inner().into()).await? { Some(product) => { product.associate_barcode(barcode.into_inner(), &mut ops); ops.apply(&app).await?; Ok(HttpResponse::Ok().finish()) } None => Ok(HttpResponse::NotFound().finish()), } }