use mongodb::bson::doc; use crate::{ cdb_col, get_mongo, transaction::{BatchTransaction, 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. pub struct Variant { pub item: String, pub variant: String, } impl Variant { pub async fn demand(&self, uuid: &str, price: Price, destination: String) -> Option { let db = get_mongo!(); // check if supply transaction exists let supply_t = cdb_col!(db, "supply"); if supply_t .find_one(doc! { "_id": uuid }, None) .await .unwrap() .is_none() { return None; } // todo : demand batch // mark as used let demand_t = cdb_col!(db, "demand"); demand_t .insert_one( doc! { "_id": uuid, "destination": destination, "price": price.as_bson() }, None, ) .await .unwrap(); Some(uuid.to_string()) } /// Records a supply transaction in the database. /// /// # Arguments /// /// * `amount` - The quantity of items supplied. /// * `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, amount: usize, price: Price, origin: &str) -> String { let db = get_mongo!(); let mut ses = db.start_session(None).await.unwrap(); ses.start_transaction(None).await.unwrap(); let col: mongodb::Collection = ses.client().database("cdb").collection("supply"); let mut transactions = vec![]; for _ in 0..amount { transactions.push(Transaction::new( &self.item, &self.variant, price.clone(), origin, )); } for transaction in &transactions { let r = col .insert_one_with_session(transaction.as_doc(), None, &mut ses) .await .unwrap(); } // batch transaction let ret_uuid = if amount == 1 { transactions.first().unwrap().uuid.clone() } else { let batch = BatchTransaction::new(transactions.iter().map(|x| x.uuid.clone()).collect()); let col: mongodb::Collection = ses .client() .database("cdb") .collection("transactions_batch"); col.insert_one_with_session(batch.as_doc(), None, &mut ses) .await .unwrap(); batch.uuid }; // todo : transaction overlap cache -> scale ses.commit_transaction().await.unwrap(); ret_uuid } }