2022-04-18 22:07:52 +02:00
|
|
|
use actix::Message;
|
2022-04-15 17:04:23 +02:00
|
|
|
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 {
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Unable to load all stocks")]
|
2022-04-15 17:04:23 +02:00
|
|
|
All,
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Unable to create stock")]
|
2022-04-15 17:04:23 +02:00
|
|
|
Create,
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Unable to update stock")]
|
2022-04-15 17:04:23 +02:00
|
|
|
Update,
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Unable to delete stock")]
|
2022-04-15 17:04:23 +02:00
|
|
|
Delete,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[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>);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 07:31:19 +02:00
|
|
|
async fn all_stocks(_msg: AllStocks, pool: PgPool) -> Result<Vec<model::Stock>> {
|
2022-04-15 17:04:23 +02:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
crate::db_async_handler!(CreateStock, create_stock, Stock);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 07:31:19 +02:00
|
|
|
async fn create_stock(msg: CreateStock, pool: PgPool) -> Result<model::Stock> {
|
2022-04-15 17:04:23 +02:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
crate::db_async_handler!(UpdateStock, update_stock, Stock);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 07:31:19 +02:00
|
|
|
async fn update_stock(msg: UpdateStock, pool: PgPool) -> Result<model::Stock> {
|
2022-04-15 17:04:23 +02:00
|
|
|
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,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
crate::db_async_handler!(DeleteStock, delete_stock, Option<model::Stock>);
|
2022-04-15 17:04:23 +02:00
|
|
|
|
2022-04-16 07:31:19 +02:00
|
|
|
async fn delete_stock(msg: DeleteStock, pool: PgPool) -> Result<Option<Stock>> {
|
2022-04-15 17:04:23 +02:00
|
|
|
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)
|
|
|
|
})
|
|
|
|
}
|