Add SQL query to count children by user: Introduced a new query to count distinct children associated with a user across all their characters. Updated UserCharacterWorker to utilize this new query, replacing the previous count query. This enhances user-specific data retrieval capabilities.
This commit is contained in:
@@ -580,6 +580,13 @@ pub const QUERY_COUNT_CHILDREN: &str = r#"
|
|||||||
SELECT COUNT(*) AS cnt FROM falukant_data.child_relation WHERE (father_character_id = $1 OR mother_character_id = $1) AND child_character_id != $2;
|
SELECT COUNT(*) AS cnt FROM falukant_data.child_relation WHERE (father_character_id = $1 OR mother_character_id = $1) AND child_character_id != $2;
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
pub const QUERY_COUNT_CHILDREN_BY_USER: &str = r#"
|
||||||
|
SELECT COUNT(DISTINCT cr.child_character_id) AS cnt
|
||||||
|
FROM falukant_data.child_relation cr
|
||||||
|
JOIN falukant_data.character parent ON (parent.id = cr.father_character_id OR parent.id = cr.mother_character_id)
|
||||||
|
WHERE parent.user_id = $1;
|
||||||
|
"#;
|
||||||
|
|
||||||
// user_character worker queries
|
// user_character worker queries
|
||||||
pub const QUERY_GET_USERS_TO_UPDATE: &str = r#"
|
pub const QUERY_GET_USERS_TO_UPDATE: &str = r#"
|
||||||
SELECT id, CURRENT_DATE - birthdate::date AS age, health
|
SELECT id, CURRENT_DATE - birthdate::date AS age, health
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ use crate::worker::sql::{
|
|||||||
QUERY_GET_SETTLEMENT_VALUE,
|
QUERY_GET_SETTLEMENT_VALUE,
|
||||||
QUERY_GET_INVENTORY_VALUE,
|
QUERY_GET_INVENTORY_VALUE,
|
||||||
QUERY_GET_CREDIT_DEBT,
|
QUERY_GET_CREDIT_DEBT,
|
||||||
QUERY_COUNT_CHILDREN,
|
QUERY_COUNT_CHILDREN_BY_USER,
|
||||||
QUERY_GET_HEIR,
|
QUERY_GET_HEIR,
|
||||||
QUERY_RANDOM_HEIR,
|
QUERY_RANDOM_HEIR,
|
||||||
QUERY_SET_CHARACTER_USER,
|
QUERY_SET_CHARACTER_USER,
|
||||||
@@ -795,8 +795,8 @@ impl UserCharacterWorker {
|
|||||||
.get()
|
.get()
|
||||||
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
||||||
|
|
||||||
conn.prepare("count_children", QUERY_COUNT_CHILDREN)?;
|
conn.prepare("count_children_by_user", QUERY_COUNT_CHILDREN_BY_USER)?;
|
||||||
let rows = conn.execute("count_children", &[&deceased_user_id])?;
|
let rows = conn.execute("count_children_by_user", &[&deceased_user_id])?;
|
||||||
|
|
||||||
Ok(rows
|
Ok(rows
|
||||||
.first()
|
.first()
|
||||||
|
|||||||
@@ -158,29 +158,12 @@ impl DirectorWorker {
|
|||||||
|
|
||||||
for director in directors {
|
for director in directors {
|
||||||
if director.may_produce {
|
if director.may_produce {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Starte Produktionsprüfung für Director {} (branch_id={})",
|
|
||||||
director.id, director.branch_id
|
|
||||||
);
|
|
||||||
self.start_productions(&director)?;
|
self.start_productions(&director)?;
|
||||||
}
|
}
|
||||||
if director.may_start_transport {
|
if director.may_start_transport {
|
||||||
eprintln!(
|
if let Err(_) = self.start_transports_stub(&director) {}
|
||||||
"[DirectorWorker] Starte Transportprüfung für Director {} (branch_id={})",
|
|
||||||
director.id, director.branch_id
|
|
||||||
);
|
|
||||||
if let Err(err) = self.start_transports_stub(&director) {
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler bei start_transports für Director {}: {err}",
|
|
||||||
director.id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if director.may_sell {
|
if director.may_sell {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Starte Verkaufsprüfung für Director {} (branch_id={})",
|
|
||||||
director.id, director.branch_id
|
|
||||||
);
|
|
||||||
self.start_sellings(&director)?;
|
self.start_sellings(&director)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -215,33 +198,14 @@ impl DirectorWorker {
|
|||||||
conn.prepare("get_to_produce", QUERY_GET_BEST_PRODUCTION)?;
|
conn.prepare("get_to_produce", QUERY_GET_BEST_PRODUCTION)?;
|
||||||
let rows = conn.execute("get_to_produce", &[&director.id, &director.branch_id])?;
|
let rows = conn.execute("get_to_produce", &[&director.id, &director.branch_id])?;
|
||||||
if rows.is_empty() {
|
if rows.is_empty() {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Keine Produktionskandidaten für Director {} gefunden.",
|
|
||||||
director.id
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut base_plan = match rows.first().and_then(Self::map_row_to_production_plan) {
|
let mut base_plan = match rows.first().and_then(Self::map_row_to_production_plan) {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => return Ok(()),
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Produktionsplan für Director {} konnte nicht gemappt werden.",
|
|
||||||
director.id
|
|
||||||
);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Produktionsplan: director_user_id={}, branch_id={}, product_id={}, money={}, certificate={}",
|
|
||||||
base_plan.falukant_user_id,
|
|
||||||
base_plan.branch_id,
|
|
||||||
base_plan.product_id,
|
|
||||||
base_plan.money,
|
|
||||||
base_plan.certificate
|
|
||||||
);
|
|
||||||
|
|
||||||
// Query zum Abfragen der aktuellen Kapazitätswerte vorbereiten
|
// Query zum Abfragen der aktuellen Kapazitätswerte vorbereiten
|
||||||
conn.prepare("get_branch_capacity", QUERY_GET_BRANCH_CAPACITY)?;
|
conn.prepare("get_branch_capacity", QUERY_GET_BRANCH_CAPACITY)?;
|
||||||
|
|
||||||
@@ -274,24 +238,12 @@ impl DirectorWorker {
|
|||||||
|
|
||||||
// Prüfen, ob noch Produktionen gestartet werden können
|
// Prüfen, ob noch Produktionen gestartet werden können
|
||||||
if running_productions >= MAX_PARALLEL_PRODUCTIONS {
|
if running_productions >= MAX_PARALLEL_PRODUCTIONS {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Maximale Anzahl an Produktionen ({}) erreicht für Branch {}.",
|
|
||||||
MAX_PARALLEL_PRODUCTIONS,
|
|
||||||
director.branch_id
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Freie Kapazität berechnen
|
// Freie Kapazität berechnen
|
||||||
let free_capacity = stock_size - used_in_stock - running_productions_quantity;
|
let free_capacity = stock_size - used_in_stock - running_productions_quantity;
|
||||||
if free_capacity <= 0 {
|
if free_capacity <= 0 {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Kein freier Lagerplatz mehr für Branch {} (stock_size={}, used={}, running_qty={}).",
|
|
||||||
director.branch_id,
|
|
||||||
stock_size,
|
|
||||||
used_in_stock,
|
|
||||||
running_productions_quantity
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,10 +254,7 @@ impl DirectorWorker {
|
|||||||
base_plan.running_productions_quantity = running_productions_quantity;
|
base_plan.running_productions_quantity = running_productions_quantity;
|
||||||
|
|
||||||
// Eine neue Produktion starten (max. 100 Stück)
|
// Eine neue Produktion starten (max. 100 Stück)
|
||||||
if let Err(err) = self.create_single_production(&mut conn, &base_plan) {
|
if self.create_single_production(&mut conn, &base_plan).is_err() {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler beim Starten einer Produktion: {err}"
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -373,7 +322,6 @@ impl DirectorWorker {
|
|||||||
// Hole aktuelle Kapazitätswerte direkt aus der DB, um Race Conditions zu vermeiden
|
// Hole aktuelle Kapazitätswerte direkt aus der DB, um Race Conditions zu vermeiden
|
||||||
let capacity_rows = conn.execute("get_branch_capacity", &[&plan.branch_id])?;
|
let capacity_rows = conn.execute("get_branch_capacity", &[&plan.branch_id])?;
|
||||||
if capacity_rows.is_empty() {
|
if capacity_rows.is_empty() {
|
||||||
eprintln!("[DirectorWorker] Keine Kapazitätsdaten für Branch {} gefunden", plan.branch_id);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,10 +343,6 @@ impl DirectorWorker {
|
|||||||
let free_capacity = stock_size - used_in_stock - running_productions_quantity;
|
let free_capacity = stock_size - used_in_stock - running_productions_quantity;
|
||||||
|
|
||||||
if free_capacity <= 0 {
|
if free_capacity <= 0 {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Keine Produktion gestartet: Kein freier Lagerplatz (stock_size={}, used={}, running_qty={})",
|
|
||||||
stock_size, used_in_stock, running_productions_quantity
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -407,42 +351,16 @@ impl DirectorWorker {
|
|||||||
|
|
||||||
let to_produce = (free_capacity.min(max_money_production)).clamp(0, 100);
|
let to_produce = (free_capacity.min(max_money_production)).clamp(0, 100);
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Produktionsberechnung: free_capacity={}, one_piece_cost={}, max_money_production={}, to_produce={}, running_productions={}",
|
|
||||||
free_capacity,
|
|
||||||
one_piece_cost,
|
|
||||||
max_money_production,
|
|
||||||
to_produce,
|
|
||||||
plan.running_productions
|
|
||||||
);
|
|
||||||
|
|
||||||
if to_produce < 1 {
|
if to_produce < 1 {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Keine Produktion gestartet: free_capacity={}, max_money_production={}, running_productions={}, running_qty={}",
|
|
||||||
free_capacity,
|
|
||||||
max_money_production,
|
|
||||||
plan.running_productions,
|
|
||||||
plan.running_productions_quantity
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let production_cost = to_produce as f64 * one_piece_cost;
|
let production_cost = to_produce as f64 * one_piece_cost;
|
||||||
|
|
||||||
if let Err(err) = self.base.change_falukant_user_money(
|
let _ = self.base.change_falukant_user_money(
|
||||||
plan.falukant_user_id,
|
plan.falukant_user_id,
|
||||||
-production_cost,
|
-production_cost,
|
||||||
"director starts production",
|
"director starts production",
|
||||||
) {
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler bei change_falukant_user_money: {err}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Debug: Log vor dem DB-Aufruf
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] calling change_falukant_user_money for start production: user_id={}, money_change={}",
|
|
||||||
plan.falukant_user_id, -production_cost
|
|
||||||
);
|
);
|
||||||
|
|
||||||
conn.prepare("insert_production", QUERY_INSERT_PRODUCTION)?;
|
conn.prepare("insert_production", QUERY_INSERT_PRODUCTION)?;
|
||||||
@@ -454,11 +372,6 @@ impl DirectorWorker {
|
|||||||
&[&plan.branch_id, &plan.product_id, &to_produce, &plan.region_id],
|
&[&plan.branch_id, &plan.product_id, &to_produce, &plan.region_id],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Produktion angelegt: branch_id={}, product_id={}, quantity={}",
|
|
||||||
plan.branch_id, plan.product_id, to_produce
|
|
||||||
);
|
|
||||||
|
|
||||||
let message = format!(
|
let message = format!(
|
||||||
r#"{{"event":"production_started","branch_id":{}}}"#,
|
r#"{{"event":"production_started","branch_id":{}}}"#,
|
||||||
plan.branch_id
|
plan.branch_id
|
||||||
@@ -478,10 +391,6 @@ impl DirectorWorker {
|
|||||||
if plan.money > 0.0 {
|
if plan.money > 0.0 {
|
||||||
(plan.money / one_piece_cost).floor() as i32
|
(plan.money / one_piece_cost).floor() as i32
|
||||||
} else {
|
} else {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Warnung: money=0 für falukant_user_id={}, verwende nur Lagerkapazität als Limit.",
|
|
||||||
plan.falukant_user_id
|
|
||||||
);
|
|
||||||
i32::MAX
|
i32::MAX
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -505,11 +414,6 @@ impl DirectorWorker {
|
|||||||
let mut items: Vec<InventoryItem> =
|
let mut items: Vec<InventoryItem> =
|
||||||
rows.into_iter().filter_map(Self::map_row_to_inventory_item).collect();
|
rows.into_iter().filter_map(Self::map_row_to_inventory_item).collect();
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Transportprüfung für Director {} (branch_id={}): {} Inventar-Items gefunden",
|
|
||||||
director.id, director.branch_id, items.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Für alle Items dieses Directors sollten die user_id-Felder identisch
|
// Für alle Items dieses Directors sollten die user_id-Felder identisch
|
||||||
// sein (Arbeitgeber des Directors).
|
// sein (Arbeitgeber des Directors).
|
||||||
let falukant_user_id = if items.is_empty() {
|
let falukant_user_id = if items.is_empty() {
|
||||||
@@ -539,49 +443,23 @@ impl DirectorWorker {
|
|||||||
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
// Falls es nichts zu transportieren gibt, prüfe auf leere Transporte
|
|
||||||
if items.is_empty() {
|
if items.is_empty() {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Keine Inventar-Items für Transporte gefunden für Director {} (branch_id={})",
|
|
||||||
director.id, director.branch_id
|
|
||||||
);
|
|
||||||
|
|
||||||
// Wenn keine Transportmittel im Branch vorhanden sind, versuche leere Transporte zu planen
|
|
||||||
if vehicles_in_branch == 0 {
|
if vehicles_in_branch == 0 {
|
||||||
eprintln!(
|
let _ = self.plan_empty_transports_for_vehicle_retrieval(
|
||||||
"[DirectorWorker] Keine Transportmittel im Branch {} vorhanden, prüfe auf leere Transporte zum Zurückholen",
|
|
||||||
director.branch_id
|
|
||||||
);
|
|
||||||
if let Err(err) = self.plan_empty_transports_for_vehicle_retrieval(
|
|
||||||
&mut conn,
|
&mut conn,
|
||||||
falukant_user_id,
|
falukant_user_id,
|
||||||
director.branch_id,
|
director.branch_id,
|
||||||
) {
|
);
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler beim Planen leerer Transporte: {err}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wenn keine Transportmittel im Branch vorhanden sind, aber Items vorhanden sind,
|
|
||||||
// versuche leere Transporte zu planen, um Fahrzeuge zurückzuholen
|
|
||||||
if vehicles_in_branch == 0 && !items.is_empty() {
|
if vehicles_in_branch == 0 && !items.is_empty() {
|
||||||
eprintln!(
|
let _ = self.plan_empty_transports_for_vehicle_retrieval(
|
||||||
"[DirectorWorker] Keine Transportmittel im Branch {} vorhanden, aber {} Items vorhanden. Prüfe auf leere Transporte zum Zurückholen",
|
|
||||||
director.branch_id, items.len()
|
|
||||||
);
|
|
||||||
if let Err(err) = self.plan_empty_transports_for_vehicle_retrieval(
|
|
||||||
&mut conn,
|
&mut conn,
|
||||||
falukant_user_id,
|
falukant_user_id,
|
||||||
director.branch_id,
|
director.branch_id,
|
||||||
) {
|
);
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler beim Planen leerer Transporte: {err}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Nach dem Planen leerer Transporte erneut prüfen, ob jetzt Transportmittel vorhanden sind
|
|
||||||
let vehicle_count_rows_after = conn.execute(
|
let vehicle_count_rows_after = conn.execute(
|
||||||
"count_vehicles_in_branch",
|
"count_vehicles_in_branch",
|
||||||
&[&falukant_user_id, &director.branch_id],
|
&[&falukant_user_id, &director.branch_id],
|
||||||
@@ -591,12 +469,7 @@ impl DirectorWorker {
|
|||||||
.next()
|
.next()
|
||||||
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
if vehicles_in_branch_after == 0 {
|
if vehicles_in_branch_after == 0 {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Nach Planen leerer Transporte immer noch keine Transportmittel im Branch {} vorhanden. Überspringe normale Transportplanung.",
|
|
||||||
director.branch_id
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,29 +478,11 @@ impl DirectorWorker {
|
|||||||
// - ggf. Transport-Einträge erzeugt
|
// - ggf. Transport-Einträge erzeugt
|
||||||
// - Inventar-Mengen reduziert
|
// - Inventar-Mengen reduziert
|
||||||
for item in items.iter_mut() {
|
for item in items.iter_mut() {
|
||||||
eprintln!(
|
let _ = self.plan_transports_for_item(
|
||||||
"[DirectorWorker] Prüfe Transport für Item: product_id={}, quantity={}, quality={}, region_id={}, branch_id={}",
|
|
||||||
item.product_id, item.quantity, item.quality, item.region_id, item.branch_id
|
|
||||||
);
|
|
||||||
|
|
||||||
let shipped = self.plan_transports_for_item(
|
|
||||||
&mut conn,
|
&mut conn,
|
||||||
falukant_user_id,
|
falukant_user_id,
|
||||||
item,
|
item,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Inventar wird bereits in plan_transports_for_item reduziert
|
|
||||||
if shipped > 0 {
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Transport geplant: {} Einheiten von Produkt {} transportiert (Inventar bereits reduziert)",
|
|
||||||
shipped, item.product_id
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Kein lohnender Transport gefunden für Produkt {} (region_id={})",
|
|
||||||
item.product_id, item.region_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nach normalen Transporten: Wenn keine Transportmittel mehr im Branch vorhanden sind,
|
// Nach normalen Transporten: Wenn keine Transportmittel mehr im Branch vorhanden sind,
|
||||||
@@ -643,19 +498,11 @@ impl DirectorWorker {
|
|||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
if vehicles_in_branch_final == 0 {
|
if vehicles_in_branch_final == 0 {
|
||||||
eprintln!(
|
let _ = self.plan_empty_transports_for_vehicle_retrieval(
|
||||||
"[DirectorWorker] Nach Transporten keine Transportmittel mehr im Branch {} vorhanden, prüfe auf leere Transporte zum Zurückholen",
|
|
||||||
director.branch_id
|
|
||||||
);
|
|
||||||
if let Err(err) = self.plan_empty_transports_for_vehicle_retrieval(
|
|
||||||
&mut conn,
|
&mut conn,
|
||||||
falukant_user_id,
|
falukant_user_id,
|
||||||
director.branch_id,
|
director.branch_id,
|
||||||
) {
|
);
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler beim Planen leerer Transporte: {err}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -841,30 +688,16 @@ impl DirectorWorker {
|
|||||||
let tax_cents = ((profit_cents as f64) * cumulative_tax_percent / 100.0).round() as i64;
|
let tax_cents = ((profit_cents as f64) * cumulative_tax_percent / 100.0).round() as i64;
|
||||||
let payout_cents = revenue_cents - tax_cents;
|
let payout_cents = revenue_cents - tax_cents;
|
||||||
|
|
||||||
eprintln!("[DirectorWorker] sell: revenue={:.2}, cost={:.2}, profit_cents={}, tax%={:.2}, tax_cents={}, payout_cents={}", sell_price, one_piece_cost * item.quantity as f64, profit_cents, cumulative_tax_percent, tax_cents, payout_cents);
|
|
||||||
|
|
||||||
if tax_cents > 0 {
|
if tax_cents > 0 {
|
||||||
let tax_amount = (tax_cents as f64) / 100.0;
|
let tax_amount = (tax_cents as f64) / 100.0;
|
||||||
if let Err(err) = self.base.change_falukant_user_money(DEFAULT_TREASURY_USER_ID, tax_amount, &format!("tax from sale product {}", item.product_id)) {
|
let _ = self.base.change_falukant_user_money(DEFAULT_TREASURY_USER_ID, tax_amount, &format!("tax from sale product {}", item.product_id));
|
||||||
eprintln!("[DirectorWorker] Fehler bei change_falukant_user_money (tax): {err}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let payout_amount = (payout_cents as f64) / 100.0;
|
let payout_amount = (payout_cents as f64) / 100.0;
|
||||||
if payout_cents != 0 && let Err(err) = self.base.change_falukant_user_money(item.user_id, payout_amount, "sell products") {
|
if payout_cents != 0 {
|
||||||
eprintln!("[DirectorWorker] Fehler bei change_falukant_user_money (sell products): {err}");
|
let _ = self.base.change_falukant_user_money(item.user_id, payout_amount, "sell products");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug: Log vor dem DB-Aufruf
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] sell: user_id={}, revenue={:.2}, tax={:.2}, payout={:.2}, product_id={}",
|
|
||||||
item.user_id,
|
|
||||||
sell_price,
|
|
||||||
(tax_cents as f64) / 100.0,
|
|
||||||
payout_amount,
|
|
||||||
item.product_id
|
|
||||||
);
|
|
||||||
|
|
||||||
conn.execute(
|
conn.execute(
|
||||||
"add_sell_log",
|
"add_sell_log",
|
||||||
&[
|
&[
|
||||||
@@ -914,23 +747,11 @@ impl DirectorWorker {
|
|||||||
// Load worth_percent by region for this product
|
// Load worth_percent by region for this product
|
||||||
let worth_by_region = Self::get_worth_by_region(conn, falukant_user_id, item.product_id)?;
|
let worth_by_region = Self::get_worth_by_region(conn, falukant_user_id, item.product_id)?;
|
||||||
if worth_by_region.is_empty() {
|
if worth_by_region.is_empty() {
|
||||||
eprintln!("[DirectorWorker] Keine worth_percent-Werte für Produkt {} gefunden", item.product_id);
|
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Gefundene Regionen für Produkt {}: {} Regionen",
|
|
||||||
item.product_id,
|
|
||||||
worth_by_region.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Compute local piece price
|
|
||||||
let local_percent = worth_by_region.get(&item.region_id).copied().unwrap_or(100.0);
|
let local_percent = worth_by_region.get(&item.region_id).copied().unwrap_or(100.0);
|
||||||
let local_piece_price = Self::compute_piece_price_for_percent(item, local_percent);
|
let local_piece_price = Self::compute_piece_price_for_percent(item, local_percent);
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Lokaler Preis für Produkt {}: {:.2} (worth_percent={:.2}, quality={})",
|
|
||||||
item.product_id, local_piece_price, local_percent, item.quality
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut best_target_region: Option<i32> = None;
|
let mut best_target_region: Option<i32> = None;
|
||||||
let mut best_quantity: i32 = 0;
|
let mut best_quantity: i32 = 0;
|
||||||
@@ -945,16 +766,7 @@ impl DirectorWorker {
|
|||||||
|
|
||||||
let remote_piece_price = Self::compute_piece_price_for_percent(item, remote_percent);
|
let remote_piece_price = Self::compute_piece_price_for_percent(item, remote_percent);
|
||||||
let delta_per_unit = remote_piece_price - local_piece_price;
|
let delta_per_unit = remote_piece_price - local_piece_price;
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: Preis {:.2}, Delta {:.2}",
|
|
||||||
region_id, remote_piece_price, delta_per_unit
|
|
||||||
);
|
|
||||||
|
|
||||||
if delta_per_unit <= 0.0 {
|
if delta_per_unit <= 0.0 {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: Kein Preisvorteil (Delta <= 0)",
|
|
||||||
region_id
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,16 +778,7 @@ impl DirectorWorker {
|
|||||||
region_id,
|
region_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: {} verfügbare Transportmittel",
|
|
||||||
region_id, vehicles.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
if vehicles.is_empty() {
|
if vehicles.is_empty() {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: Keine verfügbaren Transportmittel",
|
|
||||||
region_id
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -994,24 +797,11 @@ impl DirectorWorker {
|
|||||||
let extra_revenue = delta_per_unit * qty as f64;
|
let extra_revenue = delta_per_unit * qty as f64;
|
||||||
let transport_cost = Self::calc_transport_cost(remote_piece_price, qty);
|
let transport_cost = Self::calc_transport_cost(remote_piece_price, qty);
|
||||||
let net_gain = extra_revenue - transport_cost;
|
let net_gain = extra_revenue - transport_cost;
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: extra_revenue={:.2}, transport_cost={:.2}, net_gain={:.2}, qty={}",
|
|
||||||
region_id, extra_revenue, transport_cost, net_gain, qty
|
|
||||||
);
|
|
||||||
|
|
||||||
if net_gain <= 0.0 {
|
if net_gain <= 0.0 {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: Netto-Gewinn <= 0, überspringe",
|
|
||||||
region_id
|
|
||||||
);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if net_gain > best_gain {
|
if net_gain > best_gain {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Region {}: Neuer bester Transport (Gewinn {:.2})",
|
|
||||||
region_id, net_gain
|
|
||||||
);
|
|
||||||
best_gain = net_gain;
|
best_gain = net_gain;
|
||||||
best_target_region = Some(region_id);
|
best_target_region = Some(region_id);
|
||||||
best_quantity = qty;
|
best_quantity = qty;
|
||||||
@@ -1047,10 +837,6 @@ impl DirectorWorker {
|
|||||||
item.quantity = remaining_quantity;
|
item.quantity = remaining_quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Transport geplant: {} Einheiten von Produkt {} von Region {} nach Region {} (Stückpreis lokal {:.2}, remote {:.2}). Inventar reduziert.",
|
|
||||||
shipped, item.product_id, item.region_id, target_region, local_piece_price, best_remote_piece_price
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(shipped)
|
Ok(shipped)
|
||||||
@@ -1075,10 +861,6 @@ impl DirectorWorker {
|
|||||||
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fahrzeuge in Region {} für User {}: {}",
|
|
||||||
source_region, falukant_user_id, vehicle_count
|
|
||||||
);
|
|
||||||
|
|
||||||
// Debug: Prüfe, ob eine Route existiert
|
// Debug: Prüfe, ob eine Route existiert
|
||||||
conn.prepare("check_route", QUERY_CHECK_ROUTE)?;
|
conn.prepare("check_route", QUERY_CHECK_ROUTE)?;
|
||||||
@@ -1093,10 +875,6 @@ impl DirectorWorker {
|
|||||||
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
.and_then(|row| row.get("count").and_then(|v| v.parse::<i32>().ok()))
|
||||||
.unwrap_or(0) > 0;
|
.unwrap_or(0) > 0;
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Route von Region {} nach Region {} existiert: {}",
|
|
||||||
source_region, target_region, route_exists
|
|
||||||
);
|
|
||||||
|
|
||||||
conn.prepare(
|
conn.prepare(
|
||||||
"get_transport_vehicles_for_route",
|
"get_transport_vehicles_for_route",
|
||||||
@@ -1123,10 +901,6 @@ impl DirectorWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Gefundene Transportmittel für Route {} -> {}: {}",
|
|
||||||
source_region, target_region, result.len()
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
@@ -1210,10 +984,6 @@ impl DirectorWorker {
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
if branch_rows.is_empty() {
|
if branch_rows.is_empty() {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Keine anderen Branches für User {} gefunden",
|
|
||||||
falukant_user_id
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1292,9 +1062,6 @@ impl DirectorWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if branches_with_vehicles.is_empty() {
|
if branches_with_vehicles.is_empty() {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Keine Branches mit freien Transportmitteln gefunden"
|
|
||||||
);
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1303,10 +1070,6 @@ impl DirectorWorker {
|
|||||||
|
|
||||||
let (target_branch_id, target_region_id, vehicle_count, price_delta) = branches_with_vehicles[0];
|
let (target_branch_id, target_region_id, vehicle_count, price_delta) = branches_with_vehicles[0];
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Bester Branch für Fahrzeug-Rückholung: Branch {} (Region {}), {} Fahrzeuge, Preisvorteil: {:.2}%",
|
|
||||||
target_branch_id, target_region_id, vehicle_count, price_delta
|
|
||||||
);
|
|
||||||
|
|
||||||
// Hole die Fahrzeuge nochmal für diesen Branch
|
// Hole die Fahrzeuge nochmal für diesen Branch
|
||||||
let vehicles = Self::get_transport_vehicles_for_route(
|
let vehicles = Self::get_transport_vehicles_for_route(
|
||||||
@@ -1326,10 +1089,6 @@ impl DirectorWorker {
|
|||||||
transport_count += 1;
|
transport_count += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] {} leere Transporte geplant: Region {} -> Region {}",
|
|
||||||
transport_count, target_region_id, current_region_id
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1368,9 +1127,6 @@ impl DirectorWorker {
|
|||||||
-(item.income as f64),
|
-(item.income as f64),
|
||||||
"director payed out",
|
"director payed out",
|
||||||
) {
|
) {
|
||||||
eprintln!(
|
|
||||||
"[DirectorWorker] Fehler bei change_falukant_user_money (director payed out): {err}"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conn.execute("set_salary_payed", &[&item.id])?;
|
conn.execute("set_salary_payed", &[&item.id])?;
|
||||||
|
|||||||
@@ -580,6 +580,14 @@ pub const QUERY_COUNT_CHILDREN: &str = r#"
|
|||||||
SELECT COUNT(*) AS cnt FROM falukant_data.child_relation WHERE (father_character_id = $1 OR mother_character_id = $1) AND child_character_id != $2;
|
SELECT COUNT(*) AS cnt FROM falukant_data.child_relation WHERE (father_character_id = $1 OR mother_character_id = $1) AND child_character_id != $2;
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
/// Zählt Kinder eines Users (über alle Charaktere des Users als Elternteil). Ein Parameter: user_id.
|
||||||
|
pub const QUERY_COUNT_CHILDREN_BY_USER: &str = r#"
|
||||||
|
SELECT COUNT(DISTINCT cr.child_character_id) AS cnt
|
||||||
|
FROM falukant_data.child_relation cr
|
||||||
|
JOIN falukant_data.character parent ON (parent.id = cr.father_character_id OR parent.id = cr.mother_character_id)
|
||||||
|
WHERE parent.user_id = $1;
|
||||||
|
"#;
|
||||||
|
|
||||||
// user_character worker queries
|
// user_character worker queries
|
||||||
pub const QUERY_GET_USERS_TO_UPDATE: &str = r#"
|
pub const QUERY_GET_USERS_TO_UPDATE: &str = r#"
|
||||||
SELECT id, CURRENT_DATE - birthdate::date AS age, health
|
SELECT id, CURRENT_DATE - birthdate::date AS age, health
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ use crate::worker::sql::{
|
|||||||
QUERY_GET_SETTLEMENT_VALUE,
|
QUERY_GET_SETTLEMENT_VALUE,
|
||||||
QUERY_GET_INVENTORY_VALUE,
|
QUERY_GET_INVENTORY_VALUE,
|
||||||
QUERY_GET_CREDIT_DEBT,
|
QUERY_GET_CREDIT_DEBT,
|
||||||
QUERY_COUNT_CHILDREN,
|
QUERY_COUNT_CHILDREN_BY_USER,
|
||||||
QUERY_GET_HEIR,
|
QUERY_GET_HEIR,
|
||||||
QUERY_RANDOM_HEIR,
|
QUERY_RANDOM_HEIR,
|
||||||
QUERY_SET_CHARACTER_USER,
|
QUERY_SET_CHARACTER_USER,
|
||||||
@@ -844,8 +844,8 @@ impl UserCharacterWorker {
|
|||||||
.get()
|
.get()
|
||||||
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
.map_err(|e| DbError::new(format!("DB-Verbindung fehlgeschlagen: {e}")))?;
|
||||||
|
|
||||||
conn.prepare("count_children", QUERY_COUNT_CHILDREN)?;
|
conn.prepare("count_children_by_user", QUERY_COUNT_CHILDREN_BY_USER)?;
|
||||||
let rows = conn.execute("count_children", &[&deceased_user_id])?;
|
let rows = conn.execute("count_children_by_user", &[&deceased_user_id])?;
|
||||||
|
|
||||||
Ok(rows
|
Ok(rows
|
||||||
.first()
|
.first()
|
||||||
|
|||||||
Reference in New Issue
Block a user