bazzar/crates/stock_manager/src/db/product_variants.rs

114 lines
2.6 KiB
Rust

use db_utils::PgT;
use model::v2::*;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Failed to create product")]
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>;
#[derive(Debug)]
pub struct CreateProductVariant {
pub product_id: ProductId,
pub name: ProductName,
pub short_description: ProductShortDesc,
pub long_description: ProductLongDesc,
pub price: Price,
}
impl CreateProductVariant {
pub async fn run(self, pool: &mut PgT<'_>) -> Result<ProductVariant> {
sqlx::query_as(
r#"
INSERT INTO product_variants (
product_id,
name,
short_description,
long_description,
price
) VALUES ($1, $2, $3, $4, $5)
RETURNING id,
product_id,
name,
short_description,
long_description,
price
"#,
)
.bind(self.product_id)
.bind(self.name)
.bind(self.short_description)
.bind(self.long_description)
.bind(self.price)
.fetch_one(pool)
.await
.map_err(|e| {
tracing::error!("{}", e);
dbg!(e);
Error::CreateProductVariant
})
}
}
#[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))
}
}