From d5a82fff6a2a15411bcb6583e9fd782b7230e61c Mon Sep 17 00:00:00 2001 From: JMARyA Date: Mon, 7 Oct 2024 21:23:16 +0200 Subject: [PATCH 01/10] fix --- migrations/0000_init.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/0000_init.sql b/migrations/0000_init.sql index d617aa1..fc53325 100644 --- a/migrations/0000_init.sql +++ b/migrations/0000_init.sql @@ -6,7 +6,7 @@ CREATE TABLE flows ( ended timestamptz, "next" UUID, produced UUID[], - FOREIGN KEY "next" REFERENCES flows(id) + FOREIGN KEY("next") REFERENCES flows(id) ); CREATE TABLE flow_notes ( From b4df75dcb6cfb52f868ae790ede64c3d3a017ba9 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Mon, 7 Oct 2024 21:28:07 +0200 Subject: [PATCH 02/10] fix --- migrations/0000_init.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/0000_init.sql b/migrations/0000_init.sql index fc53325..df24d2d 100644 --- a/migrations/0000_init.sql +++ b/migrations/0000_init.sql @@ -14,7 +14,7 @@ CREATE TABLE flow_notes ( time timestamptz NOT NULL DEFAULT current_timestamp, content TEXT NOT NULL, on_flow UUID NOT NULL, - FOREIGN KEY on_flow REFERENCES flows(id) + FOREIGN KEY(on_flow) REFERENCES flows(id) ); CREATE TABLE transactions ( From 3eea2be3e8b08ccb1e7fd15562c2ea0dafec4384 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Mon, 7 Oct 2024 21:35:50 +0200 Subject: [PATCH 03/10] fix --- src/main.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index bdcfa6e..bcd321f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,6 +74,30 @@ macro_rules! get_locations { }; } + +pub static FLOW_INFO: OnceCell> = OnceCell::const_new(); + +#[macro_export] +macro_rules! get_flows { + () => { + if let Some(client) = $crate::FLOW_INFO.get() { + client + } else { + let mut flows: $crate::json_store::JSONStore<$crate::flow::FlowInfo> = + $crate::JSONStore::new("./flows"); + + let flow_keys: Vec<_> = flows.keys().cloned().collect(); + for flow_key in flow_keys { + let flow = flows.get_mut(&flow_key).unwrap(); + flow.id = flow_key.clone(); + } + + $crate::FLOW_INFO.set(flows).unwrap(); + $crate::FLOW_INFO.get().unwrap() + } + }; +} + // ░░░░░░░░░░▀▀▀██████▄▄▄░░░░░░░░░░ // ░░░░░░░░░░░░░░░░░▀▀▀████▄░░░░░░░ // ░░░░░░░░░░▄███████▀░░░▀███▄░░░░░ @@ -113,7 +137,7 @@ async fn rocket() -> _ { let config = config::get_config(); let itemdb = get_itemdb!().clone(); let locations = get_locations!().clone(); - let flows: JSONStore = JSONStore::new("./flows"); + let flows = get_flows!().clone(); integrity::verify_integrity(&config, &flows, &locations, &itemdb).await; rocket::build() From 64e23cc4ab69c3ed6282229c4a90ce96e6c9f3eb Mon Sep 17 00:00:00 2001 From: JMARyA Date: Mon, 7 Oct 2024 21:53:11 +0200 Subject: [PATCH 04/10] fix --- migrations/0000_init.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/0000_init.sql b/migrations/0000_init.sql index df24d2d..f38a7f4 100644 --- a/migrations/0000_init.sql +++ b/migrations/0000_init.sql @@ -22,7 +22,7 @@ CREATE TABLE transactions ( created timestamptz NOT NULL DEFAULT current_timestamp, item TEXT NOT NULL, variant TEXT NOT NULL, - price NUMERIC(2), + price DOUBLE PRECISION, origin TEXT, "location" TEXT, note TEXT, From b057c46cbe3e2db13fd895cec63e0ee83728bf7b Mon Sep 17 00:00:00 2001 From: JMARyA Date: Tue, 8 Oct 2024 10:42:21 +0200 Subject: [PATCH 05/10] add barcodes --- src/variant.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/variant.rs b/src/variant.rs index 03f3dc5..82a3400 100644 --- a/src/variant.rs +++ b/src/variant.rs @@ -43,6 +43,8 @@ pub struct Variant { pub min: Option, /// Days until expiry pub expiry: Option, + /// Associated barcodes + pub barcodes: Option> } impl Variant { @@ -69,6 +71,9 @@ impl Variant { .unwrap() .get("expiry") .map(|x| x.as_i64().unwrap()), + barcodes: json.as_mapping().unwrap().get("barcodes").map(|x| { + x.as_sequence().unwrap().into_iter().map(|x| x.as_i64().unwrap()).collect() + }) } } @@ -294,7 +299,8 @@ impl Variant { "variant": self.variant, "name": self.name, "min": self.min, - "expiry": self.expiry + "expiry": self.expiry, + "barcodes": self.barcodes }) } } From 6c6ee93fbf5c02aedddfb6ffdc84b336b02b8441 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Thu, 17 Oct 2024 11:33:03 +0200 Subject: [PATCH 06/10] update --- docs/Item.md | 11 +++++++++++ rocket.toml | 3 --- 2 files changed, 11 insertions(+), 3 deletions(-) delete mode 100644 rocket.toml diff --git a/docs/Item.md b/docs/Item.md index 4b9caf9..5f8d280 100644 --- a/docs/Item.md +++ b/docs/Item.md @@ -64,3 +64,14 @@ variants: ``` This will mark any item variant as expired if it's older than 30 days. + +### Barcodes +You can associate barcodes with your item variants. This is useful for Quick Adding Items. + +```yml +name: "Water" +variants: + regular: + name: "Regular Water" + barcodes: [12345678] +``` diff --git a/rocket.toml b/rocket.toml deleted file mode 100644 index 30421bb..0000000 --- a/rocket.toml +++ /dev/null @@ -1,3 +0,0 @@ -[default] -address = "0.0.0.0" -port = 8080 From 4c0769199c9872ad5de5d04ac2faf5d012c3db07 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Fri, 18 Oct 2024 10:57:38 +0200 Subject: [PATCH 07/10] image --- src/item.rs | 35 +++++++++++++++++++++++++++++------ src/main.rs | 1 - src/routes/item/mod.rs | 12 ++++++++++++ src/variant.rs | 10 +++++++--- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/item.rs b/src/item.rs index f08f72e..9fdba58 100644 --- a/src/item.rs +++ b/src/item.rs @@ -28,20 +28,37 @@ pub struct Item { pub name: String, /// Category of the Item pub category: Option, + /// Image + pub image_path: Option, /// The variants of an Item. /// Each key of the `HashMap<_>` is the ID of a variant and contains a `Variant` pub variants: HashMap, } +pub fn get_image(path: &std::path::Path) -> Option { + let parent = path.parent()?; + let file_name = path.file_stem()?.to_str()?; + + for ext in ["jpg", "jpeg", "webp", "png"] { + let mut img_file = parent.to_path_buf(); + img_file.push(&format!("{file_name}.{ext}")); + + if img_file.exists() { + return Some(img_file.display().to_string()); + } + } + + None +} + impl Item { /// Creates a new `Item` from a parsed markdown document pub fn new(doc: &mdq::Document) -> Self { - let id = std::path::Path::new(&doc.path) - .file_stem() - .unwrap() - .to_str() - .unwrap() - .to_string(); + let path = std::path::Path::new(&doc.path); + + let id = path.file_stem().unwrap().to_str().unwrap().to_string(); + + let image_path = get_image(path); let category = doc .frontmatter @@ -86,6 +103,7 @@ impl Item { id, name, category, + image_path, variants, } } @@ -131,6 +149,11 @@ impl Item { json!({ "uuid": self.id, + "image": if self.image_path.is_some() { + Some(format!("/item/{}/image", self.id)) + } else { + None + }, "name": self.name, "category": self.category, "variants": variants diff --git a/src/main.rs b/src/main.rs index bcd321f..1a63e15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,7 +74,6 @@ macro_rules! get_locations { }; } - pub static FLOW_INFO: OnceCell> = OnceCell::const_new(); #[macro_export] diff --git a/src/routes/item/mod.rs b/src/routes/item/mod.rs index 0985e06..cc149a0 100644 --- a/src/routes/item/mod.rs +++ b/src/routes/item/mod.rs @@ -9,6 +9,7 @@ use std::str::FromStr; pub use demand::*; pub use error::*; pub use location::*; +use rocket::fs::NamedFile; use rocket::post; use rocket::serde::json::Json; use serde::Deserialize; @@ -62,6 +63,17 @@ pub fn item_route( Ok(item.api_json()) } +#[get("/item//image")] +pub async fn item_image_route(item_id: &str, itemdb: &State) -> Option { + let item = itemdb.get_item(item_id)?; + + if let Some(img_path) = &item.image_path { + return Some(NamedFile::open(img_path).await.ok()?); + } + + None +} + /// Returns all variants of an Item #[get("/item//variants")] pub fn item_variants_page( diff --git a/src/variant.rs b/src/variant.rs index 82a3400..be78064 100644 --- a/src/variant.rs +++ b/src/variant.rs @@ -44,7 +44,7 @@ pub struct Variant { /// Days until expiry pub expiry: Option, /// Associated barcodes - pub barcodes: Option> + pub barcodes: Option>, } impl Variant { @@ -72,8 +72,12 @@ impl Variant { .get("expiry") .map(|x| x.as_i64().unwrap()), barcodes: json.as_mapping().unwrap().get("barcodes").map(|x| { - x.as_sequence().unwrap().into_iter().map(|x| x.as_i64().unwrap()).collect() - }) + x.as_sequence() + .unwrap() + .into_iter() + .map(|x| x.as_i64().unwrap()) + .collect() + }), } } From 2823eea3ee97296a8a1bd8b4b5aa316031a5c7bc Mon Sep 17 00:00:00 2001 From: JMARyA Date: Sat, 19 Oct 2024 20:13:37 +0200 Subject: [PATCH 08/10] fix --- src/main.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 1a63e15..2309ea5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -173,7 +173,8 @@ async fn rocket() -> _ { routes::flow::active_flows_route, routes::flow::flow_api_route, routes::flow::create_flow_note_route, - routes::flow::flow_notes_route + routes::flow::flow_notes_route, + routes::item::item_image_route ], ) .manage(itemdb) From 1cc0b61c356177747ce44e580b72cb687b25b461 Mon Sep 17 00:00:00 2001 From: JMARyA Date: Sun, 20 Oct 2024 04:04:50 +0200 Subject: [PATCH 09/10] update --- schema/item.json | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/schema/item.json b/schema/item.json index 9f27fc2..3ce9805 100644 --- a/schema/item.json +++ b/schema/item.json @@ -15,27 +15,33 @@ "type": "string" }, "variants": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "title": "Item Variant", - "description": "A Variant of an Item", - "properties": { - "name": { - "type": "string", - "title": "Variant Name", - "description": "The name of the Variant" - }, - "min": { + "type": "object", + "minProperties": 1, + "title": "Item Variant", + "description": "A Variant of an Item", + "properties": { + "name": { + "type": "string", + "title": "Variant Name", + "description": "The name of the Variant" + }, + "min": { + "type": "number", + "title": "Minimum inventory", + "description": "The minimum amount of inventory for an Item. Thre actual inventory amount should always be higher than that." + }, + "expiry": { + "type": "number", + "title": "Expiry days", + "description": "Number of days until this item variant is considered expired." + }, + "barcodes": { + "type": "array", + "title": "Associated Barcodes", + "description": "Associated Barcodes", + "items": { "type": "number", - "title": "Minimum inventory", - "description": "The minimum amount of inventory for an Item. Thre actual inventory amount should always be higher than that." - }, - "expiry": { - "type": "number", - "title": "Expiry days", - "description": "Number of days until this item variant is considered expired." + "title": "Barcode" } } } From 31d5fd2b83dbcad5f73289583f2330882e41a08e Mon Sep 17 00:00:00 2001 From: JMARyA Date: Sun, 20 Oct 2024 22:13:10 +0200 Subject: [PATCH 10/10] fix --- src/db.rs | 2 +- src/item.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/db.rs b/src/db.rs index 5c441a5..0999819 100644 --- a/src/db.rs +++ b/src/db.rs @@ -27,7 +27,7 @@ impl ItemDB { /// Retrieves an item by name pub fn get_item(&self, item: &str) -> Option<&Item> { - self.index.get(item) + self.index.get(&item.to_lowercase()) } /// Get all items diff --git a/src/item.rs b/src/item.rs index 9fdba58..a407b4a 100644 --- a/src/item.rs +++ b/src/item.rs @@ -56,7 +56,7 @@ impl Item { pub fn new(doc: &mdq::Document) -> Self { let path = std::path::Path::new(&doc.path); - let id = path.file_stem().unwrap().to_str().unwrap().to_string(); + let id = path.file_stem().unwrap().to_str().unwrap().to_lowercase(); let image_path = get_image(path);