From 91d39a4d8357e38d5a5ddc1b78cd3c73ff4a2a09 Mon Sep 17 00:00:00 2001 From: JMARyA <jmarya@hydrar.de> Date: Wed, 16 Apr 2025 04:27:45 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20refactor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{ => core}/flow.rs | 0 src/{ => core}/item.rs | 4 ++++ src/{ => core}/location.rs | 0 src/core/mod.rs | 5 +++++ src/{ => core}/transaction.rs | 5 ++++- src/{ => core}/variant.rs | 11 ++++++++++- src/main.rs | 11 ++++++----- 7 files changed, 29 insertions(+), 7 deletions(-) rename src/{ => core}/flow.rs (100%) rename src/{ => core}/item.rs (94%) rename src/{ => core}/location.rs (100%) create mode 100644 src/core/mod.rs rename src/{ => core}/transaction.rs (96%) rename src/{ => core}/variant.rs (96%) diff --git a/src/flow.rs b/src/core/flow.rs similarity index 100% rename from src/flow.rs rename to src/core/flow.rs diff --git a/src/item.rs b/src/core/item.rs similarity index 94% rename from src/item.rs rename to src/core/item.rs index a407b4a..65c182e 100644 --- a/src/item.rs +++ b/src/core/item.rs @@ -35,6 +35,7 @@ pub struct Item { pub variants: HashMap<String, Variant>, } +/// Get the path of an image file in `path` pub fn get_image(path: &std::path::Path) -> Option<String> { let parent = path.parent()?; let file_name = path.file_stem()?.to_str()?; @@ -120,12 +121,14 @@ impl Item { self.variants.get(variant).cloned() } + /// Get all active `Transaction`s of this `Item` not yet consumed pub async fn inventory(&self) -> Vec<Transaction> { sqlx::query_as("SELECT * FROM transactions WHERE item = $1 AND consumed_timestamp IS NULL ORDER BY created DESC") .bind(&self.id) .fetch_all(get_pg!()).await.unwrap() } + /// Get all active `Transaction`s of this `Item` not yet consumed of `origin` pub async fn inventory_by_origin(&self, origin: &str) -> Vec<Transaction> { sqlx::query_as("SELECT * FROM transactions WHERE item = $1 AND consumed_timestamp IS NULL AND origin = $2 ORDER BY created DESC") .bind(&self.id) @@ -133,6 +136,7 @@ impl Item { .fetch_all(get_pg!()).await.unwrap() } + /// Get all active `Transaction`s of this `Item` not yet consumed of `destination` pub async fn consumed_by_destination(&self, destination: &str) -> Vec<Transaction> { sqlx::query_as("SELECT * FROM transactions WHERE item = $1 AND consumed_timestamp IS NOT NULL AND destination = $2 ORDER BY created DESC") .bind(&self.id) diff --git a/src/location.rs b/src/core/location.rs similarity index 100% rename from src/location.rs rename to src/core/location.rs diff --git a/src/core/mod.rs b/src/core/mod.rs new file mode 100644 index 0000000..1761011 --- /dev/null +++ b/src/core/mod.rs @@ -0,0 +1,5 @@ +pub mod flow; +pub mod item; +pub mod location; +pub mod transaction; +pub mod variant; diff --git a/src/transaction.rs b/src/core/transaction.rs similarity index 96% rename from src/transaction.rs rename to src/core/transaction.rs index 5c2c71a..2b95645 100644 --- a/src/transaction.rs +++ b/src/core/transaction.rs @@ -54,14 +54,17 @@ impl Transaction { .fetch_one(get_pg!()).await.unwrap() } + /// Get a reference to the `Item` of the `Transaction` pub async fn item(&self) -> Option<&Item> { get_itemdb!().get_item(&self.item) } + /// Get a reference to the `Variant` of the `Item` of the `Transaction` pub async fn item_variant(&self) -> Option<Variant> { get_itemdb!().get_item(&self.item)?.variant(&self.variant) } + /// Get a `Transaction` via `id` pub async fn get(id: &uuid::Uuid) -> Option<Self> { sqlx::query_as("SELECT * FROM transactions WHERE id = $1") .bind(id) @@ -203,7 +206,7 @@ impl ToAPI for Transaction { "timestamp": self.created.timestamp(), "consumed": consumed, "note": self.note, - "expired": self.is_expired().await + "expired": self.is_expired().await, }) } } diff --git a/src/variant.rs b/src/core/variant.rs similarity index 96% rename from src/variant.rs rename to src/core/variant.rs index 692b44a..e14628b 100644 --- a/src/variant.rs +++ b/src/core/variant.rs @@ -104,6 +104,8 @@ impl Variant { } } + /// Get a API id for this Item Variant. + /// The ID has the format: `<ITEM>::<VARIANT>` pub fn item_variant_id(&self) -> String { format!("{}::{}", self.item, self.variant) } @@ -189,6 +191,7 @@ impl Variant { .unwrap() } + /// Get Transactions within `year` and `month` pub async fn get_transaction_timeslice(&self, year: i32, month: u32) -> Vec<Transaction> { let (start, end) = timestamp_range(year, month); @@ -198,6 +201,7 @@ impl Variant { .fetch_all(get_pg!()).await.unwrap() } + /// Get all unique origins pub async fn get_unique_origins(&self) -> Vec<String> { let res: Vec<(String,)> = sqlx::query_as("SELECT DISTINCT(origin) FROM transactions WHERE origin NOT LIKE 'flow::%' AND item = $1 AND variant = $2") .bind(&self.item) @@ -206,6 +210,7 @@ impl Variant { res.into_iter().map(|x| x.0).collect() } + /// Get all unique destinations pub async fn get_unique_destinations(&self) -> Vec<String> { let res: Vec<(String,)> = sqlx::query_as("SELECT DISTINCT(destination) FROM transactions WHERE destination NOT LIKE 'flow::%' AND item = $1 AND variant = $2") .bind(&self.item) @@ -214,6 +219,7 @@ impl Variant { res.into_iter().map(|x| x.0).collect() } + /// Get the last `limit` price values for `origin` pub async fn price_history_by_origin(&self, origin: &str, limit: Option<i64>) -> Vec<f64> { let res: Vec<(f64,)> = sqlx::query_as( &format!("SELECT price FROM transactions WHERE item = $1 AND variant = $2 AND origin = $3 ORDER BY created DESC {}", if let Some(limit) = limit { @@ -227,6 +233,7 @@ impl Variant { res.into_iter().map(|x| x.0).collect() } + /// Get the latest price for `origin` pub async fn get_latest_price(&self, origin: Option<String>) -> f64 { if let Some(origin) = origin { let res: (f64,) = sqlx::query_as("SELECT price FROM transactions WHERE item = $1 AND variant = $2 AND origin = $3 ORDER BY created DESC LIMIT 1") @@ -257,6 +264,7 @@ impl Variant { (false, 0) } + /// Check if the `Variant` satisfies `StorageConditions` pub async fn satisfy_condition(&self, conditions: &StorageConditions) -> bool { if let Some(needs) = &self.needs { if let Some(room_temp) = conditions.accurate_temperature().await { @@ -346,7 +354,8 @@ impl Variant { "name": self.name, "min": self.min, "expiry": self.expiry, - "barcodes": self.barcodes + "barcodes": self.barcodes, + "needs": self.needs }) } } diff --git a/src/main.rs b/src/main.rs index 67779c0..b97670f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,15 +7,16 @@ use rocket::{http::Method, launch}; use tokio::sync::OnceCell; mod config; +mod core; mod db; -mod flow; mod integrity; -mod item; mod json_store; -mod location; +pub use core::flow; +pub use core::item; +pub use core::location; +pub use core::transaction; +pub use core::variant; mod routes; -mod transaction; -mod variant; pub static PG: OnceCell<sqlx::PgPool> = OnceCell::const_new();