diff options
author | Akshay <[email protected]> | 2020-12-26 05:21:46 +0000 |
---|---|---|
committer | Akshay <[email protected]> | 2020-12-26 05:21:46 +0000 |
commit | 8014def1a8da3397d78d1162f9e1b8c3f22d0322 (patch) | |
tree | 346e1de0ac6aa4ca973c1b3e5897c2c44948e5a8 /backend/src/handlers | |
parent | 7c6006e1abc6094b5922ab69ccfa5449b8dbbc99 (diff) |
add transactions and quantities
- backend exposes endpoints to perform transactions
- frontend introduces a new page to "checkout" cart
Diffstat (limited to 'backend/src/handlers')
-rw-r--r-- | backend/src/handlers/cart_items.rs | 131 | ||||
-rw-r--r-- | backend/src/handlers/mod.rs | 1 | ||||
-rw-r--r-- | backend/src/handlers/transaction.rs | 74 | ||||
-rw-r--r-- | backend/src/handlers/users.rs | 4 |
4 files changed, 191 insertions, 19 deletions
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; | |||
7 | use actix_web::{web, HttpResponse, Responder}; | 7 | use actix_web::{web, HttpResponse, Responder}; |
8 | use diesel::prelude::*; | 8 | use diesel::prelude::*; |
9 | use log::{error, info}; | 9 | use log::{error, info}; |
10 | use serde::Deserialize; | 10 | use serde::Serialize; |
11 | 11 | ||
12 | pub async fn add_to_cart( | 12 | pub async fn add_to_cart( |
13 | cookie: Identity, | 13 | cookie: Identity, |
@@ -27,16 +27,41 @@ pub async fn add_to_cart( | |||
27 | let new_cart_item = AddCartItem { | 27 | let new_cart_item = AddCartItem { |
28 | cart_id: selected_user.id, | 28 | cart_id: selected_user.id, |
29 | product_id: item_details, | 29 | product_id: item_details, |
30 | quantity: Some(1), | ||
30 | }; | 31 | }; |
31 | info!( | 32 | info!( |
32 | "cart id: {:?}, product id {:?}", | 33 | "cart id: {:?}, product id {:?}", |
33 | selected_user.id, item_details | 34 | selected_user.id, item_details |
34 | ); | 35 | ); |
35 | diesel::insert_into(cart_items) | 36 | let current_entry = cart_items |
36 | .values((cart_id.eq(selected_user.id), product_id.eq(item_details))) | 37 | .filter(cart_id.eq(selected_user.id)) |
37 | .execute(&conn) | 38 | .filter(product_id.eq(item_details)) |
38 | .expect("Coundn't connect to DB"); | 39 | .limit(1) |
39 | HttpResponse::Ok().body("Inserted successfully!") | 40 | .first::<CartItem>(&conn); |
41 | match current_entry { | ||
42 | Ok(v) => { | ||
43 | info!("Item already present in cart, increasing quantity."); | ||
44 | let old_quantity = v.quantity.unwrap_or(1); | ||
45 | diesel::update( | ||
46 | cart_items | ||
47 | .filter(cart_id.eq(selected_user.id)) | ||
48 | .filter(product_id.eq(item_details)), | ||
49 | ) | ||
50 | .set(quantity.eq(old_quantity + 1)) | ||
51 | .execute(&conn) | ||
52 | .unwrap(); | ||
53 | return HttpResponse::Ok() | ||
54 | .body("Updated quantity successfully!"); | ||
55 | } | ||
56 | Err(_) => { | ||
57 | info!("Item not present, adding to cart."); | ||
58 | diesel::insert_into(cart_items) | ||
59 | .values(new_cart_item) | ||
60 | .execute(&conn) | ||
61 | .expect("Couldn't connect to DB"); | ||
62 | HttpResponse::Ok().body("Inserted successfully!") | ||
63 | } | ||
64 | } | ||
40 | } else { | 65 | } else { |
41 | error!("Unauthorized add to cart action!"); | 66 | error!("Unauthorized add to cart action!"); |
42 | return HttpResponse::Unauthorized() | 67 | return HttpResponse::Unauthorized() |
@@ -58,15 +83,44 @@ pub async fn remove_from_cart( | |||
58 | .limit(1) | 83 | .limit(1) |
59 | .first::<Customer>(&conn) | 84 | .first::<Customer>(&conn) |
60 | .expect("Couldn't connect to DB"); | 85 | .expect("Couldn't connect to DB"); |
61 | 86 | let current_entry = cart_items | |
62 | diesel::delete( | 87 | .filter(cart_id.eq(selected_user.id)) |
63 | cart_items | 88 | .filter(product_id.eq(item_details)) |
64 | .filter(cart_id.eq(selected_user.id)) | 89 | .limit(1) |
65 | .filter(product_id.eq(item_details)), | 90 | .first::<CartItem>(&conn); |
66 | ) | 91 | match current_entry { |
67 | .execute(&conn) | 92 | Ok(v) => { |
68 | .expect("Coundn't connect to DB"); | 93 | info!("Item already present in cart, increasing quantity."); |
69 | HttpResponse::Ok().body("Removed successfully!") | 94 | let old_quantity = v.quantity.unwrap_or(1); |
95 | if old_quantity == 1 { | ||
96 | diesel::delete( | ||
97 | cart_items | ||
98 | .filter(cart_id.eq(selected_user.id)) | ||
99 | .filter(product_id.eq(item_details)), | ||
100 | ) | ||
101 | .execute(&conn) | ||
102 | .expect("Coundn't connect to DB"); | ||
103 | } else { | ||
104 | diesel::update( | ||
105 | cart_items | ||
106 | .filter(cart_id.eq(selected_user.id)) | ||
107 | .filter(product_id.eq(item_details)), | ||
108 | ) | ||
109 | .set(quantity.eq(old_quantity - 1)) | ||
110 | .execute(&conn) | ||
111 | .unwrap(); | ||
112 | return HttpResponse::Ok() | ||
113 | .body("Updated quantity successfully!"); | ||
114 | } | ||
115 | return HttpResponse::Ok() | ||
116 | .body("Updated quantity successfully!"); | ||
117 | } | ||
118 | Err(_) => { | ||
119 | info!("Item not present."); | ||
120 | return HttpResponse::InternalServerError() | ||
121 | .body("Item not found!"); | ||
122 | } | ||
123 | } | ||
70 | } else { | 124 | } else { |
71 | error!("Unauthorized add to cart action!"); | 125 | error!("Unauthorized add to cart action!"); |
72 | return HttpResponse::Unauthorized() | 126 | return HttpResponse::Unauthorized() |
@@ -74,6 +128,12 @@ pub async fn remove_from_cart( | |||
74 | } | 128 | } |
75 | } | 129 | } |
76 | 130 | ||
131 | #[derive(Serialize)] | ||
132 | struct UserCartItem { | ||
133 | product_item: Product, | ||
134 | quantity: i32, | ||
135 | } | ||
136 | |||
77 | pub async fn get_user_cart_items( | 137 | pub async fn get_user_cart_items( |
78 | cookie: Identity, | 138 | cookie: Identity, |
79 | pool: web::Data<TPool>, | 139 | pool: web::Data<TPool>, |
@@ -92,11 +152,15 @@ pub async fn get_user_cart_items( | |||
92 | let cart_products = user_cart_items | 152 | let cart_products = user_cart_items |
93 | .into_iter() | 153 | .into_iter() |
94 | .map(|item| { | 154 | .map(|item| { |
95 | prod::product | 155 | let p = prod::product |
96 | .filter(prod::id.eq(item.product_id)) | 156 | .filter(prod::id.eq(item.product_id)) |
97 | .limit(1) | 157 | .limit(1) |
98 | .first::<Product>(&conn) | 158 | .first::<Product>(&conn) |
99 | .expect("Couldn't connect to db") | 159 | .expect("Couldn't connect to db"); |
160 | UserCartItem { | ||
161 | product_item: p, | ||
162 | quantity: item.quantity.unwrap_or(1), | ||
163 | } | ||
100 | }) | 164 | }) |
101 | .collect::<Vec<_>>(); | 165 | .collect::<Vec<_>>(); |
102 | return HttpResponse::Ok().json(&cart_products); | 166 | return HttpResponse::Ok().json(&cart_products); |
@@ -105,3 +169,36 @@ pub async fn get_user_cart_items( | |||
105 | .body("Need to be logged in to add to cart!"); | 169 | .body("Need to be logged in to add to cart!"); |
106 | } | 170 | } |
107 | } | 171 | } |
172 | |||
173 | pub async fn get_user_cart_total( | ||
174 | cookie: Identity, | ||
175 | pool: web::Data<TPool>, | ||
176 | ) -> impl Responder { | ||
177 | let conn = pool.get().unwrap(); | ||
178 | if let Some(uname) = cookie.identity() { | ||
179 | let selected_user = customer | ||
180 | .filter(username.eq(&uname)) | ||
181 | .limit(1) | ||
182 | .first::<Customer>(&conn) | ||
183 | .expect("Couldn't connect to DB"); | ||
184 | let user_cart_items = cart_items | ||
185 | .filter(cart_id.eq(selected_user.id)) | ||
186 | .load::<CartItem>(&conn) | ||
187 | .expect("Couldn't connect to DB"); | ||
188 | let cart_total: f32 = user_cart_items | ||
189 | .into_iter() | ||
190 | .map(|item| { | ||
191 | let p = prod::product | ||
192 | .filter(prod::id.eq(item.product_id)) | ||
193 | .limit(1) | ||
194 | .first::<Product>(&conn) | ||
195 | .expect("Couldn't connect to db"); | ||
196 | return p.price * item.quantity.unwrap_or(1) as f32; | ||
197 | }) | ||
198 | .sum(); | ||
199 | return HttpResponse::Ok().json(&cart_total); | ||
200 | } else { | ||
201 | return HttpResponse::Unauthorized() | ||
202 | .body("Need to be logged in to add to cart!"); | ||
203 | } | ||
204 | } | ||
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; | |||
2 | pub mod product; | 2 | pub mod product; |
3 | pub mod rating; | 3 | pub mod rating; |
4 | pub mod smoke; | 4 | pub mod smoke; |
5 | pub mod transaction; | ||
5 | pub mod users; | 6 | 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 @@ | |||
1 | use crate::models::{AddTransaction, CartItem, Customer, Product, Transaction}; | ||
2 | use crate::schema::cart_items::dsl::*; | ||
3 | use crate::schema::customer::dsl::*; | ||
4 | use crate::schema::product::dsl as prod; | ||
5 | use crate::schema::transaction::dsl::*; | ||
6 | use crate::TPool; | ||
7 | |||
8 | use actix_identity::Identity; | ||
9 | use actix_web::{web, HttpResponse, Responder}; | ||
10 | use diesel::prelude::*; | ||
11 | use log::{error, info}; | ||
12 | |||
13 | pub async fn checkout_cart( | ||
14 | pool: web::Data<TPool>, | ||
15 | pmt_kind: String, | ||
16 | cookie: Identity, | ||
17 | ) -> impl Responder { | ||
18 | let conn = pool.get().unwrap(); | ||
19 | info!("Checkout cart for user: {:?}", cookie.identity()); | ||
20 | if let Some(uname) = cookie.identity() { | ||
21 | let selected_user = customer | ||
22 | .filter(username.eq(&uname)) | ||
23 | .limit(1) | ||
24 | .first::<Customer>(&conn) | ||
25 | .expect("Couldn't connect to DB"); | ||
26 | let user_cart_items = cart_items | ||
27 | .filter(cart_id.eq(selected_user.id)) | ||
28 | .load::<CartItem>(&conn) | ||
29 | .expect("Couldn't connect to DB"); | ||
30 | let cart_total = user_cart_items.into_iter().fold(0., |acc, item| { | ||
31 | let item_price = prod::product | ||
32 | .filter(prod::id.eq(item.product_id)) | ||
33 | .limit(1) | ||
34 | .first::<Product>(&conn) | ||
35 | .unwrap() | ||
36 | .price; | ||
37 | acc + item.quantity.unwrap_or(1) as f32 * item_price | ||
38 | }); | ||
39 | let transaction_entry = AddTransaction { | ||
40 | customer_id: Some(selected_user.id), | ||
41 | amount: cart_total, | ||
42 | payment_type: pmt_kind, | ||
43 | }; | ||
44 | diesel::insert_into(transaction) | ||
45 | .values(transaction_entry) | ||
46 | .execute(&conn) | ||
47 | .expect("Coundn't connect to DB"); | ||
48 | return HttpResponse::Ok().body("Transaction performed successfully"); | ||
49 | } else { | ||
50 | return HttpResponse::Unauthorized().body("Login first"); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | pub async fn list_transactions( | ||
55 | pool: web::Data<TPool>, | ||
56 | cookie: Identity, | ||
57 | ) -> impl Responder { | ||
58 | let conn = pool.get().unwrap(); | ||
59 | if let Some(uname) = cookie.identity() { | ||
60 | let selected_user = customer | ||
61 | .filter(username.eq(&uname)) | ||
62 | .limit(1) | ||
63 | .first::<Customer>(&conn) | ||
64 | .expect("Couldn't connect to DB"); | ||
65 | let user_transactions = transaction | ||
66 | .filter(customer_id.eq(selected_user.id)) | ||
67 | .load::<Transaction>(&conn) | ||
68 | .expect("Couldn't connect to DB"); | ||
69 | return HttpResponse::Ok().json(&user_transactions); | ||
70 | } else { | ||
71 | return HttpResponse::Unauthorized() | ||
72 | .body("Need to be logged in to add to cart!"); | ||
73 | } | ||
74 | } | ||
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( | |||
58 | login_details: web::Json<Login>, | 58 | login_details: web::Json<Login>, |
59 | ) -> impl Responder { | 59 | ) -> impl Responder { |
60 | info!("Login hit"); | 60 | info!("Login hit"); |
61 | if let Some(uname) = cookie.identity() { | 61 | if cookie.identity().is_some() { |
62 | info!("Found existing cookie: {:?}", cookie.identity()); | 62 | info!("Found existing cookie: {:?}", cookie.identity()); |
63 | return HttpResponse::Ok().finish(); | 63 | return HttpResponse::Ok().finish(); |
64 | } | 64 | } |
@@ -84,7 +84,7 @@ pub async fn login( | |||
84 | 84 | ||
85 | pub async fn logout(cookie: Identity) -> impl Responder { | 85 | pub async fn logout(cookie: Identity) -> impl Responder { |
86 | cookie.forget(); | 86 | cookie.forget(); |
87 | HttpResponse::Found().header("location", "/").finish() | 87 | HttpResponse::Ok().body("Successful logout.") |
88 | } | 88 | } |
89 | 89 | ||
90 | pub async fn user_details( | 90 | pub async fn user_details( |