612 lines
20 KiB
Rust
612 lines
20 KiB
Rust
use bigdecimal::BigDecimal;
|
||
use chrono::DateTime;
|
||
use sqlx::Row;
|
||
use sqlx::mysql::MySqlPool;
|
||
use sqlx::mysql::MySqlPoolOptions;
|
||
|
||
use dotenvy::dotenv_override;
|
||
use std::collections::HashMap;
|
||
use std::collections::HashSet;
|
||
use std::env;
|
||
// use crate::schema::equipment::dsl::*;
|
||
// use crate::schema::worker::dsl::*;
|
||
use crate::models::*;
|
||
|
||
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_position_by_id(&self, id: i32) -> Result<Position, sqlx::Error> {
|
||
sqlx::query_as::<_, Position>("SELECT * FROM `position` WHERE id = ?")
|
||
.bind(id)
|
||
.fetch_one(&self.pool)
|
||
.await
|
||
}
|
||
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,
|
||
fire_date: worker.fire_date,
|
||
});
|
||
}
|
||
Ok(rets)
|
||
}
|
||
pub async fn get_worker_by_id(&self, id: i32) -> Result<Worker, sqlx::Error> {
|
||
match sqlx::query_as::<_, WorkerRow>("SELECT * FROM `worker` WHERE id = ?")
|
||
.bind(id)
|
||
.fetch_one(&self.pool)
|
||
.await
|
||
{
|
||
Ok(n) => Ok(Worker {
|
||
id: n.id,
|
||
full_name: n.full_name,
|
||
position: self
|
||
.get_position_by_id(n.position_id)
|
||
.await
|
||
.unwrap_or(Position::default()),
|
||
is_fired: n.is_fired,
|
||
hire_date: n.hire_date,
|
||
fire_date: n.fire_date,
|
||
}),
|
||
Err(e) => Err(e),
|
||
}
|
||
}
|
||
pub async fn get_equipment(
|
||
&self,
|
||
start: i32,
|
||
count: i32,
|
||
) -> Result<Vec<Equipment>, sqlx::Error> {
|
||
let pre_rets =
|
||
sqlx::query_as::<_, EquipmentRow>("SELECT * FROM `equipment` LIMIT ? OFFSET ?")
|
||
.bind(count)
|
||
.bind(start)
|
||
.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,
|
||
is_written_off: eq.is_written_off,
|
||
});
|
||
}
|
||
Ok(rets)
|
||
}
|
||
pub async fn get_equipment_by_id(&self, id: i32) -> Result<Equipment, sqlx::Error> {
|
||
match sqlx::query_as::<_, EquipmentRow>("SELECT * FROM `equipment` WHERE id = ?")
|
||
.bind(id)
|
||
.fetch_one(&self.pool)
|
||
.await
|
||
{
|
||
Ok(n) => Ok(Equipment {
|
||
id,
|
||
name: n.name,
|
||
inv_number: n.inv_number,
|
||
maintenance_date: n.maintenance_date,
|
||
worker: self
|
||
.get_worker_by_id(n.worker_id)
|
||
.await
|
||
.unwrap_or(Worker::default()),
|
||
is_written_off: n.is_written_off,
|
||
}),
|
||
Err(e) => Err(e),
|
||
}
|
||
}
|
||
pub async fn add_equipment(&self, equipment: Equipment) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("INSERT INTO `equipment` (id, inv_number, maintenance_date, worker_id, name, is_written_off) VALUES(0, ?, ?, ?, ?, 0);")
|
||
.bind(equipment.inv_number)
|
||
.bind(equipment.maintenance_date)
|
||
.bind(equipment.worker.id)
|
||
.bind(equipment.name)
|
||
.execute(&self.pool)
|
||
.await{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false)
|
||
}
|
||
}
|
||
pub async fn update_equipment(&self, equipment: Equipment) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE `equipment` SET inv_number=?, maintenance_date=?, worker_id=?, name=?, is_written_off=? WHERE id=?;")
|
||
.bind(equipment.inv_number)
|
||
.bind(equipment.maintenance_date)
|
||
.bind(equipment.worker.id)
|
||
.bind(equipment.name)
|
||
.bind(equipment.is_written_off)
|
||
.bind(equipment.id)
|
||
.execute(&self.pool)
|
||
.await{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false)
|
||
}
|
||
}
|
||
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 promote_worker(
|
||
&self,
|
||
worker: Worker,
|
||
position_to: Position,
|
||
date: DateTime<chrono::Local>,
|
||
) -> Result<(), sqlx::Error> {
|
||
let mut tx = self.pool.begin().await?;
|
||
sqlx::query("INSERT INTO promotion (worker_id, from_position_id, to_position_id, `date`) VALUES(?, ?, ?, ?);").bind(worker.id).bind(worker.position.id).bind(position_to.id).bind(date).execute(&mut *tx).await?;
|
||
sqlx::query("UPDATE worker SET position_id=? WHERE id=?;")
|
||
.bind(position_to.id)
|
||
.bind(worker.id)
|
||
.execute(&mut *tx)
|
||
.await?;
|
||
|
||
tx.commit().await
|
||
}
|
||
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 `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 `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 `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 `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 `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 `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 `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 `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 `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 update_position(&self, pos: Position) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE `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 `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
|
||
`profile`
|
||
JOIN
|
||
`worker`
|
||
JOIN
|
||
`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 write_off_equipment(&self, equipment_id: i32) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE `equipment` SET is_written_off=1 WHERE id=?")
|
||
.bind(equipment_id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn get_salaries(&self) -> Result<Vec<Salary>, sqlx::Error> {
|
||
let sals = sqlx::query_as::<_, SalaryRow>("SELECT * FROM `salary`")
|
||
.fetch_all(&self.pool)
|
||
.await?;
|
||
let mut rets: Vec<Salary> = Vec::new();
|
||
let workers = self.get_workers().await.unwrap();
|
||
for sal in sals {
|
||
match workers.iter().find(|w| w.id == sal.worker_id) {
|
||
Some(w) => rets.push(Salary {
|
||
id: sal.id,
|
||
worker: w.clone(),
|
||
salary_date: sal.salary_date,
|
||
salary_size: sal.salary_size,
|
||
comment: sal.comment,
|
||
}),
|
||
None => {}
|
||
}
|
||
}
|
||
|
||
Ok(rets)
|
||
}
|
||
pub async fn add_salary(
|
||
&self,
|
||
worker_id: i32,
|
||
salary_date: DateTime<chrono::Local>,
|
||
salary_size: BigDecimal,
|
||
comment: Option<String>,
|
||
) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("INSERT INTO `salary` (id, worker_id, salary_size, salary_date, comment) VALUES(0, ?, ?, ?, ?);")
|
||
.bind(worker_id)
|
||
.bind(salary_size)
|
||
.bind(salary_date)
|
||
.bind(comment.unwrap_or(String::new()))
|
||
.execute(&self.pool)
|
||
.await{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false)
|
||
}
|
||
}
|
||
pub async fn update_salary(&self, salary: Salary) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query(
|
||
"UPDATE `salary` SET worker_id=?, salary_size=?, salary_date=?, comment=? WHERE id=?;",
|
||
)
|
||
.bind(salary.worker.id)
|
||
.bind(salary.salary_size)
|
||
.bind(salary.salary_date)
|
||
.bind(salary.comment)
|
||
.bind(salary.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn remove_salary(&self, id: i32) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("DELETE FROM `salary` WHERE id=?;")
|
||
.bind(id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn get_recipes(&self) -> Result<Vec<Recipe>, sqlx::Error> {
|
||
let pre_ret = sqlx::query_as::<_, RecipeRow>("SELECT * FROM `recipe`")
|
||
.fetch_all(&self.pool)
|
||
.await
|
||
.unwrap_or(Vec::new());
|
||
|
||
let mut ret: Vec<Recipe> = Vec::new();
|
||
let elements = self.get_recipe_elements().await.unwrap_or(Vec::new());
|
||
for pr in pre_ret.iter() {
|
||
let mut els: Vec<RecipeElement> = Vec::new();
|
||
for elem in elements.clone() {
|
||
if elem.recipe_id == pr.id {
|
||
els.push(elem.clone());
|
||
}
|
||
}
|
||
ret.push(Recipe {
|
||
id: pr.id,
|
||
name: pr.name.clone(),
|
||
elements: els.into_iter().collect(),
|
||
});
|
||
}
|
||
Ok(ret)
|
||
}
|
||
pub async fn add_recipe(&self, rec: Recipe) -> Result<u64, sqlx::Error> {
|
||
let mut tx = self.pool.begin().await?;
|
||
sqlx::query("INSERT INTO `recipe` (id,name) VALUES (?,?)")
|
||
.bind(rec.id)
|
||
.bind(rec.name)
|
||
.execute(&mut *tx)
|
||
.await?;
|
||
let ret = sqlx::query("SELECT LAST_INSERT_ID();")
|
||
.fetch_one(&mut *tx)
|
||
.await?;
|
||
match tx.commit().await {
|
||
Ok(_) => Ok(ret.get(0)),
|
||
Err(_) => Ok(0),
|
||
}
|
||
}
|
||
pub async fn remove_recipe(&self, rec_id: i32) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("DELETE FROM `recipe` WHERE id=?")
|
||
.bind(rec_id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn update_recipe(&self, recipe: Recipe) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("UPDATE `recipe` SET name=? WHERE id=?;")
|
||
.bind(recipe.name)
|
||
.bind(recipe.id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
pub async fn get_recipe_elements(&self) -> Result<Vec<RecipeElement>, sqlx::Error> {
|
||
let pre_ret = sqlx::query_as::<_, RecipeElementRow>(
|
||
"SELECT id, recipe_id, material_id, equipment_id, quantity FROM `recipe_element`;",
|
||
)
|
||
.fetch_all(&self.pool)
|
||
.await;
|
||
|
||
let mats = self.get_materials().await.unwrap();
|
||
let mut ret: Vec<RecipeElement> = Vec::new();
|
||
for re in pre_ret.unwrap().iter() {
|
||
let mat = mats.iter().find(|m| m.id == re.material_id);
|
||
let eq = self.get_equipment_by_id(re.equipment_id).await.ok();
|
||
match (mat, eq) {
|
||
(Some(m), Some(e)) => {
|
||
ret.push(RecipeElement {
|
||
id: re.id,
|
||
material: m.clone(),
|
||
equipment: e.clone(),
|
||
quantity: re.quantity,
|
||
recipe_id: re.recipe_id,
|
||
});
|
||
}
|
||
(_, _) => {}
|
||
}
|
||
}
|
||
Ok(ret)
|
||
}
|
||
pub async fn add_recipe_elems(
|
||
&self,
|
||
elems: HashSet<RecipeElement>,
|
||
rec_id: i32,
|
||
) -> Result<bool, sqlx::Error> {
|
||
let mut tx = self.pool.begin().await?;
|
||
for el in elems.iter() {
|
||
sqlx::query("INSERT INTO `recipe_element` (id, recipe_id, material_id, equipment_id, quantity) VALUES(0, ?, ?, ?, ?);")
|
||
.bind(rec_id)
|
||
.bind(el.material.id)
|
||
.bind(el.equipment.id)
|
||
.bind(el.quantity)
|
||
.execute(&mut *tx)
|
||
.await?;
|
||
}
|
||
match tx.commit().await {
|
||
Ok(_) => Ok(true),
|
||
Err(e) => Err(e),
|
||
}
|
||
}
|
||
pub async fn remove_recipe_elements(&self, rec_id: i32) -> Result<bool, sqlx::Error> {
|
||
match sqlx::query("DELETE FROM `recipe_element` WHERE recipe_id=?")
|
||
.bind(rec_id)
|
||
.execute(&self.pool)
|
||
.await
|
||
{
|
||
Ok(_) => Ok(true),
|
||
Err(_) => Ok(false),
|
||
}
|
||
}
|
||
}
|
||
|
||
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),
|
||
}
|
||
}
|
||
};
|
||
}
|