From ad046bc38930a31a6b6ee2e61fe4983f6f31d3ac Mon Sep 17 00:00:00 2001 From: eraden Date: Mon, 18 Apr 2022 08:52:09 +0200 Subject: [PATCH] Remove item from cart --- api/src/actors/cart_manager.rs | 37 ++++++++++- api/src/actors/database/order_items.rs | 2 +- .../actors/database/shopping_cart_items.rs | 62 ++++++++++++++++++- api/src/model.rs | 20 +++--- 4 files changed, 108 insertions(+), 13 deletions(-) diff --git a/api/src/actors/cart_manager.rs b/api/src/actors/cart_manager.rs index d324eda..fb65c0c 100644 --- a/api/src/actors/cart_manager.rs +++ b/api/src/actors/cart_manager.rs @@ -1,6 +1,7 @@ use crate::database::Database; use crate::model::{ - AccountId, ProductId, Quantity, QuantityUnit, ShoppingCartItem, ShoppingCartState, + AccountId, ProductId, Quantity, QuantityUnit, ShoppingCartId, ShoppingCartItem, + ShoppingCartItemId, ShoppingCartState, }; use crate::{cart_async_handler, database}; use actix::{Actor, Addr, Context, Handler, Message, ResponseActFuture, WrapFuture}; @@ -15,6 +16,8 @@ pub enum Error { CantAddItem, #[error("{0}")] Db(#[from] database::Error), + #[error("Unable to update cart item")] + UpdateFailed, } pub type Result = std::result::Result; @@ -80,3 +83,35 @@ async fn add_item(msg: AddItem, db: Addr) -> Result _ => Err(Error::CantAddItem), } } +#[derive(Message)] +#[rtype(result = "Result>")] +pub struct RemoveProduct { + pub shopping_cart_id: ShoppingCartId, + pub shopping_cart_item_id: ShoppingCartItemId, +} + +cart_async_handler!(RemoveProduct, remove_product, Option); + +pub(crate) async fn remove_product( + msg: RemoveProduct, + db: Addr, +) -> Result> { + match db + .send(database::RemoveCartItem { + shopping_cart_id: msg.shopping_cart_id, + shopping_cart_item_id: Some(msg.shopping_cart_item_id), + product_id: None, + }) + .await + { + Ok(Ok(row)) => Ok(row), + Ok(Err(db_err)) => { + log::error!("{db_err}"); + Err(Error::UpdateFailed) + } + Err(act_err) => { + log::error!("{act_err:?}"); + Err(Error::UpdateFailed) + } + } +} diff --git a/api/src/actors/database/order_items.rs b/api/src/actors/database/order_items.rs index f60d7b8..fe28628 100644 --- a/api/src/actors/database/order_items.rs +++ b/api/src/actors/database/order_items.rs @@ -11,7 +11,7 @@ use super::Result; pub enum Error { #[error("Can't create order item")] CantCreate, - #[error("Can't find order item does to lack of identity")] + #[error("Can't find order item doe to lack of identity")] NoIdentity, #[error("Order item does not exists")] NotExists, diff --git a/api/src/actors/database/shopping_cart_items.rs b/api/src/actors/database/shopping_cart_items.rs index b66b00f..11ce89b 100644 --- a/api/src/actors/database/shopping_cart_items.rs +++ b/api/src/actors/database/shopping_cart_items.rs @@ -1,4 +1,4 @@ -use crate::db_async_handler; +use crate::{database, db_async_handler}; use actix::{Handler, ResponseActFuture, WrapFuture}; use sqlx::PgPool; @@ -21,6 +21,10 @@ pub enum Error { AccountCarts, #[error("Failed to load items for shopping cart {0}")] CartItems(ShoppingCartId), + #[error("Can't find shopping cart item doe to lack of identity")] + NoIdentity, + #[error("Failed to update shopping cart item with id {shopping_cart_item_id:?} and/or product id {product_id:?}")] + Update { shopping_cart_item_id: Option, product_id: Option }, } #[derive(actix::Message)] @@ -199,3 +203,59 @@ WHERE shopping_cart_id = $1 super::Error::ShoppingCartItem(Error::CartItems(shopping_cart_id)) }) } + +#[derive(actix::Message)] +#[rtype(result = "Result>")] +pub struct RemoveCartItem { + pub shopping_cart_id: ShoppingCartId, + pub shopping_cart_item_id: Option, + pub product_id: Option, +} + +db_async_handler!(RemoveCartItem, remove_cart_item, Option); + +pub(crate) async fn remove_cart_item( + msg: RemoveCartItem, + pool: PgPool, +) -> Result> { + match (msg.shopping_cart_item_id, msg.product_id) { + (Some(shopping_cart_item_id), None) => sqlx::query_as( + r#" +DELETE FROM shopping_cart_items +WHERE shopping_cart_id = $1 AND id = $2 +RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit + "#, + ) + .bind(msg.shopping_cart_id) + .bind(shopping_cart_item_id), + (Some(shopping_cart_item_id), Some(product_id)) => sqlx::query_as( + r#" +DELETE FROM shopping_cart_items +WHERE shopping_cart_id = $1 AND id = $2 AND product_id = $3 +RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit + "#, + ) + .bind(msg.shopping_cart_id) + .bind(shopping_cart_item_id) + .bind(product_id), + (None, Some(product_id)) => sqlx::query_as( + r#" +DELETE FROM shopping_cart_items +WHERE shopping_cart_id = $1 AND product_id = $2 +RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit + "#, + ) + .bind(msg.shopping_cart_id) + .bind(product_id), + _ => return Err(database::Error::ShoppingCartItem(Error::NoIdentity)), + } + .fetch_optional(&pool) + .await + .map_err(|e| { + log::error!("{e:?}"); + database::Error::ShoppingCartItem(Error::Update { + shopping_cart_item_id: msg.shopping_cart_item_id, + product_id: msg.product_id, + }) + }) +} diff --git a/api/src/model.rs b/api/src/model.rs index 3ec8566..981c6c2 100644 --- a/api/src/model.rs +++ b/api/src/model.rs @@ -326,30 +326,30 @@ impl From for Account { } } -#[derive(sqlx::Type, Serialize, Deserialize)] +#[derive(sqlx::Type, Serialize, Deserialize, Debug, Copy, Clone, Deref, Display, From)] #[sqlx(transparent)] #[serde(transparent)] -pub struct ProductId(pub RecordId); +pub struct ProductId(RecordId); -#[derive(sqlx::Type, Serialize, Deserialize)] +#[derive(sqlx::Type, Serialize, Deserialize, Debug, Clone, Deref, Display, From)] #[sqlx(transparent)] #[serde(transparent)] -pub struct ProductName(pub String); +pub struct ProductName(String); -#[derive(sqlx::Type, Serialize, Deserialize)] +#[derive(sqlx::Type, Serialize, Deserialize, Debug, Clone, Deref, Display, From)] #[sqlx(transparent)] #[serde(transparent)] -pub struct ProductShortDesc(pub String); +pub struct ProductShortDesc(String); -#[derive(sqlx::Type, Serialize, Deserialize)] +#[derive(sqlx::Type, Serialize, Deserialize, Debug, Clone, Deref, Display, From)] #[sqlx(transparent)] #[serde(transparent)] -pub struct ProductLongDesc(pub String); +pub struct ProductLongDesc(String); -#[derive(sqlx::Type, Serialize, Deserialize)] +#[derive(sqlx::Type, Serialize, Deserialize, Debug, Clone, Deref, Display, From)] #[sqlx(transparent)] #[serde(transparent)] -pub struct ProductCategory(pub String); +pub struct ProductCategory(String); #[derive(sqlx::FromRow, Serialize, Deserialize)] pub struct Product {