cdb/src/variant.rs

226 lines
6.1 KiB
Rust
Raw Normal View History

2024-07-24 14:38:56 +00:00
use mongod::Model;
2024-05-03 16:22:59 +00:00
use mongodb::bson::doc;
2024-07-24 14:38:56 +00:00
use serde::{Deserialize, Serialize};
2024-06-22 00:05:22 +00:00
use serde_json::json;
2024-05-03 16:22:59 +00:00
2024-08-28 07:38:10 +00:00
use crate::transaction::{Price, Transaction};
2024-05-03 16:22:59 +00:00
2024-08-28 07:38:10 +00:00
pub fn sort_by_timestamp() -> mongodb::bson::Document {
doc! { "timestamp": mongod::Sort::Descending }
2024-08-28 07:14:33 +00:00
}
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)
}
2024-05-03 16:22:59 +00:00
/// 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-07-24 14:38:56 +00:00
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
2024-05-03 16:22:59 +00:00
pub struct Variant {
2024-05-10 09:59:05 +00:00
/// Associated Item
2024-05-03 16:22:59 +00:00
pub item: String,
2024-08-28 07:38:10 +00:00
/// Variant ID
2024-05-03 16:22:59 +00:00
pub variant: String,
2024-08-28 07:38:10 +00:00
/// Variant Name
pub name: String,
2024-05-03 16:22:59 +00:00
}
impl Variant {
2024-05-10 09:59:05 +00:00
/// Create variant from itemdb yaml
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(),
2024-08-28 07:38:10 +00:00
name: json
2024-05-06 06:24:23 +00:00
.as_mapping()
.unwrap()
2024-08-28 07:38:10 +00:00
.get("name")
.unwrap()
.as_str()
2024-05-10 08:56:07 +00:00
.unwrap()
2024-08-28 07:38:10 +00:00
.to_string(),
2024-05-06 06:24:23 +00:00
}
}
2024-05-10 09:59:05 +00:00
pub async fn supply_log(&self) -> Vec<String> {
let filter = doc! {
"item": &self.item,
"variant": &self.variant
};
2024-08-28 07:14:33 +00:00
let result = Transaction::find_partial(filter, json!({}), None, None)
2024-08-13 02:13:38 +00:00
.await
.unwrap();
2024-05-10 09:59:05 +00:00
let mut ret = Vec::new();
for doc in result {
2024-07-24 14:38:56 +00:00
ret.push(doc._id);
2024-05-10 09:59:05 +00:00
}
ret
}
2024-08-13 02:13:38 +00:00
pub async fn inventory(&self) -> Vec<Transaction> {
let filter = doc! {
"item": &self.item,
"variant": &self.variant,
"consumed": { "$exists": false }
};
2024-08-28 07:14:33 +00:00
Transaction::find(filter, None, None).await.unwrap()
2024-08-13 02:13:38 +00:00
}
2024-05-10 09:59:05 +00:00
pub async fn demand_log(&self) -> Vec<String> {
let filter = doc! {
"item": &self.item,
2024-07-24 14:38:56 +00:00
"variant": &self.variant,
"consumed": { "$exists": true }
2024-05-10 09:59:05 +00:00
};
2024-08-28 07:14:33 +00:00
let result = Transaction::find_partial(filter, json!({}), None, None)
2024-08-13 02:13:38 +00:00
.await
.unwrap();
2024-05-10 09:59:05 +00:00
let mut ret = Vec::new();
for doc in result {
2024-07-24 14:38:56 +00:00
ret.push(doc._id);
2024-05-10 09:59:05 +00:00
}
ret
}
2024-07-24 14:38:56 +00:00
pub async fn demand(uuid: &str, price: Price, destination: &str) -> Option<()> {
// check if transaction exists
let mut t = Transaction::get(uuid).await?;
2024-08-28 07:14:33 +00:00
t.consume(price, destination).await;
2024-07-24 14:38:56 +00:00
Some(())
2024-05-03 16:22:59 +00:00
}
/// 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.
2024-07-24 14:38:56 +00:00
pub async fn supply(&self, price: Price, origin: Option<&str>) -> String {
let t = Transaction::new(&self.item, &self.variant, price, origin);
2024-05-03 16:22:59 +00:00
2024-07-24 14:38:56 +00:00
t.insert().await.unwrap();
2024-05-10 08:56:07 +00:00
2024-07-24 14:38:56 +00:00
t._id
2024-05-03 16:22:59 +00:00
}
2024-05-10 08:56:07 +00:00
2024-08-28 07:14:33 +00:00
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,
2024-08-28 07:38:10 +00:00
Some(sort_by_timestamp()),
2024-08-28 07:14:33 +00:00
)
.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);
}
2024-08-28 07:38:10 +00:00
Transaction::find(filter, Some(1), Some(sort_by_timestamp()))
2024-08-28 07:14:33 +00:00
.await
.unwrap()
.first()
.unwrap()
.price
.clone()
}
2024-08-27 21:33:09 +00:00
pub async fn stat(&self) -> serde_json::Value {
let active_transactions = self.inventory().await;
// fix : ignores currency
let total_price: f64 = active_transactions.iter().map(|x| x.price.value).sum();
json!({
"amount": active_transactions.len(),
"total_price": total_price
})
}
2024-06-22 00:05:22 +00:00
pub fn api_json(&self) -> serde_json::Value {
json!({
"item": self.item,
"variant": self.variant,
2024-08-28 07:38:10 +00:00
"name": self.name
2024-06-22 00:05:22 +00:00
})
}
2024-05-03 16:22:59 +00:00
}