Remove item from cart

This commit is contained in:
eraden 2022-04-18 08:52:09 +02:00
parent 4be0f69511
commit ad046bc389
4 changed files with 108 additions and 13 deletions

View File

@ -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<T> = std::result::Result<T, Error>;
@ -80,3 +83,35 @@ async fn add_item(msg: AddItem, db: Addr<Database>) -> Result<ShoppingCartItem>
_ => Err(Error::CantAddItem),
}
}
#[derive(Message)]
#[rtype(result = "Result<Option<ShoppingCartItem>>")]
pub struct RemoveProduct {
pub shopping_cart_id: ShoppingCartId,
pub shopping_cart_item_id: ShoppingCartItemId,
}
cart_async_handler!(RemoveProduct, remove_product, Option<ShoppingCartItem>);
pub(crate) async fn remove_product(
msg: RemoveProduct,
db: Addr<Database>,
) -> Result<Option<ShoppingCartItem>> {
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)
}
}
}

View File

@ -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,

View File

@ -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<ShoppingCartItemId>, product_id: Option<ProductId> },
}
#[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<Option<ShoppingCartItem>>")]
pub struct RemoveCartItem {
pub shopping_cart_id: ShoppingCartId,
pub shopping_cart_item_id: Option<ShoppingCartItemId>,
pub product_id: Option<ProductId>,
}
db_async_handler!(RemoveCartItem, remove_cart_item, Option<ShoppingCartItem>);
pub(crate) async fn remove_cart_item(
msg: RemoveCartItem,
pool: PgPool,
) -> Result<Option<ShoppingCartItem>> {
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,
})
})
}

View File

@ -326,30 +326,30 @@ impl From<FullAccount> 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 {