Add vehicle repair automation in DirectorWorker: Implement functionality to automatically repair vehicles based on their condition and region. Update SQL queries to support vehicle selection and repair operations, enhancing the Director's capabilities in managing vehicle maintenance.

This commit is contained in:
Torsten Schulz (local)
2025-12-22 15:07:02 +01:00
parent fce7400303
commit 08563c956c
2 changed files with 146 additions and 1 deletions

View File

@@ -35,15 +35,20 @@ use crate::worker::sql::{
QUERY_GET_USER_OFFICES,
QUERY_CUMULATIVE_TAX_NO_EXEMPT,
QUERY_CUMULATIVE_TAX_WITH_EXEMPT,
QUERY_GET_VEHICLES_TO_REPAIR_IN_REGION,
QUERY_REPAIR_VEHICLE,
};
use crate::worker::publish_update_status;
#[derive(Debug, Clone)]
struct Director {
id: i32,
branch_id: i32,
falukant_user_id: i32,
may_produce: bool,
may_sell: bool,
may_start_transport: bool,
may_repair_vehicles: bool,
}
#[derive(Debug, Clone)]
@@ -157,6 +162,14 @@ impl DirectorWorker {
}
for director in directors {
if director.may_repair_vehicles {
if let Err(err) = self.repair_vehicles(&director) {
eprintln!(
"[DirectorWorker] Fehler bei repair_vehicles für Director {}: {err}",
director.id
);
}
}
if director.may_produce {
eprintln!(
"[DirectorWorker] Starte Produktionsprüfung für Director {} (branch_id={})",
@@ -192,15 +205,106 @@ impl DirectorWorker {
Some(Director {
id: row.get("id")?.parse().ok()?,
branch_id: row.get("branch_id")?.parse().ok()?,
falukant_user_id: row.get("falukant_user_id")?.parse().ok()?,
may_produce: row.get("may_produce").map(|v| v == "t" || v == "true").unwrap_or(false),
may_sell: row.get("may_sell").map(|v| v == "t" || v == "true").unwrap_or(false),
may_start_transport: row
.get("may_start_transport")
.map(|v| v == "t" || v == "true")
.unwrap_or(false),
may_repair_vehicles: row
.get("may_repair_vehicles")
.map(|v| v == "t" || v == "true")
.unwrap_or(false),
})
}
fn repair_vehicles(&mut self, director: &Director) -> Result<(), DbError> {
self.base
.set_current_step("DirectorWorker: repair_vehicles");
let mut conn = self
.base
.pool
.get()
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
// Region des Directors/Branches bestimmen
conn.prepare("get_branch_region_for_repair", QUERY_GET_BRANCH_REGION)?;
let rows = conn.execute("get_branch_region_for_repair", &[&director.branch_id])?;
let region_id: i32 = rows
.first()
.and_then(|r| r.get("region_id"))
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(-1);
if region_id < 0 {
return Ok(());
}
conn.prepare(
"get_vehicles_to_repair",
QUERY_GET_VEHICLES_TO_REPAIR_IN_REGION,
)?;
conn.prepare("repair_vehicle", QUERY_REPAIR_VEHICLE)?;
let candidates =
conn.execute("get_vehicles_to_repair", &[&director.falukant_user_id, &region_id])?;
if candidates.is_empty() {
return Ok(());
}
let mut repaired = 0usize;
for row in candidates {
let vehicle_id = row
.get("vehicle_id")
.and_then(|v| v.parse::<i32>().ok())
.unwrap_or(-1);
let condition = row
.get("condition")
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(100.0);
let type_cost = row
.get("cost")
.and_then(|v| v.parse::<f64>().ok())
.unwrap_or(0.0);
if vehicle_id < 0 || type_cost <= 0.0 {
continue;
}
// repairCost = round(type.cost * 0.8 * (100 - condition) / 100)
let repair_cost = (type_cost * 0.8 * (100.0 - condition) / 100.0).round();
if repair_cost <= 0.0 {
continue;
}
// Preconditions (wie Backend):
// - sufficientFunds: wir versuchen abzubuchen und überspringen bei Fehler
if let Err(_err) = self.base.change_falukant_user_money(
director.falukant_user_id,
-repair_cost,
&format!("repair vehicle {}", vehicle_id),
) {
continue;
}
// Fahrzeug auf 100 setzen + available_from in Zukunft (build_time_minutes)
let _ = conn.execute("repair_vehicle", &[&vehicle_id])?;
repaired += 1;
}
if repaired > 0 {
eprintln!(
"[DirectorWorker] {} Fahrzeug(e) automatisch zur Reparatur gestartet (director_id={}, region_id={})",
repaired, director.id, region_id
);
// Frontend: Branches/Status neu laden
publish_update_status(&self.base.broker, director.falukant_user_id);
}
Ok(())
}
fn start_productions(&mut self, director: &Director) -> Result<(), DbError> {
self.base
.set_current_step("DirectorWorker: start_productions");

View File

@@ -72,7 +72,14 @@ SELECT sell_cost, sell_cost AS original_sell_cost FROM falukant_type.product WHE
"#;
pub const QUERY_GET_DIRECTORS: &str = r#"
SELECT d.may_produce, d.may_sell, d.may_start_transport, b.id AS branch_id, fu.id AS falukantUserId, d.id
SELECT
d.may_produce,
d.may_sell,
d.may_start_transport,
d.may_repair_vehicles,
b.id AS branch_id,
fu.id AS falukant_user_id,
d.id
FROM falukant_data.director d
JOIN falukant_data.falukant_user fu ON fu.id = d.employer_user_id
JOIN falukant_data.character c ON c.id = d.director_character_id
@@ -80,6 +87,40 @@ JOIN falukant_data.branch b ON b.region_id = c.region_id AND b.falukant_user_id
WHERE current_time BETWEEN '08:00:00' AND '17:00:00';
"#;
// Director: vehicle repair automation
pub const QUERY_GET_VEHICLES_TO_REPAIR_IN_REGION: &str = r#"
SELECT
v.id AS vehicle_id,
v.condition,
vt.cost,
COALESCE(vt.build_time_minutes, 0) AS build_time_minutes
FROM falukant_data.vehicle v
JOIN falukant_type.vehicle vt ON vt.id = v.vehicle_type_id
WHERE v.falukant_user_id = $1
AND v.region_id = $2
AND v.condition < 10
AND v.condition < 100
AND v.available_from <= NOW()
AND NOT EXISTS (
SELECT 1 FROM falukant_data.transport t WHERE t.vehicle_id = v.id
)
ORDER BY v.condition ASC, v.id ASC;
"#;
pub const QUERY_REPAIR_VEHICLE: &str = r#"
UPDATE falukant_data.vehicle v
SET condition = 100,
available_from = NOW() + (COALESCE(vt.build_time_minutes, 0) * INTERVAL '1 minute'),
updated_at = NOW()
FROM falukant_type.vehicle vt
WHERE vt.id = v.vehicle_type_id
AND v.id = $1
AND v.condition < 100
AND v.available_from <= NOW()
AND NOT EXISTS (SELECT 1 FROM falukant_data.transport t WHERE t.vehicle_id = v.id)
RETURNING v.id AS vehicle_id, v.available_from, COALESCE(vt.build_time_minutes, 0) AS build_time_minutes;
"#;
pub const QUERY_GET_BEST_PRODUCTION: &str = r#"
SELECT fdu.id falukant_user_id, CAST(fdu.money AS text) AS money, fdu.certificate, ftp.id product_id, ftp.label_tr, fdb.region_id,
(SELECT SUM(quantity) FROM falukant_data.stock fds WHERE fds.branch_id = fdb.id) AS stock_size,