Compare commits
2 Commits
8cb2ec92b7
...
97d73cf027
| Author | SHA1 | Date |
|---|---|---|
|
|
97d73cf027 | |
|
|
359e254c0a |
|
|
@ -770,6 +770,7 @@ dependencies = [
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
"hex",
|
"hex",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
|
"rust_xlsxwriter",
|
||||||
"sha2 0.11.0",
|
"sha2 0.11.0",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
@ -1424,6 +1425,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
|
"zlib-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3472,6 +3474,16 @@ dependencies = [
|
||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust_xlsxwriter"
|
||||||
|
version = "0.95.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f281b687352597d29efaad39701d1167d5c48aa76fb973e392bc13e9d44e7f36"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"zip",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
@ -4392,6 +4404,12 @@ dependencies = [
|
||||||
"rustc-hash 2.1.2",
|
"rustc-hash 2.1.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-path"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.20.1"
|
version = "1.20.1"
|
||||||
|
|
@ -5805,12 +5823,44 @@ dependencies = [
|
||||||
"syn 2.0.117",
|
"syn 2.0.117",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "7.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"flate2",
|
||||||
|
"indexmap",
|
||||||
|
"memchr",
|
||||||
|
"typed-path",
|
||||||
|
"zopfli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zlib-rs"
|
||||||
|
version = "0.6.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zmij"
|
name = "zmij"
|
||||||
version = "1.0.21"
|
version = "1.0.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zopfli"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"crc32fast",
|
||||||
|
"log",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ egui_dock = "0.19.1"
|
||||||
egui_extras = {version = "0.34.2", features = ["datepicker", "image"]}
|
egui_extras = {version = "0.34.2", features = ["datepicker", "image"]}
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
rust_decimal = {version = "1.42.0", features = ["macros"]}
|
rust_decimal = {version = "1.42.0", features = ["macros"]}
|
||||||
|
rust_xlsxwriter = {version="0.95.0",features=["chrono"]}
|
||||||
sha2 = "0.11.0"
|
sha2 = "0.11.0"
|
||||||
sqlx = {version="0.8.6", features = ["runtime-tokio", "mysql","bigdecimal","chrono"]}
|
sqlx = {version="0.8.6", features = ["runtime-tokio", "mysql","bigdecimal","chrono"]}
|
||||||
tokio={version = "1.52.3", features = ["full"]}
|
tokio={version = "1.52.3", features = ["full"]}
|
||||||
|
|
|
||||||
220
code/src/app.rs
220
code/src/app.rs
|
|
@ -13,6 +13,8 @@ use crate::{
|
||||||
Equipment, LoginModalState, LoginStatus, Material, MaterialCategory, MaterialRow,
|
Equipment, LoginModalState, LoginStatus, Material, MaterialCategory, MaterialRow,
|
||||||
ModalStatus, ModalWinState, Position, Salary, SalaryModalState, Worker,
|
ModalStatus, ModalWinState, Position, Salary, SalaryModalState, Worker,
|
||||||
},
|
},
|
||||||
|
recipe_tab::RecipeTabViewer,
|
||||||
|
reports::Reporter,
|
||||||
tab::*,
|
tab::*,
|
||||||
worker_tab::{self, *},
|
worker_tab::{self, *},
|
||||||
};
|
};
|
||||||
|
|
@ -142,10 +144,11 @@ impl eframe::App for App<'_> {
|
||||||
if self.rt.block_on(async {
|
if self.rt.block_on(async {
|
||||||
self.db_oper.check_admin(uname.clone()).await.unwrap()
|
self.db_oper.check_admin(uname.clone()).await.unwrap()
|
||||||
}) {
|
}) {
|
||||||
self.main_viewer.is_admin = true
|
self.main_viewer.is_admin = true;
|
||||||
} else {
|
} else {
|
||||||
self.main_viewer.is_admin = false;
|
self.main_viewer.is_admin = false;
|
||||||
}
|
}
|
||||||
|
self.main_viewer = MainTabViewer::new(self.main_viewer.is_admin);
|
||||||
} else {
|
} else {
|
||||||
self.login_modal_state.fail = true;
|
self.login_modal_state.fail = true;
|
||||||
self.login_modal_state.fail_message =
|
self.login_modal_state.fail_message =
|
||||||
|
|
@ -179,12 +182,14 @@ struct MainTabViewer {
|
||||||
worker_tree: egui_dock::DockState<Tab>,
|
worker_tree: egui_dock::DockState<Tab>,
|
||||||
material_tabs: MaterialTabViewer,
|
material_tabs: MaterialTabViewer,
|
||||||
material_tree: egui_dock::DockState<Tab>,
|
material_tree: egui_dock::DockState<Tab>,
|
||||||
|
recipe_tab: RecipeTabViewer,
|
||||||
rt: tokio::runtime::Runtime,
|
rt: tokio::runtime::Runtime,
|
||||||
equipment_modal_state: ModalWinState,
|
equipment_modal_state: ModalWinState,
|
||||||
salary_modal_state: SalaryModalState,
|
salary_modal_state: SalaryModalState,
|
||||||
is_dark_theme: bool,
|
is_dark_theme: bool,
|
||||||
interface_scale_ratio: f32,
|
interface_scale_ratio: f32,
|
||||||
is_admin: bool,
|
is_admin: bool,
|
||||||
|
reporter: Reporter,
|
||||||
}
|
}
|
||||||
impl Default for MainTabViewer {
|
impl Default for MainTabViewer {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
|
@ -223,6 +228,7 @@ impl Default for MainTabViewer {
|
||||||
tab_type: TabTypes::MaterialTypeList,
|
tab_type: TabTypes::MaterialTypeList,
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
|
recipe_tab: RecipeTabViewer::default(),
|
||||||
rt,
|
rt,
|
||||||
is_dark_theme: true,
|
is_dark_theme: true,
|
||||||
interface_scale_ratio: 1.2,
|
interface_scale_ratio: 1.2,
|
||||||
|
|
@ -251,10 +257,50 @@ impl Default for MainTabViewer {
|
||||||
workers: HashSet::new(),
|
workers: HashSet::new(),
|
||||||
},
|
},
|
||||||
is_admin: false,
|
is_admin: false,
|
||||||
|
reporter: Reporter {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl MainTabViewer {
|
impl MainTabViewer {
|
||||||
|
fn update_salary(&mut self) {
|
||||||
|
self.salaries = Arc::new(RwLock::new(
|
||||||
|
self.rt
|
||||||
|
.block_on(async { self.db_oper.get_salaries().await.unwrap() }),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
fn get_salary(&self) -> Salary {
|
||||||
|
Salary {
|
||||||
|
id: self
|
||||||
|
.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("id")
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i32>()
|
||||||
|
.unwrap(),
|
||||||
|
worker: self
|
||||||
|
.workers
|
||||||
|
.read()
|
||||||
|
.iter()
|
||||||
|
.find(|w| {
|
||||||
|
&w.id.to_string() == self.salary_modal_state.data.get("worker_id").unwrap()
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
salary_size: BigDecimal::from_str(
|
||||||
|
self.salary_modal_state.data.get("salary_size").unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
salary_date: chrono::NaiveDate::from_str(
|
||||||
|
self.salary_modal_state.data.get("salary_date").unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(0, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
.and_local_timezone(chrono::Local)
|
||||||
|
.unwrap(),
|
||||||
|
comment: self.salary_modal_state.data.get("comment").unwrap().clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
fn new(is_admin: bool) -> Self {
|
fn new(is_admin: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
is_admin,
|
is_admin,
|
||||||
|
|
@ -287,6 +333,7 @@ impl MainTabViewer {
|
||||||
let mut table = TableBuilder::new(ui)
|
let mut table = TableBuilder::new(ui)
|
||||||
.striped(true)
|
.striped(true)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
|
.vscroll(false)
|
||||||
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
|
||||||
.column(Column::auto())
|
.column(Column::auto())
|
||||||
.column(Column::auto())
|
.column(Column::auto())
|
||||||
|
|
@ -512,6 +559,7 @@ impl MainTabViewer {
|
||||||
.striped(true)
|
.striped(true)
|
||||||
.columns(Column::auto(), 5)
|
.columns(Column::auto(), 5)
|
||||||
.sense(egui::Sense::click())
|
.sense(egui::Sense::click())
|
||||||
|
.vscroll(false)
|
||||||
.header(30.0, |mut header| {
|
.header(30.0, |mut header| {
|
||||||
header.col(|ui| {
|
header.col(|ui| {
|
||||||
ui.heading("Имя сотрудника");
|
ui.heading("Имя сотрудника");
|
||||||
|
|
@ -523,13 +571,13 @@ impl MainTabViewer {
|
||||||
ui.heading("Дата");
|
ui.heading("Дата");
|
||||||
});
|
});
|
||||||
header.col(|ui| {
|
header.col(|ui| {
|
||||||
ui.heading("Описание");
|
ui.heading("Примечание");
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.body(|mut body| {
|
.body(|mut body| {
|
||||||
body.ui_mut().style_mut().interaction.selectable_labels = false;
|
body.ui_mut().style_mut().interaction.selectable_labels = false;
|
||||||
for sal in (self.salaries.read().iter().clone()) {
|
for sal in (self.salaries.read().iter().clone()) {
|
||||||
body.row(20.0, |mut row| {
|
body.row(25.0, |mut row| {
|
||||||
row.col(|ui| {
|
row.col(|ui| {
|
||||||
ui.label(&sal.worker.full_name);
|
ui.label(&sal.worker.full_name);
|
||||||
});
|
});
|
||||||
|
|
@ -540,7 +588,8 @@ impl MainTabViewer {
|
||||||
ui.label(&sal.salary_date.date_naive().to_string());
|
ui.label(&sal.salary_date.date_naive().to_string());
|
||||||
});
|
});
|
||||||
row.col(|ui| {
|
row.col(|ui| {
|
||||||
ui.label(&sal.comment);
|
let text: String = sal.comment.chars().take(15).collect();
|
||||||
|
ui.label(text);
|
||||||
});
|
});
|
||||||
row.col(|ui| {
|
row.col(|ui| {
|
||||||
if ui.button("Удалить").clicked() {
|
if ui.button("Удалить").clicked() {
|
||||||
|
|
@ -553,9 +602,10 @@ impl MainTabViewer {
|
||||||
self.salary_modal_state
|
self.salary_modal_state
|
||||||
.data
|
.data
|
||||||
.insert("salary_size".to_owned(), sal.salary_size.to_string());
|
.insert("salary_size".to_owned(), sal.salary_size.to_string());
|
||||||
self.salary_modal_state
|
self.salary_modal_state.data.insert(
|
||||||
.data
|
"salary_date".to_owned(),
|
||||||
.insert("salary_date".to_owned(), sal.salary_date.to_string());
|
sal.salary_date.date_naive().to_string(),
|
||||||
|
);
|
||||||
self.salary_modal_state
|
self.salary_modal_state
|
||||||
.data
|
.data
|
||||||
.insert("comment".to_owned(), sal.comment.clone());
|
.insert("comment".to_owned(), sal.comment.clone());
|
||||||
|
|
@ -588,10 +638,16 @@ impl MainTabViewer {
|
||||||
});
|
});
|
||||||
if self.salary_modal_state.is_open {
|
if self.salary_modal_state.is_open {
|
||||||
egui::Modal::new(egui::Id::new("salary_modal")).show(ui.ctx(), |ui| {
|
egui::Modal::new(egui::Id::new("salary_modal")).show(ui.ctx(), |ui| {
|
||||||
if ui.button("Закрыть").clicked() || ui.input(|i| i.key_pressed(egui::Key::Escape))
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("Закрыть").clicked()
|
||||||
|
|| ui.input(|i| i.key_pressed(egui::Key::Escape))
|
||||||
{
|
{
|
||||||
self.salary_modal_state.is_open = false;
|
self.salary_modal_state.is_open = false;
|
||||||
}
|
}
|
||||||
|
if ui.button("Отчёт").clicked() {
|
||||||
|
self.reporter.payment_report(self.get_salary().clone());
|
||||||
|
}
|
||||||
|
});
|
||||||
if self.salary_modal_state.status != ModalStatus::Remove {
|
if self.salary_modal_state.status != ModalStatus::Remove {
|
||||||
egui::Grid::new("process_salary_grid").show(ui, |ui| {
|
egui::Grid::new("process_salary_grid").show(ui, |ui| {
|
||||||
let size = ui.available_size();
|
let size = ui.available_size();
|
||||||
|
|
@ -639,27 +695,146 @@ impl MainTabViewer {
|
||||||
size,
|
size,
|
||||||
egui::TextEdit::singleline(
|
egui::TextEdit::singleline(
|
||||||
self.salary_modal_state.data.get_mut("salary_date").unwrap(),
|
self.salary_modal_state.data.get_mut("salary_date").unwrap(),
|
||||||
),
|
)
|
||||||
|
.hint_text("1970-01-01"),
|
||||||
);
|
);
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
ui.label("Примечание:");
|
ui.label("Примечание:");
|
||||||
ui.add_sized(size,
|
ui.add_sized(
|
||||||
egui::TextEdit::singleline(self.salary_modal_state.data.get_mut("comment").unwrap()));
|
size,
|
||||||
|
egui::TextEdit::multiline(
|
||||||
|
self.salary_modal_state.data.get_mut("comment").unwrap(),
|
||||||
|
),
|
||||||
|
);
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
}else{
|
let wname = self
|
||||||
let wname = self.workers.read().clone().iter().find(|w| w.id.to_string() == self.salary_modal_state.data.get("worker_id").unwrap()).unwrap().full_name;
|
.workers
|
||||||
|
.read()
|
||||||
|
.clone()
|
||||||
|
.iter()
|
||||||
|
.find(|w| {
|
||||||
|
&w.id.to_string()
|
||||||
|
== self.salary_modal_state.data.get("worker_id").unwrap()
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.full_name
|
||||||
|
.clone();
|
||||||
ui.label("Вы уверены, что хотите удалить запись о выплате:");
|
ui.label("Вы уверены, что хотите удалить запись о выплате:");
|
||||||
ui.label(format!("{}: {} | ${}", self.salary_modal_state.data.get("salary_date").unwrap(), wname, self.salary_modal_state.data.get("salary_size").unwrap()));
|
ui.label(format!(
|
||||||
|
"{}: {} | ${}",
|
||||||
|
self.salary_modal_state.data.get("salary_date").unwrap(),
|
||||||
|
wname,
|
||||||
|
self.salary_modal_state.data.get("salary_size").unwrap()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let btext = match self.salary_modal_state.status{
|
let btext = match self.salary_modal_state.status {
|
||||||
ModalStatus::Add => "Добавить",
|
ModalStatus::Add => "Добавить",
|
||||||
ModalStatus::Edit => "Сохранить",
|
ModalStatus::Edit => "Сохранить",
|
||||||
ModalStatus::Remove => "Удалить"
|
ModalStatus::Remove => "Удалить",
|
||||||
};
|
};
|
||||||
if ui.button(btext).clicked(){
|
if ui.button(btext).clicked() {
|
||||||
|
match self.salary_modal_state.status {
|
||||||
|
ModalStatus::Add => {
|
||||||
|
self.rt.block_on(async {
|
||||||
|
for w in self.salary_modal_state.workers.iter() {
|
||||||
|
self.db_oper
|
||||||
|
.add_salary(
|
||||||
|
w.id,
|
||||||
|
chrono::NaiveDate::from_str(
|
||||||
|
self.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("salary_date")
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(0, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
.and_local_timezone(chrono::Local)
|
||||||
|
.unwrap(),
|
||||||
|
BigDecimal::from_str(
|
||||||
|
self.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("salary_size")
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
Some(
|
||||||
|
self.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("comment")
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ModalStatus::Edit => {
|
||||||
|
let sal = Salary {
|
||||||
|
id: self
|
||||||
|
.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("id")
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i32>()
|
||||||
|
.unwrap(),
|
||||||
|
worker: self
|
||||||
|
.workers
|
||||||
|
.read()
|
||||||
|
.iter()
|
||||||
|
.find(|w| {
|
||||||
|
&w.id.to_string()
|
||||||
|
== self
|
||||||
|
.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("worker_id")
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
salary_size: BigDecimal::from_str(
|
||||||
|
self.salary_modal_state.data.get("salary_size").unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
salary_date: chrono::NaiveDate::parse_from_str(
|
||||||
|
self.salary_modal_state.data.get("salary_date").unwrap(),
|
||||||
|
"%Y-%m-%d",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.and_hms_opt(0, 0, 0)
|
||||||
|
.unwrap()
|
||||||
|
.and_local_timezone(chrono::Local)
|
||||||
|
.unwrap(),
|
||||||
|
comment: self
|
||||||
|
.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("comment")
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
};
|
||||||
|
self.rt.block_on(async {
|
||||||
|
self.db_oper.update_salary(sal).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ModalStatus::Remove => self.rt.block_on(async {
|
||||||
|
self.db_oper
|
||||||
|
.remove_salary(
|
||||||
|
self.salary_modal_state
|
||||||
|
.data
|
||||||
|
.get("id")
|
||||||
|
.unwrap()
|
||||||
|
.parse::<i32>()
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
self.salary_modal_state.is_open = false;
|
||||||
|
self.update_salary();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -681,6 +856,10 @@ impl MainTabViewer {
|
||||||
self.interface_scale_ratio = 1.2;
|
self.interface_scale_ratio = 1.2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_recipe(&mut self, ui: &mut egui::Ui) {
|
||||||
|
self.recipe_tab.show_recipe_list(ui);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl egui_dock::TabViewer for MainTabViewer {
|
impl egui_dock::TabViewer for MainTabViewer {
|
||||||
|
|
@ -706,6 +885,9 @@ impl egui_dock::TabViewer for MainTabViewer {
|
||||||
TabTypes::Settings => {
|
TabTypes::Settings => {
|
||||||
&self.show_settings(ui);
|
&self.show_settings(ui);
|
||||||
}
|
}
|
||||||
|
TabTypes::Recipe => {
|
||||||
|
&self.show_recipe(ui);
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
ui.label("Welcome to Avalonia!");
|
ui.label("Welcome to Avalonia!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -365,14 +365,14 @@ impl DBOperator {
|
||||||
}
|
}
|
||||||
pub async fn add_salary(
|
pub async fn add_salary(
|
||||||
&self,
|
&self,
|
||||||
worker: Worker,
|
worker_id: i32,
|
||||||
salary_date: DateTime<chrono::Local>,
|
salary_date: DateTime<chrono::Local>,
|
||||||
salary_size: Option<BigDecimal>,
|
salary_size: BigDecimal,
|
||||||
comment: Option<String>,
|
comment: Option<String>,
|
||||||
) -> Result<bool, sqlx::Error> {
|
) -> Result<bool, sqlx::Error> {
|
||||||
match sqlx::query("INSERT INTO Brewery.salary (id, worker_id, salary_size, salary_date, comment) VALUES(0, ?, ?, ?, ?);")
|
match sqlx::query("INSERT INTO Brewery.salary (id, worker_id, salary_size, salary_date, comment) VALUES(0, ?, ?, ?, ?);")
|
||||||
.bind(worker.id)
|
.bind(worker_id)
|
||||||
.bind(salary_size.unwrap_or(worker.position.wage))
|
.bind(salary_size)
|
||||||
.bind(salary_date)
|
.bind(salary_date)
|
||||||
.bind(comment.unwrap_or(String::new()))
|
.bind(comment.unwrap_or(String::new()))
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
|
|
@ -381,6 +381,29 @@ impl DBOperator {
|
||||||
Err(_) => Ok(false)
|
Err(_) => Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub async fn update_salary(&self, salary: Salary) -> Result<bool, sqlx::Error> {
|
||||||
|
match sqlx::query("UPDATE Brewery.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 Brewery.salary WHERE id=?;")
|
||||||
|
.bind(id)
|
||||||
|
.execute(&self.pool)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(_) => Ok(true),
|
||||||
|
Err(_) => Ok(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn estabilish_connection() -> Result<(), sqlx::Error> {
|
pub async fn estabilish_connection() -> Result<(), sqlx::Error> {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,13 @@
|
||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
|
use crate::reports::Reporter;
|
||||||
mod app;
|
mod app;
|
||||||
mod database;
|
mod database;
|
||||||
mod material_tab;
|
mod material_tab;
|
||||||
mod models;
|
mod models;
|
||||||
mod payment_tab;
|
mod payment_tab;
|
||||||
mod recipe_tab;
|
mod recipe_tab;
|
||||||
|
mod reports;
|
||||||
mod tab;
|
mod tab;
|
||||||
mod worker_database;
|
mod worker_database;
|
||||||
mod worker_tab;
|
mod worker_tab;
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,15 @@ impl MaterialTabViewer {
|
||||||
}
|
}
|
||||||
fn show_material(&mut self, ui: &mut egui::Ui) {
|
fn show_material(&mut self, ui: &mut egui::Ui) {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
if self.is_admin {
|
||||||
if ui.button("Добавить").clicked() {
|
if ui.button("Добавить").clicked() {
|
||||||
self.process_material_state.is_open = true;
|
self.process_material_state.is_open = true;
|
||||||
self.process_material_state.status = ModalStatus::Add;
|
self.process_material_state.status = ModalStatus::Add;
|
||||||
}
|
}
|
||||||
if ui.button("Удалить").clicked() {
|
// if ui.button("Удалить").clicked() {
|
||||||
self.process_material_state.is_open = true;
|
// self.process_material_state.is_open = true;
|
||||||
self.process_material_state.status = ModalStatus::Remove;
|
// self.process_material_state.status = ModalStatus::Remove;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
if ui.button("Обновить").clicked() {
|
if ui.button("Обновить").clicked() {
|
||||||
self.update_materials();
|
self.update_materials();
|
||||||
|
|
@ -352,15 +354,13 @@ impl MaterialTabViewer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_material_type(&mut self, ui: &mut egui::Ui) {
|
fn show_material_category(&mut self, ui: &mut egui::Ui) {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
|
if self.is_admin {
|
||||||
if ui.button("Добавить").clicked() {
|
if ui.button("Добавить").clicked() {
|
||||||
self.process_mcat_state.is_open = true;
|
self.process_mcat_state.is_open = true;
|
||||||
self.process_mcat_state.status = ModalStatus::Add;
|
self.process_mcat_state.status = ModalStatus::Add;
|
||||||
}
|
}
|
||||||
if ui.button("Удалить").clicked() {
|
|
||||||
self.process_mcat_state.is_open = true;
|
|
||||||
self.process_mcat_state.status = ModalStatus::Remove;
|
|
||||||
}
|
}
|
||||||
if ui.button("Обновить").clicked() {
|
if ui.button("Обновить").clicked() {
|
||||||
self.update_material_category();
|
self.update_material_category();
|
||||||
|
|
@ -526,7 +526,7 @@ impl egui_dock::TabViewer for MaterialTabViewer {
|
||||||
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
|
fn ui(&mut self, ui: &mut egui::Ui, tab: &mut Self::Tab) {
|
||||||
match &tab.tab_type {
|
match &tab.tab_type {
|
||||||
TabTypes::MaterialList => self.show_material(ui),
|
TabTypes::MaterialList => self.show_material(ui),
|
||||||
TabTypes::MaterialTypeList => self.show_material_type(ui),
|
TabTypes::MaterialTypeList => self.show_material_category(ui),
|
||||||
_ => {
|
_ => {
|
||||||
ui.label("Каким образом?");
|
ui.label("Каким образом?");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ pub struct SalaryRow {
|
||||||
pub salary_date: chrono::DateTime<chrono::Local>,
|
pub salary_date: chrono::DateTime<chrono::Local>,
|
||||||
pub comment: String,
|
pub comment: String,
|
||||||
}
|
}
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Salary {
|
pub struct Salary {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub worker: Worker,
|
pub worker: Worker,
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,33 @@
|
||||||
use crate::tab::{Tab, TabTypes};
|
use tokio::sync::RwLock;
|
||||||
use std::default::Default;
|
|
||||||
|
|
||||||
struct RecipeTabViewer {
|
use crate::{
|
||||||
|
database::DBOperator,
|
||||||
|
models::{Equipment, Material, Recipe, RecipeElement},
|
||||||
|
tab::{Tab, TabTypes},
|
||||||
|
};
|
||||||
|
use std::{default::Default, sync::Arc};
|
||||||
|
|
||||||
|
pub struct RecipeTabViewer {
|
||||||
is_admin: bool,
|
is_admin: bool,
|
||||||
|
rt: tokio::runtime::Runtime,
|
||||||
|
db_oper: DBOperator,
|
||||||
|
|
||||||
|
recipes: Arc<RwLock<Vec<Recipe>>>,
|
||||||
|
recipe_elements: Arc<RwLock<Vec<RecipeElement>>>,
|
||||||
|
materials: Arc<RwLock<Vec<Material>>>,
|
||||||
|
equipment: Arc<RwLock<Vec<Equipment>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecipeTabViewer {
|
impl RecipeTabViewer {
|
||||||
fn new(is_admin: bool) -> Self {
|
pub fn new(is_admin: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
is_admin,
|
is_admin,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn show_recipe_list(&mut self, ui: &mut egui::Ui) {}
|
pub fn show_recipe_list(&mut self, ui: &mut egui::Ui) {
|
||||||
fn show_recipe_detail(&mut self, ui: &mut egui::Ui) {}
|
ui.label("Goida");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl egui_dock::TabViewer for RecipeTabViewer {
|
impl egui_dock::TabViewer for RecipeTabViewer {
|
||||||
type Tab = Tab;
|
type Tab = Tab;
|
||||||
|
|
@ -27,9 +41,6 @@ impl egui_dock::TabViewer for RecipeTabViewer {
|
||||||
TabTypes::RecipeList => {
|
TabTypes::RecipeList => {
|
||||||
self.show_recipe_list(ui);
|
self.show_recipe_list(ui);
|
||||||
}
|
}
|
||||||
TabTypes::RecipeDetail => {
|
|
||||||
self.show_recipe_detail(ui);
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
ui.label("Помогите!!");
|
ui.label("Помогите!!");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
use bigdecimal::ToPrimitive;
|
||||||
|
use rust_xlsxwriter::{Format, Workbook, XlsxError};
|
||||||
|
|
||||||
|
use crate::models::Salary;
|
||||||
|
|
||||||
|
pub struct Reporter {}
|
||||||
|
impl Reporter {
|
||||||
|
pub fn test_report(&self) -> Result<(), XlsxError> {
|
||||||
|
let mut workbook = Workbook::new();
|
||||||
|
|
||||||
|
let mut worksheet = workbook.add_worksheet();
|
||||||
|
|
||||||
|
worksheet.write_string(0, 0, "ZOV");
|
||||||
|
worksheet.write_formula(0, 1, "=RAND()");
|
||||||
|
|
||||||
|
workbook.save("test.xlsx");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub fn payment_report(&self, sal: Salary) -> Result<(), XlsxError> {
|
||||||
|
let mut wb = Workbook::new();
|
||||||
|
let mut ws = wb.add_worksheet();
|
||||||
|
let money_format = Format::new().set_num_format("#,##0.00 ₽");
|
||||||
|
ws.write_string(0, 0, "ФИО");
|
||||||
|
ws.write_string(0, 1, "Размер оплаты");
|
||||||
|
ws.write_string(0, 2, "Дата оплаты");
|
||||||
|
ws.write_string(0, 3, "Комментарий");
|
||||||
|
|
||||||
|
ws.write_string(1, 0, &sal.worker.full_name);
|
||||||
|
ws.write_with_format(1, 1, sal.salary_size.to_f64().unwrap(), &money_format);
|
||||||
|
ws.write_datetime(1, 2, sal.salary_date.date_naive());
|
||||||
|
ws.write_string(1, 3, sal.comment);
|
||||||
|
ws.autofit();
|
||||||
|
|
||||||
|
wb.save(format!(
|
||||||
|
"report-worker-{}.xlsx",
|
||||||
|
chrono::Local::now().to_string()
|
||||||
|
));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue