Compare commits

...

2 Commits

3 changed files with 135 additions and 31 deletions

View File

@ -1,11 +1,9 @@
use std::sync::Arc; use std::sync::Arc;
use chrono::NaiveDate;
use egui::mutex::RwLock; use egui::mutex::RwLock;
use egui_dock::{DockArea, Style, TabViewer}; use egui_dock::{DockArea, Style, TabViewer};
use rust_decimal::prelude::Zero; use sqlx::types::BigDecimal;
use sqlx::{Connection, MySqlConnection, MySqlPool, types::BigDecimal}; use crate::{database::DBOperator, models::{Equipment, Position, Worker}};
use crate::{database::DBOperator, models::{self, Equipment, Position, Salary, Worker}};
static TABS_CAN_BE_WINDOWS: bool = false; static TABS_CAN_BE_WINDOWS: bool = false;
@ -33,7 +31,7 @@ pub struct App{
impl Default for App{ impl Default for App{
fn default() -> Self{ fn default() -> Self{
let mut tree = egui_dock::DockState::new(vec![ let tree = egui_dock::DockState::new(vec![
Tab{ Tab{
tab_type: TabTypes::Equipment, tab_type: TabTypes::Equipment,
title:"Оборудование".to_owned(), title:"Оборудование".to_owned(),
@ -50,10 +48,6 @@ impl Default for App{
tab_type: TabTypes::Salary, tab_type: TabTypes::Salary,
title:"Выплаты".to_owned(), title:"Выплаты".to_owned(),
}, },
Tab{
tab_type: TabTypes::Position,
title: "Должности".to_owned(),
},
Tab{ Tab{
tab_type: TabTypes::Recipe, tab_type: TabTypes::Recipe,
title: "Рецепты".to_owned(), title: "Рецепты".to_owned(),
@ -86,8 +80,8 @@ impl eframe::App for App{
.style(Style::from_egui(ui.style().as_ref())) .style(Style::from_egui(ui.style().as_ref()))
.show_inside(ui, &mut self.main_viewer); .show_inside(ui, &mut self.main_viewer);
} }
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if (self.main_viewer.is_dark_theme){ if self.main_viewer.is_dark_theme {
ctx.set_visuals(egui::Visuals::dark()); ctx.set_visuals(egui::Visuals::dark());
}else{ }else{
ctx.set_visuals(egui::Visuals::light()); ctx.set_visuals(egui::Visuals::light());
@ -201,7 +195,7 @@ impl MainTabViewer{
ui.label("Сырьё короче да"); ui.label("Сырьё короче да");
} }
fn show_salary(&mut self, ui: &mut egui::Ui){ fn show_salary(&mut self, ui: &mut egui::Ui){
ui.label("Помогите");
} }
fn show_settings(&mut self, ui: &mut egui::Ui){ fn show_settings(&mut self, ui: &mut egui::Ui){
ui.checkbox(&mut self.is_dark_theme, "Тёмная тема"); ui.checkbox(&mut self.is_dark_theme, "Тёмная тема");
@ -277,6 +271,8 @@ struct WorkerTabViewer{
edit_worker_position: Position, edit_worker_position: Position,
rt: tokio::runtime::Runtime, rt: tokio::runtime::Runtime,
show_position_delete_modal: bool,
delete_position: Position,
} }
@ -284,6 +280,9 @@ impl WorkerTabViewer{
fn update_workers(&mut self){ fn update_workers(&mut self){
self.workers = Arc::new(RwLock::new(Option::Some(self.rt.block_on(async{self.db_oper.get_workers().await.unwrap()})))); self.workers = Arc::new(RwLock::new(Option::Some(self.rt.block_on(async{self.db_oper.get_workers().await.unwrap()}))));
} }
fn update_positions(&mut self){
self.positions = Arc::new(RwLock::new(Option::Some(self.rt.block_on(async{self.db_oper.get_position().await.unwrap()}))));
}
fn show_worker(&mut self, ui: &mut egui::Ui){ fn show_worker(&mut self, ui: &mut egui::Ui){
ui.horizontal(|ui|{ ui.horizontal(|ui|{
@ -295,6 +294,20 @@ impl WorkerTabViewer{
}; };
if ui.button("Редактировать").clicked() { if ui.button("Редактировать").clicked() {
self.show_worker_edit_modal = true; self.show_worker_edit_modal = true;
self.rt.block_on(async{
let wrkr = match self.db_oper.get_worker_by_id(self.edit_worker_id).await{
Ok(worker)=>{
worker
},
Err(_)=>{
Worker::default()
}
};
self.edit_worker_name = wrkr.full_name;
self.edit_worker_hire_date = wrkr.hire_date.format("%Y-%m-%d").to_string();
self.edit_worker_position = wrkr.position;
self.edit_worker_is_fired = wrkr.is_fired;
});
} }
if ui.button("Обновить").clicked(){ if ui.button("Обновить").clicked(){
self.update_workers(); self.update_workers();
@ -328,7 +341,7 @@ impl WorkerTabViewer{
}); });
if(chrono::NaiveDate::parse_from_str(&self.add_worker_hire_date, "%d-%m-%Y").is_err()){ if chrono::NaiveDate::parse_from_str(&self.add_worker_hire_date, "%d-%m-%Y").is_err() {
ui.label(egui::RichText::new("ДАТА УКАЗАНА НЕВЕРНО").color(egui::Color32::RED)); ui.label(egui::RichText::new("ДАТА УКАЗАНА НЕВЕРНО").color(egui::Color32::RED));
self.can_add_worker = false; self.can_add_worker = false;
}else{ }else{
@ -379,7 +392,6 @@ impl WorkerTabViewer{
}); });
}); });
if self.edit_worker_id != old{ if self.edit_worker_id != old{
println!("Ура перемена");
self.rt.block_on(async{ self.rt.block_on(async{
let wrkr = match self.db_oper.get_worker_by_id(self.edit_worker_id).await{ let wrkr = match self.db_oper.get_worker_by_id(self.edit_worker_id).await{
Ok(worker)=>{ Ok(worker)=>{
@ -417,11 +429,33 @@ impl WorkerTabViewer{
}); });
ui.end_row(); ui.end_row();
ui.label("Дата найма");
ui.text_edit_singleline(&mut self.edit_worker_hire_date);
ui.end_row();
ui.checkbox(&mut self.edit_worker_is_fired, "Уволен"); ui.checkbox(&mut self.edit_worker_is_fired, "Уволен");
ui.end_row(); ui.end_row();
}); });
if chrono::NaiveDate::parse_from_str(&self.edit_worker_hire_date, "%Y-%m-%d").is_ok() && self.edit_worker_name.len() > 0{
self.can_edit_worker = true;
}else{
self.can_edit_worker = false;
}
let resp = ui.add_enabled(self.can_edit_worker, egui::Button::new("Добавить"));
if resp.clicked(){
self.rt.block_on(async{
let ndate = chrono::NaiveDate::parse_from_str(&self.edit_worker_hire_date, "%Y-%m-%d").unwrap();
self.db_oper.update_worker(Worker {
id: self.edit_worker_id,
full_name: self.edit_worker_name.clone(),
hire_date: ndate.and_hms_opt(0,0, 0).unwrap().and_local_timezone(chrono::Local).unwrap(),
position: self.edit_worker_position.clone(),
is_fired: self.edit_worker_is_fired }).await.unwrap();
});
self.update_workers();
self.show_worker_edit_modal = false;
}
}); });
} }
for wk in self.workers.read().clone().unwrap().iter(){ for wk in self.workers.read().clone().unwrap().iter(){
@ -454,6 +488,12 @@ impl WorkerTabViewer{
if ui.button("Добавить").clicked(){ if ui.button("Добавить").clicked(){
self.show_position_add_modal = true; self.show_position_add_modal = true;
} }
if ui.button("Удалить").clicked(){
self.show_position_delete_modal = true;
self.delete_position = self.positions.read().clone().unwrap()[0].clone();
self.update_positions();
self.update_workers();
}
}); });
for eq in self.positions.read().clone().unwrap().iter(){ for eq in self.positions.read().clone().unwrap().iter(){
ui.push_id(&eq.name, |ui|{ ui.push_id(&eq.name, |ui|{
@ -488,8 +528,42 @@ impl WorkerTabViewer{
ui.end_row(); ui.end_row();
}); });
let resp = ui.add_enabled(self.add_position_name.len()>0&&self.add_position_wage.len()>0,egui::Button::new("Добавить") );
if resp.clicked(){
self.rt.block_on(async{
self.db_oper.add_position(Position {
id: 0,
name: self.add_position_name.clone(),
wage: BigDecimal::from(self.add_position_wage.trim().parse::<i32>().unwrap()) }).await.ok();
});
self.update_positions();
self.show_position_add_modal = false;
}
});
}
if self.show_position_delete_modal{
egui::Modal::new("delete_position".into()).show(ui.ctx(), |ui|{
if ui.button("Закрыть").clicked(){
self.show_position_delete_modal = false;
}
egui::ComboBox::from_label("Должность").selected_text(&self.delete_position.name)
.show_ui(ui, |ui|{
self.rt.block_on(async{
for pos in self.positions.read().clone().unwrap().iter(){
ui.selectable_value(&mut self.delete_position, pos.clone(), &pos.name);
}
});
});
let can_delete = self.workers.read().clone().unwrap().iter().find(|wrkr| wrkr.position.id == self.delete_position.id).iter().len() == 0;
if !can_delete{
ui.label(egui::RichText::new("Есть сотрудники с этой должностью").color(egui::Color32::YELLOW));
}
let resp = ui.add_enabled(can_delete, egui::Button::new("Удалить"));
if resp.clicked(){
self.rt.block_on(async{
self.db_oper.delete_position(self.delete_position.clone()).await.unwrap();
});
}
}); });
} }
} }
@ -526,6 +600,7 @@ impl Default for WorkerTabViewer{
show_worker_add_modal: false, show_worker_add_modal: false,
show_worker_edit_modal: false, show_worker_edit_modal: false,
show_position_add_modal: false, show_position_add_modal: false,
show_position_delete_modal: false,
fire_worker_id: String::new(), fire_worker_id: String::new(),
add_worker_name: String::new(), add_worker_name: String::new(),
add_worker_position: Position::default(), add_worker_position: Position::default(),
@ -534,6 +609,7 @@ impl Default for WorkerTabViewer{
can_edit_worker: false, can_edit_worker: false,
add_position_name: String::new(), add_position_name: String::new(),
add_position_wage: String::new(), add_position_wage: String::new(),
delete_position: Position::default(),
edit_worker_id: 1, edit_worker_id: 1,
edit_worker_name: String::new(), edit_worker_name: String::new(),

View File

@ -3,7 +3,6 @@ use sqlx::mysql::MySqlPool;
use dotenvy::dotenv_override; use dotenvy::dotenv_override;
use sqlx::mysql::MySqlQueryResult;
use std::env; use std::env;
// use crate::schema::equipment::dsl::*; // use crate::schema::equipment::dsl::*;
// use crate::schema::worker::dsl::*; // use crate::schema::worker::dsl::*;
@ -64,13 +63,13 @@ impl DBOperator{
} }
pub async fn add_worker(&self, worker: Worker) -> Result<bool,sqlx::Error>{ pub async fn add_worker(&self, worker: Worker) -> 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) // 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, ?, ?, ?, ?);") match sqlx::query("INSERT INTO Brewery.worker (id, position_id, hire_date, is_fired, full_name) VALUES(0, ?, ?, ?, ?);")
.bind(worker.position.id) .bind(worker.position.id)
.bind(worker.hire_date) .bind(worker.hire_date)
.bind(worker.is_fired) .bind(worker.is_fired)
.bind(worker.full_name) .bind(worker.full_name)
.execute(&self.pool) .execute(&self.pool)
.await){ .await {
Ok(_) =>{ Ok(_) =>{
return Ok(true) return Ok(true)
}, },
@ -79,12 +78,43 @@ impl DBOperator{
} }
} }
} }
pub async fn change_worker_fire_state(&self, worker_id: i32, is_fired: bool) -> Result<bool,sqlx::Error>{ pub async fn add_position(&self, position: Position) -> Result<bool,sqlx::Error>{
match(sqlx::query("UPDATE Brewery.worker SET is_fired=? WHERE id=?;") match sqlx::query("INSERT INTO Brewery.`position` (id, name, wage) VALUES(0, ?, ?);")
.bind(if is_fired {1} else {0}) .bind(position.name)
.bind(worker_id) .bind(position.wage)
.execute(&self.pool) .execute(&self.pool)
.await){ .await{
Ok(_)=>{
Ok(true)
},
Err(_)=>{
Ok(false)
}
}
}
pub async fn delete_position(&self, position: Position) -> Result<bool,sqlx::Error>{
match sqlx::query("DELETE FROM Brewer.`position` WHERE id = ?;")
.bind(position.id)
.execute(&self.pool)
.await{
Ok(_)=>{
Ok(true)
},
Err(_)=>{
Ok(false)
}
}
}
pub async fn update_worker(&self, worker: Worker) -> 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(_) =>{
Ok(true) Ok(true)
}, },
@ -116,7 +146,7 @@ impl DBOperator{
pub async fn estabilish_connection() -> Result<(), sqlx::Error>{ pub async fn estabilish_connection() -> Result<(), sqlx::Error>{
dotenv_override().ok(); dotenv_override().ok();
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL установи!"); let db_url = env::var("DATABASE_URL").expect("DATABASE_URL установи!");
let pool = MySqlPoolOptions::new() let _pool = MySqlPoolOptions::new()
.max_connections(5) .max_connections(5)
.connect(&db_url).await?; .connect(&db_url).await?;

View File

@ -1,16 +1,14 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use egui::mutex::RwLock;
use sqlx::MySqlPool;
use crate::database::DBOperator;
mod app; mod app;
mod models; mod models;
mod database; mod database;
// mod schema; // mod schema;
fn main() fn main()
{ {
dotenvy::dotenv().ok(); database::estabilish_connection(); dotenvy::dotenv().ok();
database::estabilish_connection();
let native_opts = eframe::NativeOptions { let native_opts = eframe::NativeOptions {
viewport: egui::ViewportBuilder::default() viewport: egui::ViewportBuilder::default()
.with_inner_size([400.0,300.0]) .with_inner_size([400.0,300.0])