diff options
| author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-09-23 08:33:06 +0200 |
|---|---|---|
| committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-09-23 08:34:45 +0200 |
| commit | 2dc74d621399be454abbbff892fb46204ddc6e7b (patch) | |
| tree | f9525527fc09c465d4e2e4a4f665bfd444b889f8 /crates/rocie-server/src/storage/sql/get | |
| parent | feat: Provide basic barcode handling support (diff) | |
| download | server-2dc74d621399be454abbbff892fb46204ddc6e7b.zip | |
feat(treewide): Add tests and barcode buying/consuming
Diffstat (limited to 'crates/rocie-server/src/storage/sql/get')
4 files changed, 111 insertions, 2 deletions
diff --git a/crates/rocie-server/src/storage/sql/get/barcode/mod.rs b/crates/rocie-server/src/storage/sql/get/barcode/mod.rs new file mode 100644 index 0000000..7b656b1 --- /dev/null +++ b/crates/rocie-server/src/storage/sql/get/barcode/mod.rs @@ -0,0 +1,50 @@ +use crate::{ + app::App, + storage::sql::{ + barcode::{Barcode, BarcodeId, UnitAmount}, + unit::UnitId, + }, +}; + +use sqlx::query; + +impl Barcode { + pub(crate) async fn from_id(app: &App, id: BarcodeId) -> Result<Option<Self>, from_id::Error> { + let db_id = id.to_db(); + + let record = query!( + " + SELECT product_id, amount, unit + FROM barcodes + WHERE id = ? +", + db_id + ) + .fetch_optional(&app.db) + .await?; + + if let Some(record) = record { + Ok(Some(Self { + id, + amount: UnitAmount { + value: u32::try_from(record.amount).expect("Is strictly positive"), + unit: UnitId::from_db(&record.unit), + }, + })) + } else { + Ok(None) + } + } +} + +pub(crate) mod from_id { + use actix_web::ResponseError; + + #[derive(thiserror::Error, Debug)] + pub(crate) enum Error { + #[error("Failed to execute the sql query")] + SqlError(#[from] sqlx::Error), + } + + impl ResponseError for Error {} +} diff --git a/crates/rocie-server/src/storage/sql/get/mod.rs b/crates/rocie-server/src/storage/sql/get/mod.rs index fa22f81..048cb3d 100644 --- a/crates/rocie-server/src/storage/sql/get/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/mod.rs @@ -1,2 +1,4 @@ pub(crate) mod product; +pub(crate) mod product_amount; pub(crate) mod unit; +pub(crate) mod barcode; diff --git a/crates/rocie-server/src/storage/sql/get/product/mod.rs b/crates/rocie-server/src/storage/sql/get/product/mod.rs index d23297a..541f388 100644 --- a/crates/rocie-server/src/storage/sql/get/product/mod.rs +++ b/crates/rocie-server/src/storage/sql/get/product/mod.rs @@ -1,7 +1,8 @@ use crate::{ app::App, storage::sql::{ - product::{Barcode, Product, ProductId, UnitAmount}, + barcode::{Barcode, BarcodeId, UnitAmount}, + product::{Product, ProductId}, unit::UnitId, }, }; @@ -63,7 +64,7 @@ impl Product { associated_bar_codes: barcodes .into_iter() .map(|record| Barcode { - id: u32::try_from(record.id).expect("Should be strictly positive"), + id: BarcodeId::from_db(record.id), amount: UnitAmount { value: u32::try_from(record.amount) .expect("Should be strictly positve"), diff --git a/crates/rocie-server/src/storage/sql/get/product_amount/mod.rs b/crates/rocie-server/src/storage/sql/get/product_amount/mod.rs new file mode 100644 index 0000000..7700274 --- /dev/null +++ b/crates/rocie-server/src/storage/sql/get/product_amount/mod.rs @@ -0,0 +1,56 @@ +use crate::{ + app::App, + storage::sql::{ + barcode::UnitAmount, product::ProductId, product_amount::ProductAmount, unit::UnitId, + }, +}; + +use sqlx::query; + +impl ProductAmount { + pub(crate) async fn from_id( + app: &App, + product_id: ProductId, + ) -> Result<Option<Self>, from_id::Error> { + let record = query!( + r#" +SELECT + SUM(barcodes.amount - IFNULL(buys.used_amount,0)) "available_amount: u32", + barcodes.unit +FROM barcodes + JOIN products ON products.id = ? + JOIN buys ON buys.barcode_id = barcodes.id +GROUP BY barcodes.unit; +"#, + product_id + ) + .fetch_all(&app.db) + .await?; + + assert!(record.len() <= 1, "We currently only support one unit"); + + if let Some(record) = record.first() { + Ok(Some(Self { + product_id, + amount: UnitAmount { + value: record.available_amount.expect("Should always be set"), + unit: UnitId::from_db(&record.unit), + }, + })) + } else { + Ok(None) + } + } +} + +pub(crate) mod from_id { + use actix_web::ResponseError; + + #[derive(thiserror::Error, Debug)] + pub(crate) enum Error { + #[error("Failed to execute the sql query")] + SqlError(#[from] sqlx::Error), + } + + impl ResponseError for Error {} +} |
