Я устал и башка не варит
parent
f2c6de7137
commit
09ed906aa7
|
|
@ -777,6 +777,7 @@ dependencies = [
|
||||||
"egui_extras",
|
"egui_extras",
|
||||||
"hex",
|
"hex",
|
||||||
"jiff",
|
"jiff",
|
||||||
|
"ordered-float",
|
||||||
"rust_decimal",
|
"rust_decimal",
|
||||||
"rust_xlsxwriter",
|
"rust_xlsxwriter",
|
||||||
"sha2 0.11.0",
|
"sha2 0.11.0",
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ egui_dock = "0.19.1"
|
||||||
egui_extras = {version = "0.34.2", features = ["datepicker"]}
|
egui_extras = {version = "0.34.2", features = ["datepicker"]}
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
jiff = "0.2.29"
|
jiff = "0.2.29"
|
||||||
|
ordered-float = "5.3.0"
|
||||||
rust_decimal = {version = "1.42.0", features = ["macros"]}
|
rust_decimal = {version = "1.42.0", features = ["macros"]}
|
||||||
rust_xlsxwriter = {version="0.95.0",features=["chrono"]}
|
rust_xlsxwriter = {version="0.95.0",features=["chrono"]}
|
||||||
sha2 = "0.11.0"
|
sha2 = "0.11.0"
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,7 @@ impl MainTabViewer {
|
||||||
worker_tabs: WorkerTabViewer::new(is_admin),
|
worker_tabs: WorkerTabViewer::new(is_admin),
|
||||||
material_tabs: MaterialTabViewer::new(is_admin),
|
material_tabs: MaterialTabViewer::new(is_admin),
|
||||||
recipe_tab: RecipeTabViewer::new(is_admin),
|
recipe_tab: RecipeTabViewer::new(is_admin),
|
||||||
|
order_tabs: OrderTabViewer::new(is_admin),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use sqlx::mysql::MySqlPool;
|
||||||
use sqlx::mysql::MySqlPoolOptions;
|
use sqlx::mysql::MySqlPoolOptions;
|
||||||
|
|
||||||
use dotenvy::dotenv_override;
|
use dotenvy::dotenv_override;
|
||||||
|
use std::collections::BTreeSet;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
@ -524,7 +525,7 @@ impl DBOperator {
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let pelems = self.get_recipe_elements().await.unwrap_or(Vec::new());
|
let pelems = self.get_recipe_elements().await.unwrap_or(Vec::new());
|
||||||
let mut elems: HashSet<RecipeElement> = HashSet::new();
|
let mut elems: BTreeSet<RecipeElement> = BTreeSet::new();
|
||||||
for pr in pelems {
|
for pr in pelems {
|
||||||
if pr.recipe_id == pret.id {
|
if pr.recipe_id == pret.id {
|
||||||
elems.insert(pr.clone());
|
elems.insert(pr.clone());
|
||||||
|
|
@ -536,8 +537,10 @@ impl DBOperator {
|
||||||
elements: elems,
|
elements: elems,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn get_recipes(&self) -> Result<Vec<Recipe>, sqlx::Error> {
|
pub async fn get_recipes(&self, start: i32, length: i32) -> Result<Vec<Recipe>, sqlx::Error> {
|
||||||
let pre_ret = sqlx::query_as::<_, RecipeRow>("SELECT * FROM `recipe`")
|
let pre_ret = sqlx::query_as::<_, RecipeRow>("SELECT * FROM `recipe` LIMIT ? OFFSET ?")
|
||||||
|
.bind(length)
|
||||||
|
.bind(start)
|
||||||
.fetch_all(&self.pool)
|
.fetch_all(&self.pool)
|
||||||
.await
|
.await
|
||||||
.unwrap_or(Vec::new());
|
.unwrap_or(Vec::new());
|
||||||
|
|
@ -624,7 +627,7 @@ impl DBOperator {
|
||||||
}
|
}
|
||||||
pub async fn add_recipe_elems(
|
pub async fn add_recipe_elems(
|
||||||
&self,
|
&self,
|
||||||
elems: HashSet<RecipeElement>,
|
elems: BTreeSet<RecipeElement>,
|
||||||
rec_id: i32,
|
rec_id: i32,
|
||||||
) -> Result<bool, sqlx::Error> {
|
) -> Result<bool, sqlx::Error> {
|
||||||
let mut tx = self.pool.begin().await?;
|
let mut tx = self.pool.begin().await?;
|
||||||
|
|
@ -665,11 +668,17 @@ impl DBOperator {
|
||||||
|
|
||||||
let mut ret: Vec<Order> = Vec::new();
|
let mut ret: Vec<Order> = Vec::new();
|
||||||
for or in pret {
|
for or in pret {
|
||||||
|
let hs: BTreeSet<OrderElement> = self
|
||||||
|
.get_order_elements_by_order_id(or.id)
|
||||||
|
.await
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.collect();
|
||||||
ret.push(Order {
|
ret.push(Order {
|
||||||
id: or.id,
|
id: or.id,
|
||||||
order_date: or.order_date,
|
order_date: or.order_date,
|
||||||
client: self.get_client_by_id(or.client_id).await.unwrap(),
|
client: self.get_client_by_id(or.client_id).await.unwrap(),
|
||||||
elements: self.get_order_elements_by_order_id(or.id).await,
|
elements: hs,
|
||||||
total_price: or.total_price,
|
total_price: or.total_price,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -706,17 +715,11 @@ impl DBOperator {
|
||||||
.fetch_one(&self.pool)
|
.fetch_one(&self.pool)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut recipe: Recipe = Recipe::default();
|
|
||||||
for rec in self.get_recipes().await.unwrap() {
|
|
||||||
if rec.id == pret.recipe_id {
|
|
||||||
recipe = rec.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Product {
|
Product {
|
||||||
id: pret.id,
|
id: pret.id,
|
||||||
recipe,
|
recipe: self.get_recipe_by_id(pret.recipe_id).await,
|
||||||
price_per_unit: pret.price_per_unit,
|
price_per_unit: pret.price_per_unit,
|
||||||
volume: pret.volume,
|
volume: ordered_float::OrderedFloat(pret.volume),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub async fn get_products(&self, start: i32, length: i32) -> Vec<Product> {
|
pub async fn get_products(&self, start: i32, length: i32) -> Vec<Product> {
|
||||||
|
|
@ -732,7 +735,7 @@ impl DBOperator {
|
||||||
ret.push(Product {
|
ret.push(Product {
|
||||||
id: pr.id,
|
id: pr.id,
|
||||||
recipe: self.get_recipe_by_id(pr.recipe_id).await,
|
recipe: self.get_recipe_by_id(pr.recipe_id).await,
|
||||||
volume: pr.volume,
|
volume: ordered_float::OrderedFloat(pr.volume),
|
||||||
price_per_unit: pr.price_per_unit,
|
price_per_unit: pr.price_per_unit,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -744,7 +747,7 @@ impl DBOperator {
|
||||||
"INSERT INTO `product` (recipe_id, volume, price_per_unit) VALUES(?, ?, ?);",
|
"INSERT INTO `product` (recipe_id, volume, price_per_unit) VALUES(?, ?, ?);",
|
||||||
)
|
)
|
||||||
.bind(prod.recipe.id)
|
.bind(prod.recipe.id)
|
||||||
.bind(prod.volume)
|
.bind(prod.volume.into_inner())
|
||||||
.bind(prod.price_per_unit)
|
.bind(prod.price_per_unit)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
.await
|
.await
|
||||||
|
|
@ -756,7 +759,7 @@ impl DBOperator {
|
||||||
pub async fn update_product(&self, prod: Product) -> Result<(), sqlx::Error> {
|
pub async fn update_product(&self, prod: Product) -> Result<(), sqlx::Error> {
|
||||||
match sqlx::query("UPDATE product SET recipe_id=?, volume=?, price_per_unit=? WHERE id=?;")
|
match sqlx::query("UPDATE product SET recipe_id=?, volume=?, price_per_unit=? WHERE id=?;")
|
||||||
.bind(prod.recipe.id)
|
.bind(prod.recipe.id)
|
||||||
.bind(prod.volume)
|
.bind(prod.volume.into_inner())
|
||||||
.bind(prod.price_per_unit)
|
.bind(prod.price_per_unit)
|
||||||
.bind(prod.id)
|
.bind(prod.id)
|
||||||
.execute(&self.pool)
|
.execute(&self.pool)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
use std::{any::TypeId, collections::HashSet, ops::Deref};
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
collections::{BTreeSet, HashSet},
|
||||||
|
ops::Deref,
|
||||||
|
};
|
||||||
|
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use egui::TextBuffer;
|
use egui::TextBuffer;
|
||||||
|
|
@ -7,7 +11,7 @@ use sqlx::{
|
||||||
types::{BigDecimal, chrono::DateTime},
|
types::{BigDecimal, chrono::DateTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Hash, sqlx::FromRow, PartialEq, std::cmp::Eq)]
|
#[derive(Clone, Hash, sqlx::FromRow, PartialEq, std::cmp::Eq, PartialOrd, Ord)]
|
||||||
pub struct Position {
|
pub struct Position {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -22,7 +26,7 @@ impl Default for Position {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Default, Clone, Hash, std::cmp::Eq, PartialEq)]
|
#[derive(Default, Clone, Hash, std::cmp::Eq, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct Worker {
|
pub struct Worker {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub full_name: String,
|
pub full_name: String,
|
||||||
|
|
@ -57,7 +61,7 @@ pub struct Salary {
|
||||||
pub comment: String,
|
pub comment: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Hash, PartialEq, Eq)]
|
#[derive(Default, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Equipment {
|
pub struct Equipment {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -75,7 +79,7 @@ pub struct EquipmentRow {
|
||||||
pub worker_id: i32,
|
pub worker_id: i32,
|
||||||
pub is_written_off: bool,
|
pub is_written_off: bool,
|
||||||
}
|
}
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Default)]
|
#[derive(Clone, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
|
||||||
pub struct Material {
|
pub struct Material {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
@ -89,12 +93,12 @@ pub struct MaterialRow {
|
||||||
pub quantity: i32,
|
pub quantity: i32,
|
||||||
pub category_id: i32,
|
pub category_id: i32,
|
||||||
}
|
}
|
||||||
#[derive(sqlx::FromRow, Default, Clone, PartialEq, Eq, Hash)]
|
#[derive(sqlx::FromRow, Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct MaterialCategory {
|
pub struct MaterialCategory {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Default)]
|
#[derive(Clone, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
|
||||||
pub struct RecipeElement {
|
pub struct RecipeElement {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub material: Material,
|
pub material: Material,
|
||||||
|
|
@ -110,29 +114,30 @@ pub struct RecipeElementRow {
|
||||||
pub quantity: i32,
|
pub quantity: i32,
|
||||||
pub recipe_id: i32,
|
pub recipe_id: i32,
|
||||||
}
|
}
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct Recipe {
|
pub struct Recipe {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub elements: HashSet<RecipeElement>,
|
pub elements: BTreeSet<RecipeElement>,
|
||||||
}
|
}
|
||||||
#[derive(FromRow)]
|
#[derive(FromRow)]
|
||||||
pub struct RecipeRow {
|
pub struct RecipeRow {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
}
|
}
|
||||||
#[derive(FromRow)]
|
#[derive(FromRow, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub address: String,
|
pub address: String,
|
||||||
}
|
}
|
||||||
|
#[derive(Default, PartialEq, PartialOrd, Eq, Ord)]
|
||||||
pub struct Order {
|
pub struct Order {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub client: Client,
|
pub client: Client,
|
||||||
pub order_date: chrono::DateTime<chrono::Local>,
|
pub order_date: chrono::DateTime<chrono::Local>,
|
||||||
pub total_price: BigDecimal,
|
pub total_price: BigDecimal,
|
||||||
pub elements: std::vec::Vec<OrderElement>,
|
pub elements: BTreeSet<OrderElement>,
|
||||||
}
|
}
|
||||||
#[derive(FromRow)]
|
#[derive(FromRow)]
|
||||||
pub struct OrderRow {
|
pub struct OrderRow {
|
||||||
|
|
@ -141,6 +146,7 @@ pub struct OrderRow {
|
||||||
pub order_date: chrono::DateTime<chrono::Local>,
|
pub order_date: chrono::DateTime<chrono::Local>,
|
||||||
pub total_price: BigDecimal,
|
pub total_price: BigDecimal,
|
||||||
}
|
}
|
||||||
|
#[derive(PartialEq, PartialOrd, Ord, Eq, Clone, Default)]
|
||||||
pub struct OrderElement {
|
pub struct OrderElement {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub product: Product,
|
pub product: Product,
|
||||||
|
|
@ -155,11 +161,11 @@ pub struct OrderElementRow {
|
||||||
pub total_price: BigDecimal,
|
pub total_price: BigDecimal,
|
||||||
pub is_incoming: bool,
|
pub is_incoming: bool,
|
||||||
}
|
}
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
||||||
pub struct Product {
|
pub struct Product {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub recipe: Recipe,
|
pub recipe: Recipe,
|
||||||
pub volume: f64,
|
pub volume: ordered_float::OrderedFloat<f64>,
|
||||||
pub price_per_unit: BigDecimal,
|
pub price_per_unit: BigDecimal,
|
||||||
}
|
}
|
||||||
#[derive(FromRow)]
|
#[derive(FromRow)]
|
||||||
|
|
@ -236,13 +242,20 @@ pub struct RecipeModalState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ElementModalState {
|
pub struct RecipeElementModalState {
|
||||||
pub is_open: bool,
|
pub is_open: bool,
|
||||||
pub can_finish: bool,
|
pub can_finish: bool,
|
||||||
pub element: RecipeElement,
|
pub element: RecipeElement,
|
||||||
pub status: ModalStatus,
|
pub status: ModalStatus,
|
||||||
}
|
}
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
pub struct OrderElementModalState {
|
||||||
|
pub is_open: bool,
|
||||||
|
pub can_finish: bool,
|
||||||
|
pub element: OrderElement,
|
||||||
|
pub status: ModalStatus,
|
||||||
|
}
|
||||||
|
#[derive(Default)]
|
||||||
pub struct ProductModalState {
|
pub struct ProductModalState {
|
||||||
pub is_open: bool,
|
pub is_open: bool,
|
||||||
pub can_finish: bool,
|
pub can_finish: bool,
|
||||||
|
|
@ -250,6 +263,13 @@ pub struct ProductModalState {
|
||||||
pub recipe: Recipe,
|
pub recipe: Recipe,
|
||||||
pub status: ModalStatus,
|
pub status: ModalStatus,
|
||||||
}
|
}
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OrderModalState {
|
||||||
|
pub is_open: bool,
|
||||||
|
pub can_finish: bool,
|
||||||
|
pub order: Order,
|
||||||
|
pub status: ModalStatus,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq)]
|
#[derive(Default, PartialEq)]
|
||||||
pub enum ModalStatus {
|
pub enum ModalStatus {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use bigdecimal::ToPrimitive;
|
||||||
use egui::{Sense, mutex::RwLock};
|
use egui::{Sense, mutex::RwLock};
|
||||||
use egui_extras::Column;
|
use egui_extras::Column;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::DBOperator,
|
database::DBOperator,
|
||||||
misc,
|
misc,
|
||||||
models::Order,
|
models::{ModalStatus, Order, OrderElement, OrderElementModalState, OrderModalState},
|
||||||
tab::{TABS_CAN_BE_WINDOWS, Tab, TabTypes},
|
tab::{TABS_CAN_BE_WINDOWS, Tab, TabTypes},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -20,6 +21,8 @@ pub struct OrderTabViewer {
|
||||||
outcoming_order_page: i32,
|
outcoming_order_page: i32,
|
||||||
|
|
||||||
is_admin: bool,
|
is_admin: bool,
|
||||||
|
process_order_state: OrderModalState,
|
||||||
|
process_element_state: OrderElementModalState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OrderTabViewer {
|
impl OrderTabViewer {
|
||||||
|
|
@ -29,21 +32,105 @@ impl OrderTabViewer {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn update_orders(&mut self) {
|
||||||
|
self.rt.block_on(async {
|
||||||
|
self.incoming_orders = Arc::new(RwLock::new(
|
||||||
|
self.db_oper
|
||||||
|
.get_orders(
|
||||||
|
self.incoming_order_page * misc::ELEMENTS_PER_PAGE,
|
||||||
|
misc::ELEMENTS_PER_PAGE,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
));
|
||||||
|
self.outcoming_orders = Arc::new(RwLock::new(
|
||||||
|
self.db_oper
|
||||||
|
.get_orders(
|
||||||
|
self.outcoming_order_page * misc::ELEMENTS_PER_PAGE,
|
||||||
|
misc::ELEMENTS_PER_PAGE,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await,
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
fn show_order_element_modal(&mut self, ui: &mut egui::Ui) {
|
||||||
|
egui::Modal::new(egui::Id::new("order_element_modal")).show(ui.ctx(), |ui| {
|
||||||
|
if ui.button("Закрыть").clicked() {
|
||||||
|
self.process_element_state.is_open = false;
|
||||||
|
}
|
||||||
|
egui::Grid::new("order_element_grid").show(ui, |ui| {
|
||||||
|
ui.label("Продукт:");
|
||||||
|
///
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("Количество:");
|
||||||
|
ui.add(
|
||||||
|
egui::Slider::new(&mut self.process_element_state.element.quantity, 0..=100)
|
||||||
|
.clamping(egui::SliderClamping::Never),
|
||||||
|
);
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("Итоговая цена:");
|
||||||
|
ui.label(format!(
|
||||||
|
"{}",
|
||||||
|
self.process_element_state
|
||||||
|
.element
|
||||||
|
.product
|
||||||
|
.price_per_unit
|
||||||
|
.clone()
|
||||||
|
* self.process_element_state.element.quantity
|
||||||
|
))
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
pub fn show_orders(&mut self, ui: &mut egui::Ui, incoming_orders: bool) {
|
pub fn show_orders(&mut self, ui: &mut egui::Ui, incoming_orders: bool) {
|
||||||
let orders = if incoming_orders {
|
let orders = if incoming_orders {
|
||||||
&self.incoming_orders
|
self.incoming_orders.clone()
|
||||||
} else {
|
} else {
|
||||||
&self.outcoming_orders
|
self.outcoming_orders.clone()
|
||||||
};
|
};
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if ui.button("Добавить").clicked() {}
|
if self.is_admin {
|
||||||
if ui.button("<-").clicked() {}
|
if ui.button("Добавить").clicked() {
|
||||||
|
self.process_order_state.is_open = true;
|
||||||
|
self.process_order_state.order = Order::default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.button("<-").clicked() {
|
||||||
|
if incoming_orders {
|
||||||
|
if self.incoming_orders.read().len() > 0 {
|
||||||
|
self.incoming_order_page -= 1;
|
||||||
|
self.update_orders();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.outcoming_orders.read().len() > 0 {
|
||||||
|
self.outcoming_order_page -= 1;
|
||||||
|
self.update_orders();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
ui.monospace(if incoming_orders {
|
ui.monospace(if incoming_orders {
|
||||||
self.incoming_order_page.to_string()
|
self.incoming_order_page.to_string()
|
||||||
} else {
|
} else {
|
||||||
self.outcoming_order_page.to_string()
|
self.outcoming_order_page.to_string()
|
||||||
});
|
});
|
||||||
if ui.button("->").clicked() {}
|
if ui.button("->").clicked() {
|
||||||
|
if incoming_orders {
|
||||||
|
if self.incoming_orders.read().len().to_i32().unwrap()
|
||||||
|
== misc::ELEMENTS_PER_PAGE
|
||||||
|
{
|
||||||
|
self.incoming_order_page += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if self.outcoming_orders.read().len().to_i32().unwrap()
|
||||||
|
== misc::ELEMENTS_PER_PAGE
|
||||||
|
{
|
||||||
|
self.outcoming_order_page += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
egui_extras::TableBuilder::new(ui)
|
egui_extras::TableBuilder::new(ui)
|
||||||
|
|
@ -92,6 +179,58 @@ impl OrderTabViewer {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if self.process_order_state.is_open {
|
||||||
|
egui::Modal::new(egui::Id::new("order_process_modal")).show(ui.ctx(), |ui| {
|
||||||
|
if ui.button("Закрыть").clicked() {
|
||||||
|
self.process_order_state.is_open = false
|
||||||
|
}
|
||||||
|
egui::Grid::new("order_process_grid").show(ui, |ui| {
|
||||||
|
ui.label("ID заказа:");
|
||||||
|
ui.label(self.process_order_state.order.id.to_string());
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label(if incoming_orders {
|
||||||
|
"Заказчик"
|
||||||
|
} else {
|
||||||
|
"Клиент"
|
||||||
|
});
|
||||||
|
//ВЫБОР КЛИЕНТА
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("Элементы");
|
||||||
|
egui::ComboBox::new("order_process_combobox", "")
|
||||||
|
.close_behavior(egui::PopupCloseBehavior::CloseOnClickOutside)
|
||||||
|
.selected_text(match self.process_order_state.order.elements.len() {
|
||||||
|
0 => "Пусто".to_owned(),
|
||||||
|
_ => format!("{} элем.", self.process_order_state.order.elements.len()),
|
||||||
|
})
|
||||||
|
.show_ui(ui, |ui| {
|
||||||
|
if ui.button("Новый элемент").clicked() {
|
||||||
|
self.process_element_state.is_open = true;
|
||||||
|
self.process_element_state.status = ModalStatus::Add;
|
||||||
|
self.process_element_state.element = OrderElement::default();
|
||||||
|
}
|
||||||
|
|
||||||
|
for el in self.process_order_state.order.elements.clone().iter() {
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
if ui.button("x").clicked() {
|
||||||
|
self.process_order_state.order.elements.remove(el);
|
||||||
|
}
|
||||||
|
ui.label(format!(
|
||||||
|
"{} ({})\n{}/шт.",
|
||||||
|
el.product.recipe.name,
|
||||||
|
el.quantity,
|
||||||
|
el.product.price_per_unit
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if self.process_element_state.is_open {
|
||||||
|
self.show_order_element_modal(ui);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,6 +279,8 @@ impl Default for OrderTabViewer {
|
||||||
db_oper,
|
db_oper,
|
||||||
rt,
|
rt,
|
||||||
is_admin: false,
|
is_admin: false,
|
||||||
|
process_order_state: OrderModalState::default(),
|
||||||
|
process_element_state: OrderElementModalState::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
database::DBOperator,
|
database::DBOperator,
|
||||||
misc,
|
misc,
|
||||||
models::{
|
models::{
|
||||||
ElementModalState, Equipment, Material, ModalStatus, Product, ProductModalState, Recipe,
|
RecipeElementModalState, Equipment, Material, ModalStatus, Product, ProductModalState, Recipe,
|
||||||
RecipeElement, RecipeModalState,
|
RecipeElement, RecipeModalState,
|
||||||
},
|
},
|
||||||
tab::{self, Tab, TabTypes},
|
tab::{self, Tab, TabTypes},
|
||||||
|
|
@ -29,10 +29,11 @@ pub struct RecipeTabViewer {
|
||||||
products: Arc<RwLock<Vec<Product>>>,
|
products: Arc<RwLock<Vec<Product>>>,
|
||||||
|
|
||||||
process_recipe_status: RecipeModalState,
|
process_recipe_status: RecipeModalState,
|
||||||
process_element_status: ElementModalState,
|
process_element_status: RecipeElementModalState,
|
||||||
process_product_status: ProductModalState,
|
process_product_status: ProductModalState,
|
||||||
old_price: BigDecimal,
|
old_price: BigDecimal,
|
||||||
product_page: i32,
|
product_page: i32,
|
||||||
|
recipe_page: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RecipeTabViewer {
|
impl RecipeTabViewer {
|
||||||
|
|
@ -43,10 +44,12 @@ impl RecipeTabViewer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn update_recipes(&mut self) {
|
fn update_recipes(&mut self) {
|
||||||
self.recipes =
|
self.recipes = Arc::new(RwLock::new(self.rt.block_on(async {
|
||||||
Arc::new(RwLock::new(self.rt.block_on(async {
|
self.db_oper
|
||||||
self.db_oper.get_recipes().await.unwrap_or(Vec::new())
|
.get_recipes(self.recipe_page, misc::ELEMENTS_PER_PAGE)
|
||||||
})));
|
.await
|
||||||
|
.unwrap_or(Vec::new())
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
pub fn update_products(&mut self) {
|
pub fn update_products(&mut self) {
|
||||||
self.products = Arc::new(RwLock::new(self.rt.block_on(async {
|
self.products = Arc::new(RwLock::new(self.rt.block_on(async {
|
||||||
|
|
@ -229,6 +232,19 @@ impl RecipeTabViewer {
|
||||||
self.process_recipe_status.status = ModalStatus::Add;
|
self.process_recipe_status.status = ModalStatus::Add;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ui.button("<-").clicked() {
|
||||||
|
if self.recipe_page > 0 {
|
||||||
|
self.recipe_page -= 1;
|
||||||
|
self.update_recipes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ui.monospace(self.recipe_page.to_string());
|
||||||
|
if ui.button("->").clicked() {
|
||||||
|
if self.recipes.read().len().to_i32().unwrap() > misc::ELEMENTS_PER_PAGE {
|
||||||
|
self.recipe_page += 1;
|
||||||
|
self.update_recipes();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
TableBuilder::new(ui)
|
TableBuilder::new(ui)
|
||||||
.striped(true)
|
.striped(true)
|
||||||
|
|
@ -293,12 +309,14 @@ impl RecipeTabViewer {
|
||||||
if ui.button("<-").clicked() {
|
if ui.button("<-").clicked() {
|
||||||
if self.product_page > 0 {
|
if self.product_page > 0 {
|
||||||
self.product_page -= 1;
|
self.product_page -= 1;
|
||||||
|
self.update_products();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.monospace(self.product_page.to_string());
|
ui.monospace(self.product_page.to_string());
|
||||||
if ui.button("->").clicked() {
|
if ui.button("->").clicked() {
|
||||||
if self.products.read().len() == 5 {
|
if self.products.read().len() == 5 {
|
||||||
self.product_page += 1;
|
self.product_page += 1;
|
||||||
|
self.update_products();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -319,7 +337,7 @@ impl RecipeTabViewer {
|
||||||
ui.heading("Цена за ед.");
|
ui.heading("Цена за ед.");
|
||||||
});
|
});
|
||||||
head.col(|ui| {
|
head.col(|ui| {
|
||||||
ui.heading(" ");
|
ui.heading(" ");
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.body(|mut body| {
|
.body(|mut body| {
|
||||||
|
|
@ -386,7 +404,7 @@ impl egui_dock::TabViewer for RecipeTabViewer {
|
||||||
ui.add_sized(
|
ui.add_sized(
|
||||||
size,
|
size,
|
||||||
egui::Slider::new(
|
egui::Slider::new(
|
||||||
&mut self.process_product_status.product.volume,
|
&mut self.process_product_status.product.volume.into_inner(),
|
||||||
0.0..=100.0,
|
0.0..=100.0,
|
||||||
)
|
)
|
||||||
.clamping(egui::SliderClamping::Never),
|
.clamping(egui::SliderClamping::Never),
|
||||||
|
|
@ -414,7 +432,7 @@ impl egui_dock::TabViewer for RecipeTabViewer {
|
||||||
ModalStatus::Remove => true,
|
ModalStatus::Remove => true,
|
||||||
_ => {
|
_ => {
|
||||||
self.process_product_status.product.price_per_unit > 0
|
self.process_product_status.product.price_per_unit > 0
|
||||||
&& self.process_product_status.product.volume > 0.0
|
&& self.process_product_status.product.volume.into_inner() > 0.0
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let btext = match self.process_product_status.status {
|
let btext = match self.process_product_status.status {
|
||||||
|
|
@ -475,9 +493,12 @@ impl Default for RecipeTabViewer {
|
||||||
Self {
|
Self {
|
||||||
is_admin: false,
|
is_admin: false,
|
||||||
|
|
||||||
recipes: Arc::new(RwLock::new(
|
recipes: Arc::new(RwLock::new(rt.block_on(async {
|
||||||
rt.block_on(async { db_oper.get_recipes().await.unwrap_or(Vec::new()) }),
|
db_oper
|
||||||
)),
|
.get_recipes(0, misc::ELEMENTS_PER_PAGE)
|
||||||
|
.await
|
||||||
|
.unwrap_or(Vec::new())
|
||||||
|
}))),
|
||||||
materials: Arc::new(RwLock::new(
|
materials: Arc::new(RwLock::new(
|
||||||
rt.block_on(async { db_oper.get_materials().await.unwrap_or(Vec::new()) }),
|
rt.block_on(async { db_oper.get_materials().await.unwrap_or(Vec::new()) }),
|
||||||
)),
|
)),
|
||||||
|
|
@ -498,7 +519,7 @@ impl Default for RecipeTabViewer {
|
||||||
status: crate::models::ModalStatus::Add,
|
status: crate::models::ModalStatus::Add,
|
||||||
elements: HashSet::new(),
|
elements: HashSet::new(),
|
||||||
},
|
},
|
||||||
process_element_status: ElementModalState {
|
process_element_status: RecipeElementModalState {
|
||||||
is_open: false,
|
is_open: false,
|
||||||
can_finish: false,
|
can_finish: false,
|
||||||
element: RecipeElement::default(),
|
element: RecipeElement::default(),
|
||||||
|
|
@ -508,6 +529,7 @@ impl Default for RecipeTabViewer {
|
||||||
old_price: BigDecimal::default(),
|
old_price: BigDecimal::default(),
|
||||||
|
|
||||||
product_page: 0,
|
product_page: 0,
|
||||||
|
recipe_page: 0,
|
||||||
|
|
||||||
rt,
|
rt,
|
||||||
db_oper,
|
db_oper,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue