diff --git a/src/db.rs b/src/db.rs index 44517c6..718b69c 100644 --- a/src/db.rs +++ b/src/db.rs @@ -3,6 +3,7 @@ use crate::item::{Item, ItemEntry}; #[macro_export] macro_rules! collect_results { ($res:expr) => {{ + use futures::stream::TryStreamExt; let mut ret = vec![]; while let Some(doc) = $res.try_next().await.unwrap() { diff --git a/src/main.rs b/src/main.rs index 0481d66..da179b6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,6 +42,7 @@ async fn main() -> std::io::Result<()> { .service(routes::item::supply_route) .service(routes::item::item_variants_page) .service(routes::item::get_items_route) + .service(routes::item::demand_route) }) .bind(("0.0.0.0".to_string(), 8080))? .run() diff --git a/src/routes/item/mod.rs b/src/routes/item/mod.rs index cf4ef16..e4690f0 100644 --- a/src/routes/item/mod.rs +++ b/src/routes/item/mod.rs @@ -4,6 +4,7 @@ use serde::Deserialize; use crate::item; use crate::routes::bad_req; +use crate::variant::Variant; macro_rules! get_itemdb { ($req:expr) => {{ @@ -12,6 +13,40 @@ macro_rules! get_itemdb { }}; } +pub fn item_does_not_exist_error() -> actix_web::Error { + bad_req("The item does not exist") +} + +pub fn variant_does_not_exist_error() -> actix_web::Error { + bad_req("The item does not exist") +} + +#[derive(Debug, Deserialize)] +pub struct DemandForm { + uuid: String, + destination: String, + price: String, +} + +#[post("/demand")] +pub async fn demand_route( + req: HttpRequest, + f: actix_web::web::Form, +) -> actix_web::Result { + let itemdb = get_itemdb!(req); + let uuid = Variant::demand( + &f.uuid, + f.price + .clone() + .try_into() + .map_err(|_| bad_req("Price malformed"))?, + &f.destination, + ) + .await + .ok_or_else(|| bad_req("Demand failed"))?; + + Ok(actix_web::HttpResponse::Ok().json(serde_json::json!({"uuid": uuid}))) +} #[derive(Deserialize, Debug)] pub struct SupplyForm { item: String, @@ -30,10 +65,10 @@ pub async fn supply_route( println!("{form:?}"); let variant = itemdb .get_item(&form.item) - .ok_or_else(|| actix_web::error::ErrorBadRequest("The item does not exist"))? + .ok_or_else(item_does_not_exist_error)? .variant(&form.variant) .await - .ok_or_else(|| actix_web::error::ErrorBadRequest("The variant does not exist"))?; + .ok_or_else(variant_does_not_exist_error)?; let transaction_id = variant .supply( @@ -45,6 +80,7 @@ pub async fn supply_route( &form.origin, ) .await; + Ok(actix_web::HttpResponse::Ok().json(serde_json::json!({"uuid": transaction_id}))) } @@ -65,9 +101,7 @@ pub struct AddVariantForm { pub async fn item_variants_page(r: HttpRequest) -> actix_web::Result { let id = r.match_info().query("item_id"); let itemdb = get_itemdb!(r); - let item = itemdb - .get_item(id) - .ok_or_else(|| bad_req("The item does not exist"))?; + let item = itemdb.get_item(id).ok_or_else(item_does_not_exist_error)?; let variants = item.get_variants().await; Ok(HttpResponse::Ok().json(serde_json::json!({ @@ -75,3 +109,39 @@ pub async fn item_variants_page(r: HttpRequest) -> actix_web::Result actix_web::Result { + let itemdb = get_itemdb!(r); + let item_id = r.match_info().query("item_id"); + let variant_id = r.match_info().query("variant_id"); + + let variant = itemdb + .get_item(item_id) + .ok_or_else(item_does_not_exist_error)? + .variant(variant_id) + .await + .ok_or_else(variant_does_not_exist_error)?; + + let transactions = variant.supply_log().await; + + Ok(HttpResponse::Ok().json(serde_json::json!(transactions))) +} + +#[get("/item/{item_id}/{variant_id}/demand")] +pub async fn demand_log_route(r: HttpRequest) -> actix_web::Result { + let itemdb = get_itemdb!(r); + let item_id = r.match_info().query("item_id"); + let variant_id = r.match_info().query("variant_id"); + + let variant = itemdb + .get_item(item_id) + .ok_or_else(item_does_not_exist_error)? + .variant(variant_id) + .await + .ok_or_else(variant_does_not_exist_error)?; + + let transactions = variant.demand_log().await; + + Ok(HttpResponse::Ok().json(serde_json::json!(transactions))) +} diff --git a/src/variant.rs b/src/variant.rs index 9c3c40f..ab6ff1e 100644 --- a/src/variant.rs +++ b/src/variant.rs @@ -2,7 +2,7 @@ use mongodb::bson::doc; use crate::{ cache::InventoryCache, - cdb_col, get_mongo, + cdb_col, collect_results, get_mongo, transaction::{BatchTransaction, Price, Transaction}, }; @@ -14,13 +14,18 @@ use crate::{ /// configurations. #[derive(Debug, Clone)] pub struct Variant { + /// Associated Item pub item: String, + /// Variant Name pub variant: String, + /// Amount of items this variant represents pub amount: u64, + /// Dependencies for the item variant. pub depends: Vec, } impl Variant { + /// Create variant from itemdb yaml pub fn from_yml(json: &serde_yaml::Value, variant: &str, item: &str) -> Self { Self { item: item.to_string(), @@ -46,7 +51,55 @@ impl Variant { } } - pub async fn demand(&self, uuid: &str, price: Price, destination: String) -> Option { + pub async fn supply_log(&self) -> Vec { + let db = get_mongo!(); + + let supply = cdb_col!(db, "supply"); + + let filter = doc! { + "item": &self.item, + "variant": &self.variant + }; + + let mut db_res = supply.find(filter, None).await.unwrap(); + + let result: Vec = collect_results!(db_res); + + let mut ret = Vec::new(); + + for doc in result { + ret.push(doc.get("_id").unwrap().as_str().unwrap().to_string()); + } + + ret + } + + pub async fn demand_log(&self) -> Vec { + // todo : add referenced supply + + let db = get_mongo!(); + + let demand = cdb_col!(db, "demand"); + + let filter = doc! { + "item": &self.item, + "variant": &self.variant + }; + + let mut db_res = demand.find(filter, None).await.unwrap(); + + let result: Vec = collect_results!(db_res); + + let mut ret = Vec::new(); + + for doc in result { + ret.push(doc.get("_id").unwrap().as_str().unwrap().to_string()); + } + + ret + } + + pub async fn demand(uuid: &str, price: Price, destination: &str) -> Option { let db = get_mongo!(); // check if supply transaction exists @@ -76,6 +129,9 @@ impl Variant { .await .unwrap(); + // update cache + InventoryCache::remove(uuid).await; + Some(uuid.to_string()) }