bazzar/actors/database_manager/src/stocks.rs

163 lines
3.6 KiB
Rust
Raw Normal View History

2022-04-18 22:07:52 +02:00
use actix::Message;
2022-05-06 11:47:18 +02:00
use model::{ProductId, Quantity, QuantityUnit, Stock, StockId};
use sqlx::PgPool;
2022-05-12 20:33:16 +02:00
use crate::{MultiLoad, Result};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Unable to load all stocks")]
All,
#[error("Unable to create stock")]
Create,
#[error("Unable to update stock")]
Update,
#[error("Unable to delete stock")]
Delete,
2022-05-12 20:33:16 +02:00
#[error("Unable find stock for product")]
ProductStock,
}
#[derive(Message)]
#[rtype(result = "Result<Vec<model::Stock>>")]
pub struct AllStocks;
2022-04-16 18:57:37 +02:00
crate::db_async_handler!(AllStocks, all_stocks, Vec<Stock>);
async fn all_stocks(_msg: AllStocks, pool: PgPool) -> Result<Vec<model::Stock>> {
sqlx::query_as(
r#"
SELECT id, product_id, quantity, quantity_unit
FROM stocks
"#,
)
.fetch_all(&pool)
.await
.map_err(|e| {
log::error!("{e:?}");
2022-05-06 11:47:18 +02:00
crate::Error::Stock(Error::All)
})
}
#[derive(Message)]
#[rtype(result = "Result<model::Stock>")]
pub struct CreateStock {
pub product_id: ProductId,
pub quantity: Quantity,
pub quantity_unit: QuantityUnit,
}
2022-04-16 18:57:37 +02:00
crate::db_async_handler!(CreateStock, create_stock, Stock);
async fn create_stock(msg: CreateStock, pool: PgPool) -> Result<model::Stock> {
sqlx::query_as(
r#"
2022-04-19 16:49:30 +02:00
INSERT INTO stocks (product_id, quantity, quantity_unit)
VALUES ($1, $2, $3)
RETURNING id, product_id, quantity, quantity_unit
"#,
)
.bind(msg.product_id)
.bind(msg.quantity)
.bind(msg.quantity_unit)
.fetch_one(&pool)
.await
.map_err(|e| {
log::error!("{e:?}");
2022-05-06 11:47:18 +02:00
crate::Error::Stock(Error::Create)
})
}
#[derive(Message)]
#[rtype(result = "Result<model::Stock>")]
pub struct UpdateStock {
pub id: StockId,
pub product_id: ProductId,
pub quantity: Quantity,
pub quantity_unit: QuantityUnit,
}
2022-04-16 18:57:37 +02:00
crate::db_async_handler!(UpdateStock, update_stock, Stock);
async fn update_stock(msg: UpdateStock, pool: PgPool) -> Result<model::Stock> {
sqlx::query_as(
r#"
UPDATE stocks
SET product_id = $1 AND
quantity = $2
quantity_unit = $3
WHERE id = $4
RETURNING id, product_id, quantity, quantity_unit
"#,
)
.bind(msg.product_id)
.bind(msg.quantity)
.bind(msg.quantity_unit)
.bind(msg.id)
.fetch_one(&pool)
.await
.map_err(|e| {
log::error!("{e:?}");
2022-05-06 11:47:18 +02:00
crate::Error::Stock(Error::Update)
})
}
#[derive(Message)]
#[rtype(result = "Result<Option<model::Stock>>")]
pub struct DeleteStock {
pub stock_id: StockId,
}
2022-04-16 18:57:37 +02:00
crate::db_async_handler!(DeleteStock, delete_stock, Option<model::Stock>);
async fn delete_stock(msg: DeleteStock, pool: PgPool) -> Result<Option<Stock>> {
sqlx::query_as(
r#"
DELETE FROM stocks
WHERE id = $1
RETURNING id, product_id, quantity, quantity_unit
"#,
)
.bind(msg.stock_id)
.fetch_optional(&pool)
.await
.map_err(|e| {
log::error!("{e:?}");
2022-05-06 11:47:18 +02:00
crate::Error::Stock(Error::Delete)
})
}
2022-05-12 20:33:16 +02:00
#[derive(Message)]
#[rtype(result = "Result<Vec<model::Stock>>")]
pub struct ProductsStock {
pub product_ids: Vec<ProductId>,
}
crate::db_async_handler!(
ProductsStock,
product_stock,
Vec<model::Stock>,
inner_product_stock
);
async fn product_stock(
msg: ProductsStock,
pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<Vec<model::Stock>> {
Ok(MultiLoad::new(
pool,
r#"
SELECT id, product_id, quantity, quantity_unit
FROM stocks
WHERE
"#,
" product_id =",
)
.load(
msg.product_ids.len(),
msg.product_ids.into_iter().map(|id| *id),
|_e| crate::Error::Stock(Error::ProductStock),
)
.await?)
}