From 500dac9b2e7b69aa287df5930bba039ba4086758 Mon Sep 17 00:00:00 2001 From: eraden Date: Thu, 10 Nov 2022 06:36:55 +0100 Subject: [PATCH] Operations on product variants --- crates/db-utils/src/lib.rs | 17 ++++- .../stock_manager/src/db/product_variants.rs | 70 +++++++++++++++++-- crates/stock_manager/src/db/products.rs | 3 - 3 files changed, 79 insertions(+), 11 deletions(-) diff --git a/crates/db-utils/src/lib.rs b/crates/db-utils/src/lib.rs index c3b873f..05e4841 100644 --- a/crates/db-utils/src/lib.rs +++ b/crates/db-utils/src/lib.rs @@ -1,11 +1,14 @@ use sqlx::Arguments; +pub type PgT<'l> = sqlx::Transaction<'l, sqlx::Postgres>; + pub struct MultiLoad<'transaction, 'transaction2, 'header, 'condition, T> { pool: &'transaction mut sqlx::Transaction<'transaction2, sqlx::Postgres>, header: &'header str, condition: &'condition str, sort: Option, size: Option, + allow_over_max: bool, __phantom: std::marker::PhantomData, } @@ -24,11 +27,17 @@ where header, condition, sort: None, - size: None, + size: Some(200), + allow_over_max: false, __phantom: Default::default(), } } + pub fn allow_over_max(mut self) -> Self { + self.allow_over_max = true; + self + } + pub fn with_sorting>(mut self, order: S) -> Self { self.sort = Some(order.into()); self @@ -50,7 +59,11 @@ where ErrorFn: Fn(sqlx::Error) -> Error, { let mut res = Vec::new(); - let size = self.size.unwrap_or(20).min(200); + let size = if self.allow_over_max { + self.size.unwrap_or(200) + } else { + self.size.unwrap_or(20).min(200) + }; for ids in items.fold( Vec::>::with_capacity(len), diff --git a/crates/stock_manager/src/db/product_variants.rs b/crates/stock_manager/src/db/product_variants.rs index e9d296b..0d8101d 100644 --- a/crates/stock_manager/src/db/product_variants.rs +++ b/crates/stock_manager/src/db/product_variants.rs @@ -1,9 +1,14 @@ +use db_utils::PgT; use model::v2::*; #[derive(Debug, thiserror::Error)] pub enum Error { - #[error("")] + #[error("Failed to create product")] CreateProductVariant, + #[error("Failed to load variants for products {0:?}")] + ProductsVariants(Vec), + #[error("Failed to delete product variant {0:?}")] + DeleteProductVariant(ProductVariantId), } pub type Result = std::result::Result; @@ -18,10 +23,7 @@ pub struct CreateProductVariant { } impl CreateProductVariant { - pub async fn run( - self, - pool: &mut sqlx::Transaction<'_, sqlx::Postgres>, - ) -> Result { + pub async fn run(self, pool: &mut PgT<'_>) -> Result { sqlx::query_as( r#" INSERT INTO product_variants ( @@ -31,7 +33,7 @@ INSERT INTO product_variants ( long_description, price ) VALUES ($1, $2, $3, $4, $5) -RETURNINGS id, +RETURNING id, product_id, name, short_description, @@ -53,3 +55,59 @@ RETURNINGS id, }) } } + +#[derive(Debug)] +pub struct ProductsVariants { + pub product_ids: Vec, + pub limit: Option, + pub offset: Option, +} + +impl ProductsVariants { + pub async fn run(self, pool: &mut PgT<'_>) -> Result> { + db_utils::MultiLoad::new( + pool, + r#" +SELECT pv.id, + pv.product_id, + pv.name, + pv.short_description, + pv.long_description, + pv.price +FROM product_variants pv +INNER JOIN products ps + ON pv.product_id = ps.id +WHERE + "#, + "products.id = ", + ) + .allow_over_max() + .with_size(1000) + .load( + self.product_ids.len(), + self.product_ids.iter().copied().map(|id| *id), + |_| Error::ProductsVariants(self.product_ids.clone()), + ) + .await + } +} + +#[derive(Debug)] +pub struct DeleteProductVariant { + pub product_variant_id: ProductVariantId, +} + +impl DeleteProductVariant { + pub async fn run(self, pool: &mut PgT<'_>) -> Result> { + sqlx::query_as( + r#" +DELETE FROM product_variants +WHERE id = $1 + "#, + ) + .bind(self.product_variant_id) + .fetch_optional(pool) + .await + .map_err(|_e| Error::DeleteProductVariant(self.product_variant_id)) + } +} diff --git a/crates/stock_manager/src/db/products.rs b/crates/stock_manager/src/db/products.rs index 04deed6..0bf5195 100644 --- a/crates/stock_manager/src/db/products.rs +++ b/crates/stock_manager/src/db/products.rs @@ -342,10 +342,7 @@ mod tests { let updated = UpdateProduct { id: original.id, name: ProductName::new("a9s0dja0sjd0jas09dj"), - short_description: ProductShortDesc::new("ajs9d8ua9sdu9ahsd98has"), - long_description: ProductLongDesc::new("hja89sdy9yha9sdy98ayusd9hya9sy8dh"), category: None, - price: Price::from_u32(823794), deliver_days_flag: Day::Tuesday | Day::Saturday, } .run(&mut t)