Operations on product variants

This commit is contained in:
eraden 2022-11-10 06:36:55 +01:00
parent 755363c23f
commit 500dac9b2e
3 changed files with 79 additions and 11 deletions

View File

@ -1,11 +1,14 @@
use sqlx::Arguments; use sqlx::Arguments;
pub type PgT<'l> = sqlx::Transaction<'l, sqlx::Postgres>;
pub struct MultiLoad<'transaction, 'transaction2, 'header, 'condition, T> { pub struct MultiLoad<'transaction, 'transaction2, 'header, 'condition, T> {
pool: &'transaction mut sqlx::Transaction<'transaction2, sqlx::Postgres>, pool: &'transaction mut sqlx::Transaction<'transaction2, sqlx::Postgres>,
header: &'header str, header: &'header str,
condition: &'condition str, condition: &'condition str,
sort: Option<String>, sort: Option<String>,
size: Option<usize>, size: Option<usize>,
allow_over_max: bool,
__phantom: std::marker::PhantomData<T>, __phantom: std::marker::PhantomData<T>,
} }
@ -24,11 +27,17 @@ where
header, header,
condition, condition,
sort: None, sort: None,
size: None, size: Some(200),
allow_over_max: false,
__phantom: Default::default(), __phantom: Default::default(),
} }
} }
pub fn allow_over_max(mut self) -> Self {
self.allow_over_max = true;
self
}
pub fn with_sorting<S: Into<String>>(mut self, order: S) -> Self { pub fn with_sorting<S: Into<String>>(mut self, order: S) -> Self {
self.sort = Some(order.into()); self.sort = Some(order.into());
self self
@ -50,7 +59,11 @@ where
ErrorFn: Fn(sqlx::Error) -> Error, ErrorFn: Fn(sqlx::Error) -> Error,
{ {
let mut res = Vec::new(); 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( for ids in items.fold(
Vec::<Vec<model::RecordId>>::with_capacity(len), Vec::<Vec<model::RecordId>>::with_capacity(len),

View File

@ -1,9 +1,14 @@
use db_utils::PgT;
use model::v2::*; use model::v2::*;
#[derive(Debug, thiserror::Error)] #[derive(Debug, thiserror::Error)]
pub enum Error { pub enum Error {
#[error("")] #[error("Failed to create product")]
CreateProductVariant, CreateProductVariant,
#[error("Failed to load variants for products {0:?}")]
ProductsVariants(Vec<ProductId>),
#[error("Failed to delete product variant {0:?}")]
DeleteProductVariant(ProductVariantId),
} }
pub type Result<T> = std::result::Result<T, Error>; pub type Result<T> = std::result::Result<T, Error>;
@ -18,10 +23,7 @@ pub struct CreateProductVariant {
} }
impl CreateProductVariant { impl CreateProductVariant {
pub async fn run( pub async fn run(self, pool: &mut PgT<'_>) -> Result<ProductVariant> {
self,
pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<ProductVariant> {
sqlx::query_as( sqlx::query_as(
r#" r#"
INSERT INTO product_variants ( INSERT INTO product_variants (
@ -31,7 +33,7 @@ INSERT INTO product_variants (
long_description, long_description,
price price
) VALUES ($1, $2, $3, $4, $5) ) VALUES ($1, $2, $3, $4, $5)
RETURNINGS id, RETURNING id,
product_id, product_id,
name, name,
short_description, short_description,
@ -53,3 +55,59 @@ RETURNINGS id,
}) })
} }
} }
#[derive(Debug)]
pub struct ProductsVariants {
pub product_ids: Vec<ProductId>,
pub limit: Option<i32>,
pub offset: Option<i32>,
}
impl ProductsVariants {
pub async fn run(self, pool: &mut PgT<'_>) -> Result<Vec<ProductVariant>> {
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<Option<ProductVariant>> {
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))
}
}

View File

@ -342,10 +342,7 @@ mod tests {
let updated = UpdateProduct { let updated = UpdateProduct {
id: original.id, id: original.id,
name: ProductName::new("a9s0dja0sjd0jas09dj"), name: ProductName::new("a9s0dja0sjd0jas09dj"),
short_description: ProductShortDesc::new("ajs9d8ua9sdu9ahsd98has"),
long_description: ProductLongDesc::new("hja89sdy9yha9sdy98ayusd9hya9sy8dh"),
category: None, category: None,
price: Price::from_u32(823794),
deliver_days_flag: Day::Tuesday | Day::Saturday, deliver_days_flag: Day::Tuesday | Day::Saturday,
} }
.run(&mut t) .run(&mut t)