diff --git a/src/worker/produce.rs b/src/worker/produce.rs index 4479967..ad16644 100644 --- a/src/worker/produce.rs +++ b/src/worker/produce.rs @@ -16,6 +16,7 @@ use crate::worker::sql::{ QUERY_ADD_OVERPRODUCTION_NOTIFICATION, QUERY_FIND_OVERPRODUCTION_NOTIFICATION, QUERY_UPDATE_OVERPRODUCTION_NOTIFICATION, + QUERY_GET_BRANCH_CAPACITY, }; /// Abbildet eine abgeschlossene Produktion aus der Datenbank. @@ -128,9 +129,19 @@ impl ProduceWorker { self.base .set_current_step("Process Finished Productions"); - // Nur Fehler loggen; keine Debug-Infos + eprintln!("[ProduceWorker] {} fertige Produktionen gefunden", finished_productions.len()); + // Verarbeite Produktionen einzeln und prüfe nach jeder, ob noch Platz ist for production in finished_productions { + // Prüfe nochmal, ob genug Lagerplatz vorhanden ist, bevor wir verarbeiten + if !self.has_enough_capacity(production.branch_id, production.quantity) { + eprintln!( + "[ProduceWorker] Überspringe Produktion {} (branch_id={}, quantity={}): Kein ausreichender Lagerplatz", + production.production_id, production.branch_id, production.quantity + ); + continue; + } + self.handle_finished_production(&production); } } @@ -218,6 +229,43 @@ impl ProduceWorker { .collect()) } + fn has_enough_capacity(&self, branch_id: i32, required_quantity: i32) -> bool { + let mut conn = match self.base.pool.get() { + Ok(c) => c, + Err(_) => return false, + }; + + if let Err(_) = conn.prepare("check_branch_capacity", QUERY_GET_BRANCH_CAPACITY) { + return false; + } + + let rows = match conn.execute("check_branch_capacity", &[&branch_id]) { + Ok(r) => r, + Err(_) => return false, + }; + + if rows.is_empty() { + return false; + } + + let row = &rows[0]; + let stock_size: i32 = row + .get("stock_size") + .and_then(|v| v.parse::().ok()) + .unwrap_or(0); + let used_in_stock: i32 = row + .get("used_in_stock") + .and_then(|v| v.parse::().ok()) + .unwrap_or(0); + let running_productions_quantity: i32 = row + .get("running_productions_quantity") + .and_then(|v| v.parse::().ok()) + .unwrap_or(0); + + let free_capacity = stock_size - used_in_stock - running_productions_quantity; + free_capacity >= required_quantity + } + fn store_in_stock( &self, stock_id: i32, diff --git a/src/worker/sql.rs b/src/worker/sql.rs index adeea95..6e88ce7 100644 --- a/src/worker/sql.rs +++ b/src/worker/sql.rs @@ -1435,10 +1435,12 @@ pub const QUERY_GET_FINISHED_PRODUCTIONS: &str = r#" -- Wetter-Effekte derzeit aus der Qualitätsberechnung entfernt WHERE p.start_timestamp + INTERVAL '1 minute' * pr.production_time <= NOW() -- Nur Produktionen zurückgeben, für die genug Lagerplatz vorhanden ist - -- running_productions_quantity enthält bereits p.quantity, daher prüfen wir: - -- (stock_size - used_in_stock - running_productions_quantity) >= 0 - -- Das bedeutet: Nach Abzug aller laufenden Produktionen muss noch Platz vorhanden sein - AND (capacity.stock_size - capacity.used_in_stock - capacity.running_productions_quantity) >= 0 + -- running_productions_quantity enthält bereits p.quantity + -- Nach dem Abschluss von p muss Platz sein: stock_size - used_in_stock - (running_productions_quantity - p.quantity) >= p.quantity + -- Vereinfacht: stock_size - used_in_stock - running_productions_quantity + p.quantity >= p.quantity + -- Oder: stock_size - used_in_stock - running_productions_quantity >= 0 + -- ABER: Wir müssen sicherstellen, dass p.quantity auch wirklich Platz hat + AND (capacity.stock_size - capacity.used_in_stock - capacity.running_productions_quantity + p.quantity) >= p.quantity ORDER BY p.start_timestamp; "#;