bazzar/api/src/actors/database/stocks.rs

129 lines
2.9 KiB
Rust
Raw Normal View History

use actix::{Handler, Message, ResponseActFuture, WrapFuture};
use sqlx::PgPool;
use super::Result;
use crate::database::Database;
use crate::model::{ProductId, Quantity, QuantityUnit, Stock, StockId};
use crate::{database, model};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Unable to load all products")]
All,
#[error("Unable to create product")]
Create,
#[error("Unable to update product")]
Update,
#[error("Unable to delete product")]
Delete,
}
#[derive(Message)]
#[rtype(result = "Result<Vec<model::Stock>>")]
pub struct AllStocks;
crate::async_handler!(AllStocks, all, Vec<Stock>);
async fn all(_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:?}");
database::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,
}
crate::async_handler!(CreateStock, create_product, Stock);
async fn create_product(msg: CreateStock, pool: PgPool) -> Result<model::Stock> {
sqlx::query_as(
r#"
INSERT INTO stocks (product_id, quantity)
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:?}");
database::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,
}
crate::async_handler!(UpdateStock, update_product, Stock);
async fn update_product(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:?}");
database::Error::Stock(Error::Update)
})
}
#[derive(Message)]
#[rtype(result = "Result<Option<model::Stock>>")]
pub struct DeleteStock {
pub stock_id: StockId,
}
crate::async_handler!(DeleteStock, delete_product, Option<model::Stock>);
async fn delete_product(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:?}");
database::Error::Stock(Error::Delete)
})
}