This commit is contained in:
JMARyA 2024-08-28 09:14:33 +02:00
parent 74b07a0ea3
commit 92e2da9cae
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
5 changed files with 300 additions and 143 deletions

View file

@ -1,19 +1,27 @@
use mongod::{
derive::{Model, Referencable},
Validate,
Model, Validate,
};
use mongodb::bson::doc;
use serde::{Deserialize, Serialize};
use serde_json::json;
/// A Transaction of an Item Variant
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
pub struct Transaction {
/// UUID
pub _id: String,
/// Associated Item
pub item: String,
/// Associated Variant
pub variant: String,
/// Price of obtaining the Item
pub price: Price,
/// Origin of the Item
pub origin: Option<String>,
/// Info on consumption of the Item
pub consumed: Option<Consumed>,
/// Timestamp of the Transaction
pub timestamp: i64,
}
@ -23,10 +31,15 @@ impl Validate for Transaction {
}
}
/// Information about consumed Items
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Consumed {
/// Destination of the Item or who consumed it
pub destination: String,
/// Price the Item was exported or consumed at
pub price: Price,
/// Timestamp of Consumption
pub timestamp: i64,
}
impl Transaction {
@ -42,6 +55,15 @@ impl Transaction {
}
}
/// Consumes the Item with `price` and `destination`
pub async fn consume(&mut self, price: Price, destination: &str) {
self.update(&json!({
"consumed": Consumed{destination: destination.to_string(),price, timestamp: chrono::Utc::now().timestamp() }
}))
.await
.ok().unwrap()
}
pub fn api_json(&self) -> serde_json::Value {
json!({
"uuid": self._id,
@ -49,14 +71,18 @@ impl Transaction {
"variant": self.variant,
"price": self.price,
"origin": self.origin,
"timestamp": self.timestamp
"timestamp": self.timestamp,
"consumed": self.consumed
})
}
}
/// Economic Price
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Price {
/// Value of the currency
pub value: f64,
/// Kind of currency
pub currency: String,
}

View file

@ -5,6 +5,30 @@ use serde_json::json;
use crate::transaction::{Consumed, Price, Transaction};
pub fn sort_by_timestamp() -> Option<mongodb::bson::Document> {
Some(doc! { "timestamp": mongod::Sort::Descending })
}
pub fn timestamp_range(year: i32, month: u32) -> (i64, i64) {
let d = chrono::NaiveDate::from_ymd_opt(year, month, 0).unwrap();
let t = chrono::NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap();
let start = chrono::NaiveDateTime::new(d, t).and_utc().timestamp();
assert!(month <= 12);
let end = if month == 12 {
let d = chrono::NaiveDate::from_ymd_opt(year + 1, month, 0).unwrap();
let t = chrono::NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap();
chrono::NaiveDateTime::new(d, t).and_utc().timestamp()
} else {
let d = chrono::NaiveDate::from_ymd_opt(year, month + 1, 0).unwrap();
let t = chrono::NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap();
chrono::NaiveDateTime::new(d, t).and_utc().timestamp()
};
(start, end)
}
/// Represents a specific instance of an item with potential variations.
///
/// This struct is used to describe a particular variation or instance of an item
@ -55,7 +79,7 @@ impl Variant {
"variant": &self.variant
};
let result = Transaction::find_partial(filter, json!({}), None)
let result = Transaction::find_partial(filter, json!({}), None, None)
.await
.unwrap();
@ -75,7 +99,7 @@ impl Variant {
"consumed": { "$exists": false }
};
Transaction::find(filter, None).await.unwrap()
Transaction::find(filter, None, None).await.unwrap()
}
pub async fn demand_log(&self) -> Vec<String> {
@ -85,7 +109,7 @@ impl Variant {
"consumed": { "$exists": true }
};
let result = Transaction::find_partial(filter, json!({}), None)
let result = Transaction::find_partial(filter, json!({}), None, None)
.await
.unwrap();
@ -101,12 +125,7 @@ impl Variant {
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()?;
t.consume(price, destination).await;
Some(())
}
@ -128,6 +147,73 @@ impl Variant {
t._id
}
pub async fn get_all_transactions(&self) -> Vec<Transaction> {
let filter = doc! {
"item": &self.item,
"variant": &self.variant
};
Transaction::find(filter, None, None).await.unwrap()
}
pub async fn get_transaction_timeslice(&self, year: i32, month: u32) -> Vec<Transaction> {
let (start, end) = timestamp_range(year, month);
Transaction::find(
doc! {
"timestamp": {
"$gte": start,
"$lte": end
}
},
None,
sort_by_timestamp(),
)
.await
.unwrap()
}
pub async fn get_unique_origins(&self) -> Vec<String> {
Transaction::unique(
doc! {
"item": &self.item,
"variant": &self.variant
},
"origin",
)
.await
}
pub async fn get_unique_destinations(&self) -> Vec<String> {
Transaction::unique(
doc! {
"item": &self.item,
"variant": &self.variant
},
"consumed.destination",
)
.await
}
pub async fn get_latest_price(&self, origin: Option<String>) -> Price {
let mut filter = doc! {
"item": &self.item,
"variant": &self.variant
};
if let Some(origin) = origin {
filter.insert("origin", origin);
}
Transaction::find(filter, Some(1), sort_by_timestamp())
.await
.unwrap()
.first()
.unwrap()
.price
.clone()
}
pub async fn stat(&self) -> serde_json::Value {
let active_transactions = self.inventory().await;