use tokio_postgres::Client as PgClient; use std::sync::Arc; use crate::models::client::{BindingClient, Client}; use crate::storages::traits::ClientRepository; use async_trait::async_trait; pub struct PostgresClientRepository { pub connection: Arc } #[async_trait] impl ClientRepository for PostgresClientRepository { async fn create(&self, client: BindingClient) -> Result { let result = self.connection.query( "INSERT INTO Client(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(result.unwrap_err().to_string()) } } async fn read(&self, id: i32) -> Result { let result= self.connection.query( "SELECT * FROM Client WHERE id = $1", &[&id] ).await; if let Ok(rows) = result { let row = rows.get(0).ok_or("Client 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(result.unwrap_err().to_string()) } } async fn read_all(&self) -> Result, String> { let result = self.connection.query( "SELECT * FROM Client", &[] ).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(result.unwrap_err().to_string()) } } async fn update(&self, id: i32, client: BindingClient) -> Result { let result = self.connection.query( "UPDATE Client 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(result.unwrap_err().to_string()) } } async fn delete(&self, id: i32) -> Result<(), String> { let result = self.connection.execute( "DELETE FROM Client WHERE id = $1", &[&id] ).await; if let Ok(rows) = result { if rows == 0 { Err("Client not found".to_owned()) } else { Ok(()) } } else { Err(result.unwrap_err().to_string()) } } }