dolibarr.stundenzettel/debug_netto.php
data 292db5d40c Version 2.0.0: PWA Mobile App + Produktliste-Verbesserungen
PWA (neue Dateien):
- Vollständige Progressive Web App mit Token-basierter Auth
- 4 Swipe-Panels: Alle STZ, Stundenzettel, Produktliste, Lieferauflistung
- Kundensuche, Leistungen-Accordion, Mehraufwand-Sektion
- Produkt-Übernahme aus Auftrag + Mehraufwand in STZ
- Service Worker, Manifest, App-Icons für Installation

Desktop-Änderungen:
- Produktliste: Checkboxen immer sichtbar (außer bereits auf STZ)
- Lieferauflistung: Vereinfachte Ansicht (nur Verbaut-Spalte)
- Admin: PWA-Link in Einstellungen
- Sprachdatei: PWA-Übersetzungen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 21:21:14 +01:00

147 lines
6.4 KiB
PHP
Executable file

<?php
/**
* Debug-Script für Netto STZ Berechnung
* Aufruf: debug_netto.php?order_id=21
*/
// Load Dolibarr environment
$res = 0;
if (!$res && file_exists("../main.inc.php")) $res = @include "../main.inc.php";
if (!$res && file_exists("../../main.inc.php")) $res = @include "../../main.inc.php";
if (!$res) die("Include of main fails");
dol_include_once('/stundenzettel/lib/stundenzettel.lib.php');
$order_id = GETPOST('order_id', 'int');
if (empty($order_id)) {
die("Bitte order_id angeben: debug_netto.php?order_id=XXX");
}
echo "<h2>Debug Netto STZ für Auftrag #".$order_id."</h2>";
// 1. Auftrag und Kunde prüfen
$sqlOrder = "SELECT c.rowid, c.ref, c.fk_soc, s.nom as customer_name FROM ".MAIN_DB_PREFIX."commande c";
$sqlOrder .= " LEFT JOIN ".MAIN_DB_PREFIX."societe s ON s.rowid = c.fk_soc";
$sqlOrder .= " WHERE c.rowid = ".((int)$order_id);
$resqlOrder = $db->query($sqlOrder);
$order = $db->fetch_object($resqlOrder);
echo "<h3>Auftrag</h3>";
echo "<pre>Ref: ".$order->ref."\nKunde: ".$order->customer_name." (ID: ".$order->fk_soc.")</pre>";
// 2. Standard-Leistung des Kunden
$sqlService = "SELECT stundenzettel_default_service FROM ".MAIN_DB_PREFIX."societe_extrafields WHERE fk_object = ".((int)$order->fk_soc);
$resqlService = $db->query($sqlService);
$serviceObj = $db->fetch_object($resqlService);
$defaultServiceId = $serviceObj ? (int)$serviceObj->stundenzettel_default_service : 0;
echo "<h3>Standard-Leistung beim Kunden</h3>";
if ($defaultServiceId > 0) {
$sqlProd = "SELECT rowid, ref, label, price FROM ".MAIN_DB_PREFIX."product WHERE rowid = ".((int)$defaultServiceId);
$resqlProd = $db->query($sqlProd);
$prod = $db->fetch_object($resqlProd);
echo "<pre>Service ID: ".$defaultServiceId."\nRef: ".$prod->ref."\nLabel: ".$prod->label."\nPreis: ".price($prod->price)." EUR</pre>";
// Kundenspezifischer Preis?
$priceInfo = getCustomerPrice($db, $defaultServiceId, $order->fk_soc);
echo "<pre>Effektiver Preis (mit Kundenpreis): ".price($priceInfo['price'])." EUR";
echo " (".($priceInfo['is_customer_price'] ? "Kundenpreis" : "Standardpreis").")</pre>";
} else {
echo "<pre style='color:red'>KEINE Standard-Leistung beim Kunden hinterlegt!</pre>";
}
// 3. Stundenzettel des Auftrags
echo "<h3>Stundenzettel des Auftrags</h3>";
$sqlStz = "SELECT s.rowid, s.ref, s.status, s.hourly_rate, s.hourly_rate_is_custom,";
$sqlStz .= " (SELECT SUM(duration) FROM ".MAIN_DB_PREFIX."stundenzettel_leistung WHERE fk_stundenzettel = s.rowid) as total_minutes";
$sqlStz .= " FROM ".MAIN_DB_PREFIX."stundenzettel s";
$sqlStz .= " WHERE s.fk_commande = ".((int)$order_id);
$resqlStz = $db->query($sqlStz);
echo "<table border='1' cellpadding='5'>";
echo "<tr><th>ID</th><th>Ref</th><th>Status</th><th>Leistungen</th></tr>";
$totalNetto = 0;
while ($stz = $db->fetch_object($resqlStz)) {
$statusText = ($stz->status == 0) ? '<span style="color:orange">Entwurf</span>' : '<span style="color:green">Freigegeben</span>';
// Leistungen dieses Stundenzettels laden
$sqlLeist = "SELECT l.duration, l.fk_product, l.description, p.ref as product_ref, p.label as product_label, p.price as product_price";
$sqlLeist .= " FROM ".MAIN_DB_PREFIX."stundenzettel_leistung l";
$sqlLeist .= " LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = l.fk_product";
$sqlLeist .= " WHERE l.fk_stundenzettel = ".((int)$stz->rowid);
$resqlLeist = $db->query($sqlLeist);
$leistungenHtml = "<table border='1' style='font-size:12px'>";
$leistungenHtml .= "<tr><th>Dauer</th><th>Leistung</th><th>Preis</th><th>Berechnung</th></tr>";
$stzSubtotal = 0;
while ($leist = $db->fetch_object($resqlLeist)) {
$hours = $leist->duration / 60;
$hourlyRate = 0;
$rateSource = "<span style='color:red'>KEINER!</span>";
if ($leist->fk_product > 0) {
$priceInfo = getCustomerPrice($db, $leist->fk_product, $order->fk_soc);
$hourlyRate = $priceInfo['price'];
$rateSource = $leist->product_ref." - ".$leist->product_label;
if ($priceInfo['is_customer_price']) {
$rateSource .= " <span style='color:green'>(Kundenpreis)</span>";
}
} elseif ($stz->hourly_rate > 0) {
$hourlyRate = (float)$stz->hourly_rate;
$rateSource = "Stundenzettel-Rate";
} elseif ($defaultServiceId > 0) {
$priceInfo = getCustomerPrice($db, $defaultServiceId, $order->fk_soc);
$hourlyRate = $priceInfo['price'];
$rateSource = "Kunden-Standard";
}
$subtotal = ($stz->status >= 1) ? ($hourlyRate * $hours) : 0;
if ($stz->status >= 1) {
$stzSubtotal += $subtotal;
}
$calcText = ($stz->status >= 1)
? price($hourlyRate)." x ".$hours."h = <b>".price($subtotal)."</b>"
: "<i>Nicht freigegeben</i>";
$leistungenHtml .= "<tr>";
$leistungenHtml .= "<td>".$hours."h</td>";
$leistungenHtml .= "<td>".$rateSource."</td>";
$leistungenHtml .= "<td>".price($hourlyRate)." EUR</td>";
$leistungenHtml .= "<td>".$calcText."</td>";
$leistungenHtml .= "</tr>";
}
$leistungenHtml .= "<tr><td colspan='3'><b>Summe:</b></td><td><b>".price($stzSubtotal)." EUR</b></td></tr>";
$leistungenHtml .= "</table>";
$totalNetto += $stzSubtotal;
echo "<tr>";
echo "<td>".$stz->rowid."</td>";
echo "<td>".$stz->ref."</td>";
echo "<td>".$statusText."</td>";
echo "<td>".$leistungenHtml."</td>";
echo "</tr>";
}
echo "</table>";
echo "<h3>Ergebnis</h3>";
echo "<pre style='font-size:18px; color:blue'>Berechneter Netto STZ: <b>".price($totalNetto)." EUR</b></pre>";
// 4. Aktueller Wert in der Datenbank
$sqlCurrent = "SELECT stundenzettel_netto FROM ".MAIN_DB_PREFIX."commande_extrafields WHERE fk_object = ".((int)$order_id);
$resqlCurrent = $db->query($sqlCurrent);
$current = $db->fetch_object($resqlCurrent);
$currentValue = $current ? $current->stundenzettel_netto : "NICHT GESETZT";
echo "<pre>Aktueller Wert in DB: ".($currentValue !== "NICHT GESETZT" ? price($currentValue)." EUR" : $currentValue)."</pre>";
echo "<hr><p><a href='debug_netto.php?order_id=".$order_id."&update=1'>Jetzt neu berechnen und speichern</a></p>";
if (GETPOST('update', 'int')) {
$result = updateOrderNettoSTZ($db, $order_id);
echo "<p style='color:green; font-weight:bold'>Berechnung durchgeführt! Ergebnis: ".price($result)." EUR</p>";
echo "<p><a href='debug_netto.php?order_id=".$order_id."'>Seite neu laden</a></p>";
}