use std::collections::HashSet; use crate::{collect_results, id_of}; use futures::TryStreamExt; use mongodb::{bson::doc, ClientSession, Collection}; use crate::variant::Variant; // todo : api key auth // ITEM // VARIANTS // QUANTIZATION // IMPORT / EXPORT // DEPENDENCIES // DEMAND STATS // SEASONAL REVIEWS #[derive(serde::Deserialize, serde::Serialize)] pub struct ItemVariantEntry { pub item_name: String, pub variant_name: String, } #[derive(serde::Deserialize, serde::Serialize)] pub struct ItemInventoryEntry { pub item_name: String, pub variant_name: String, pub origin: String, pub price: f64, } #[derive(serde::Deserialize, serde::Serialize)] pub struct ItemEntry { pub name: String, pub category: String, } impl ItemEntry { pub fn new(doc: mdq::Document) -> Self { let name = std::path::Path::new(&doc.path) .file_stem() .unwrap() .to_str() .unwrap() .to_string(); let category = doc .frontmatter .as_mapping() .unwrap() .get("category") .unwrap() .as_str() .unwrap() .to_string(); Self { name, category } } pub async fn init_db(&self, mongodb: &mongodb::Client) { log::info!("Adding item {} to DB", self.name); let items: Collection = mongodb.database("cdb").collection("items"); let doc = mongodb::bson::doc! { "_id": self.name.clone(), "name": self.name.clone(), "category": self.category.clone() }; if items .find_one(id_of!(&self.name), None) .await .unwrap() .is_none() { items.insert_one(doc, None).await.unwrap(); } else { items .find_one_and_update(id_of!(&self.name), doc, None) .await .unwrap(); } } } /// 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. pub struct Item { db: mongodb::Client, pub item: ItemEntry, } impl Item { pub fn new(db: mongodb::Client, item: ItemEntry) -> Self { Self { db, item } } pub async fn get_inventory_entries(&self) -> Vec { let quantities: Collection = self.db.database("cdb").collection("item_quantities"); let mut found = quantities .find(doc! { "item_name": self.item.name.clone()}, None) .await .unwrap(); collect_results!(found) } pub async fn get_origins(&self) -> Vec { let quantities: Collection = self.db.database("cdb").collection("item_quantities"); let mut found = quantities .find(doc! { "item_name": self.item.name.clone()}, None) .await .unwrap(); let mut hashset = HashSet::new(); while let Some(res) = found.try_next().await.unwrap() { hashset.insert(res.origin); } hashset.into_iter().collect() } pub async fn get_variants(&self) -> Vec { let variants: Collection = self.db.database("cdb").collection("item_variants"); let mut found_variants = variants .find( doc! { "item_name": self.item.name.clone() }, None, ) .await .unwrap(); let mut ret = vec!["Generic".to_string()]; while let Some(doc) = found_variants.try_next().await.unwrap() { ret.push(doc.variant_name); } ret } pub async fn variant(&self, variant: &str) -> Option { let variants: Collection = self.db.database("cdb").collection("variants"); let res = variants .find_one( doc! { "item": self.item.name.clone(), "variant": variant }, None, ) .await .unwrap()?; Some(Variant { item: self.item.name.clone(), variant: variant.to_string(), }) } pub async fn add_variant(&self, name: &str, amount: usize) { let variants: Collection = self.db.database("cdb").collection("variants"); variants .insert_one( mongodb::bson::doc! { "_id": format!("{}-{}", self.item.name.clone(), name), "item": self.item.name.clone(), "variant": name, "amount": amount as i64 }, None, ) .await .unwrap(); } }