Widget offene Rechnungen: Zaehler im Kopf + konfigurierbare Zeilenanzahl [deploy]
All checks were successful
Deploy mahnung / deploy (push) Successful in 14s

- Kopf-Badge zeigt jetzt die tatsaechliche Anzahl offener Rechnungen statt "..."
- Neues Setup-Select MAHNUNG_BOX_MAXLINES (Alle/5/10/20/30/50)
- Widget laedt alle offenen Rechnungen (korrekter Zaehler), rendert nur die
  eingestellte Anzahl + "..."-Ueberlaufzeile; Default 0 = alle anzeigen
- Lang-Keys de_DE/en_US ergaenzt, (%s) aus Widget-Titel entfernt

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-07-09 12:56:03 +02:00
parent 41765cc5df
commit 84e9692ffe
4 changed files with 44 additions and 7 deletions

View file

@ -93,12 +93,15 @@ if ($action === 'save_consts' && $user->hasRight('mahnung', 'setup')) {
$b2b = str_replace(',', '.', GETPOST('MAHNUNG_AUFSCHLAG_B2B', 'alphanohtml'));
$pau = str_replace(',', '.', GETPOST('MAHNUNG_PAUSCHALE_B2B', 'alphanohtml'));
$topic = GETPOST('MAHNUNG_NTFY_TOPIC', 'alphanohtml');
$boxmax = (int) GETPOST('MAHNUNG_BOX_MAXLINES', 'int');
dolibarr_set_const($db, 'MAHNUNG_BASISZINS', (string) (float) $basis, 'chaine', 0, '', 0);
dolibarr_set_const($db, 'MAHNUNG_AUFSCHLAG_B2C', (string) (float) $b2c, 'chaine', 0, '', 0);
dolibarr_set_const($db, 'MAHNUNG_AUFSCHLAG_B2B', (string) (float) $b2b, 'chaine', 0, '', 0);
dolibarr_set_const($db, 'MAHNUNG_PAUSCHALE_B2B', (string) (float) $pau, 'chaine', 0, '', 0);
dolibarr_set_const($db, 'MAHNUNG_NTFY_TOPIC', (string) $topic, 'chaine', 0, '', $conf->entity);
// Widget-Anzeige: max. Zeilen offener Rechnungen (0 = alle)
dolibarr_set_const($db, 'MAHNUNG_BOX_MAXLINES', (string) $boxmax, 'chaine', 0, '', 0);
setEventMessages($langs->trans('MahnungSettingsSaved'), null, 'mesgs');
header('Location: '.$_SERVER['PHP_SELF']);
@ -265,6 +268,17 @@ print '<tr class="oddeven"><td>'.$langs->trans('MahnungNtfyTopic').'</td>';
print '<td><input type="text" name="MAHNUNG_NTFY_TOPIC" size="40" value="'.dol_escape_htmltag(getDolGlobalString('MAHNUNG_NTFY_TOPIC', 'vk-builds')).'">';
print ' <span class="opacitymedium">'.$langs->trans('MahnungNtfyTopicHelp').'</span></td></tr>';
// Widget: max. Anzahl angezeigter offener Rechnungen (0 = alle)
$curBoxMax = getDolGlobalInt('MAHNUNG_BOX_MAXLINES', 0);
print '<tr class="oddeven"><td>'.$langs->trans('MahnungBoxMaxLines').'</td>';
print '<td><select name="MAHNUNG_BOX_MAXLINES">';
$boxMaxOpts = array(0 => $langs->trans('MahnungBoxMaxLinesAll'), 5 => '5', 10 => '10', 20 => '20', 30 => '30', 50 => '50');
foreach ($boxMaxOpts as $v => $lbl) {
print '<option value="'.$v.'"'.($curBoxMax === $v ? ' selected' : '').'>'.$lbl.'</option>';
}
print '</select>';
print ' <span class="opacitymedium">'.$langs->trans('MahnungBoxMaxLinesHelp').'</span></td></tr>';
print '</table>';
print '<br><div class="center"><input type="submit" class="button" value="'.$langs->trans('Save').'"></div>';
print '</form>';

View file

@ -52,9 +52,12 @@ class box_mahnung_offen extends ModeleBoxes
$facturestatic = new Facture($this->db);
$societestatic = new Societe($this->db);
$textHead = $langs->trans("MahnungBoxOffeneRechnungen", $this->max);
// Kopf mit Titel; die echte Anzahl offener Rechnungen wird nach der Query
// als Badge ergaenzt (siehe unten). Fuer die fruehen Return-Pfade
// (fehlende Rechte / SQL-Fehler) bleibt es beim reinen Titel.
$textHead = $langs->trans("MahnungBoxOffeneRechnungen");
$this->info_box_head = array(
'text' => $textHead.'<a class="paddingleft valignmiddle" href="'.DOL_URL_ROOT.'/compta/facture/list.php?search_status=1&sortfield=f.date_lim_reglement,f.ref&sortorder=ASC,ASC"><span class="badge">...</span></a>',
'text' => $textHead,
'limit' => dol_strlen($textHead),
);
@ -100,7 +103,8 @@ class box_mahnung_offen extends ModeleBoxes
$sql .= " f.rowid, f.ref, f.type, f.datef, f.date_lim_reglement,";
$sql .= " f.total_ht, f.total_tva, f.total_ttc, f.paye, f.fk_statut";
$sql .= " ORDER BY f.date_lim_reglement ASC, f.ref ASC";
$sql .= $this->db->plimit($this->max + 1, 0);
// Kein plimit: alle offenen Rechnungen laden, damit der Zaehler im Kopf
// stimmt. Die Anzeige wird bei Bedarf ueber MAHNUNG_BOX_MAXLINES begrenzt.
$result = $this->db->query($sql);
if (!$result) {
@ -115,6 +119,12 @@ class box_mahnung_offen extends ModeleBoxes
$line = 0;
$l_due_date = $langs->trans('Late').' ('.strtolower($langs->trans('DateDue')).': %s)';
// Echte Anzahl offener Rechnungen als Badge im Kopf (verlinkt auf die Liste).
// $num entspricht dank GROUP BY genau einer Zeile je offener Rechnung.
$this->info_box_head['text'] = $textHead
.'<a class="paddingleft valignmiddle" href="'.DOL_URL_ROOT.'/compta/facture/list.php?search_status=1&sortfield=f.date_lim_reglement,f.ref&sortorder=ASC,ASC"'
.' title="'.dol_escape_htmltag($textHead).'"><span class="badge">'.((int) $num).'</span></a>';
// Damit das Widget auch ohne offene Rechnungen sichtbar bleibt:
// leeres info_box_contents würde ModeleBoxes::showBox nichts rendern lassen.
if ($num == 0) {
@ -124,7 +134,13 @@ class box_mahnung_offen extends ModeleBoxes
);
}
while ($line < min($num, $this->max)) {
// Anzeige-Limit aus dem Setup (0 = alle offenen Rechnungen anzeigen).
// Es werden immer alle geladen (fuer den korrekten Zaehler im Kopf),
// aber nur $renderLimit Zeilen gerendert.
$boxmax = getDolGlobalInt('MAHNUNG_BOX_MAXLINES', 0);
$renderLimit = ($boxmax > 0) ? min($num, $boxmax) : $num;
while ($line < $renderLimit) {
$objp = $this->db->fetch_object($result);
$datelimit = $this->db->jdate($objp->datelimit);
@ -217,7 +233,8 @@ class box_mahnung_offen extends ModeleBoxes
$line++;
}
if ($this->max < $num) {
// Mehr offene Rechnungen vorhanden als angezeigt: "..."-Zeile als Verweis
if ($boxmax > 0 && $num > $boxmax) {
$this->info_box_contents[$line][] = array('td' => 'colspan="6"', 'text' => '...');
$line++;
}

View file

@ -204,8 +204,11 @@ MahnungCronBuildVorschlagDesc = Sucht täglich überfällige Rechnungen und send
#
# Widget
#
MahnungBoxOffeneRechnungen = Überfällige Rechnungen mit Mahnstufe (%s)
MahnungBoxOffeneRechnungen = Überfällige Rechnungen mit Mahnstufe
MahnungBoxKeineOffenenRechnungen = Keine offenen Kundenrechnungen
MahnungBoxMaxLines = Widget: angezeigte offene Rechnungen
MahnungBoxMaxLinesAll = Alle
MahnungBoxMaxLinesHelp = Wie viele offene Rechnungen das Home-Widget maximal anzeigt. „Alle" = ohne Begrenzung. Der Zähler im Widget-Kopf zeigt immer die tatsächliche Gesamtzahl.
#
# Dokumentenmodelle

View file

@ -329,8 +329,11 @@ MahnungSetupTemplateVars = Available template variables
MahnungTriggerBeschreibung = Dunning trigger: marks open dunnings as closed on payment receipt.
MahnungBoxStufe = Stage %s
MahnungBoxStufeVom = Stage %s from %s
MahnungBoxOffeneRechnungen = Overdue customer invoices with dunning stage (%s)
MahnungBoxOffeneRechnungen = Overdue customer invoices with dunning stage
MahnungBoxKeineOffenenRechnungen = No open customer invoices
MahnungBoxMaxLines = Widget: displayed open invoices
MahnungBoxMaxLinesAll = All
MahnungBoxMaxLinesHelp = How many open invoices the home widget shows at most. "All" = no limit. The counter in the widget header always shows the real total.
MahnungVorschlagStufeNichtKonfiguriert = Stage 1 not configured
MahnungVorschlagFristNichtErreicht = Stage 1 deadline (%s days) not yet reached (overdue %s days)
MahnungVorschlagAlleStufenAusgeschoepft = All dunning stages exhausted (last stage %s)