use std::collections::HashMap; use mongod::{ derive::{Model, Referencable}, Validate, }; use mongodb::bson::doc; use serde::{Deserialize, Serialize}; use serde_json::json; use crate::variant::Variant; // todo : api key auth // ITEM // VARIANTS // QUANTIZATION // IMPORT / EXPORT // DEPENDENCIES // DEMAND STATS // SEASONAL REVIEWS /// Represents a single item in a collection of physical goods. /// /// This struct serves as a blueprint for describing individual items within /// a larger inventory or database of physical goods. It includes fields for /// the name of the item and its category. #[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)] pub struct Item { /// The ID pub _id: String, /// The name of the Item pub name: String, /// Category of the Item pub category: Option, /// The variants of an Item. /// Each key of the `HashMap<_>` is the ID of a variant and contains a `Variant` pub variants: HashMap, } impl Validate for Item { async fn validate(&self) -> Result<(), String> { Ok(()) } } 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 category = doc .frontmatter .as_mapping() .unwrap() .get("category") .map(|x| x.as_str().unwrap().to_string()); let name = doc .frontmatter .as_mapping() .unwrap() .get("name") .unwrap() .as_str() .unwrap() .to_string(); let mut variants = HashMap::new(); let variants_lst = doc .frontmatter .as_mapping() .unwrap() .get("variants") .map(|x| x.as_mapping().unwrap().clone()) .unwrap(); assert!( !variants_lst.is_empty(), "Item {id} needs at least one variant." ); for (variant_id, variant) in variants_lst { variants.insert( variant_id.as_str().unwrap().to_string(), Variant::from_yml(&variant, variant_id.as_str().unwrap(), &id), ); } Self { _id: id, name, category, variants, } } } impl Item { /// Get this items variant names pub fn get_variants(&self) -> Vec { self.variants.keys().cloned().collect() } /// Get a `Variant` of an `Item` pub fn variant(&self, variant: &str) -> Option { self.variants.get(variant).cloned() } pub fn api_json(&self) -> serde_json::Value { let variants: HashMap = self .variants .iter() .map(|(key, value)| (key.clone(), value.api_json())) .collect(); json!({ "item": self.name, "category": self.category, "variants": variants }) } }