use mongod::Model; use mongodb::bson::doc; use serde::{Deserialize, Serialize}; use serde_json::json; use crate::transaction::{Consumed, Price, Transaction}; /// Represents a specific instance of an item with potential variations. /// /// This struct is used to describe a particular variation or instance of an item /// in the real world. It may include attributes or properties that deviate from /// the standard definition of the item. For example, different colors, sizes, or /// configurations. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct Variant { /// Associated Item pub item: String, /// Variant Name pub variant: String, /// Amount of items this variant represents pub amount: u64, /// Dependencies for the item variant. pub depends: Vec, } impl Variant { /// Create variant from itemdb yaml pub fn from_yml(json: &serde_yaml::Value, variant: &str, item: &str) -> Self { Self { item: item.to_string(), variant: variant.to_string(), amount: json .as_mapping() .unwrap() .get("amount") .map_or(1, |x| x.as_u64().unwrap()), depends: json .as_mapping() .unwrap() .get("depends") .map(|x| { x.as_sequence() .unwrap() .iter() .map(|x| x.as_str().unwrap().to_string()) .collect() }) .unwrap_or_default(), } } pub async fn supply_log(&self) -> Vec { let filter = doc! { "item": &self.item, "variant": &self.variant }; let result = Transaction::find_partial(filter, json!({}), None).await.unwrap(); let mut ret = Vec::new(); for doc in result { ret.push(doc._id); } ret } pub async fn demand_log(&self) -> Vec { let filter = doc! { "item": &self.item, "variant": &self.variant, "consumed": { "$exists": true } }; let result = Transaction::find_partial(filter, json!({}), None).await.unwrap(); let mut ret = Vec::new(); for doc in result { ret.push(doc._id); } ret } pub async fn demand(uuid: &str, price: Price, destination: &str) -> Option<()> { // check if transaction exists let mut t = Transaction::get(uuid).await?; t.update(&json!({ "consumed": Consumed{ destination: destination.to_string(), price } })).await.ok()?; Some(()) } /// Records a supply transaction in the database. /// /// # Arguments /// /// * `price` - The price of the supplied items. /// * `origin` - The origin or source of the supplied items. /// /// # Returns /// /// Returns a UUID string representing the transaction. pub async fn supply(&self, price: Price, origin: Option<&str>) -> String { let t = Transaction::new(&self.item, &self.variant, price, origin); t.insert().await.unwrap(); t._id } pub fn api_json(&self) -> serde_json::Value { json!({ "item": self.item, "variant": self.variant, "amount": self.amount as u32, "depends": self.depends }) } }