Compare commits

..

No commits in common. "31d5fd2b83dbcad5f73289583f2330882e41a08e" and "55b318b2f17b6c74caac16eb1b22b3ee7c690202" have entirely different histories.

9 changed files with 36 additions and 119 deletions

View file

@ -64,14 +64,3 @@ 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]
```

View file

@ -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 (
@ -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 (
@ -22,7 +22,7 @@ CREATE TABLE transactions (
created timestamptz NOT NULL DEFAULT current_timestamp,
item TEXT NOT NULL,
variant TEXT NOT NULL,
price DOUBLE PRECISION,
price NUMERIC(2),
origin TEXT,
"location" TEXT,
note TEXT,

3
rocket.toml Normal file
View file

@ -0,0 +1,3 @@
[default]
address = "0.0.0.0"
port = 8080

View file

@ -15,33 +15,27 @@
"type": "string"
},
"variants": {
"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": "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": "number",
"title": "Barcode"
"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."
}
}
}

View file

@ -27,7 +27,7 @@ impl ItemDB {
/// Retrieves an item by name
pub fn get_item(&self, item: &str) -> Option<&Item> {
self.index.get(&item.to_lowercase())
self.index.get(item)
}
/// Get all items

View file

@ -28,37 +28,20 @@ pub struct Item {
pub name: String,
/// Category of the Item
pub category: Option<String>,
/// Image
pub image_path: Option<String>,
/// The variants of an Item.
/// Each key of the `HashMap<_>` is the ID of a variant and contains a `Variant`
pub variants: HashMap<String, Variant>,
}
pub fn get_image(path: &std::path::Path) -> Option<String> {
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 path = std::path::Path::new(&doc.path);
let id = path.file_stem().unwrap().to_str().unwrap().to_lowercase();
let image_path = get_image(path);
let id = std::path::Path::new(&doc.path)
.file_stem()
.unwrap()
.to_str()
.unwrap()
.to_string();
let category = doc
.frontmatter
@ -103,7 +86,6 @@ impl Item {
id,
name,
category,
image_path,
variants,
}
}
@ -149,11 +131,6 @@ 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

View file

@ -74,29 +74,6 @@ macro_rules! get_locations {
};
}
pub static FLOW_INFO: OnceCell<JSONStore<FlowInfo>> = 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()
}
};
}
// ░░░░░░░░░░▀▀▀██████▄▄▄░░░░░░░░░░
// ░░░░░░░░░░░░░░░░░▀▀▀████▄░░░░░░░
// ░░░░░░░░░░▄███████▀░░░▀███▄░░░░░
@ -136,7 +113,7 @@ async fn rocket() -> _ {
let config = config::get_config();
let itemdb = get_itemdb!().clone();
let locations = get_locations!().clone();
let flows = get_flows!().clone();
let flows: JSONStore<FlowInfo> = JSONStore::new("./flows");
integrity::verify_integrity(&config, &flows, &locations, &itemdb).await;
rocket::build()
@ -173,8 +150,7 @@ 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::item::item_image_route
routes::flow::flow_notes_route
],
)
.manage(itemdb)

View file

@ -9,7 +9,6 @@ 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;
@ -63,17 +62,6 @@ pub fn item_route(
Ok(item.api_json())
}
#[get("/item/<item_id>/image")]
pub async fn item_image_route(item_id: &str, itemdb: &State<ItemDB>) -> Option<NamedFile> {
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/<item_id>/variants")]
pub fn item_variants_page(

View file

@ -43,8 +43,6 @@ pub struct Variant {
pub min: Option<i64>,
/// Days until expiry
pub expiry: Option<i64>,
/// Associated barcodes
pub barcodes: Option<Vec<i64>>,
}
impl Variant {
@ -71,13 +69,6 @@ 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()
}),
}
}
@ -303,8 +294,7 @@ impl Variant {
"variant": self.variant,
"name": self.name,
"min": self.min,
"expiry": self.expiry,
"barcodes": self.barcodes
"expiry": self.expiry
})
}
}