cdb/src/item.rs
2024-05-03 18:45:23 +02:00

189 lines
5 KiB
Rust

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::bson::Document> =
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<ItemInventoryEntry> {
let quantities: Collection<ItemInventoryEntry> =
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<String> {
let quantities: Collection<ItemInventoryEntry> =
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<String> {
let variants: Collection<ItemVariantEntry> =
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<Variant> {
let variants: Collection<mongodb::bson::Document> =
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<mongodb::bson::Document> =
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();
}
}