dolibarr.stundenzettel/admin/setup.php
data dabcdbde13 Version 2.1.0: Rechnungsübernahme erweitert
- Neuer Button "Ohne Produktgruppen" für flache Übernahme ohne Sections/Zwischensummen
- Mehraufwand-Produktgruppe über Modul-Einstellung konfigurierbar
- Standard-Bankkonto wird automatisch aus Einstellung gesetzt
- "Ihr Zeichen" (ref_client) vom Auftrag übernommen
- Extrafelder Angebotsnummer/Auftragsnummer vom Auftrag kopiert
- Verwaiste Zwischensummen werden nach Rechnungserstellung bereinigt
- Zwei neue Modul-Einstellungen: Bankkonto und Mehraufwand-Sektion

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 18:39:37 +01:00

318 lines
14 KiB
PHP
Executable file

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* Stundenzettel - Modulkonfiguration
*/
// Load Dolibarr environment
$res = 0;
// Von /custom/stundenzettel/admin/ zu /main.inc.php = 3 Ebenen hoch
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/lib/admin.lib.php';
// Load translation files
$langs->loadLangs(array("admin", "stundenzettel@stundenzettel"));
// Access control
if (!$user->admin) {
accessforbidden();
}
$action = GETPOST('action', 'aZ09');
/*
* Actions
*/
if ($action == 'setTIME_INPUT_MODE') {
$value = GETPOST('value', 'alpha');
if (dolibarr_set_const($db, 'STUNDENZETTEL_TIME_INPUT_MODE', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
if ($action == 'setDEFAULT_FILTER') {
$value = GETPOST('filter_value', 'alpha');
if (dolibarr_set_const($db, 'STUNDENZETTEL_DEFAULT_FILTER', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
if ($action == 'setDEFAULT_DATE') {
$value = GETPOST('date_value', 'alpha');
if (dolibarr_set_const($db, 'STUNDENZETTEL_DEFAULT_DATE', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
if ($action == 'setINVOICE_HOURS_MODE') {
$value = GETPOST('hours_mode_value', 'alpha');
if (dolibarr_set_const($db, 'STUNDENZETTEL_INVOICE_HOURS_MODE', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
if ($action == 'setDEFAULT_SECTIONS') {
$sections = GETPOST('default_sections', 'array');
$value = implode(',', $sections);
if (dolibarr_set_const($db, 'STUNDENZETTEL_DEFAULT_SECTIONS', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
if ($action == 'setINVOICE_BANK_ACCOUNT') {
$value = GETPOST('bank_account_value', 'int');
if (dolibarr_set_const($db, 'STUNDENZETTEL_INVOICE_BANK_ACCOUNT', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
if ($action == 'setINVOICE_MEHRAUFWAND_SECTION') {
$value = GETPOST('mehraufwand_section_value', 'alpha');
if (dolibarr_set_const($db, 'STUNDENZETTEL_INVOICE_MEHRAUFWAND_SECTION', $value, 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
} else {
setEventMessages($langs->trans("Error"), null, 'errors');
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
/*
* View
*/
$page_name = "StundenzettelSetup";
llxHeader('', $langs->trans($page_name), '');
// Subheader
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup');
// Configuration header
$head = array();
$h = 0;
$head[$h][0] = $_SERVER["PHP_SELF"];
$head[$h][1] = $langs->trans("Settings");
$head[$h][2] = 'settings';
$h++;
print dol_get_fiche_head($head, 'settings', $langs->trans("Stundenzettel"), -1, 'clock');
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th class="titlefield">'.$langs->trans("Parameter").'</th>';
print '<th style="width: 300px;">'.$langs->trans("Value").'</th>';
print '<th class="right" style="width: 100px;"></th>';
print '</tr>';
// Zeiteingabe-Modus
$currentMode = getDolGlobalString('STUNDENZETTEL_TIME_INPUT_MODE', 'dropdown');
print '<tr class="oddeven">';
print '<td>'.$langs->trans("TimeInputMode").'</td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setTIME_INPUT_MODE">';
print '<select name="value" class="flat minwidth200">';
print '<option value="dropdown"'.($currentMode == 'dropdown' ? ' selected' : '').'>'.$langs->trans("TimeInputDropdown").'</option>';
print '<option value="text"'.($currentMode == 'text' ? ' selected' : '').'>'.$langs->trans("TimeInputText").'</option>';
print '</select>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
// Standard-Filter
$currentFilter = getDolGlobalString('STUNDENZETTEL_DEFAULT_FILTER', 'open');
print '<tr class="oddeven">';
print '<td>'.$langs->trans("DefaultFilter").'<br><small class="opacitymedium">'.$langs->trans("DefaultFilterDesc").'</small></td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setDEFAULT_FILTER">';
print '<select name="filter_value" class="flat minwidth200">';
print '<option value="open"'.($currentFilter == 'open' ? ' selected' : '').'>'.$langs->trans("FilterOpen").'</option>';
print '<option value="done"'.($currentFilter == 'done' ? ' selected' : '').'>'.$langs->trans("FilterDone").'</option>';
print '<option value="all"'.($currentFilter == 'all' ? ' selected' : '').'>'.$langs->trans("FilterAll").'</option>';
print '</select>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
// Standard-Datum für Stundenzettel
$currentDate = getDolGlobalString('STUNDENZETTEL_DEFAULT_DATE', 'today');
print '<tr class="oddeven">';
print '<td>'.$langs->trans("DefaultDate").'<br><small class="opacitymedium">'.$langs->trans("DefaultDateDesc").'</small></td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setDEFAULT_DATE">';
print '<select name="date_value" class="flat minwidth200">';
print '<option value="today"'.($currentDate == 'today' ? ' selected' : '').'>'.$langs->trans("DateToday").'</option>';
print '<option value="last_open"'.($currentDate == 'last_open' ? ' selected' : '').'>'.$langs->trans("DateLastOpen").'</option>';
print '</select>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
// Stunden-Übernahme Modus
$currentHoursMode = getDolGlobalString('STUNDENZETTEL_INVOICE_HOURS_MODE', 'total');
print '<tr class="oddeven">';
print '<td>'.$langs->trans("InvoiceHoursMode").'<br><small class="opacitymedium">'.$langs->trans("SelectInvoiceHoursMode").'</small></td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setINVOICE_HOURS_MODE">';
print '<select name="hours_mode_value" class="flat minwidth200">';
print '<option value="total"'.($currentHoursMode == 'total' ? ' selected' : '').'>'.$langs->trans("InvoiceHoursModeTotal").'</option>';
print '<option value="perday"'.($currentHoursMode == 'perday' ? ' selected' : '').'>'.$langs->trans("InvoiceHoursModePerDay").'</option>';
print '</select>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
// Standard-Bereiche anzeigen
$currentSections = getDolGlobalString('STUNDENZETTEL_DEFAULT_SECTIONS', '');
$selectedSections = !empty($currentSections) ? explode(',', $currentSections) : array();
print '<tr class="oddeven">';
print '<td>'.$langs->trans("DefaultSections").'<br><small class="opacitymedium">'.$langs->trans("DefaultSectionsDesc").'</small></td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setDEFAULT_SECTIONS">';
print '<div style="display: flex; flex-direction: column; gap: 5px;">';
print '<label><input type="checkbox" name="default_sections[]" value="entfaellt"'.(in_array('entfaellt', $selectedSections) ? ' checked' : '').'> '.$langs->trans("Entfaellt").'</label>';
print '<label><input type="checkbox" name="default_sections[]" value="mehraufwand"'.(in_array('mehraufwand', $selectedSections) ? ' checked' : '').'> '.$langs->trans("Mehraufwand").'</label>';
print '<label><input type="checkbox" name="default_sections[]" value="ruecknahme"'.(in_array('ruecknahme', $selectedSections) ? ' checked' : '').'> '.$langs->trans("Ruecknahme").'</label>';
print '<label><input type="checkbox" name="default_sections[]" value="merkzettel"'.(in_array('merkzettel', $selectedSections) ? ' checked' : '').'> '.$langs->trans("NotesMemo").'</label>';
print '</div>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
print '</table>';
// Rechnungsübernahme-Einstellungen
print '<br>';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th class="titlefield">'.$langs->trans("InvoiceTransferSettings").'</th>';
print '<th style="width: 300px;">'.$langs->trans("Value").'</th>';
print '<th class="right" style="width: 100px;"></th>';
print '</tr>';
// Bankkonto für Rechnungen
$currentBankAccount = getDolGlobalString('STUNDENZETTEL_INVOICE_BANK_ACCOUNT', '0');
$sqlBankAccounts = "SELECT rowid, ref, label FROM ".MAIN_DB_PREFIX."bank_account WHERE clos = 0 ORDER BY label";
$resqlBank = $db->query($sqlBankAccounts);
print '<tr class="oddeven">';
print '<td>'.$langs->trans("InvoiceBankAccount").'<br><small class="opacitymedium">'.$langs->trans("InvoiceBankAccountDesc").'</small></td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setINVOICE_BANK_ACCOUNT">';
print '<select name="bank_account_value" class="flat minwidth200">';
print '<option value="0">'.$langs->trans("None").'</option>';
if ($resqlBank) {
while ($objBank = $db->fetch_object($resqlBank)) {
$selected = ($currentBankAccount == $objBank->rowid) ? ' selected' : '';
print '<option value="'.$objBank->rowid.'"'.$selected.'>'.dol_escape_htmltag($objBank->label.' ('.$objBank->ref.')').'</option>';
}
}
print '</select>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
// Mehraufwand als Produktgruppe
$currentMehraufwandSection = getDolGlobalString('STUNDENZETTEL_INVOICE_MEHRAUFWAND_SECTION', '1');
print '<tr class="oddeven">';
print '<td>'.$langs->trans("InvoiceMehraufwandSection").'<br><small class="opacitymedium">'.$langs->trans("InvoiceMehraufwandSectionDesc").'</small></td>';
print '<td>';
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'" style="display: inline;">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="setINVOICE_MEHRAUFWAND_SECTION">';
print '<select name="mehraufwand_section_value" class="flat minwidth200">';
print '<option value="1"'.($currentMehraufwandSection == '1' ? ' selected' : '').'>'.$langs->trans("Yes").'</option>';
print '<option value="0"'.($currentMehraufwandSection == '0' ? ' selected' : '').'>'.$langs->trans("No").'</option>';
print '</select>';
print '</td>';
print '<td class="right">';
print '<input type="submit" class="button small" value="'.$langs->trans("Modify").'">';
print '</form>';
print '</td>';
print '</tr>';
print '</table>';
// PWA Mobile App Bereich
print '<br>';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th class="titlefield">'.$langs->trans("PWAMobileApp").'</th>';
print '<th style="width: 300px;">'.$langs->trans("Value").'</th>';
print '<th class="right" style="width: 100px;"></th>';
print '</tr>';
$pwaUrl = dol_buildpath('/stundenzettel/pwa.php', 2);
print '<tr class="oddeven">';
print '<td>'.$langs->trans("PWADescription").'<br><small class="opacitymedium">'.$langs->trans("PWAInstallHint").'</small></td>';
print '<td>';
print '<a href="'.$pwaUrl.'" target="_blank" class="butAction small" style="display: inline-block; text-decoration: none;">';
print $langs->trans("PWALink").' &#8599;';
print '</a>';
print '</td>';
print '<td></td>';
print '</tr>';
print '</table>';
print dol_get_fiche_end();
llxFooter();
$db->close();