From 8a044653f7521e942d7e76fef26f0e33aa71bffd Mon Sep 17 00:00:00 2001 From: core Date: Sun, 18 Jun 2023 14:01:43 -0400 Subject: [PATCH] cash orders --- backend/src/db_orders.rs | 17 ++ backend/src/main.rs | 8 +- backend/src/route_order.rs | 121 +++++++++++ frontend/package.json | 2 + frontend/src/lib/components/Header.svelte | 6 + frontend/src/routes/+page.svelte | 191 ++++++++++++++++-- .../src/routes/manage/orders/+page.svelte | 173 ++++++++++++++++ frontend/src/routes/manage/orders/style.scss | 8 + frontend/static/smui-dark.css | 2 +- frontend/static/smui.css | 2 +- frontend/yarn.lock | 24 +++ 11 files changed, 537 insertions(+), 17 deletions(-) create mode 100644 backend/src/db_orders.rs create mode 100644 backend/src/route_order.rs create mode 100644 frontend/src/routes/manage/orders/+page.svelte create mode 100644 frontend/src/routes/manage/orders/style.scss diff --git a/backend/src/db_orders.rs b/backend/src/db_orders.rs new file mode 100644 index 0000000..6a7d063 --- /dev/null +++ b/backend/src/db_orders.rs @@ -0,0 +1,17 @@ +use std::collections::HashMap; +use bonsaidb::core::schema::Collection; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Collection)] +#[collection(name = "orders")] +pub struct Order { + pub order_type: OrderType, + pub total_usd: f64, + pub products: HashMap +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub enum OrderType { + Cash, + Stripe +} \ No newline at end of file diff --git a/backend/src/main.rs b/backend/src/main.rs index b758e97..7dc1dc7 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -7,14 +7,18 @@ use bonsaidb::local::AsyncDatabase; use bonsaidb::local::config::{Builder, StorageConfiguration}; use crate::db_products::Product; +use crate::db_orders::Order; +use crate::route_order::{cash_order, get_orders}; use crate::route_products::{create_product, delete_product, get_product, get_products, update_product}; pub mod db_products; pub mod route_products; pub mod error; +pub mod route_order; +pub mod db_orders; #[derive(Debug, Schema)] -#[schema(name = "lmsposschema", collections = [Product])] +#[schema(name = "lmsposschema", collections = [Product, Order])] pub struct DbSchema; pub struct AppState { @@ -41,6 +45,8 @@ async fn main() -> Result<(), Box> { .service(get_product) .service(delete_product) .service(status) + .service(get_orders) + .service(cash_order) }) .bind(("127.0.0.1", 8080))? .run() diff --git a/backend/src/route_order.rs b/backend/src/route_order.rs new file mode 100644 index 0000000..9066d01 --- /dev/null +++ b/backend/src/route_order.rs @@ -0,0 +1,121 @@ +use std::collections::HashMap; +use actix_web::{get, HttpResponse, post}; +use actix_web::web::{Data, Json}; +use bonsaidb::core::schema::SerializedCollection; +use serde::{Deserialize, Serialize}; +use crate::AppState; +use crate::db_orders::{Order, OrderType}; +use crate::db_products::Product; +use crate::error::APIError; + +#[derive(Deserialize)] +pub struct CashOrderRequest { + pub products: HashMap, + pub adjust_stock: bool +} + +#[derive(Serialize)] +pub struct CashOrderResponse { + pub order_id: u64 +} + +#[post("/cash_order")] +pub async fn cash_order(req: Json, db: Data) -> HttpResponse { + // load product data + let mut products = match Product::get_multiple_async(req.products.keys(), &db.db).await { + Ok(r) => r, + Err(e) => { + return HttpResponse::InternalServerError().json(APIError { + code: "DB_ERROR".to_string(), + message: e.to_string(), + }) + } + }; + + let mut price_total: f64 = 0.0; + + for product in &products { + price_total += req.products[&product.header.id] as f64 * product.contents.price_usd; + } + + let doc = Order { + order_type: OrderType::Cash, + total_usd: price_total, + products: req.products.clone(), + }; + + if req.adjust_stock { + for product in &mut products { + if product.contents.stock < req.products[&product.header.id] { + return HttpResponse::BadRequest().json(APIError { + code: "NOT_ENOUGH_STOCK".to_string(), + message: "Cannot sell more items than are in stock backend".to_string(), + }); + } + } + } + + let order = match doc.push_into_async(&db.db).await { + Ok(r) => r, + Err(e) => { + return HttpResponse::InternalServerError().json(APIError { + code: "DB_ERROR".to_string(), + message: e.to_string(), + }) + } + }; + + if req.adjust_stock { + for product in &mut products { + product.contents.stock -= req.products[&product.header.id]; + match product.update_async(&db.db).await { + Ok(_) => (), + Err(e) => { + return HttpResponse::InternalServerError().json(APIError { + code: "DB_ERROR".to_string(), + message: e.to_string(), + }) + } + } + } + } + + HttpResponse::Ok().json(CashOrderResponse { + order_id: order.header.id, + }) +} + +#[derive(Serialize)] +pub struct OrdersResponse { + pub orders: Vec +} + +#[derive(Serialize)] +pub struct OrderResponse { + pub id: u64, + pub order_type: OrderType, + pub total_usd: f64, + pub products: HashMap +} + +#[get("/orders")] +pub async fn get_orders(db: Data) -> HttpResponse { + let orders = match Order::list_async(0.., &db.db).await { + Ok(p) => p, + Err(e) => { + return HttpResponse::InternalServerError().json(APIError { + code: "DB_ERROR".to_string(), + message: e.to_string(), + }) + } + }; + + let resp: Vec = orders.iter().map(|u| OrderResponse { + id: u.header.id, + order_type: u.contents.order_type.clone(), + total_usd: u.contents.total_usd, + products: u.contents.products.clone(), + }).collect(); + + HttpResponse::Ok().json(OrdersResponse { orders: resp }) +} \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index b298752..c229be7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,9 +16,11 @@ "@material/typography": "^14.0.0", "@smui/button": "^7.0.0-beta.8", "@smui/card": "^7.0.0-beta.8", + "@smui/checkbox": "^7.0.0-beta.8", "@smui/circular-progress": "^7.0.0-beta.8", "@smui/data-table": "^7.0.0-beta.8", "@smui/dialog": "^7.0.0-beta.8", + "@smui/form-field": "^7.0.0-beta.8", "@smui/icon-button": "^7.0.0-beta.8", "@smui/linear-progress": "^7.0.0-beta.8", "@smui/paper": "^7.0.0-beta.8", diff --git a/frontend/src/lib/components/Header.svelte b/frontend/src/lib/components/Header.svelte index 1f5f85b..c74fbe7 100644 --- a/frontend/src/lib/components/Header.svelte +++ b/frontend/src/lib/components/Header.svelte @@ -23,6 +23,12 @@ + + + +