359 lines
12 KiB
Rust
359 lines
12 KiB
Rust
use sqlx::Row;
|
||
use sqlx::mysql::MySqlPool;
|
||
use sqlx::mysql::MySqlPoolOptions;
|
||
|
||
use dotenvy::dotenv_override;
|
||
use std::collections::HashMap;
|
||
use std::env;
|
||
// use crate::schema::equipment::dsl::*;
|
||
// use crate::schema::worker::dsl::*;
|
||
use crate::models::*;
|
||
use anyhow::anyhow;
|
||
|
||
pub struct DBOperator {
|
||
pool: MySqlPool,
|
||
}
|
||
impl DBOperator {
|
||
pub async fn new() -> Self {
|
||
dotenv_override().ok();
|
||
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL установи!");
|
||
Self {
|
||
pool: MySqlPool::connect(&db_url).await.unwrap(),
|
||
}
|
||
}
|
||
pub async fn get_position(&self) -> Result<Vec<Position>, sqlx::Error> {
|
||
let rets: Vec<Position> = sqlx::query_as::<_, Position>("SELECT * FROM `position`")
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
Ok(rets)
|
||
}
|
||
pub async fn get_workers(&self) -> Result<Vec<Worker>, sqlx::Error> {
|
||
let pre_rets: Vec<WorkerRow> = sqlx::query_as::<_, WorkerRow>("SELECT * FROM `worker`")
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
let mut rets: Vec<Worker> = Vec::new();
|
||
let pos = self.get_position().await.unwrap();
|
||
for worker in pre_rets {
|
||
let mut ppos = Position::default();
|
||
for position in pos.clone() {
|
||
if position.id == worker.position_id {
|
||
ppos = position.clone();
|
||
break;
|
||
}
|
||
}
|
||
rets.push(Worker {
|
||
id: worker.id,
|
||
full_name: worker.full_name,
|
||
hire_date: worker.hire_date,
|
||
position: ppos,
|
||
is_fired: worker.is_fired,
|
||
});
|
||
}
|
||
Ok(rets)
|
||
}
|
||
pub async fn get_equipment(&self) -> Result<Vec<Equipment>, sqlx::Error> {
|
||
let pre_rets = sqlx::query_as::<_, EquipmentRow>("SELECT * FROM `equipment`")
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
let mut rets: Vec<Equipment> = Vec::new();
|
||
let workers = self.get_workers().await?;
|
||
for eq in pre_rets {
|
||
let mut pworker = Worker::default();
|
||
for worker in workers.clone() {
|
||
if worker.id == eq.worker_id {
|
||
pworker = worker.clone();
|
||
break;
|
||
}
|
||
}
|
||
rets.push(Equipment {
|
||
id: eq.id,
|
||
name: eq.name,
|
||
inv_number: eq.inv_number,
|
||
maintenance_date: eq.maintenance_date,
|
||
worker: pworker,
|
||
});
|
||
}
|
||
Ok(rets)
|
||
}
|
||
pub async fn get_mcat(&self) -> Result<Vec<MaterialCategory>, sqlx::Error> {
|
||
let rets = sqlx::query_as::<_, MaterialCategory>("SELECT * FROM `material_category`")
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
Ok(rets)
|
||
}
|
||
pub async fn get_materials(&self) -> Result<Vec<Material>, sqlx::Error> {
|
||
let mats = sqlx::query_as::<_, MaterialRow>("SELECT * FROM `material`")
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
let cats = self.get_mcat().await?;
|
||
let cat_map: HashMap<_, MaterialCategory> =
|
||
cats.into_iter().map(|cat| (cat.id, cat)).collect();
|
||
let mut rets = Vec::with_capacity(mats.len());
|
||
for mat in mats {
|
||
let cat = cat_map
|
||
.get(&mat.category_id)
|
||
.expect("Никто не знает как, но БД не смогла связать материал с его категорией. Заставьте разраба это починить.")
|
||
.clone();
|
||
rets.push(Material {
|
||
id: mat.id,
|
||
name: mat.name,
|
||
quantity: mat.quantity,
|
||
category: cat,
|
||
});
|
||
}
|
||
Ok(rets)
|
||
}
|
||
pub async fn check_worker(&self, worker: Worker) -> Result<bool, sqlx::Error> {
|
||
let ret = sqlx::query(&format!(
|
||
"SELECT * FROM `worker` WHERE full_name = {}, position_id = {}, hire_date = {}",
|
||
worker.full_name,
|
||
worker.position.id,
|
||
worker.hire_date.to_string()
|
||
))
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
if ret.len() > 0 {
|
||
return Ok(true);
|
||
}
|
||
Ok(false)
|
||
}
|
||
pub async fn add_worker(&self, worker: WorkerRow) -> Result<bool, sqlx::Error> {
|
||
// sqlx::query!("INSERT INTO Brewery.worker (id, position_id, hire_date, is_fired, full_name) VALUES(0, ?, ?, ?, ?);",worker.position.id, worker.hire_date ,worker.is_fired,worker.full_name)
|
||
match sqlx::query("INSERT INTO Brewery.worker (id, position_id, hire_date, is_fired, full_name) VALUES(0, ?, ?, ?, ?);")
|
||
.bind(worker.position_id)
|
||
.bind(worker.hire_date)
|
||
.bind(worker.is_fired)
|
||
.bind(worker.full_name)
|
||
.execute(&self.pool)
|
||
.await {
|
||
Ok(_) =>{
|
||
return Ok(true)
|
||
},
|
||
Err(_) =>{
|
||
Ok(false)
|
||
}
|
||
}
|
||
}
|
||
pub async fn add_position(&self, position: Position) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("INSERT INTO Brewery.`position` (id, name, wage) VALUES(0, ?, ?);")
|
||
.bind(position.name)
|
||
.bind(position.wage)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn add_material_category(
|
||
&self,
|
||
mat_cat: MaterialCategory,
|
||
) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("INSERT INTO Brewery.`material_category` (id, name) VALUES (0, ?)")
|
||
.bind(mat_cat.name)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn add_material(&self, mat: MaterialRow) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query(
|
||
"INSERT INTO Brewery.material (id, name, quantity, category_id) VALUES(0, ?, ?, ?);",
|
||
)
|
||
.bind(mat.name)
|
||
.bind(mat.quantity)
|
||
.bind(mat.category_id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn delete_position(&self, position: Position) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("DELETE FROM Brewery.`position` WHERE id = ?;")
|
||
.bind(position.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn delete_material_category(
|
||
&self,
|
||
mat_cat: MaterialCategory,
|
||
) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("DELETE FROM Brewery.`material_category` WHERE id = ?;")
|
||
.bind(mat_cat.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn delete_material(&self, mat: MaterialRow) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("DELETE FROM Brewery.`material` WHERE id = ?;")
|
||
.bind(mat.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
|
||
pub async fn update_worker(&self, worker: WorkerRow) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE Brewery.worker SET position_id=?, hire_date=?, is_fired=?, full_name=? WHERE id=?;")
|
||
.bind(worker.position_id)
|
||
.bind(worker.hire_date)
|
||
.bind(worker.is_fired)
|
||
.bind(worker.full_name)
|
||
.bind(worker.id)
|
||
.execute(&self.pool)
|
||
.await{
|
||
Ok(_) =>{
|
||
Ok(true)
|
||
},
|
||
Err(_)=>{
|
||
Ok(false)
|
||
}
|
||
}
|
||
}
|
||
pub async fn update_material_category(
|
||
&self,
|
||
mat_cat: MaterialCategory,
|
||
) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE Brewery.`material_category` SET name=? WHERE id=?;")
|
||
.bind(mat_cat.name)
|
||
.bind(mat_cat.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn update_material(&self, mat: MaterialRow) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query(
|
||
"UPDATE Brewery.material SET name=?, quantity=?, category_id=? WHERE id=?;",
|
||
)
|
||
.bind(mat.name)
|
||
.bind(mat.quantity)
|
||
.bind(mat.category_id)
|
||
.bind(mat.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn get_worker_by_id(&self, worker_id: i32) -> Result<Worker, sqlx::Error> {
|
||
let preret = sqlx::query_as::<_, WorkerRow>("SELECT * FROM `worker` WHERE id = ?;")
|
||
.bind(worker_id)
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
let poses = self.get_position().await?;
|
||
let ret = Ok(Worker {
|
||
id: preret[0].id,
|
||
full_name: preret[0].full_name.clone(),
|
||
hire_date: preret[0].hire_date,
|
||
is_fired: preret[0].is_fired,
|
||
position: poses
|
||
.iter()
|
||
.find(|&pos| &pos.id == &preret[0].position_id)
|
||
.unwrap()
|
||
.clone(),
|
||
});
|
||
ret
|
||
}
|
||
|
||
pub async fn update_position(&self, pos: Position) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE Brewery.position SET name=?, wage=? WHERE id=?")
|
||
.bind(pos.name)
|
||
.bind(pos.wage)
|
||
.bind(pos.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn check_password(
|
||
&self,
|
||
username: String,
|
||
password_hash: String,
|
||
) -> Result<bool, sqlx::Error> {
|
||
let ans = sqlx::query("SELECT * FROM Brewery.profile WHERE login=? AND password=?")
|
||
.bind(username)
|
||
.bind(password_hash)
|
||
.fetch_all(&self.pool)
|
||
.await;
|
||
match ans {
|
||
Ok(n) => {
|
||
if n.len() > 0 {
|
||
return Ok(true);
|
||
} else {
|
||
return Ok(false);
|
||
}
|
||
}
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn check_admin(&self, username: String) -> Result<bool, sqlx::Error> {
|
||
let ans: bool = sqlx::query_scalar(
|
||
r#"SELECT
|
||
position.is_admin,
|
||
profile.worker_id,
|
||
worker.id,
|
||
profile.login,
|
||
position.id
|
||
FROM
|
||
Brewery.profile
|
||
JOIN
|
||
Brewery.worker
|
||
JOIN
|
||
Brewery.position
|
||
ON profile.worker_id = worker.id
|
||
AND profile.login=?
|
||
AND worker.position_id =position.id"#,
|
||
)
|
||
.bind(username)
|
||
.fetch_one(&self.pool)
|
||
.await
|
||
.unwrap();
|
||
Ok(ans)
|
||
}
|
||
}
|
||
|
||
pub async fn estabilish_connection() -> Result<(), sqlx::Error> {
|
||
dotenv_override().ok();
|
||
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL установи!");
|
||
let _pool = MySqlPoolOptions::new()
|
||
.max_connections(5)
|
||
.connect(&db_url)
|
||
.await?;
|
||
|
||
Ok(())
|
||
}
|
||
|
||
macro_rules! add_get {
|
||
($fn_name:ident, $table:ident) => {
|
||
pub async fn $fn_name(&self, $id: i32) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE `$table` SET WHERE id = ?")
|
||
.bind($id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(e) => Err(e),
|
||
}
|
||
}
|
||
};
|
||
}
|