From 998b72321284d0880b89b45f7d962db071238773 Mon Sep 17 00:00:00 2001 From: ultrageese Date: Mon, 22 Jun 2026 09:15:08 +1000 Subject: [PATCH] =?UTF-8?q?=D0=B1=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- code/src/database.rs | 42 ++--- code/src/lib.rs | 353 ------------------------------------------- code/src/main.rs | 2 +- 3 files changed, 22 insertions(+), 375 deletions(-) delete mode 100644 code/src/lib.rs diff --git a/code/src/database.rs b/code/src/database.rs index e225cf5..b161632 100644 --- a/code/src/database.rs +++ b/code/src/database.rs @@ -92,7 +92,7 @@ impl DBOperator { } } pub async fn update_equipment(&self, equipment: Equipment) -> Result { - match sqlx::query("UPDATE Brewery.equipment SET inv_number=?, maintenance_date=?, worker_id=?, name=?, is_written_off=? WHERE id=?;") + 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) @@ -149,7 +149,7 @@ impl DBOperator { } pub async fn add_worker(&self, worker: WorkerRow) -> Result { // 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 `worker` (id, position_id, hire_date, is_fired, full_name) VALUES(0, ?, ?, ?, ?);") .bind(worker.position_id) .bind(worker.hire_date) .bind(worker.is_fired) @@ -165,7 +165,7 @@ impl DBOperator { } } pub async fn add_position(&self, position: Position) -> Result { - match sqlx::query("INSERT INTO Brewery.`position` (id, name, wage) VALUES(0, ?, ?);") + match sqlx::query("INSERT INTO `position` (id, name, wage) VALUES(0, ?, ?);") .bind(position.name) .bind(position.wage) .execute(&self.pool) @@ -190,7 +190,7 @@ impl DBOperator { } pub async fn add_material(&self, mat: MaterialRow) -> Result { match sqlx::query( - "INSERT INTO Brewery.material (id, name, quantity, category_id) VALUES(0, ?, ?, ?);", + "INSERT INTO `material` (id, name, quantity, category_id) VALUES(0, ?, ?, ?);", ) .bind(mat.name) .bind(mat.quantity) @@ -203,7 +203,7 @@ impl DBOperator { } } pub async fn delete_position(&self, position: Position) -> Result { - match sqlx::query("DELETE FROM Brewery.`position` WHERE id = ?;") + match sqlx::query("DELETE FROM `position` WHERE id = ?;") .bind(position.id) .execute(&self.pool) .await @@ -216,7 +216,7 @@ impl DBOperator { &self, mat_cat: MaterialCategory, ) -> Result { - match sqlx::query("DELETE FROM Brewery.`material_category` WHERE id = ?;") + match sqlx::query("DELETE FROM `material_category` WHERE id = ?;") .bind(mat_cat.id) .execute(&self.pool) .await @@ -226,7 +226,7 @@ impl DBOperator { } } pub async fn delete_material(&self, mat: MaterialRow) -> Result { - match sqlx::query("DELETE FROM Brewery.`material` WHERE id = ?;") + match sqlx::query("DELETE FROM `material` WHERE id = ?;") .bind(mat.id) .execute(&self.pool) .await @@ -237,7 +237,7 @@ impl DBOperator { } pub async fn update_worker(&self, worker: WorkerRow) -> Result { - match sqlx::query("UPDATE Brewery.worker SET position_id=?, hire_date=?, is_fired=?, full_name=? WHERE id=?;") + 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) @@ -257,7 +257,7 @@ impl DBOperator { &self, mat_cat: MaterialCategory, ) -> Result { - match sqlx::query("UPDATE Brewery.`material_category` SET name=? WHERE id=?;") + match sqlx::query("UPDATE `material_category` SET name=? WHERE id=?;") .bind(mat_cat.name) .bind(mat_cat.id) .execute(&self.pool) @@ -269,7 +269,7 @@ impl DBOperator { } pub async fn update_material(&self, mat: MaterialRow) -> Result { match sqlx::query( - "UPDATE Brewery.material SET name=?, quantity=?, category_id=? WHERE id=?;", + "UPDATE `material` SET name=?, quantity=?, category_id=? WHERE id=?;", ) .bind(mat.name) .bind(mat.quantity) @@ -303,7 +303,7 @@ impl DBOperator { } pub async fn update_position(&self, pos: Position) -> Result { - match sqlx::query("UPDATE Brewery.position SET name=?, wage=? WHERE id=?") + match sqlx::query("UPDATE `position`SET name=?, wage=? WHERE id=?") .bind(pos.name) .bind(pos.wage) .bind(pos.id) @@ -319,7 +319,7 @@ impl DBOperator { username: String, password_hash: String, ) -> Result { - let ans = sqlx::query("SELECT * FROM Brewery.profile WHERE login=? AND password=?") + let ans = sqlx::query("SELECT * FROM `profile` WHERE login=? AND password=?") .bind(username) .bind(password_hash) .fetch_all(&self.pool) @@ -344,11 +344,11 @@ impl DBOperator { profile.login, position.id FROM - Brewery.profile + `profile` JOIN - Brewery.worker + `worker` JOIN - Brewery.position + `position` ON profile.worker_id = worker.id AND profile.login=? AND worker.position_id =position.id"#, @@ -397,7 +397,7 @@ impl DBOperator { salary_size: BigDecimal, comment: Option, ) -> Result { - match sqlx::query("INSERT INTO Brewery.salary (id, worker_id, salary_size, salary_date, comment) VALUES(0, ?, ?, ?, ?);") + 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) @@ -409,7 +409,7 @@ impl DBOperator { } } pub async fn update_salary(&self, salary: Salary) -> Result { - match sqlx::query("UPDATE Brewery.salary SET worker_id=?, salary_size=?, salary_date=?, comment=? WHERE id=?;") + 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) @@ -422,7 +422,7 @@ impl DBOperator { } } pub async fn remove_salary(&self, id: i32) -> Result { - match sqlx::query("DELETE FROM Brewery.salary WHERE id=?;") + match sqlx::query("DELETE FROM `salary` WHERE id=?;") .bind(id) .execute(&self.pool) .await @@ -432,7 +432,7 @@ impl DBOperator { } } pub async fn get_recipes(&self) -> Result, sqlx::Error> { - let pre_ret = sqlx::query_as::<_, RecipeRow>("SELECT * FROM recipe") + let pre_ret = sqlx::query_as::<_, RecipeRow>("SELECT * FROM `recipe`") .fetch_all(&self.pool) .await .unwrap_or(Vec::new()); @@ -480,7 +480,7 @@ impl DBOperator { } } pub async fn update_recipe(&self, recipe: Recipe) -> Result { - match sqlx::query("UPDATE Brewery.recipe SET name=? WHERE id=?;") + match sqlx::query("UPDATE `recipe` SET name=? WHERE id=?;") .bind(recipe.name) .bind(recipe.id) .execute(&self.pool) @@ -491,7 +491,7 @@ impl DBOperator { } } pub async fn get_recipe_elements(&self) -> Result, sqlx::Error> { - let pre_ret = sqlx::query_as::<_, RecipeElementRow>("SELECT id, recipe_id, material_id, equipment_id, quantity FROM Brewery.recipe_element;").fetch_all(&self.pool).await; + 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 eqs = self.get_equipment().await.unwrap(); diff --git a/code/src/lib.rs b/code/src/lib.rs deleted file mode 100644 index fe13481..0000000 --- a/code/src/lib.rs +++ /dev/null @@ -1,353 +0,0 @@ -#[cfg(test)] -mod tests { - use super::database::DBOperator; - use crate::models::*; - use bigdecimal::BigDecimal; - use chrono::Local; - use std::collections::HashSet; - - // ============================================================ - // UNIT TESTS (no database required) - // ============================================================ - - /// Test 1: Position default values and construction - #[test] - fn test_position_default_and_construction() { - let default_pos = Position::default(); - assert_eq!(default_pos.id, 1); - assert_eq!(default_pos.name, ""); - assert_eq!(default_pos.wage, BigDecimal::from(0)); - - let custom_pos = Position { - id: 42, - name: "Пивовар".to_string(), - wage: BigDecimal::from(65000), - }; - assert_eq!(custom_pos.id, 42); - assert_eq!(custom_pos.name, "Пивовар"); - assert_eq!(custom_pos.wage, BigDecimal::from(65000)); - } - - /// Test 2: Worker default values and construction with nested Position - #[test] - fn test_worker_default_and_construction() { - let default_worker = Worker::default(); - assert_eq!(default_worker.id, 0); - assert_eq!(default_worker.full_name, ""); - assert!(!default_worker.is_fired); - - let pos = Position { - id: 3, - name: "Пивовар".to_string(), - wage: BigDecimal::from(65000), - }; - let worker = Worker { - id: 1, - full_name: "Иванов Иван".to_string(), - hire_date: Local::now(), - position: pos.clone(), - is_fired: false, - }; - assert_eq!(worker.full_name, "Иванов Иван"); - assert_eq!(worker.position.name, "Пивовар"); - assert_eq!(worker.position.wage, BigDecimal::from(65000)); - assert!(!worker.is_fired); - } - - /// Test 3: MaterialCategory default and Material construction with category - #[test] - fn test_material_and_category_construction() { - let default_cat = MaterialCategory::default(); - assert_eq!(default_cat.id, 0); - assert_eq!(default_cat.name, ""); - - let cat = MaterialCategory { - id: 2, - name: "Солод".to_string(), - }; - let mat = Material { - id: 1, - name: "Курский тёмный".to_string(), - quantity: 20, - category: cat.clone(), - }; - assert_eq!(mat.name, "Курский тёмный"); - assert_eq!(mat.quantity, 20); - assert_eq!(mat.category.name, "Солод"); - } - - /// Test 4: ModalStatus default and equality (using matches! to avoid Debug) - #[test] - fn test_modal_status_default_and_equality() { - let default_status = ModalStatus::default(); - assert!(matches!(default_status, ModalStatus::Add)); - assert!(!matches!(default_status, ModalStatus::Edit)); - assert!(!matches!(default_status, ModalStatus::Remove)); - - let edit_status = ModalStatus::Edit; - assert!(matches!(edit_status, ModalStatus::Edit)); - assert!(!matches!(edit_status, ModalStatus::Add)); - } - - /// Test 5: Equipment default and construction with nested Worker - #[test] - fn test_equipment_default_and_construction() { - let default_eq = Equipment::default(); - assert_eq!(default_eq.id, 0); - assert_eq!(default_eq.name, ""); - assert_eq!(default_eq.inv_number, ""); - assert!(!default_eq.is_written_off); - - let pos = Position { - id: 1, - name: "Уборщик".to_string(), - wage: BigDecimal::from(20000), - }; - let worker = Worker { - id: 1, - full_name: "Иван Петров".to_string(), - hire_date: Local::now(), - position: pos, - is_fired: false, - }; - let equipment = Equipment { - id: 1, - name: "Метла деревяная".to_string(), - inv_number: "М-1".to_string(), - maintenance_date: Local::now(), - worker: worker.clone(), - is_written_off: false, - }; - assert_eq!(equipment.name, "Метла деревяная"); - assert_eq!(equipment.inv_number, "М-1"); - assert_eq!(equipment.worker.full_name, "Иван Петров"); - assert!(!equipment.is_written_off); - } - - // ============================================================ - // INTEGRATION TESTS (require database connection) - // ============================================================ - - /// Test 6: Integration — get_position returns positions from DB - #[tokio::test] - async fn test_integration_get_position() { - let db = DBOperator::new().await; - let positions = db.get_position().await.expect("get_position failed"); - // The seed data has 4 positions: Уборщик, Кладовщик, Пивовар, Менеджер - assert!( - positions.len() >= 4, - "Expected at least 4 positions, got {}", - positions.len() - ); - let names: Vec<&str> = positions.iter().map(|p| p.name.as_str()).collect(); - assert!(names.contains(&"Уборщик"), "Should contain Уборщик"); - assert!(names.contains(&"Пивовар"), "Should contain Пивовар"); - } - - /// Test 7: Integration — add_worker and get_workers round-trip - #[tokio::test] - async fn test_integration_add_and_get_worker() { - let db = DBOperator::new().await; - - // Add a new worker - let new_worker = WorkerRow { - id: 0, // auto-increment - full_name: "Тестовый Работник Для Теста".to_string(), - hire_date: Local::now(), - position_id: 1, // Уборщик - is_fired: false, - }; - let add_result = db.add_worker(new_worker).await.expect("add_worker failed"); - assert!(add_result, "add_worker should return true"); - - // Verify the worker appears in get_workers - let workers = db.get_workers().await.expect("get_workers failed"); - let found = workers - .iter() - .any(|w| w.full_name == "Тестовый Работник Для Теста"); - assert!(found, "Newly added worker should appear in get_workers"); - - // Cleanup: find and mark the test worker as fired - let test_worker = workers - .iter() - .find(|w| w.full_name == "Тестовый Работник Для Теста") - .expect("Test worker not found for cleanup"); - let fired_row = WorkerRow { - id: test_worker.id, - full_name: test_worker.full_name.clone(), - hire_date: test_worker.hire_date, - position_id: test_worker.position.id, - is_fired: true, - }; - db.update_worker(fired_row) - .await - .expect("update_worker (fire) failed"); - } - - /// Test 8: Integration — material_category full CRUD round-trip - #[tokio::test] - async fn test_integration_material_category_crud() { - let db = DBOperator::new().await; - - // Add a new category - let new_cat = MaterialCategory { - id: 0, - name: "Тестовая Категория Интеграция".to_string(), - }; - let add_result = db - .add_material_category(new_cat) - .await - .expect("add_material_category failed"); - assert!(add_result, "add_material_category should return true"); - - // Verify it appears in get_mcat - let cats = db.get_mcat().await.expect("get_mcat failed"); - let found_cat = cats - .iter() - .find(|c| c.name == "Тестовая Категория Интеграция") - .expect("New category not found in get_mcat"); - - // Update the category - let mut updated_cat = found_cat.clone(); - updated_cat.name = "Обновлённая Тестовая Категория".to_string(); - let update_result = db - .update_material_category(updated_cat.clone()) - .await - .expect("update_material_category failed"); - assert!(update_result, "update_material_category should return true"); - - // Verify update - let cats_after = db.get_mcat().await.expect("get_mcat after update failed"); - let updated = cats_after - .iter() - .find(|c| c.id == found_cat.id) - .expect("Category not found after update"); - assert_eq!(updated.name, "Обновлённая Тестовая Категория"); - - // Delete the category - let delete_result = db - .delete_material_category(updated_cat) - .await - .expect("delete_material_category failed"); - assert!(delete_result, "delete_material_category should return true"); - - // Verify deletion - let cats_final = db.get_mcat().await.expect("get_mcat after delete failed"); - let not_found = cats_final.iter().find(|c| c.id == found_cat.id).is_none(); - assert!(not_found, "Deleted category should not appear in get_mcat"); - } - - /// Test 9: Integration — salary full CRUD round-trip - #[tokio::test] - async fn test_integration_salary_crud() { - let db = DBOperator::new().await; - - // Get existing workers to use a valid worker_id - let workers = db.get_workers().await.expect("get_workers failed"); - let worker = workers.first().expect("No workers in DB for salary test"); - - let salary_date = Local::now(); - let salary_size = BigDecimal::from(99999); - let comment = Some("Интеграционный тест зарплаты".to_string()); - - // Add salary - let add_result = db - .add_salary(worker.id, salary_date, salary_size.clone(), comment.clone()) - .await - .expect("add_salary failed"); - assert!(add_result, "add_salary should return true"); - - // Verify it appears in get_salaries - let salaries = db.get_salaries().await.expect("get_salaries failed"); - let found_sal = salaries - .iter() - .find(|s| { - s.worker.id == worker.id - && s.salary_size == salary_size - && s.comment == "Интеграционный тест зарплаты" - }) - .expect("Newly added salary not found in get_salaries"); - - // Remove the salary - let remove_result = db - .remove_salary(found_sal.id) - .await - .expect("remove_salary failed"); - assert!(remove_result, "remove_salary should return true"); - - // Verify removal - let salaries_after = db - .get_salaries() - .await - .expect("get_salaries after remove failed"); - let not_found = salaries_after - .iter() - .find(|s| s.id == found_sal.id) - .is_none(); - assert!( - not_found, - "Removed salary should not appear in get_salaries" - ); - } - - /// Test 10: Integration — recipe full CRUD round-trip - #[tokio::test] - async fn test_integration_recipe_crud() { - let db = DBOperator::new().await; - - // Add a new recipe - let new_recipe = Recipe { - id: 0, - name: "Тестовый Рецепт Интеграция".to_string(), - elements: HashSet::new(), - }; - let recipe_id = db.add_recipe(new_recipe).await.expect("add_recipe failed"); - assert!(recipe_id > 0, "add_recipe should return a valid ID"); - - // Verify it appears in get_recipes - let recipes = db.get_recipes().await.expect("get_recipes failed"); - let found_recipe = recipes - .iter() - .find(|r| r.name == "Тестовый Рецепт Интеграция") - .expect("Newly added recipe not found in get_recipes"); - assert_eq!(found_recipe.id as u64, recipe_id); - - // Update the recipe - let mut updated_recipe = found_recipe.clone(); - updated_recipe.name = "Обновлённый Тестовый Рецепт".to_string(); - let update_result = db - .update_recipe(updated_recipe.clone()) - .await - .expect("update_recipe failed"); - assert!(update_result, "update_recipe should return true"); - - // Verify update - let recipes_after = db - .get_recipes() - .await - .expect("get_recipes after update failed"); - let updated = recipes_after - .iter() - .find(|r| r.id == found_recipe.id) - .expect("Recipe not found after update"); - assert_eq!(updated.name, "Обновлённый Тестовый Рецепт"); - - // Remove the recipe - let remove_result = db - .remove_recipe(found_recipe.id) - .await - .expect("remove_recipe failed"); - assert!(remove_result, "remove_recipe should return true"); - - // Verify removal - let recipes_final = db - .get_recipes() - .await - .expect("get_recipes after remove failed"); - let not_found = recipes_final - .iter() - .find(|r| r.id == found_recipe.id) - .is_none(); - assert!(not_found, "Removed recipe should not appear in get_recipes"); - } -} diff --git a/code/src/main.rs b/code/src/main.rs index 99e59d6..c5c9db0 100644 --- a/code/src/main.rs +++ b/code/src/main.rs @@ -11,7 +11,7 @@ mod reports; mod tab; mod worker_database; mod worker_tab; -mod lib; + fn main() { dotenvy::dotenv().ok();