This commit is contained in:
JMARyA 2024-08-28 09:38:10 +02:00
parent 92e2da9cae
commit acf5ebae78
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 56 additions and 47 deletions

View file

@ -1,3 +1,5 @@
use mongod::Model;
use crate::item::Item; use crate::item::Item;
/// Item database /// Item database
@ -15,6 +17,7 @@ impl ItemDB {
for item in &index.documents { for item in &index.documents {
let item = Item::new(item); let item = Item::new(item);
item.insert_overwrite().await.unwrap();
log::info!("Adding item {} to DB", item.name); log::info!("Adding item {} to DB", item.name);
} }
@ -23,13 +26,11 @@ impl ItemDB {
/// Retrieves an item by name /// Retrieves an item by name
pub fn get_item(&self, item: &str) -> Option<Item> { pub fn get_item(&self, item: &str) -> Option<Item> {
Some(
self.index self.index
.documents .documents
.iter() .iter()
.map(Item::new) // <-- todo : performance? .map(Item::new) // <-- todo : performance?
.find(|x| x.name == item)?, .find(|x| x.name == item)
)
} }
/// Get all items /// Get all items

View file

@ -27,14 +27,14 @@ use crate::variant::Variant;
/// the name of the item and its category. /// the name of the item and its category.
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)] #[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
pub struct Item { pub struct Item {
/// The ID is the same as the name /// The ID
pub _id: String, pub _id: String,
/// The name of the Item /// The name of the Item
pub name: String, pub name: String,
/// Category of the Item /// Category of the Item
pub category: String, pub category: Option<String>,
/// The variants of an Item. /// The variants of an Item.
/// Each key of the `HashMap<_>` is the name of a variant and contains a `Variant` /// Each key of the `HashMap<_>` is the ID of a variant and contains a `Variant`
pub variants: HashMap<String, Variant>, pub variants: HashMap<String, Variant>,
} }
@ -47,17 +47,25 @@ impl Validate for Item {
impl Item { impl Item {
/// Creates a new `Item` from a parsed markdown document /// Creates a new `Item` from a parsed markdown document
pub fn new(doc: &mdq::Document) -> Self { pub fn new(doc: &mdq::Document) -> Self {
let name = std::path::Path::new(&doc.path) let id = std::path::Path::new(&doc.path)
.file_stem() .file_stem()
.unwrap() .unwrap()
.to_str() .to_str()
.unwrap() .unwrap()
.to_string(); .to_string();
let category = doc let category = doc
.frontmatter .frontmatter
.as_mapping() .as_mapping()
.unwrap() .unwrap()
.get("category") .get("category")
.map(|x| x.as_str().unwrap().to_string());
let name = doc
.frontmatter
.as_mapping()
.unwrap()
.get("name")
.unwrap() .unwrap()
.as_str() .as_str()
.unwrap() .unwrap()
@ -65,22 +73,28 @@ impl Item {
let mut variants = HashMap::new(); let mut variants = HashMap::new();
for (variant_name, variant) in doc let variants_lst = doc
.frontmatter .frontmatter
.as_mapping() .as_mapping()
.unwrap() .unwrap()
.get("variants") .get("variants")
.map(|x| x.as_mapping().unwrap().clone()) .map(|x| x.as_mapping().unwrap().clone())
.unwrap_or_default() .unwrap();
{
assert!(
!variants_lst.is_empty(),
"Item {id} needs at least one variant."
);
for (variant_id, variant) in variants_lst {
variants.insert( variants.insert(
variant_name.as_str().unwrap().to_string(), variant_id.as_str().unwrap().to_string(),
Variant::from_yml(&variant, variant_name.as_str().unwrap(), &name), Variant::from_yml(&variant, variant_id.as_str().unwrap(), &id),
); );
} }
Self { Self {
_id: name.clone(), _id: id,
name, name,
category, category,
variants, variants,

View file

@ -18,9 +18,10 @@ pub struct DemandForm {
price: String, price: String,
} }
/// Consumes a Transaction with Price and Destination
#[post("/demand", data = "<f>")] #[post("/demand", data = "<f>")]
pub async fn demand_route(f: Json<DemandForm>) -> FallibleApiResponse { pub async fn demand_route(f: Json<DemandForm>) -> FallibleApiResponse {
let uuid = Variant::demand( Variant::demand(
&f.uuid, &f.uuid,
f.price f.price
.clone() .clone()
@ -31,9 +32,10 @@ pub async fn demand_route(f: Json<DemandForm>) -> FallibleApiResponse {
.await .await
.ok_or_else(|| api_error("Demand failed"))?; .ok_or_else(|| api_error("Demand failed"))?;
Ok(json!({"uuid": uuid})) Ok(json!({"ok": 1}))
} }
/// Returns all used transactions for Item Variant
#[get("/item/<item_id>/<variant_id>/demand")] #[get("/item/<item_id>/<variant_id>/demand")]
pub async fn demand_log_route( pub async fn demand_log_route(
item_id: &str, item_id: &str,

View file

@ -18,6 +18,7 @@ pub struct SupplyForm {
origin: Option<String>, origin: Option<String>,
} }
/// Route for supply action. Creates a new Transaction for the specified Item Variant.
#[post("/supply", data = "<form>")] #[post("/supply", data = "<form>")]
pub async fn supply_route(form: Json<SupplyForm>, itemdb: &State<ItemDB>) -> FallibleApiResponse { pub async fn supply_route(form: Json<SupplyForm>, itemdb: &State<ItemDB>) -> FallibleApiResponse {
println!("{form:?}"); println!("{form:?}");
@ -40,6 +41,7 @@ pub async fn supply_route(form: Json<SupplyForm>, itemdb: &State<ItemDB>) -> Fal
Ok(json!({"uuid": transaction_id})) Ok(json!({"uuid": transaction_id}))
} }
/// Returns a list of Transaction UUIDs for the Item Variant
#[get("/item/<item_id>/<variant_id>/supply")] #[get("/item/<item_id>/<variant_id>/supply")]
pub async fn supply_log_route( pub async fn supply_log_route(
item_id: &str, item_id: &str,
@ -57,6 +59,7 @@ pub async fn supply_log_route(
Ok(json!(transactions)) Ok(json!(transactions))
} }
/// Returns current active Transactions for Item Variant
#[get("/item/<item_id>/<variant_id>/inventory")] #[get("/item/<item_id>/<variant_id>/inventory")]
pub async fn inventory_route( pub async fn inventory_route(
item_id: &str, item_id: &str,
@ -77,6 +80,7 @@ pub async fn inventory_route(
.collect::<Vec<_>>())) .collect::<Vec<_>>()))
} }
/// Returns statistics for the Item Variant
#[get("/item/<item_id>/<variant_id>/stat")] #[get("/item/<item_id>/<variant_id>/stat")]
pub async fn variant_stat_route( pub async fn variant_stat_route(
item_id: &str, item_id: &str,

View file

@ -50,7 +50,7 @@ impl Transaction {
variant: variant.to_string(), variant: variant.to_string(),
price, price,
consumed: None, consumed: None,
origin: origin.map(|x| x.to_string()), origin: origin.map(std::string::ToString::to_string),
timestamp: chrono::Utc::now().timestamp(), timestamp: chrono::Utc::now().timestamp(),
} }
} }
@ -61,7 +61,7 @@ impl Transaction {
"consumed": Consumed{destination: destination.to_string(),price, timestamp: chrono::Utc::now().timestamp() } "consumed": Consumed{destination: destination.to_string(),price, timestamp: chrono::Utc::now().timestamp() }
})) }))
.await .await
.ok().unwrap() .ok().unwrap();
} }
pub fn api_json(&self) -> serde_json::Value { pub fn api_json(&self) -> serde_json::Value {

View file

@ -3,10 +3,10 @@ use mongodb::bson::doc;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::json; use serde_json::json;
use crate::transaction::{Consumed, Price, Transaction}; use crate::transaction::{Price, Transaction};
pub fn sort_by_timestamp() -> Option<mongodb::bson::Document> { pub fn sort_by_timestamp() -> mongodb::bson::Document {
Some(doc! { "timestamp": mongod::Sort::Descending }) doc! { "timestamp": mongod::Sort::Descending }
} }
pub fn timestamp_range(year: i32, month: u32) -> (i64, i64) { pub fn timestamp_range(year: i32, month: u32) -> (i64, i64) {
@ -39,12 +39,10 @@ pub fn timestamp_range(year: i32, month: u32) -> (i64, i64) {
pub struct Variant { pub struct Variant {
/// Associated Item /// Associated Item
pub item: String, pub item: String,
/// Variant Name /// Variant ID
pub variant: String, pub variant: String,
/// Amount of items this variant represents /// Variant Name
pub amount: u64, pub name: String,
/// Dependencies for the item variant.
pub depends: Vec<String>,
} }
impl Variant { impl Variant {
@ -53,23 +51,14 @@ impl Variant {
Self { Self {
item: item.to_string(), item: item.to_string(),
variant: variant.to_string(), variant: variant.to_string(),
amount: json name: json
.as_mapping() .as_mapping()
.unwrap() .unwrap()
.get("amount") .get("name")
.map_or(1, |x| x.as_u64().unwrap()),
depends: json
.as_mapping()
.unwrap() .unwrap()
.get("depends") .as_str()
.map(|x| {
x.as_sequence()
.unwrap() .unwrap()
.iter() .to_string(),
.map(|x| x.as_str().unwrap().to_string())
.collect()
})
.unwrap_or_default(),
} }
} }
@ -167,7 +156,7 @@ impl Variant {
} }
}, },
None, None,
sort_by_timestamp(), Some(sort_by_timestamp()),
) )
.await .await
.unwrap() .unwrap()
@ -205,7 +194,7 @@ impl Variant {
filter.insert("origin", origin); filter.insert("origin", origin);
} }
Transaction::find(filter, Some(1), sort_by_timestamp()) Transaction::find(filter, Some(1), Some(sort_by_timestamp()))
.await .await
.unwrap() .unwrap()
.first() .first()
@ -230,8 +219,7 @@ impl Variant {
json!({ json!({
"item": self.item, "item": self.item,
"variant": self.variant, "variant": self.variant,
"amount": self.amount as u32, "name": self.name
"depends": self.depends
}) })
} }
} }