2024-05-03 16:22:59 +00:00
|
|
|
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.
|
2024-05-06 06:24:23 +00:00
|
|
|
#[derive(Debug, Clone)]
|
2024-05-03 16:22:59 +00:00
|
|
|
pub struct Variant {
|
|
|
|
pub item: String,
|
|
|
|
pub variant: String,
|
2024-05-06 06:24:23 +00:00
|
|
|
pub amount: u64,
|
2024-05-03 16:22:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Variant {
|
2024-05-06 06:24:23 +00:00
|
|
|
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(|x| x.as_u64().unwrap())
|
|
|
|
.unwrap_or(1),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-03 16:22:59 +00:00
|
|
|
pub async fn demand(&self, uuid: &str, price: Price, destination: String) -> Option<String> {
|
|
|
|
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();
|
2024-05-03 17:07:42 +00:00
|
|
|
ses.start_transaction(None).await.unwrap();
|
2024-05-03 16:22:59 +00:00
|
|
|
|
|
|
|
let col: mongodb::Collection<mongodb::bson::Document> =
|
|
|
|
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<mongodb::bson::Document> = 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
|
|
|
|
}
|
|
|
|
}
|