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>
229 lines
8.9 KiB
PHP
Executable file
229 lines
8.9 KiB
PHP
Executable file
<?php
|
|
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
|
|
*
|
|
* Stundenzettel - Liste
|
|
*/
|
|
|
|
// 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 && file_exists("../../../main.inc.php")) $res = @include "../../../main.inc.php";
|
|
if (!$res) die("Include of main fails");
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
|
|
dol_include_once('/stundenzettel/class/stundenzettel.class.php');
|
|
|
|
// Load translation files
|
|
$langs->loadLangs(array("stundenzettel@stundenzettel", "orders"));
|
|
|
|
// Security check
|
|
if (!$user->hasRight('stundenzettel', 'read')) {
|
|
accessforbidden();
|
|
}
|
|
|
|
// Berechtigungen prüfen
|
|
$permissiontoreadall = $user->hasRight('stundenzettel', 'read', 'all') || $user->admin;
|
|
$permissiontowriteall = $user->hasRight('stundenzettel', 'write', 'all') || $user->admin;
|
|
$permissiontodeleteall = $user->hasRight('stundenzettel', 'delete', 'all') || $user->admin;
|
|
|
|
// Get parameters
|
|
$action = GETPOST('action', 'aZ09');
|
|
$massaction = GETPOST('massaction', 'alpha');
|
|
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'stundenzettellist';
|
|
|
|
$search_ref = GETPOST('search_ref', 'alpha');
|
|
$search_order = GETPOST('search_order', 'alpha');
|
|
$search_soc = GETPOST('search_soc', 'alpha');
|
|
$search_status = GETPOST('search_status', 'int');
|
|
$search_author = GETPOST('search_author', 'int');
|
|
|
|
// __USER_ID__ ersetzen falls verwendet
|
|
if ($search_author == '__USER_ID__' || GETPOST('search_author', 'alpha') == '__USER_ID__') {
|
|
$search_author = $user->id;
|
|
}
|
|
|
|
$sortfield = GETPOST('sortfield', 'aZ09comma');
|
|
$sortorder = GETPOST('sortorder', 'aZ09comma');
|
|
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
|
|
if (empty($page) || $page < 0) $page = 0;
|
|
$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
|
|
$offset = $limit * $page;
|
|
|
|
if (!$sortfield) $sortfield = 's.date_stundenzettel';
|
|
if (!$sortorder) $sortorder = 'DESC';
|
|
|
|
// Build SQL
|
|
$sql = "SELECT s.rowid, s.ref, s.date_stundenzettel, s.status, s.fk_commande, s.fk_soc,";
|
|
$sql .= " c.ref as order_ref, soc.nom as soc_name";
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."stundenzettel as s";
|
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."commande as c ON c.rowid = s.fk_commande";
|
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as soc ON soc.rowid = s.fk_soc";
|
|
$sql .= " WHERE s.entity = ".((int)$conf->entity);
|
|
|
|
if ($search_ref) {
|
|
$sql .= natural_search('s.ref', $search_ref);
|
|
}
|
|
if ($search_order) {
|
|
$sql .= natural_search('c.ref', $search_order);
|
|
}
|
|
if ($search_soc) {
|
|
$sql .= natural_search('soc.nom', $search_soc);
|
|
}
|
|
if ($search_status !== '' && $search_status >= 0) {
|
|
$sql .= " AND s.status = ".((int)$search_status);
|
|
}
|
|
if ($search_author > 0) {
|
|
$sql .= " AND s.fk_user_author = ".((int)$search_author);
|
|
}
|
|
|
|
// Einschränkung auf eigene Stundenzettel, wenn keine Berechtigung für alle
|
|
if (!$permissiontoreadall) {
|
|
$sql .= " AND s.fk_user_author = ".((int)$user->id);
|
|
}
|
|
|
|
$sql .= $db->order($sortfield, $sortorder);
|
|
|
|
// Count total
|
|
$nbtotalofrecords = '';
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
$nbtotalofrecords = $db->num_rows($resql);
|
|
}
|
|
|
|
$sql .= $db->plimit($limit + 1, $offset);
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$form = new Form($db);
|
|
$formother = new FormOther($db);
|
|
$objectstatic = new Stundenzettel($db);
|
|
|
|
$title = $langs->trans("StundenzettelList");
|
|
|
|
// Linkes Menü aktivieren
|
|
$_GET['mainmenu'] = 'stundenzettel';
|
|
|
|
llxHeader('', $title, '', '', 0, 0, '', '', '', 'mod-stundenzettel page-list');
|
|
|
|
$param = '';
|
|
if ($search_ref) $param .= '&search_ref='.urlencode($search_ref);
|
|
if ($search_order) $param .= '&search_order='.urlencode($search_order);
|
|
if ($search_soc) $param .= '&search_soc='.urlencode($search_soc);
|
|
if ($search_status !== '') $param .= '&search_status='.urlencode($search_status);
|
|
if ($search_author > 0) $param .= '&search_author='.urlencode($search_author);
|
|
|
|
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" name="formfilter">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
|
|
$newcardbutton = '';
|
|
if ($user->hasRight('stundenzettel', 'write')) {
|
|
$newcardbutton = '<a class="butActionNew" href="'.dol_buildpath('/stundenzettel/card.php?action=create', 1).'">';
|
|
$newcardbutton .= '<span class="fa fa-plus-circle valignmiddle"></span>';
|
|
$newcardbutton .= '</a>';
|
|
}
|
|
|
|
print_barre_liste($title, $page, $_SERVER['PHP_SELF'], $param, $sortfield, $sortorder, '', $nbtotalofrecords, $nbtotalofrecords, 'clock', 0, $newcardbutton, '', $limit);
|
|
|
|
print '<div class="div-table-responsive-no-min">';
|
|
print '<table class="tagtable nobottomiftotal liste">';
|
|
|
|
// Header
|
|
print '<tr class="liste_titre_filter">';
|
|
print '<td class="liste_titre"><input type="text" class="flat" name="search_ref" value="'.dol_escape_htmltag($search_ref).'" size="10"></td>';
|
|
print '<td class="liste_titre"></td>';
|
|
print '<td class="liste_titre"><input type="text" class="flat" name="search_order" value="'.dol_escape_htmltag($search_order).'" size="10"></td>';
|
|
print '<td class="liste_titre"><input type="text" class="flat" name="search_soc" value="'.dol_escape_htmltag($search_soc).'" size="15"></td>';
|
|
print '<td class="liste_titre center">';
|
|
print '<select name="search_status" class="flat">';
|
|
print '<option value="">--</option>';
|
|
print '<option value="0"'.($search_status === '0' ? ' selected' : '').'>'.$langs->trans("StatusDraft").'</option>';
|
|
print '<option value="1"'.($search_status === '1' ? ' selected' : '').'>'.$langs->trans("StatusValidated").'</option>';
|
|
print '<option value="2"'.($search_status === '2' ? ' selected' : '').'>'.$langs->trans("StatusInvoiced").'</option>';
|
|
print '</select>';
|
|
print '</td>';
|
|
print '<td class="liste_titre center">';
|
|
print '<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"), 'search.png', '', '', 1).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
|
|
print '<input type="image" class="liste_titre" name="button_removefilter" src="'.img_picto($langs->trans("RemoveFilter"), 'searchclear.png', '', '', 1).'" title="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'">';
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
print '<tr class="liste_titre">';
|
|
print_liste_field_titre("Ref", $_SERVER['PHP_SELF'], "s.ref", "", $param, "", $sortfield, $sortorder);
|
|
print_liste_field_titre("Date", $_SERVER['PHP_SELF'], "s.date_stundenzettel", "", $param, "", $sortfield, $sortorder);
|
|
print_liste_field_titre("Order", $_SERVER['PHP_SELF'], "c.ref", "", $param, "", $sortfield, $sortorder);
|
|
print_liste_field_titre("Customer", $_SERVER['PHP_SELF'], "soc.nom", "", $param, "", $sortfield, $sortorder);
|
|
print_liste_field_titre("Status", $_SERVER['PHP_SELF'], "s.status", "", $param, "", $sortfield, $sortorder, 'center ');
|
|
print_liste_field_titre("", $_SERVER['PHP_SELF'], "", "", $param, "", $sortfield, $sortorder, 'center ');
|
|
print '</tr>';
|
|
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
$num = $db->num_rows($resql);
|
|
$i = 0;
|
|
|
|
while ($i < min($num, $limit)) {
|
|
$obj = $db->fetch_object($resql);
|
|
|
|
print '<tr class="oddeven">';
|
|
|
|
// Ref
|
|
print '<td>';
|
|
print '<a href="'.dol_buildpath('/stundenzettel/card.php?id='.$obj->rowid, 1).'">';
|
|
print img_picto('', 'clock', 'class="pictofixedwidth"').$obj->ref;
|
|
print '</a>';
|
|
print '</td>';
|
|
|
|
// Datum
|
|
print '<td>'.dol_print_date($db->jdate($obj->date_stundenzettel), 'day').'</td>';
|
|
|
|
// Auftrag
|
|
print '<td>';
|
|
if ($obj->order_ref) {
|
|
print '<a href="'.DOL_URL_ROOT.'/commande/card.php?id='.$obj->fk_commande.'">';
|
|
print img_picto('', 'order', 'class="pictofixedwidth"').$obj->order_ref;
|
|
print '</a>';
|
|
}
|
|
print '</td>';
|
|
|
|
// Kunde
|
|
print '<td>';
|
|
if ($obj->soc_name) {
|
|
print '<a href="'.DOL_URL_ROOT.'/societe/card.php?socid='.$obj->fk_soc.'">';
|
|
print $obj->soc_name;
|
|
print '</a>';
|
|
}
|
|
print '</td>';
|
|
|
|
// Status
|
|
print '<td class="center">'.$objectstatic->LibStatut($obj->status, 5).'</td>';
|
|
|
|
// Actions
|
|
print '<td class="center nowraponall">';
|
|
if ($obj->fk_commande > 0) {
|
|
print '<a style="display:inline-block;margin-right:10px;" href="'.dol_buildpath('/stundenzettel/stundenzettel_commande.php?id='.$obj->fk_commande.'&tab=products&noredirect=1', 1).'" title="Stundenzettel bearbeiten">'.img_picto('Stundenzettel bearbeiten', 'edit').'</a>';
|
|
}
|
|
print '<a href="'.dol_buildpath('/stundenzettel/card.php?id='.$obj->rowid, 1).'">'.img_picto($langs->trans("View"), 'eye').'</a>';
|
|
print '</td>';
|
|
|
|
print '</tr>';
|
|
$i++;
|
|
}
|
|
|
|
if ($num == 0) {
|
|
print '<tr class="oddeven"><td colspan="6" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
|
|
}
|
|
|
|
$db->free($resql);
|
|
} else {
|
|
dol_print_error($db);
|
|
}
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
print '</form>';
|
|
|
|
llxFooter();
|
|
$db->close();
|