From f98d1e6903fd29d25561dc327b2620395c943e46 Mon Sep 17 00:00:00 2001 From: eraden Date: Wed, 23 Nov 2022 16:03:58 +0100 Subject: [PATCH] Product variant in shopping cart --- .../migrations/202204131841_init.sql | 2 +- .../src/db/shopping_cart_items.rs | 75 +++++++-------- crates/channels/src/stocks/mod.rs | 12 +++ crates/channels/src/stocks/product.rs | 40 ++++++++ crates/model/src/api.rs | 10 +- crates/model/src/lib.rs | 7 +- crates/stock_manager/src/actions/product.rs | 52 +++++++++- .../src/actions/product_variant.rs | 48 +++++++++- .../stock_manager/src/db/product_variants.rs | 43 +++++++++ crates/stock_manager/src/db/products.rs | 94 ++++++------------- crates/stock_manager/src/db/stocks.rs | 4 +- crates/stock_manager/src/rpc.rs | 16 ++++ 12 files changed, 290 insertions(+), 113 deletions(-) diff --git a/crates/cart_manager/migrations/202204131841_init.sql b/crates/cart_manager/migrations/202204131841_init.sql index 75261bf..161e5b4 100644 --- a/crates/cart_manager/migrations/202204131841_init.sql +++ b/crates/cart_manager/migrations/202204131841_init.sql @@ -25,7 +25,7 @@ CREATE TABLE shopping_carts ( CREATE TABLE shopping_cart_items ( id serial NOT NULL, - product_id integer NOT NULL, + product_variant_id integer NOT NULL, shopping_cart_id integer, quantity integer DEFAULT 0 NOT NULL, quantity_unit "QuantityUnit" NOT NULL, diff --git a/crates/cart_manager/src/db/shopping_cart_items.rs b/crates/cart_manager/src/db/shopping_cart_items.rs index 393241d..1cf2ea3 100644 --- a/crates/cart_manager/src/db/shopping_cart_items.rs +++ b/crates/cart_manager/src/db/shopping_cart_items.rs @@ -1,3 +1,4 @@ +use model::v2::ProductVariantId; use model::*; pub type Result = std::result::Result; @@ -18,10 +19,10 @@ pub enum Error { 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:?}")] + #[error("Failed to update shopping cart item with id {shopping_cart_item_id:?} and/or product variant id {product_variant_id:?}")] Update { shopping_cart_item_id: Option, - product_id: Option, + product_variant_id: Option, }, } @@ -36,7 +37,7 @@ impl AllShoppingCartItems { sqlx::query_as( r#" SELECT shopping_cart_items.id, - shopping_cart_items.product_id, + shopping_cart_items.product_variant_id, shopping_cart_items.shopping_cart_id, shopping_cart_items.quantity, shopping_cart_items.quantity_unit @@ -72,7 +73,7 @@ impl AccountShoppingCartItems { Some(shopping_cart_id) => sqlx::query_as( r#" SELECT shopping_cart_items.id as id, - shopping_cart_items.product_id as product_id, + shopping_cart_items.product_variant_id as product_variant_id, shopping_cart_items.shopping_cart_id as shopping_cart_id, shopping_cart_items.quantity as quantity, shopping_cart_items.quantity_unit as quantity_unit @@ -88,7 +89,7 @@ ORDER BY shopping_cart_items.id None => sqlx::query_as( r#" SELECT shopping_cart_items.id as id, - shopping_cart_items.product_id as product_id, + shopping_cart_items.product_variant_id as product_variant_id, shopping_cart_items.shopping_cart_id as shopping_cart_id, shopping_cart_items.quantity as quantity, shopping_cart_items.quantity_unit as quantity_unit @@ -112,7 +113,7 @@ ORDER BY shopping_cart_items.id #[derive(Debug)] pub struct CreateShoppingCartItem { - pub product_id: ProductId, + pub product_variant_id: ProductVariantId, pub shopping_cart_id: ShoppingCartId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, @@ -126,12 +127,12 @@ impl CreateShoppingCartItem { let msg = self; sqlx::query_as( r#" -INSERT INTO shopping_cart_items (product_id, shopping_cart_id, quantity, quantity_unit) +INSERT INTO shopping_cart_items (product_variant_id, shopping_cart_id, quantity, quantity_unit) VALUES ($1, $2, $3, $4) -RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit +RETURNING id, product_variant_id, shopping_cart_id, quantity, quantity_unit "#, ) - .bind(msg.product_id) + .bind(msg.product_variant_id) .bind(msg.shopping_cart_id) .bind(msg.quantity) .bind(msg.quantity_unit) @@ -148,7 +149,7 @@ RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit #[derive(Debug)] pub struct UpdateShoppingCartItem { pub id: ShoppingCartItemId, - pub product_id: ProductId, + pub product_variant_id: ProductVariantId, pub shopping_cart_id: ShoppingCartId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, @@ -163,13 +164,13 @@ impl UpdateShoppingCartItem { sqlx::query_as( r#" UPDATE shopping_cart_items -SET product_id = $2, shopping_cart_id = $3, quantity = $4, quantity_unit = $5 +SET product_variant_id = $2, shopping_cart_id = $3, quantity = $4, quantity_unit = $5 WHERE id = $1 -RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit +RETURNING id, product_variant_id, shopping_cart_id, quantity, quantity_unit "#, ) .bind(msg.id) - .bind(msg.product_id) + .bind(msg.product_variant_id) .bind(msg.shopping_cart_id) .bind(msg.quantity) .bind(msg.quantity_unit) @@ -197,7 +198,7 @@ impl DeleteShoppingCartItem { r#" DELETE FROM shopping_cart_items WHERE id = $1 -RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit +RETURNING id, product_variant_id, shopping_cart_id, quantity, quantity_unit "#, ) .bind(msg.id) @@ -223,7 +224,7 @@ impl FindShoppingCartItem { let msg = self; sqlx::query_as( r#" -SELECT id, product_id, shopping_cart_id, quantity, quantity_unit +SELECT id, product_variant_id, shopping_cart_id, quantity, quantity_unit FROM shopping_cart_items WHERE id = $1 "#, @@ -240,7 +241,7 @@ WHERE id = $1 #[derive(Debug)] pub struct ActiveCartItemByProduct { - pub product_id: ProductId, + pub product_variant_id: ProductVariantId, } impl ActiveCartItemByProduct { @@ -252,19 +253,19 @@ impl ActiveCartItemByProduct { sqlx::query_as( r#" SELECT shopping_cart_items.id, - shopping_cart_items.product_id, + shopping_cart_items.product_variant_id, shopping_cart_items.shopping_cart_id, shopping_cart_items.quantity, shopping_cart_items.quantity_unit FROM shopping_cart_items INNER JOIN shopping_carts ON shopping_cart_items.shopping_cart_id = shopping_carts.id -WHERE product_id = $1 +WHERE product_variant_id = $1 AND shopping_carts.state = $2 ORDER BY shopping_cart_items.id ASC "#, ) - .bind(msg.product_id) + .bind(msg.product_variant_id) .bind(model::ShoppingCartState::Active) .fetch_optional(t) .await @@ -290,7 +291,7 @@ impl CartItems { sqlx::query_as( r#" SELECT id, - product_id, + product_variant_id, shopping_cart_id, quantity, quantity_unit @@ -313,7 +314,7 @@ ORDER BY shopping_cart_items.id ASC pub struct RemoveCartItem { pub shopping_cart_id: ShoppingCartId, pub shopping_cart_item_id: Option, - pub product_id: Option, + pub product_variant_id: Option, } impl RemoveCartItem { @@ -322,35 +323,35 @@ impl RemoveCartItem { t: &mut sqlx::Transaction<'_, sqlx::Postgres>, ) -> Result> { let msg = self; - match (msg.shopping_cart_item_id, msg.product_id) { + match (msg.shopping_cart_item_id, msg.product_variant_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 +RETURNING id, product_variant_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( + (Some(shopping_cart_item_id), Some(product_variant_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 +WHERE shopping_cart_id = $1 AND id = $2 AND product_variant_id = $3 +RETURNING id, product_variant_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( + .bind(product_variant_id), + (None, Some(product_variant_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 +WHERE shopping_cart_id = $1 AND product_variant_id = $2 +RETURNING id, product_variant_id, shopping_cart_id, quantity, quantity_unit "#, ) .bind(msg.shopping_cart_id) - .bind(product_id), + .bind(product_variant_id), _ => return Err(Error::NoIdentity), } .fetch_optional(t) @@ -359,7 +360,7 @@ RETURNING id, product_id, shopping_cart_id, quantity, quantity_unit tracing::error!("{e:?}"); Error::Update { shopping_cart_item_id: msg.shopping_cart_item_id, - product_id: msg.product_id, + product_variant_id: msg.product_variant_id, } }) } @@ -423,7 +424,7 @@ WHERE buyer_id = $1 async fn test_shopping_cart_item( t: &mut sqlx::Transaction<'_, sqlx::Postgres>, shopping_cart_id: Option, - product_id: Option, + product_variant_id: Option, ) -> ShoppingCartItem { let shopping_cart_id = match shopping_cart_id { Some(id) => id, @@ -433,12 +434,12 @@ WHERE buyer_id = $1 .id } }; - let product_id = match product_id { + let product_variant_id = match product_variant_id { Some(id) => id, _ => 1.into(), }; CreateShoppingCartItem { - product_id, + product_variant_id, shopping_cart_id, quantity: Quantity::from_u32(496879), quantity_unit: QuantityUnit::Gram, @@ -565,7 +566,7 @@ WHERE buyer_id = $1 let updated = UpdateShoppingCartItem { id: item.id, - product_id: item.product_id, + product_variant_id: item.product_variant_id, shopping_cart_id: item.shopping_cart_id, quantity: Quantity::from_u32(987979879), quantity_unit: QuantityUnit::Kilogram, @@ -579,7 +580,7 @@ WHERE buyer_id = $1 updated, ShoppingCartItem { id: item.id, - product_id: item.product_id, + product_variant_id: item.product_variant_id, shopping_cart_id: item.shopping_cart_id, quantity: Quantity::from_u32(987979879), quantity_unit: QuantityUnit::Kilogram, diff --git a/crates/channels/src/stocks/mod.rs b/crates/channels/src/stocks/mod.rs index 47a9fed..33da68d 100644 --- a/crates/channels/src/stocks/mod.rs +++ b/crates/channels/src/stocks/mod.rs @@ -50,6 +50,10 @@ pub enum Error { UpdateProductStock(ProductVariantId), #[error("Failed to load all product photos")] AllProductPhotos, + #[error("Failed to load products {0:?}")] + FindProducts(Vec), + #[error("Failed to load product variants {0:?}")] + FindProductVariants(Vec), } pub mod rpc { @@ -113,6 +117,14 @@ pub mod rpc { /// List of products with stock size and photos async fn detailed_products(input: detailed_products::Input) -> detailed_products::Output; + + /// List of products for shopping cart + async fn shopping_cart_products(input: find_products::Input) -> find_products::Output; + + /// List of products variants for shopping cart + async fn shopping_cart_product_variants( + input: find_product_variants::Input, + ) -> find_product_variants::Output; } pub async fn create_client(config: SharedAppConfig) -> StocksClient { diff --git a/crates/channels/src/stocks/product.rs b/crates/channels/src/stocks/product.rs index e0aaff7..4c59c98 100644 --- a/crates/channels/src/stocks/product.rs +++ b/crates/channels/src/stocks/product.rs @@ -80,6 +80,46 @@ pub mod delete_product { pub type Output = Result; } +pub mod find_products { + use model::v2::*; + + use crate::stocks::Error; + + #[derive(Debug, serde::Serialize, serde::Deserialize)] + pub struct Input { + pub variant_ids: Vec, + pub limit: Limit, + pub offset: Offset, + } + + #[derive(Debug, serde::Serialize, serde::Deserialize)] + pub struct Details { + pub products: Vec, + } + + pub type Output = Result; +} + +pub mod find_product_variants { + use model::v2::*; + + use crate::stocks::Error; + + #[derive(Debug, serde::Serialize, serde::Deserialize)] + pub struct Input { + pub variant_ids: Vec, + pub limit: Limit, + pub offset: Offset, + } + + #[derive(Debug, serde::Serialize, serde::Deserialize)] + pub struct Details { + pub product_variants: Vec, + } + + pub type Output = Result; +} + #[derive(Copy, Clone, Debug, PartialOrd, PartialEq, serde::Serialize, serde::Deserialize)] pub enum Topic { ProductCreated, diff --git a/crates/model/src/api.rs b/crates/model/src/api.rs index 8bf04c4..45b1b7d 100644 --- a/crates/model/src/api.rs +++ b/crates/model/src/api.rs @@ -173,7 +173,7 @@ pub struct Order { #[derive(Serialize, Deserialize, Debug)] pub struct ShoppingCartItem { pub id: ShoppingCartItemId, - pub product_id: ProductId, + pub product_variant_id: ProductVariantId, pub shopping_cart_id: ShoppingCartId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, @@ -183,7 +183,7 @@ impl From for ShoppingCartItem { fn from( crate::ShoppingCartItem { id, - product_id, + product_variant_id, shopping_cart_id, quantity, quantity_unit, @@ -191,7 +191,7 @@ impl From for ShoppingCartItem { ) -> Self { Self { id, - product_id, + product_variant_id, shopping_cart_id, quantity, quantity_unit, @@ -233,13 +233,13 @@ impl From<(crate::ShoppingCart, Vec)> for ShoppingCart .map( |crate::ShoppingCartItem { id, - product_id, + product_variant_id, shopping_cart_id, quantity, quantity_unit, }| ShoppingCartItem { id, - product_id, + product_variant_id, shopping_cart_id, quantity, quantity_unit, diff --git a/crates/model/src/lib.rs b/crates/model/src/lib.rs index 4f8d791..a516403 100644 --- a/crates/model/src/lib.rs +++ b/crates/model/src/lib.rs @@ -14,6 +14,7 @@ use serde::de::{Error, Visitor}; use serde::{Deserialize, Deserializer, Serialize}; pub use crate::encrypt::*; +use crate::v2::ProductVariantId; #[derive(Debug, Hash, thiserror::Error)] pub enum TransformError { @@ -961,7 +962,7 @@ pub mod v2 { pub use crate::{ Day, Days, FileName, Limit, LocalPath, Offset, PhotoId, Price, ProductCategory, ProductId, ProductLongDesc, ProductName, ProductPhotoId, ProductShortDesc, Quantity, QuantityUnit, - RecordId, StockId, UniqueName, + RecordId, ShoppingCartId, StockId, UniqueName, }; #[cfg_attr(feature = "db", derive(sqlx::Type))] @@ -988,7 +989,7 @@ pub mod v2 { #[cfg_attr(feature = "db", sqlx(transparent))] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Deref, From)] #[serde(transparent)] - pub struct ProductVariantId(RecordId); + pub struct ProductVariantId(pub RecordId); #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct DetailedProductVariant { @@ -1215,7 +1216,7 @@ pub struct ShoppingCartItemId(RecordId); #[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct ShoppingCartItem { pub id: ShoppingCartItemId, - pub product_id: ProductId, + pub product_variant_id: ProductVariantId, pub shopping_cart_id: ShoppingCartId, pub quantity: Quantity, pub quantity_unit: QuantityUnit, diff --git a/crates/stock_manager/src/actions/product.rs b/crates/stock_manager/src/actions/product.rs index e831dd4..0e73897 100644 --- a/crates/stock_manager/src/actions/product.rs +++ b/crates/stock_manager/src/actions/product.rs @@ -1,4 +1,4 @@ -use channels::stocks::{create_product, delete_product, update_product, Error}; +use channels::stocks::{create_product, delete_product, find_products, update_product, Error}; use channels::AsyncClient; use config::SharedAppConfig; use db_utils::PgT; @@ -195,6 +195,49 @@ pub async fn inner_delete_product( dbm.run(t).await.map(|product| (input.product_id, product)) } +pub async fn find_products( + input: find_products::Input, + db: Database, + _mqtt: AsyncClient, + _config: SharedAppConfig, +) -> find_products::Output { + let mut t = begin_t!(db, Error::InternalServerError); + + match inner_find_products(input, &mut t).await { + Ok(details) => { + if let Err(e) = t.commit().await { + tracing::error!("{}", e); + Err(Error::InternalServerError) + } else { + Ok(details) + } + } + Err(e) => { + t.rollback().await.ok(); + Err(e) + } + } +} + +async fn inner_find_products( + input: find_products::Input, + t: &mut PgT<'_>, +) -> find_products::Output { + let dbm = crate::db::ShoppingCartProducts { + variant_ids: input.variant_ids.clone(), + limit: input.limit, + offset: input.offset, + }; + + match dbm.run(t).await { + Ok(products) => Ok(find_products::Details { products }), + Err(e) => { + tracing::warn!("{}", e); + Err(Error::FindProducts(input.variant_ids)) + } + } +} + #[cfg(test)] mod tests { use config::UpdateConfig; @@ -303,4 +346,11 @@ mod tests { let (id, _new_product) = res.unwrap(); assert_eq!(id, product.id); } + + #[tokio::test] + async fn shopping_cart_products() { + testx::db_t_ref!(t); + + testx::db_rollback!(t); + } } diff --git a/crates/stock_manager/src/actions/product_variant.rs b/crates/stock_manager/src/actions/product_variant.rs index 7e3e13c..fc39dd1 100644 --- a/crates/stock_manager/src/actions/product_variant.rs +++ b/crates/stock_manager/src/actions/product_variant.rs @@ -1,5 +1,6 @@ use channels::stocks::{ - create_product_variant, delete_product_variant, update_product_variant, Error, + create_product_variant, delete_product_variant, find_product_variants, update_product_variant, + Error, }; use channels::AsyncClient; use config::SharedAppConfig; @@ -151,6 +152,51 @@ async fn inner_delete_product_variant( } } +pub async fn find_product_variants( + input: find_product_variants::Input, + db: Database, + _mqtt: AsyncClient, + _config: SharedAppConfig, +) -> find_product_variants::Output { + let variant_ids = input.variant_ids.clone(); + let mut t = begin_t!(db, Error::InternalServerError); + match inner_find_product_variants(input, &mut t).await { + Ok(details) => { + if let Err(e) = t.commit().await { + tracing::warn!("{}", e); + Err(Error::FindProductVariants(variant_ids)) + } else { + Ok(details) + } + } + Err(e) => { + t.rollback().await.ok(); + Err(e) + } + } +} + +pub async fn inner_find_product_variants( + input: find_product_variants::Input, + t: &mut PgT<'_>, +) -> find_product_variants::Output { + let dbm = crate::db::ShoppingCartProductVariants { + variant_ids: input.variant_ids.clone(), + limit: input.limit, + offset: input.offset, + }; + + match dbm.run(t).await { + Ok(variants) => Ok(find_product_variants::Details { + product_variants: variants, + }), + Err(e) => { + tracing::warn!("{}", e); + Err(Error::FindProductVariants(input.variant_ids)) + } + } +} + #[cfg(test)] mod test { use channels::stocks::{ diff --git a/crates/stock_manager/src/db/product_variants.rs b/crates/stock_manager/src/db/product_variants.rs index 99262da..d9441e5 100644 --- a/crates/stock_manager/src/db/product_variants.rs +++ b/crates/stock_manager/src/db/product_variants.rs @@ -1,5 +1,6 @@ use db_utils::PgT; use model::v2::*; +use model::Ranged; #[derive(Debug, PartialEq, thiserror::Error)] pub enum Error { @@ -7,12 +8,54 @@ pub enum Error { CreateProductVariant, #[error("Failed to load variants for products {0:?}")] ProductsVariants(Vec), + #[error("Failed to load variants with ids {0:?}")] + FindProductsVariants(Vec), #[error("Failed to delete product variant {0:?}")] DeleteProductVariant(ProductVariantId), } pub type Result = std::result::Result; +#[derive(Debug)] +pub struct ShoppingCartProductVariants { + pub variant_ids: Vec, + pub limit: Limit, + pub offset: Offset, +} + +impl ShoppingCartProductVariants { + pub async fn run(self, t: &mut PgT<'_>) -> Result> { + db_utils::MultiLoad::new( + t, + r#" +SELECT id, + product_id, + name, + short_description, + long_description, + price +FROM product_variants +WHERE + "#, + "shopping_cart_id = $1", + ) + .with_sorting("products.id") + .with_padding( + self.limit.in_range(1..200).into_raw(), + self.offset.in_range(0..u32::MAX).into_raw(), + ) + .load( + self.variant_ids.len(), + self.variant_ids.iter().map(|id| id.0), + |e| { + tracing::warn!("{e:?}"); + Error::FindProductsVariants(self.variant_ids.clone()) + }, + ) + .await + } +} + #[derive(Debug)] pub struct CreateProductVariant { pub product_id: ProductId, diff --git a/crates/stock_manager/src/db/products.rs b/crates/stock_manager/src/db/products.rs index b45b326..ef74525 100644 --- a/crates/stock_manager/src/db/products.rs +++ b/crates/stock_manager/src/db/products.rs @@ -1,8 +1,8 @@ use db_utils::PgT; use model::v2::*; -use model::{Ranged, ShoppingCartId}; +use model::Ranged; -#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, thiserror::Error)] +#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, thiserror::Error)] pub enum Error { #[error("Unable to load all products")] All, @@ -12,12 +12,10 @@ pub enum Error { Update(ProductId), #[error("Unable to delete product")] Delete(ProductId), - #[error("Unable to find products for shopping cart")] - ShoppingCartProducts(ShoppingCartId), #[error("Product with id {0} can't be found")] Single(ProductId), - #[error("Failed to load products for given ids")] - FindProducts, + #[error("Failed to load products for given variant ids")] + FindProductsByVariants(Vec), } pub type Result = std::result::Result; @@ -44,8 +42,8 @@ ORDER BY id LIMIT $1 OFFSET $2 "#, ) - .bind(self.limit.max(1).min(200)) - .bind(self.offset.max(0)) + .bind(self.limit.in_range(1..200)) + .bind(self.offset.in_range(0..u32::MAX)) .fetch_all(pool) .await .map_err(|e| { @@ -193,71 +191,41 @@ RETURNING id, #[derive(Debug)] pub struct ShoppingCartProducts { - pub shopping_cart_id: ShoppingCartId, + pub variant_ids: Vec, pub limit: Limit, pub offset: Offset, } impl ShoppingCartProducts { pub async fn run(self, t: &mut PgT<'_>) -> Result> { - sqlx::query_as( + db_utils::MultiLoad::new( + t, r#" -SELECT products.id, - products.name, - products.category, - products.deliver_days_flag -FROM products -INNER JOIN shopping_cart_items ON shopping_cart_items.product_id = products.id -WHERE shopping_cart_id = $1 -ORDER BY products.id -LIMIT $2 OFFSET $3 +SELECT p.id, + p.name, + p.category, + p.deliver_days_flag +FROM products p +INNER JOIN product_variants v + ON v.product_id = p.id +WHERE "#, + "p.id = $1", + ) + .with_sorting("p.id") + .with_padding( + self.limit.in_range(1..200).into_raw(), + self.offset.in_range(0..u32::MAX).into_raw(), + ) + .load( + self.variant_ids.len(), + self.variant_ids.iter().map(|id| id.0), + |e| { + tracing::warn!("{e:?}"); + Error::FindProductsByVariants(self.variant_ids.clone()) + }, ) - .bind(self.shopping_cart_id) - .bind(self.limit.in_range(1..200)) - .bind(self.offset.in_range(0..u32::MAX)) - .fetch_all(t) .await - .map_err(|e| { - tracing::warn!("{e:?}"); - Error::ShoppingCartProducts(self.shopping_cart_id) - }) - } -} - -#[derive(Debug)] -pub struct FindProducts { - pub product_ids: Vec, -} - -impl FindProducts { - pub async fn run( - self, - pool: &mut sqlx::Transaction<'_, sqlx::Postgres>, - ) -> Result> { - let mut loader = db_utils::MultiLoad::new( - pool, - r#" -SELECT id, - name, - category, - deliver_days_flag -FROM products -WHERE - "#, - "products.id =", - ) - .with_size(200); - loader - .load( - self.product_ids.len(), - self.product_ids.into_iter().map(|id| *id), - |e| { - tracing::warn!("{e:?}"); - Error::FindProducts - }, - ) - .await } } diff --git a/crates/stock_manager/src/db/stocks.rs b/crates/stock_manager/src/db/stocks.rs index 237094a..1ab3d32 100644 --- a/crates/stock_manager/src/db/stocks.rs +++ b/crates/stock_manager/src/db/stocks.rs @@ -10,8 +10,8 @@ pub enum Error { Update(StockId), #[error("Unable to delete stock {0:?}")] Delete(StockId), - #[error("Unable to delete all stock for variant {0:?}")] - DeleteAllProductStocks(ProductId), + // #[error("Unable to delete all stock for variant {0:?}")] + // DeleteAllProductStocks(ProductId), #[error("Unable find stock for product")] ProductVariantStock, #[error("Stock {0:?} does not exists")] diff --git a/crates/stock_manager/src/rpc.rs b/crates/stock_manager/src/rpc.rs index 2d20a83..c316062 100644 --- a/crates/stock_manager/src/rpc.rs +++ b/crates/stock_manager/src/rpc.rs @@ -125,6 +125,22 @@ pub mod rpc { ) -> detailed_products::Output { actions::detailed_products(input, self.db, self.mqtt_client, self.config).await } + + async fn shopping_cart_products( + self, + _: context::Context, + input: find_products::Input, + ) -> find_products::Output { + actions::find_products(input, self.db, self.mqtt_client, self.config).await + } + + async fn shopping_cart_product_variants( + self, + _: context::Context, + input: find_product_variants::Input, + ) -> find_product_variants::Output { + actions::find_product_variants(input, self.db, self.mqtt_client, self.config).await + } } }