diff --git a/card.php b/card.php index 7dc17f8..eba1166 100644 --- a/card.php +++ b/card.php @@ -13,6 +13,7 @@ if (!$res) die("Include of main fails"); require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; +require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; dol_include_once('/stundenzettel/class/stundenzettel.class.php'); @@ -233,8 +234,9 @@ if ($action == 'add_leistung' && $permissiontoadd) { $time_start = GETPOST('time_start', 'alpha'); $time_end = GETPOST('time_end', 'alpha'); $description = GETPOST('leistung_description', 'restricthtml'); + $fk_product = GETPOST('fk_product', 'int'); - $result = $object->addLeistung($user, $date, $time_start, $time_end, $description); + $result = $object->addLeistung($user, $date, $time_start, $time_end, $description, $fk_product); if ($result > 0) { setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); } else { @@ -259,8 +261,9 @@ if ($action == 'update_leistung' && $permissiontoadd) { $time_start = GETPOST('time_start', 'alpha'); $time_end = GETPOST('time_end', 'alpha'); $description = GETPOST('leistung_description', 'restricthtml'); + $fk_product = GETPOST('fk_product', 'int'); - $result = $object->updateLeistung($leistung_id, $date, $time_start, $time_end, $description); + $result = $object->updateLeistung($leistung_id, $date, $time_start, $time_end, $description, $fk_product); if ($result > 0) { setEventMessages($langs->trans('RecordModified'), null, 'mesgs'); } else { @@ -423,16 +426,31 @@ if ($action == 'add_product' && $permissiontoadd) { exit; } -// Entfällt hinzufügen (Produkt aus Auftrag das nicht verbaut wird) +// Entfällt hinzufügen (Produkt aus Auftrag oder Mehraufwand das nicht verbaut wird) if ($action == 'add_entfaellt' && $permissiontoadd) { $entfaellt_product_raw = GETPOST('entfaellt_product', 'alpha'); $qty = GETPOST('entfaellt_qty', 'int'); $reason = GETPOST('entfaellt_description', 'restricthtml'); - // Prüfen ob es ein Freitext-Produkt ist (Format: "freetext_ROWID") + // Prüfen ob es ein Freitext-Produkt, Mehraufwand oder normales Produkt ist $fk_product = 0; $freetext_description = ''; - if (strpos($entfaellt_product_raw, 'freetext_') === 0) { + $commandedet_id = 0; + $mehraufwand_id = 0; + + if (strpos($entfaellt_product_raw, 'mehraufwand_') === 0) { + // Mehraufwand-Produkt (Format: "mehraufwand_ROWID") + $mehraufwand_id = (int)substr($entfaellt_product_raw, 12); + // Produkt-ID und Beschreibung aus stundenzettel_product laden + $sqlMehr = "SELECT fk_product, description FROM ".MAIN_DB_PREFIX."stundenzettel_product WHERE rowid = ".((int)$mehraufwand_id); + $resqlMehr = $db->query($sqlMehr); + if ($resqlMehr && ($objMehr = $db->fetch_object($resqlMehr))) { + $fk_product = (int)$objMehr->fk_product; + if ($fk_product == 0) { + $freetext_description = $objMehr->description; + } + } + } elseif (strpos($entfaellt_product_raw, 'freetext_') === 0) { // Freitext-Produkt aus dem Auftrag $commandedet_id = (int)substr($entfaellt_product_raw, 9); // Beschreibung aus commandedet laden @@ -455,7 +473,18 @@ if ($action == 'add_entfaellt' && $permissiontoadd) { if ($fk_product > 0 || !empty($freetext_description)) { // Server-seitige Validierung: Prüfen ob Menge noch verfügbar ist - if ($object->fk_commande > 0) { + if ($mehraufwand_id > 0) { + // Mehraufwand-Validierung: Prüfe verfügbare Menge + $sqlCheck = "SELECT qty, qty_done FROM ".MAIN_DB_PREFIX."stundenzettel_product WHERE rowid = ".((int)$mehraufwand_id); + $resqlCheck = $db->query($sqlCheck); + if ($resqlCheck && ($objCheck = $db->fetch_object($resqlCheck))) { + $qty_available = $objCheck->qty - $objCheck->qty_done; + if ($qty > $qty_available) { + setEventMessages($langs->trans('ErrorQtyExceedsAvailable', $qty_available), null, 'errors'); + $error++; + } + } + } elseif ($object->fk_commande > 0) { if ($fk_product > 0) { // Produkt-Validierung $sqlCheck = "SELECT cd.qty,"; @@ -503,20 +532,49 @@ if ($action == 'add_entfaellt' && $permissiontoadd) { } if (!$error) { - // Produkt zum Stundenzettel hinzufügen mit origin='omitted' - $result = $object->addProduct( - $fk_product, - 0, // fk_commandedet - 0, // fk_manager_line - 0, // qty_original - $qty, // qty_done (Menge die entfällt) - 'omitted', // origin (entfällt) - $description // description (Grund) - ); - if ($result > 0) { - setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); + if ($mehraufwand_id > 0) { + // Mehraufwand: Menge vom qty_done erhöhen statt neuen Eintrag erstellen + // Oder: Menge vom Mehraufwand reduzieren und als Entfällt anlegen + // Wir reduzieren qty des Mehraufwands und legen einen neuen Entfällt-Eintrag an + $sqlUpdateMehr = "UPDATE ".MAIN_DB_PREFIX."stundenzettel_product SET qty = qty - ".((int)$qty); + $sqlUpdateMehr .= " WHERE rowid = ".((int)$mehraufwand_id); + $db->query($sqlUpdateMehr); + + // Entfällt-Eintrag mit Hinweis auf Mehraufwand anlegen + $entfaelltDesc = $langs->trans("Mehraufwand").': '.$description; + if (!empty($reason)) { + $entfaelltDesc .= ' - '.$reason; + } + $result = $object->addProduct( + $fk_product, + 0, // fk_commandedet + 0, // fk_manager_line + 0, // qty_original + $qty, // qty_done (Menge die entfällt) + 'omitted', // origin (entfällt) + $entfaelltDesc // description (Grund) + ); + if ($result > 0) { + setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); + } else { + setEventMessages($object->error, null, 'errors'); + } } else { - setEventMessages($object->error, null, 'errors'); + // Produkt zum Stundenzettel hinzufügen mit origin='omitted' + $result = $object->addProduct( + $fk_product, + 0, // fk_commandedet + 0, // fk_manager_line + 0, // qty_original + $qty, // qty_done (Menge die entfällt) + 'omitted', // origin (entfällt) + $description // description (Grund) + ); + if ($result > 0) { + setEventMessages($langs->trans('RecordSaved'), null, 'mesgs'); + } else { + setEventMessages($object->error, null, 'errors'); + } } } } else { @@ -724,6 +782,9 @@ $_GET['mainmenu'] = 'stundenzettel'; llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-stundenzettel page-card'); +// Mobile CSS einbinden +print ''; + // JavaScript für Mengenprüfung print ''; + // ============================================= + // BEREICH: LEISTUNGEN / ARBEITSZEITEN + // ============================================= + print '
'; + print '
'.$langs->trans("Leistungen").' / '.$langs->trans("TotalHours").'
'; + + // Leistungen nach Leistungsposition gruppiert laden + $sqlLeistungen = "SELECT "; + $sqlLeistungen .= " COALESCE(l.fk_product, 0) as service_id,"; + $sqlLeistungen .= " p.ref as service_ref, p.label as service_label,"; + $sqlLeistungen .= " SUM(l.duration) as total_minutes,"; + $sqlLeistungen .= " COUNT(l.rowid) as entry_count"; + $sqlLeistungen .= " FROM ".MAIN_DB_PREFIX."stundenzettel_leistung l"; + $sqlLeistungen .= " JOIN ".MAIN_DB_PREFIX."stundenzettel s ON s.rowid = l.fk_stundenzettel"; + $sqlLeistungen .= " LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = l.fk_product"; + $sqlLeistungen .= " WHERE s.fk_commande = ".((int)$order->id); + $sqlLeistungen .= " GROUP BY COALESCE(l.fk_product, 0), p.ref, p.label"; + $sqlLeistungen .= " ORDER BY p.ref, p.label"; + + $resqlLeistungen = $db->query($sqlLeistungen); + $totalMinutesAll = 0; + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + if ($resqlLeistungen) { + $numLeistungen = $db->num_rows($resqlLeistungen); + if ($numLeistungen > 0) { + while ($objL = $db->fetch_object($resqlLeistungen)) { + $totalMinutesAll += $objL->total_minutes; + $hours = floor($objL->total_minutes / 60); + $mins = $objL->total_minutes % 60; + + print ''; + + // Leistungsposition + print ''; + + // Stunden + print ''; + + // Anzahl Einträge + print ''; + + print ''; + } + + // Summenzeile + $totalHours = floor($totalMinutesAll / 60); + $totalMins = $totalMinutesAll % 60; + print ''; + print ''; + print ''; + print ''; + print ''; + + } else { + print ''; + } + } + + print '
'.$langs->trans("DefaultService").''.$langs->trans("TotalHours").''.$langs->trans("Entries").'
'; + if ($objL->service_id > 0) { + print ''; + print img_picto('', 'service', 'class="pictofixedwidth"'); + print $objL->service_ref.' - '.$objL->service_label; + print ''; + } else { + print ''.img_picto('', 'service', 'class="pictofixedwidth"').$langs->trans("NotSet").''; + } + print ''.sprintf('%d:%02d h', $hours, $mins).''.$objL->entry_count.'
'.$langs->trans("Total").''.sprintf('%d:%02d h', $totalHours, $totalMins).'
'.$langs->trans("NoRecordFound").'
'; + print '
'; + + // Details pro Stundenzettel + print '
'; + print '
'.$langs->trans("Leistungen").' '.$langs->trans("perStundenzettel").'
'; + + $sqlLeistDetail = "SELECT l.rowid, l.fk_stundenzettel, l.fk_product, l.date_leistung,"; + $sqlLeistDetail .= " l.time_start, l.time_end, l.duration, l.description,"; + $sqlLeistDetail .= " s.ref as stz_ref, s.date_stundenzettel,"; + $sqlLeistDetail .= " p.ref as service_ref, p.label as service_label"; + $sqlLeistDetail .= " FROM ".MAIN_DB_PREFIX."stundenzettel_leistung l"; + $sqlLeistDetail .= " JOIN ".MAIN_DB_PREFIX."stundenzettel s ON s.rowid = l.fk_stundenzettel"; + $sqlLeistDetail .= " LEFT JOIN ".MAIN_DB_PREFIX."product p ON p.rowid = l.fk_product"; + $sqlLeistDetail .= " WHERE s.fk_commande = ".((int)$order->id); + $sqlLeistDetail .= " ORDER BY s.date_stundenzettel DESC, l.date_leistung, l.time_start"; + + $resqlLeistDetail = $db->query($sqlLeistDetail); + + print '
'; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + print ''; + + if ($resqlLeistDetail) { + $numDetail = $db->num_rows($resqlLeistDetail); + if ($numDetail > 0) { + while ($objLD = $db->fetch_object($resqlLeistDetail)) { + $hours = floor($objLD->duration / 60); + $mins = $objLD->duration % 60; + + print ''; + + // Stundenzettel + print ''; + + // Datum + print ''; + + // Zeit + print ''; + + // Dauer + print ''; + + // Leistungsposition + print ''; + + // Beschreibung + print ''; + + print ''; + } + } else { + print ''; + } + } + + print '
'.$langs->trans("Stundenzettel").''.$langs->trans("Date").''.$langs->trans("LeistungTimeStart").' - '.$langs->trans("LeistungTimeEnd").''.$langs->trans("LeistungDuration").''.$langs->trans("DefaultService").''.$langs->trans("Description").'
'; + print ''; + print $objLD->stz_ref; + print ''; + print ''.dol_print_date($db->jdate($objLD->date_leistung), 'day').''; + if ($objLD->time_start && $objLD->time_end) { + print substr($objLD->time_start, 0, 5).' - '.substr($objLD->time_end, 0, 5); + } else { + print '-'; + } + print ''.sprintf('%d:%02d h', $hours, $mins).''; + if ($objLD->fk_product > 0) { + print ''.$objLD->service_ref.''; + } else { + print '-'; + } + print ''; + if (!empty($objLD->description)) { + $desc = strip_tags($objLD->description); + if (strlen($desc) > 50) $desc = substr($desc, 0, 47).'...'; + print dol_escape_htmltag($desc); + } else { + print '-'; + } + print '
'.$langs->trans("NoRecordFound").'
'; + print '
'; + print '
'; // fichehalfleft + // Button: In Rechnung übertragen (nur wenn alles erledigt) if ($total_remaining <= 0 && $total_delivered > 0) { - print '
'; + print '
'; print ''; print img_picto('', 'bill', 'class="pictofixedwidth"').$langs->trans("TransferToInvoice"); print '';