From 8014def1a8da3397d78d1162f9e1b8c3f22d0322 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 26 Dec 2020 10:51:46 +0530 Subject: add transactions and quantities - backend exposes endpoints to perform transactions - frontend introduces a new page to "checkout" cart --- backend/src/handlers/cart_items.rs | 131 +++++++++++++++++++++++++++++++----- backend/src/handlers/mod.rs | 1 + backend/src/handlers/transaction.rs | 74 ++++++++++++++++++++ backend/src/handlers/users.rs | 4 +- 4 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 backend/src/handlers/transaction.rs (limited to 'backend/src/handlers') diff --git a/backend/src/handlers/cart_items.rs b/backend/src/handlers/cart_items.rs index 25baaeb..e17f4c4 100644 --- a/backend/src/handlers/cart_items.rs +++ b/backend/src/handlers/cart_items.rs @@ -7,7 +7,7 @@ use actix_identity::Identity; use actix_web::{web, HttpResponse, Responder}; use diesel::prelude::*; use log::{error, info}; -use serde::Deserialize; +use serde::Serialize; pub async fn add_to_cart( cookie: Identity, @@ -27,16 +27,41 @@ pub async fn add_to_cart( let new_cart_item = AddCartItem { cart_id: selected_user.id, product_id: item_details, + quantity: Some(1), }; info!( "cart id: {:?}, product id {:?}", selected_user.id, item_details ); - diesel::insert_into(cart_items) - .values((cart_id.eq(selected_user.id), product_id.eq(item_details))) - .execute(&conn) - .expect("Coundn't connect to DB"); - HttpResponse::Ok().body("Inserted successfully!") + let current_entry = cart_items + .filter(cart_id.eq(selected_user.id)) + .filter(product_id.eq(item_details)) + .limit(1) + .first::(&conn); + match current_entry { + Ok(v) => { + info!("Item already present in cart, increasing quantity."); + let old_quantity = v.quantity.unwrap_or(1); + diesel::update( + cart_items + .filter(cart_id.eq(selected_user.id)) + .filter(product_id.eq(item_details)), + ) + .set(quantity.eq(old_quantity + 1)) + .execute(&conn) + .unwrap(); + return HttpResponse::Ok() + .body("Updated quantity successfully!"); + } + Err(_) => { + info!("Item not present, adding to cart."); + diesel::insert_into(cart_items) + .values(new_cart_item) + .execute(&conn) + .expect("Couldn't connect to DB"); + HttpResponse::Ok().body("Inserted successfully!") + } + } } else { error!("Unauthorized add to cart action!"); return HttpResponse::Unauthorized() @@ -58,15 +83,44 @@ pub async fn remove_from_cart( .limit(1) .first::(&conn) .expect("Couldn't connect to DB"); - - diesel::delete( - cart_items - .filter(cart_id.eq(selected_user.id)) - .filter(product_id.eq(item_details)), - ) - .execute(&conn) - .expect("Coundn't connect to DB"); - HttpResponse::Ok().body("Removed successfully!") + let current_entry = cart_items + .filter(cart_id.eq(selected_user.id)) + .filter(product_id.eq(item_details)) + .limit(1) + .first::(&conn); + match current_entry { + Ok(v) => { + info!("Item already present in cart, increasing quantity."); + let old_quantity = v.quantity.unwrap_or(1); + if old_quantity == 1 { + diesel::delete( + cart_items + .filter(cart_id.eq(selected_user.id)) + .filter(product_id.eq(item_details)), + ) + .execute(&conn) + .expect("Coundn't connect to DB"); + } else { + diesel::update( + cart_items + .filter(cart_id.eq(selected_user.id)) + .filter(product_id.eq(item_details)), + ) + .set(quantity.eq(old_quantity - 1)) + .execute(&conn) + .unwrap(); + return HttpResponse::Ok() + .body("Updated quantity successfully!"); + } + return HttpResponse::Ok() + .body("Updated quantity successfully!"); + } + Err(_) => { + info!("Item not present."); + return HttpResponse::InternalServerError() + .body("Item not found!"); + } + } } else { error!("Unauthorized add to cart action!"); return HttpResponse::Unauthorized() @@ -74,6 +128,12 @@ pub async fn remove_from_cart( } } +#[derive(Serialize)] +struct UserCartItem { + product_item: Product, + quantity: i32, +} + pub async fn get_user_cart_items( cookie: Identity, pool: web::Data, @@ -92,11 +152,15 @@ pub async fn get_user_cart_items( let cart_products = user_cart_items .into_iter() .map(|item| { - prod::product + let p = prod::product .filter(prod::id.eq(item.product_id)) .limit(1) .first::(&conn) - .expect("Couldn't connect to db") + .expect("Couldn't connect to db"); + UserCartItem { + product_item: p, + quantity: item.quantity.unwrap_or(1), + } }) .collect::>(); return HttpResponse::Ok().json(&cart_products); @@ -105,3 +169,36 @@ pub async fn get_user_cart_items( .body("Need to be logged in to add to cart!"); } } + +pub async fn get_user_cart_total( + cookie: Identity, + pool: web::Data, +) -> impl Responder { + let conn = pool.get().unwrap(); + if let Some(uname) = cookie.identity() { + let selected_user = customer + .filter(username.eq(&uname)) + .limit(1) + .first::(&conn) + .expect("Couldn't connect to DB"); + let user_cart_items = cart_items + .filter(cart_id.eq(selected_user.id)) + .load::(&conn) + .expect("Couldn't connect to DB"); + let cart_total: f32 = user_cart_items + .into_iter() + .map(|item| { + let p = prod::product + .filter(prod::id.eq(item.product_id)) + .limit(1) + .first::(&conn) + .expect("Couldn't connect to db"); + return p.price * item.quantity.unwrap_or(1) as f32; + }) + .sum(); + return HttpResponse::Ok().json(&cart_total); + } else { + return HttpResponse::Unauthorized() + .body("Need to be logged in to add to cart!"); + } +} diff --git a/backend/src/handlers/mod.rs b/backend/src/handlers/mod.rs index 9416857..e4ecb3a 100644 --- a/backend/src/handlers/mod.rs +++ b/backend/src/handlers/mod.rs @@ -2,4 +2,5 @@ pub mod cart_items; pub mod product; pub mod rating; pub mod smoke; +pub mod transaction; pub mod users; diff --git a/backend/src/handlers/transaction.rs b/backend/src/handlers/transaction.rs new file mode 100644 index 0000000..1e87312 --- /dev/null +++ b/backend/src/handlers/transaction.rs @@ -0,0 +1,74 @@ +use crate::models::{AddTransaction, CartItem, Customer, Product, Transaction}; +use crate::schema::cart_items::dsl::*; +use crate::schema::customer::dsl::*; +use crate::schema::product::dsl as prod; +use crate::schema::transaction::dsl::*; +use crate::TPool; + +use actix_identity::Identity; +use actix_web::{web, HttpResponse, Responder}; +use diesel::prelude::*; +use log::{error, info}; + +pub async fn checkout_cart( + pool: web::Data, + pmt_kind: String, + cookie: Identity, +) -> impl Responder { + let conn = pool.get().unwrap(); + info!("Checkout cart for user: {:?}", cookie.identity()); + if let Some(uname) = cookie.identity() { + let selected_user = customer + .filter(username.eq(&uname)) + .limit(1) + .first::(&conn) + .expect("Couldn't connect to DB"); + let user_cart_items = cart_items + .filter(cart_id.eq(selected_user.id)) + .load::(&conn) + .expect("Couldn't connect to DB"); + let cart_total = user_cart_items.into_iter().fold(0., |acc, item| { + let item_price = prod::product + .filter(prod::id.eq(item.product_id)) + .limit(1) + .first::(&conn) + .unwrap() + .price; + acc + item.quantity.unwrap_or(1) as f32 * item_price + }); + let transaction_entry = AddTransaction { + customer_id: Some(selected_user.id), + amount: cart_total, + payment_type: pmt_kind, + }; + diesel::insert_into(transaction) + .values(transaction_entry) + .execute(&conn) + .expect("Coundn't connect to DB"); + return HttpResponse::Ok().body("Transaction performed successfully"); + } else { + return HttpResponse::Unauthorized().body("Login first"); + } +} + +pub async fn list_transactions( + pool: web::Data, + cookie: Identity, +) -> impl Responder { + let conn = pool.get().unwrap(); + if let Some(uname) = cookie.identity() { + let selected_user = customer + .filter(username.eq(&uname)) + .limit(1) + .first::(&conn) + .expect("Couldn't connect to DB"); + let user_transactions = transaction + .filter(customer_id.eq(selected_user.id)) + .load::(&conn) + .expect("Couldn't connect to DB"); + return HttpResponse::Ok().json(&user_transactions); + } else { + return HttpResponse::Unauthorized() + .body("Need to be logged in to add to cart!"); + } +} diff --git a/backend/src/handlers/users.rs b/backend/src/handlers/users.rs index 24fb591..a043c1f 100644 --- a/backend/src/handlers/users.rs +++ b/backend/src/handlers/users.rs @@ -58,7 +58,7 @@ pub async fn login( login_details: web::Json, ) -> impl Responder { info!("Login hit"); - if let Some(uname) = cookie.identity() { + if cookie.identity().is_some() { info!("Found existing cookie: {:?}", cookie.identity()); return HttpResponse::Ok().finish(); } @@ -84,7 +84,7 @@ pub async fn login( pub async fn logout(cookie: Identity) -> impl Responder { cookie.forget(); - HttpResponse::Found().header("location", "/").finish() + HttpResponse::Ok().body("Successful logout.") } pub async fn user_details( -- cgit v1.2.3