diff --git a/backend/src/endpoints/mod.rs b/backend/src/endpoints/mod.rs index 4783b7d..2c3aab9 100644 --- a/backend/src/endpoints/mod.rs +++ b/backend/src/endpoints/mod.rs @@ -1,4 +1,5 @@ pub mod client; pub mod car_station; pub mod car; -pub mod rent; \ No newline at end of file +pub mod rent; +pub mod owner; \ No newline at end of file diff --git a/backend/src/endpoints/owner.rs b/backend/src/endpoints/owner.rs new file mode 100644 index 0000000..0c65251 --- /dev/null +++ b/backend/src/endpoints/owner.rs @@ -0,0 +1,59 @@ +use std::sync::Mutex; +use crate::models::client::*; +use actix_web::{web, get, post, patch, delete, Responder, HttpResponse}; +use crate::State; + +#[get("/")] +pub async fn get_owners(state: web::Data>) -> impl Responder { + match state.lock() { + Ok(guard) => match guard.owner_repository.read_all().await { + Ok(result) => HttpResponse::Ok().json(result), + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + }, + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + } +} + +#[get("/{id}")] +pub async fn get_owner(state: web::Data>, path: web::Path<(u32, )>) -> impl Responder { + match state.lock() { + Ok(guard) => match guard.owner_repository.read(path.into_inner().0).await { + Ok(result) => HttpResponse::Ok().json(result), + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + }, + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + } +} + +#[post("/")] +pub async fn create_owner(state: web::Data>, json: web::Json) -> impl Responder { + match state.lock() { + Ok(guard) => match guard.owner_repository.create(json.0).await { + Ok(result) => HttpResponse::Ok().json(result), + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + }, + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + } +} + +#[patch("/{id}")] +pub async fn update_owner(state: web::Data>, json: web::Json, path: web::Path<(u32, )>) -> impl Responder { + match state.lock() { + Ok(guard) => match guard.owner_repository.update(path.into_inner().0, json.0).await { + Ok(result) => HttpResponse::Ok().json(result), + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + }, + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + } +} + +#[delete("/{id}")] +pub async fn delete_owner(state: web::Data>, path: web::Path<(u32, )>) -> impl Responder { + match state.lock() { + Ok(guard) => match guard.owner_repository.delete(path.into_inner().0).await { + Ok(result) => HttpResponse::Ok().json(result), + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + }, + Err(error) => HttpResponse::InternalServerError().json(error.to_string()) + } +} \ No newline at end of file diff --git a/backend/src/lib.rs b/backend/src/lib.rs index c992058..7278f76 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -1,3 +1,5 @@ +use storages::traits::OwnerRepository; + use crate::storages::traits::{CarRepository, CarStationRepository, ClientRepository, RentRepository}; pub mod endpoints; @@ -8,5 +10,6 @@ pub struct State { pub car_repository: Box, pub car_station_repository: Box, pub client_repository: Box, + pub owner_repository: Box, pub rent_repository: Box } \ No newline at end of file diff --git a/backend/src/main.rs b/backend/src/main.rs index 129ff81..7a37b36 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -8,10 +8,12 @@ use backend::storages::postgres::car::PostgresCarRepository; use backend::storages::postgres::car_station::PostgresCarStationRepository; use backend::storages::postgres::client::PostgresClientRepository; use backend::storages::postgres::rent::PostgresRentRepository; +use backend::storages::postgres::owner::PostgresOwnerRepository; use backend::endpoints::car_station::*; use backend::endpoints::car::*; use backend::endpoints::client::*; use backend::endpoints::rent::*; +use backend::endpoints::owner::*; #[actix_web::main] async fn main() -> std::io::Result<()> { @@ -34,12 +36,15 @@ async fn main() -> std::io::Result<()> { let client_repository = PostgresClientRepository { connection: Arc::clone(&client) }; + let owner_repository = PostgresOwnerRepository { connection: Arc::clone(&client) }; + let rent_repository = PostgresRentRepository { connection: Arc::clone(&client) }; let state = Data::new(Mutex::new(State { car_repository: Box::new(car_repository), car_station_repository: Box::new(car_station_repository), client_repository: Box::new(client_repository), + owner_repository: Box::new(owner_repository), rent_repository: Box::new(rent_repository) })); @@ -62,6 +67,14 @@ async fn main() -> std::io::Result<()> { .service(update_client) .service(delete_client) ) + .service( + web::scope("/owners") + .service(get_owners) + .service(get_owner) + .service(create_owner) + .service(update_owner) + .service(delete_owner) + ) .service( web::scope("/car_stations") .service(get_car_stations) diff --git a/backend/src/storages/postgres/mod.rs b/backend/src/storages/postgres/mod.rs index 4783b7d..2c3aab9 100644 --- a/backend/src/storages/postgres/mod.rs +++ b/backend/src/storages/postgres/mod.rs @@ -1,4 +1,5 @@ pub mod client; pub mod car_station; pub mod car; -pub mod rent; \ No newline at end of file +pub mod rent; +pub mod owner; \ No newline at end of file diff --git a/backend/src/storages/postgres/owner.rs b/backend/src/storages/postgres/owner.rs new file mode 100644 index 0000000..7f63f2d --- /dev/null +++ b/backend/src/storages/postgres/owner.rs @@ -0,0 +1,111 @@ +use tokio_postgres::Client as PgClient; +use std::sync::Arc; +use crate::models::client::{BindingClient, Client}; +use crate::storages::traits::OwnerRepository; +use async_trait::async_trait; + +pub struct PostgresOwnerRepository { + pub connection: Arc +} + +#[async_trait] +impl OwnerRepository for PostgresOwnerRepository { + async fn create(&self, client: BindingClient) -> Result { + let result = self.connection.query( + "INSERT INTO Owner(name, surname, middlename, phone) \ + VALUES ($1, $2, $3, $4) RETURNING *", + &[&client.name, &client.surname, &client.middlename, &client.phone] + ).await; + + if let Ok(rows) = &result { + let row = rows.get(0).unwrap(); + Ok(Client { + id: row.get("id"), + name: row.get("name"), + surname: row.get("surname"), + middlename: row.get("middlename"), + phone: row.get("phone") + }) + } else { + Err("Something gone wrong during creation of Owner".to_owned()) + } + } + + async fn read(&self, id: u32) -> Result { + let result= self.connection.query( + "SELECT * FROM Owner WHERE id = $1", &[&id] + ).await; + + if let Ok(rows) = result { + + let row = rows.get(0).ok_or("Owner not found".to_owned())?; + Ok(Client { + id: row.get("id"), + name: row.get("name"), + surname: row.get("surname"), + middlename: row.get("middlename"), + phone: row.get("phone") + }) + } else { + Err("Something gone wrong during reading of Owner".to_owned()) + } + } + + async fn read_all(&self) -> Result, String> { + let result = self.connection.query( + "SELECT * FROM Owner", &[] + ).await; + + if let Ok(rows) = result { + Ok( + rows.into_iter().map(|r| Client { + id: r.get("id"), + name: r.get("name"), + surname: r.get("surname"), + middlename: r.get("middlename"), + phone: r.get("phone") + }).collect() + ) + } else { + Err("Something gone wrong during reading Owner".to_owned()) + } + } + + async fn update(&self, id: u32, client: BindingClient) -> Result { + let result = self.connection.query( + "UPDATE Owner SET name = $1, surname = $2, middlename = $3, phone = $4 \ + WHERE id = $5 RETURNING *", + &[&client.name, &client.surname, &client.middlename, &client.phone, &id] + ).await; + + if let Ok(rows) = result { + let row = rows.get(0).unwrap(); + Ok(Client { + id: row.get("id"), + name: row.get("name"), + surname: row.get("surname"), + middlename: row.get("middlename"), + phone: row.get("phone") + }) + } else { + Err("Something gone wrong during updating of Owner".to_owned()) + } + } + + async fn delete(&self, id: u32) -> Result<(), String> { + let result = self.connection.execute( + "DELETE FROM Owner WHERE id = $1", + &[&id] + ).await; + + if let Ok(rows) = result { + if rows == 0 { + Err("Owner not found".to_owned()) + } else { + Ok(()) + } + } else { + Err("Something gone wrong during deleting of Owner".to_owned()) + } + } +} diff --git a/backend/src/storages/traits.rs b/backend/src/storages/traits.rs index 82d2e34..5a38418 100644 --- a/backend/src/storages/traits.rs +++ b/backend/src/storages/traits.rs @@ -38,4 +38,13 @@ pub trait RentRepository { async fn read_all(&self) -> Result, String>; async fn update(&self, id: u32, rent: BindingRent) -> Result; async fn delete(&self, id: u32) -> Result<(), String>; +} + +#[async_trait] +pub trait OwnerRepository { + async fn create(&self, client: BindingClient) -> Result; + async fn read(&self, id: u32) -> Result; + async fn read_all(&self) -> Result, String>; + async fn update(&self, id: u32, client: BindingClient) -> Result; + async fn delete(&self, id: u32) -> Result<(), String>; } \ No newline at end of file