From d8c29e1ec80beafe0bd196b7795e4c15cb7de968 Mon Sep 17 00:00:00 2001 From: Ninjdai Date: Fri, 1 Aug 2025 14:46:04 +0200 Subject: [PATCH] feat: Book instance bulk creation endpoint --- src/main.rs | 2 + src/routes/book_instance.rs | 80 +++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/main.rs b/src/main.rs index e187c25..70d7976 100644 --- a/src/main.rs +++ b/src/main.rs @@ -76,6 +76,8 @@ async fn main() { .routes(routes!(routes::book_instance::get_book_instance_by_id)) .routes(routes!(routes::book_instance::create_book_instance)) .routes(routes!(routes::book_instance::update_book_instance)) + .routes(routes!(routes::book_instance::sell_book_instance)) + .routes(routes!(routes::book_instance::bulk_create_book_instance)) // Owner API .routes(routes!(routes::owner::get_owner_by_id)) .routes(routes!(routes::owner::create_owner)) diff --git a/src/routes/book_instance.rs b/src/routes/book_instance.rs index 7e10919..9eb8bea 100644 --- a/src/routes/book_instance.rs +++ b/src/routes/book_instance.rs @@ -136,3 +136,83 @@ pub async fn update_book_instance( (StatusCode::NOT_FOUND, Json(None)) } } + +#[derive(Deserialize, Serialize, utoipa::ToSchema)] +pub struct BookInstanceSaleParams { + price: i32, +} + +#[axum::debug_handler] +#[utoipa::path( + post, + path = "/book_instance/{id}/sell", + params(BookInstanceByIdParams), + request_body = BookInstanceSaleParams, + responses( + (status = OK, body = book_instance::Model, description = "Successfully sold book instance"), + (status = NOT_FOUND, description = "No book instance with specified id was found"), + ), + summary = "Sell a book instance", + description = "Sell a book instance", + tag = "book-instance-api", +)] +pub async fn sell_book_instance( + State(state): State>, + Path(id): Path, + Json(instance_payload): Json, +) -> (StatusCode, Json>) { + + if let Ok(Some(book_instance)) = BookInstance::find_by_id(id).one(state.db_conn.as_ref()).await { + let mut book_instance: book_instance::ActiveModel = book_instance.into(); + book_instance.sold_price = Set(Some(instance_payload.price)); + book_instance.status = Set(book_instance::BookStatus::Sold); + + match book_instance.update(state.db_conn.as_ref()).await { + Err(e) => { + log::error!(target: "api", "Error while selling book instance from api: {:#?}", e); + (StatusCode::INTERNAL_SERVER_ERROR, Json(None)) + }, + Ok(res) => { + let model = res.try_into_model().expect("All fields should be set once the book instance is saved"); + (StatusCode::OK, Json(Some(model))) + } + } + } else { + (StatusCode::NOT_FOUND, Json(None)) + } +} +#[axum::debug_handler] +#[utoipa::path( + post, + path = "/book_instance/bulk", + request_body = Vec, + responses( + (status = OK, description = "Successfully created book instances"), + ), + summary = "Create new book instances in bulk", + description = "Create new book instances in bulk", + tag = "book-instance-api", +)] +pub async fn bulk_create_book_instance( + State(state): State>, + Json(instance_payload): Json>, +) -> StatusCode { + + let instances = instance_payload + .into_iter() + .map(|p| book_instance::ActiveModel { + book_id: Set(p.book_id), + owner_id: Set(p.owner_id), + price: Set(p.price), + status: Set(book_instance::BookStatus::Available), + ..Default::default() + }); + + match BookInstance::insert_many(instances).exec(state.db_conn.as_ref()).await { + Err(e) => { + log::error!(target: "api", "Error while bulk inserting new book instances: {:#?}", e); + StatusCode::INTERNAL_SERVER_ERROR + }, + Ok(_) => StatusCode::OK + } +}