pub enum TransactionType { Batch(BatchTransaction), Normal(Transaction), } impl TransactionType { pub fn from(b: mongodb::bson::Document) -> Self { if let Ok(kind) = b.get_str("kind") { if kind == "batch" { return Self::Batch(BatchTransaction::from(b)); } } Self::Normal(Transaction::from(b)) } } pub struct Transaction { pub uuid: String, pub item: String, pub variant: String, pub price: Price, pub origin: String, pub timestamp: i64, } impl Transaction { pub fn new(item: &str, variant: &str, price: Price, origin: &str) -> Self { Self { uuid: uuid::Uuid::new_v4().to_string(), item: item.to_string(), variant: variant.to_string(), price, origin: origin.to_string(), timestamp: chrono::Utc::now().timestamp(), } } pub fn as_doc(&self) -> mongodb::bson::Document { mongodb::bson::doc! { "_id": &self.uuid, "item": &self.item, "variant": &self.variant, "price": self.price.as_bson(), "origin": &self.origin, "timestamp": self.timestamp } } fn from(b: mongodb::bson::Document) -> Self { let uuid = b.get_str("oid").unwrap().to_string(); let item = b.get_str("item").unwrap().to_string(); let variant = b.get_str("variant").unwrap().to_string(); let origin = b.get_str("origin").unwrap().to_string(); let timestamp = b.get_i64("timestamp").unwrap(); let price = Price::from(b); Self { uuid, item, variant, price, origin, timestamp, } } } pub struct BatchTransaction { pub uuid: String, pub transactions: Vec, } impl BatchTransaction { pub fn new(transactions: Vec) -> Self { Self { uuid: uuid::Uuid::new_v4().to_string(), transactions, } } pub fn as_doc(&self) -> mongodb::bson::Document { mongodb::bson::doc! { "_id": &self.uuid, "kind": "batch", "transactions": &self.transactions } } fn from(b: mongodb::bson::Document) -> Self { let uuid = b.get_str("_id").unwrap().to_string(); let transactions = b .get_array("transactions") .unwrap() .into_iter() .map(|x| x.as_str().unwrap().to_string()) .collect(); Self { uuid, transactions } } } #[derive(Debug, Clone)] pub struct Price { pub value: f64, pub currency: String, } impl Price { pub fn new(value: f64, currency: &str) -> Self { Self { value, currency: currency.to_string(), } } fn parse(price: &str) -> Option { let (value, currency) = price.split_once(' ')?; Some(Self { value: value.parse().ok()?, currency: currency.to_string(), }) } pub fn as_bson(&self) -> mongodb::bson::Bson { mongodb::bson::bson!({ "value": self.value, "currency": self.currency.clone() }) } } impl From for Price { fn from(value: mongodb::bson::Document) -> Self { Self { value: value.get_f64("value").unwrap(), currency: value.get_str("currency").unwrap().to_string(), } } } impl TryFrom for Price { type Error = (); fn try_from(value: String) -> Result { Self::parse(&value).ok_or(()) } }