Merge branch 'master' of https://gitea.suz-ppk.ru/UltraGoose/BreweryControlSystem
commit
d0e54c29c0
|
|
@ -60,7 +60,7 @@ CREATE TABLE `equipment` (
|
|||
PRIMARY KEY (`id`),
|
||||
KEY `fk_worker1` (`worker_id`),
|
||||
CONSTRAINT `fk_worker1` FOREIGN KEY (`worker_id`) REFERENCES `worker` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
|
@ -71,8 +71,12 @@ SET @OLD_AUTOCOMMIT=@@AUTOCOMMIT, @@AUTOCOMMIT=0;
|
|||
LOCK TABLES `equipment` WRITE;
|
||||
/*!40000 ALTER TABLE `equipment` DISABLE KEYS */;
|
||||
INSERT INTO `equipment` VALUES
|
||||
(1,'М-1','1970-01-01 00:00:00',1,'Метла деревяная',0),
|
||||
(2,'М-2','1970-01-01 00:00:00',2,'Метла деревяная',0);
|
||||
(3,'ПВ-11','2026-06-19 14:00:00',6,'Пивоварня \"Моисей\"',0),
|
||||
(4,'ПВ-12','2001-04-30 13:00:00',5,'Пивоварня \"Дружба\"',0),
|
||||
(5,'СД-1','2005-05-24 13:00:00',7,'Солододробилка',0),
|
||||
(6,'СД-2','2006-06-25 13:00:00',2,'Солододробилка',0),
|
||||
(7,'КТЛ-5','1991-02-01 14:00:00',1,'Сусловарный котёл',0),
|
||||
(8,'КТЛ-10','2026-02-01 14:00:00',5,'Сусловарный котёл',0);
|
||||
/*!40000 ALTER TABLE `equipment` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
COMMIT;
|
||||
|
|
@ -123,7 +127,7 @@ CREATE TABLE `material_category` (
|
|||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
|
@ -313,7 +317,7 @@ CREATE TABLE `recipe` (
|
|||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(50) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
|
@ -323,6 +327,8 @@ CREATE TABLE `recipe` (
|
|||
SET @OLD_AUTOCOMMIT=@@AUTOCOMMIT, @@AUTOCOMMIT=0;
|
||||
LOCK TABLES `recipe` WRITE;
|
||||
/*!40000 ALTER TABLE `recipe` DISABLE KEYS */;
|
||||
INSERT INTO `recipe` VALUES
|
||||
(1,'Пиво светлое');
|
||||
/*!40000 ALTER TABLE `recipe` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
COMMIT;
|
||||
|
|
@ -348,7 +354,7 @@ CREATE TABLE `recipe_element` (
|
|||
CONSTRAINT `fk_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipment` (`id`),
|
||||
CONSTRAINT `fk_material` FOREIGN KEY (`material_id`) REFERENCES `material` (`id`),
|
||||
CONSTRAINT `fk_recipe` FOREIGN KEY (`recipe_id`) REFERENCES `recipe` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
|
@ -379,7 +385,7 @@ CREATE TABLE `salary` (
|
|||
PRIMARY KEY (`id`),
|
||||
KEY `fk_worker` (`worker_id`),
|
||||
CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `worker` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
|
@ -390,7 +396,12 @@ SET @OLD_AUTOCOMMIT=@@AUTOCOMMIT, @@AUTOCOMMIT=0;
|
|||
LOCK TABLES `salary` WRITE;
|
||||
/*!40000 ALTER TABLE `salary` DISABLE KEYS */;
|
||||
INSERT INTO `salary` VALUES
|
||||
(2,3,30000,'1970-01-20 00:00:00','Премия за пиво');
|
||||
(2,3,30000,'1970-01-20 00:00:00','Премия за пиво'),
|
||||
(3,5,2000,'1980-02-19 14:00:00','За красивые глаза'),
|
||||
(4,4,2000,'1980-02-19 14:00:00','За красивые глаза'),
|
||||
(5,10,1000,'2026-06-21 14:00:00','да поможет нам бог'),
|
||||
(6,2,1000,'2026-06-21 14:00:00','да поможет нам бог'),
|
||||
(7,8,1000,'2026-06-21 14:00:00','да поможет нам бог');
|
||||
/*!40000 ALTER TABLE `salary` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
COMMIT;
|
||||
|
|
@ -438,7 +449,7 @@ CREATE TABLE `worker` (
|
|||
PRIMARY KEY (`id`),
|
||||
KEY `fk_position` (`position_id`),
|
||||
CONSTRAINT `fk_position` FOREIGN KEY (`position_id`) REFERENCES `position` (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
|
|
@ -459,8 +470,7 @@ INSERT INTO `worker` VALUES
|
|||
(8,4,'2026-04-24 00:00:00',0,'Иванов Иван'),
|
||||
(9,3,'2024-04-21 14:00:00',0,'Власов Иннокентий'),
|
||||
(10,2,'1970-01-19 14:00:00',0,'Петров Пётр Петрович'),
|
||||
(11,2,'2003-02-01 14:00:00',0,'Никитин Олег Михайлович'),
|
||||
(12,2,'2008-02-01 14:00:00',1,'Славик');
|
||||
(11,2,'2003-02-01 14:00:00',0,'Никитин Олег Михайлович');
|
||||
/*!40000 ALTER TABLE `worker` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
COMMIT;
|
||||
|
|
@ -475,4 +485,4 @@ SET AUTOCOMMIT=@OLD_AUTOCOMMIT;
|
|||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*M!100616 SET NOTE_VERBOSITY=@OLD_NOTE_VERBOSITY */;
|
||||
|
||||
-- Dump completed on 2026-06-19 20:04:08
|
||||
-- Dump completed on 2026-06-22 8:47:40
|
||||
|
|
|
|||
|
|
@ -325,10 +325,13 @@ impl MainTabViewer {
|
|||
.insert("name".into(), "".into());
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.insert("inv_numver".into(), "".into());
|
||||
.insert("inv_number".into(), "".into());
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.insert("worker_id".into(), "0".into());
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.insert("maintenance_date".into(), "".into());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -342,6 +345,7 @@ impl MainTabViewer {
|
|||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.column(Column::auto())
|
||||
.sense(egui::Sense::click())
|
||||
.header(30.0, |mut header| {
|
||||
header.col(|ui| {
|
||||
|
|
@ -356,6 +360,9 @@ impl MainTabViewer {
|
|||
header.col(|ui| {
|
||||
ui.heading("Дата последнего\nтехобслуживания");
|
||||
});
|
||||
header.col(|ui| {
|
||||
ui.heading("Списано");
|
||||
});
|
||||
})
|
||||
.body(|mut body| {
|
||||
body.ui_mut().style_mut().interaction.selectable_labels = false;
|
||||
|
|
@ -373,6 +380,9 @@ impl MainTabViewer {
|
|||
row.col(|ui| {
|
||||
ui.label(eq.maintenance_date.date_naive().to_string());
|
||||
});
|
||||
row.col(|ui| {
|
||||
ui.label(if eq.is_written_off { "Да" } else { "Нет" });
|
||||
});
|
||||
row.col(|ui| {
|
||||
if self.is_admin {
|
||||
if ui.button("Списать").clicked() {
|
||||
|
|
@ -426,15 +436,21 @@ impl MainTabViewer {
|
|||
egui::Grid::new("process_equipment_grid").show(ui, |ui| {
|
||||
ui.label("Название");
|
||||
let mut name = self.equipment_modal_state.data.get_mut("name").unwrap();
|
||||
ui.add_sized(Vec2::new(200.0, 20.0), egui::TextEdit::singleline(name));
|
||||
ui.add_sized(
|
||||
Vec2::new(200.0, 20.0),
|
||||
egui::TextEdit::singleline(name).hint_text("Название оборудования"),
|
||||
);
|
||||
ui.end_row();
|
||||
|
||||
ui.label("Инв. номер");
|
||||
ui.text_edit_singleline(
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.get_mut("inv_number")
|
||||
.unwrap(),
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.get_mut("inv_number")
|
||||
.unwrap(),
|
||||
)
|
||||
.hint_text("НН-00"),
|
||||
);
|
||||
ui.end_row();
|
||||
|
||||
|
|
@ -473,11 +489,14 @@ impl MainTabViewer {
|
|||
ui.end_row();
|
||||
|
||||
ui.label("Дата последнего\nтехобслуживания");
|
||||
ui.text_edit_singleline(
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.get_mut("maintenance_date")
|
||||
.unwrap(),
|
||||
ui.add(
|
||||
egui::TextEdit::singleline(
|
||||
self.equipment_modal_state
|
||||
.data
|
||||
.get_mut("maintenance_date")
|
||||
.unwrap(),
|
||||
)
|
||||
.hint_text("1970-01-01"),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
|
|
|
|||
351
code/src/lib.rs
351
code/src/lib.rs
|
|
@ -1,6 +1,353 @@
|
|||
#[cfg(test)]
|
||||
mod tests{
|
||||
use super::*;
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,8 @@ mod reports;
|
|||
mod tab;
|
||||
mod worker_database;
|
||||
mod worker_tab;
|
||||
// mod schema;
|
||||
mod lib;
|
||||
|
||||
fn main() {
|
||||
dotenvy::dotenv().ok();
|
||||
database::estabilish_connection();
|
||||
|
|
|
|||
Loading…
Reference in New Issue