docs + locations
This commit is contained in:
parent
e1618b40ef
commit
48f00d8f6f
17 changed files with 390 additions and 33 deletions
44
src/json_store.rs
Normal file
44
src/json_store.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use std::{collections::HashMap, ops::Deref};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
pub struct JSONStore<T> {
|
||||
documents: HashMap<String, T>,
|
||||
}
|
||||
|
||||
impl<T: for<'a> Deserialize<'a>> JSONStore<T> {
|
||||
pub fn new(dir: &str) -> Self {
|
||||
let mut documents = HashMap::new();
|
||||
|
||||
for e in walkdir::WalkDir::new(dir)
|
||||
.into_iter()
|
||||
.filter_map(std::result::Result::ok)
|
||||
{
|
||||
if e.path().is_dir() {
|
||||
continue;
|
||||
}
|
||||
if e.path().extension().is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if e.path().extension().unwrap().to_str().unwrap() == "json" {
|
||||
let path = e.path().to_str().unwrap().to_owned();
|
||||
let file_name = e.path().file_stem().unwrap().to_str().unwrap().to_string();
|
||||
let content = std::fs::read_to_string(path).unwrap();
|
||||
let json = serde_json::from_str(&content).unwrap();
|
||||
|
||||
documents.insert(file_name, json);
|
||||
}
|
||||
}
|
||||
|
||||
Self { documents }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for JSONStore<T> {
|
||||
type Target = HashMap<String, T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.documents
|
||||
}
|
||||
}
|
70
src/location.rs
Normal file
70
src/location.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use mongod::{
|
||||
derive::{Model, Referencable},
|
||||
Model, ToAPI, Validate,
|
||||
};
|
||||
use mongodb::bson::doc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
/// A Storage Location
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
|
||||
pub struct Location {
|
||||
/// UUID
|
||||
pub _id: String,
|
||||
/// Name
|
||||
pub name: String,
|
||||
/// Parent
|
||||
pub parent: Option<String>,
|
||||
/// Storage Conditions
|
||||
pub conditions: Option<StorageConditions>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct StorageConditions {
|
||||
/// Median temperature
|
||||
pub temperature: i64,
|
||||
}
|
||||
|
||||
impl Validate for Location {
|
||||
async fn validate(&self) -> Result<(), String> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToAPI for Location {
|
||||
async fn api(&self) -> serde_json::Value {
|
||||
json!({
|
||||
"id": self._id,
|
||||
"name": self.name,
|
||||
"parent": self.parent,
|
||||
"conditions": self.conditions
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Location {
|
||||
pub async fn add(id: &str, o: serde_json::Value) {
|
||||
let l = Location {
|
||||
_id: id.to_string(),
|
||||
name: o
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.get("name")
|
||||
.unwrap()
|
||||
.as_str()
|
||||
.unwrap()
|
||||
.to_string(),
|
||||
parent: o
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.get("parent")
|
||||
.map(|x| x.as_str().unwrap().to_string()),
|
||||
conditions: serde_json::from_value(
|
||||
o.as_object().unwrap().get("conditions").unwrap().clone(),
|
||||
)
|
||||
.unwrap(),
|
||||
};
|
||||
|
||||
l.insert_overwrite().await.unwrap();
|
||||
}
|
||||
}
|
13
src/main.rs
13
src/main.rs
|
@ -1,8 +1,15 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use json_store::JSONStore;
|
||||
use location::Location;
|
||||
use mongod::Model;
|
||||
use rocket::routes as route;
|
||||
use rocket::{http::Method, launch};
|
||||
|
||||
mod db;
|
||||
mod item;
|
||||
mod json_store;
|
||||
mod location;
|
||||
mod process;
|
||||
mod routes;
|
||||
mod transaction;
|
||||
|
@ -41,6 +48,11 @@ async fn rocket() -> _ {
|
|||
.expect("error creating CORS options");
|
||||
|
||||
let itemdb = db::ItemDB::new("./itemdb").await;
|
||||
let locations: JSONStore<Location> = JSONStore::new("./locations");
|
||||
|
||||
for location in locations.deref() {
|
||||
location.1.insert_overwrite().await.unwrap();
|
||||
}
|
||||
|
||||
rocket::build()
|
||||
.mount(
|
||||
|
@ -60,5 +72,6 @@ async fn rocket() -> _ {
|
|||
],
|
||||
)
|
||||
.manage(itemdb)
|
||||
.manage(locations)
|
||||
.attach(cors)
|
||||
}
|
||||
|
|
26
src/routes/item/location.rs
Normal file
26
src/routes/item/location.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
use mongod::ToAPI;
|
||||
use rocket::{get, State};
|
||||
|
||||
use crate::{
|
||||
json_store::JSONStore,
|
||||
location::Location,
|
||||
routes::{api_error, FallibleApiResponse},
|
||||
};
|
||||
|
||||
#[get("/location/<id>")]
|
||||
pub async fn location_info(
|
||||
id: &str,
|
||||
locations: &State<JSONStore<Location>>,
|
||||
) -> FallibleApiResponse {
|
||||
let loc = locations
|
||||
.get(id)
|
||||
.ok_or_else(|| api_error("No location with that ID"))?;
|
||||
Ok(loc.api().await)
|
||||
}
|
||||
|
||||
#[get("/locations")]
|
||||
pub async fn locations_info(locations: &State<JSONStore<Location>>) -> FallibleApiResponse {
|
||||
// todo : recursive location map
|
||||
|
||||
unimplemented!()
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
mod demand;
|
||||
mod error;
|
||||
mod location;
|
||||
mod supply;
|
||||
|
||||
pub use demand::*;
|
||||
pub use error::*;
|
||||
pub use location::*;
|
||||
use mongod::Model;
|
||||
use mongod::ToAPI;
|
||||
pub use supply::*;
|
||||
|
|
|
@ -16,6 +16,7 @@ pub struct SupplyForm {
|
|||
variant: String,
|
||||
price: String,
|
||||
origin: Option<String>,
|
||||
location: Option<String>,
|
||||
}
|
||||
|
||||
/// Route for supply action. Creates a new Transaction for the specified Item Variant.
|
||||
|
@ -35,6 +36,7 @@ pub async fn supply_route(form: Json<SupplyForm>, itemdb: &State<ItemDB>) -> Fal
|
|||
.try_into()
|
||||
.map_err(|()| api_error("Price malformed"))?,
|
||||
form.origin.as_deref(),
|
||||
form.location.as_deref(),
|
||||
)
|
||||
.await;
|
||||
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
use mongod::{
|
||||
assert_reference_of,
|
||||
derive::{Model, Referencable},
|
||||
Model, Validate,
|
||||
reference_of, Model, Referencable, Reference, Validate,
|
||||
};
|
||||
use mongodb::bson::doc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::item::Item;
|
||||
use crate::{item::Item, location::Location};
|
||||
|
||||
/// A Transaction of an Item Variant
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Model, Referencable)]
|
||||
|
@ -21,6 +22,8 @@ pub struct Transaction {
|
|||
pub price: Price,
|
||||
/// Origin of the Item
|
||||
pub origin: Option<String>,
|
||||
/// The location of the Item
|
||||
pub location: Option<Reference>,
|
||||
/// Info on consumption of the Item
|
||||
pub consumed: Option<Consumed>,
|
||||
/// Timestamp of the Transaction
|
||||
|
@ -29,6 +32,10 @@ pub struct Transaction {
|
|||
|
||||
impl Validate for Transaction {
|
||||
async fn validate(&self) -> Result<(), String> {
|
||||
if let Some(location) = &self.location {
|
||||
assert_reference_of!(location, Location);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +52,13 @@ pub struct Consumed {
|
|||
}
|
||||
|
||||
impl Transaction {
|
||||
pub fn new(item: &str, variant: &str, price: Price, origin: Option<&str>) -> Self {
|
||||
pub async fn new(
|
||||
item: &str,
|
||||
variant: &str,
|
||||
price: Price,
|
||||
origin: Option<&str>,
|
||||
location: Option<&str>,
|
||||
) -> Self {
|
||||
Self {
|
||||
_id: uuid::Uuid::new_v4().to_string(),
|
||||
item: item.to_string(),
|
||||
|
@ -53,6 +66,11 @@ impl Transaction {
|
|||
price,
|
||||
consumed: None,
|
||||
origin: origin.map(std::string::ToString::to_string),
|
||||
location: if let Some(location) = location {
|
||||
reference_of!(Location, location)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
timestamp: chrono::Utc::now().timestamp(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,8 +142,13 @@ impl Variant {
|
|||
/// # Returns
|
||||
///
|
||||
/// Returns a UUID string representing the transaction.
|
||||
pub async fn supply(&self, price: Price, origin: Option<&str>) -> String {
|
||||
let t = Transaction::new(&self.item, &self.variant, price, origin);
|
||||
pub async fn supply(
|
||||
&self,
|
||||
price: Price,
|
||||
origin: Option<&str>,
|
||||
location: Option<&str>,
|
||||
) -> String {
|
||||
let t = Transaction::new(&self.item, &self.variant, price, origin, location).await;
|
||||
|
||||
t.insert().await.unwrap();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue