diff options
Diffstat (limited to 'backend/src/handlers/product.rs')
-rw-r--r-- | backend/src/handlers/product.rs | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/backend/src/handlers/product.rs b/backend/src/handlers/product.rs new file mode 100644 index 0000000..41a47a0 --- /dev/null +++ b/backend/src/handlers/product.rs | |||
@@ -0,0 +1,138 @@ | |||
1 | use crate::models::{Customer, NewProduct, Product, Rating, UpdateProduct}; | ||
2 | use crate::schema::customer::dsl as cust; | ||
3 | use crate::schema::product::dsl::*; | ||
4 | use crate::schema::rating::dsl as rating; | ||
5 | use crate::TPool; | ||
6 | |||
7 | use actix_web::{web, HttpResponse, Responder}; | ||
8 | use chrono::naive::NaiveDate; | ||
9 | use diesel::prelude::*; | ||
10 | use log::{error, info}; | ||
11 | use serde::{Deserialize, Serialize}; | ||
12 | |||
13 | pub async fn new_product( | ||
14 | pool: web::Data<TPool>, | ||
15 | item: web::Json<NewProduct>, | ||
16 | ) -> impl Responder { | ||
17 | info!("New product hit: {:?}", item.name); | ||
18 | let conn = pool.get().unwrap(); | ||
19 | diesel::insert_into(product) | ||
20 | .values(item.into_inner()) | ||
21 | .execute(&conn) | ||
22 | .expect("Coundn't connect to DB"); | ||
23 | HttpResponse::Ok().body("Inserted successfully!") | ||
24 | } | ||
25 | |||
26 | pub async fn product_details( | ||
27 | pool: web::Data<TPool>, | ||
28 | product_id: web::Path<i32>, | ||
29 | ) -> impl Responder { | ||
30 | let conn = pool.get().unwrap(); | ||
31 | let product_id = product_id.into_inner(); | ||
32 | info!("Fetching product details for {}", product_id); | ||
33 | let selected_product = product | ||
34 | .filter(id.eq(&product_id)) | ||
35 | .limit(1) | ||
36 | .first::<Product>(&conn); | ||
37 | match selected_product { | ||
38 | Ok(m) => { | ||
39 | info!("Found product: {}", product_id); | ||
40 | HttpResponse::Ok().json(m) | ||
41 | } | ||
42 | Err(_) => { | ||
43 | error!("Product not found: {}", product_id); | ||
44 | HttpResponse::NotFound().finish() | ||
45 | } | ||
46 | } | ||
47 | } | ||
48 | |||
49 | pub async fn update_product( | ||
50 | pool: web::Data<TPool>, | ||
51 | product_id: web::Path<i32>, | ||
52 | product_details: web::Json<UpdateProduct>, | ||
53 | ) -> impl Responder { | ||
54 | let conn = pool.get().unwrap(); | ||
55 | let product_id = product_id.into_inner(); | ||
56 | let product_details = product_details.into_inner(); | ||
57 | info!("Updating product: {:?}", product_id); | ||
58 | match diesel::update(product.filter(id.eq(product_id))) | ||
59 | .set(( | ||
60 | name.eq(product_details.name), | ||
61 | kind.eq(product_details.kind), | ||
62 | price.eq(product_details.price), | ||
63 | description.eq(product_details.description), | ||
64 | )) | ||
65 | .execute(&conn) | ||
66 | { | ||
67 | Ok(_) => { | ||
68 | return HttpResponse::Ok().body("Changed product successfully") | ||
69 | } | ||
70 | _ => { | ||
71 | return HttpResponse::InternalServerError() | ||
72 | .body("Unable to update record") | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | |||
77 | pub async fn get_all_products(pool: web::Data<TPool>) -> impl Responder { | ||
78 | let conn = pool.get().unwrap(); | ||
79 | info!("Generating and returning catalog ..."); | ||
80 | match product.load::<Product>(&conn) { | ||
81 | Ok(products) => return HttpResponse::Ok().json(&products), | ||
82 | Err(_) => { | ||
83 | return HttpResponse::InternalServerError() | ||
84 | .body("Unable to fetch product catalog") | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | #[derive(Serialize, Deserialize, Debug)] | ||
90 | struct ProductRating { | ||
91 | pub comment_text: Option<String>, | ||
92 | pub comment_date: NaiveDate, | ||
93 | pub product_name: String, | ||
94 | pub customer_name: String, | ||
95 | pub stars: Option<i32>, | ||
96 | } | ||
97 | |||
98 | pub async fn get_product_reviews( | ||
99 | pool: web::Data<TPool>, | ||
100 | product_id: web::Path<i32>, | ||
101 | ) -> impl Responder { | ||
102 | let conn = pool.get().unwrap(); | ||
103 | info!("Fetching product reviews for {}", product_id); | ||
104 | let pid = product_id.into_inner(); | ||
105 | let rating_entries = rating::rating | ||
106 | .filter(rating::product_id.eq(pid)) | ||
107 | .load::<Rating>(&conn) | ||
108 | .expect("Couldn't connect to DB"); | ||
109 | let json_ratings = rating_entries | ||
110 | .into_iter() | ||
111 | .map(move |p| { | ||
112 | let selected_product = product | ||
113 | .filter(id.eq(&p.product_id.unwrap())) | ||
114 | .limit(1) | ||
115 | .first::<Product>(&conn) | ||
116 | .unwrap() | ||
117 | .name | ||
118 | .clone(); | ||
119 | |||
120 | let selected_customer = cust::customer | ||
121 | .filter(cust::id.eq(&p.customer_id.unwrap())) | ||
122 | .limit(1) | ||
123 | .first::<Customer>(&conn) | ||
124 | .unwrap() | ||
125 | .username | ||
126 | .clone(); | ||
127 | |||
128 | ProductRating { | ||
129 | comment_text: p.comment_text, | ||
130 | comment_date: p.comment_date.unwrap(), | ||
131 | product_name: selected_product, | ||
132 | customer_name: selected_customer, | ||
133 | stars: p.stars, | ||
134 | } | ||
135 | }) | ||
136 | .collect::<Vec<_>>(); | ||
137 | return HttpResponse::Ok().json(&json_ratings); | ||
138 | } | ||