Fix: Widget zeigt alle offenen Rechnungen wie Original + Mahnstufe [deploy]
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s

Widget basiert jetzt 1:1 auf box_factures_imp.php:
- Alle offenen Rechnungen (nicht nur ueberfaellige)
- Status-Icon wie Original (LibStatut)
- Summenzeile ueber alle offenen (separate Query)
- Link zur Rechnungsliste im Header
Plus: Extra-Spalte Mahnstufe mit farbigem Badge (wenn vorhanden)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-05-10 18:44:45 +02:00
parent 7387d3ac1e
commit ec0c843492

View file

@ -9,6 +9,7 @@
* \file htdocs/custom/mahnung/core/boxes/box_mahnung_offen.php
* \ingroup mahnung
* \brief Widget: Aelteste offene Kundenrechnungen mit Mahnstufe.
* Basiert auf box_factures_imp.php, erweitert um Mahnstufe-Spalte.
*/
require_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php';
@ -17,12 +18,12 @@ require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
require_once DOL_DOCUMENT_ROOT.'/custom/mahnung/class/mahnung.class.php';
/**
* Widget: Offene Kundenrechnungen mit aktueller Mahnstufe.
* Widget: Aelteste offene Kundenrechnungen mit Mahnstufe-Badge.
*/
class box_mahnung_offen extends ModeleBoxes
{
public $boxcode = "mahnungoffenerechnungen";
public $boximg = "fa-envelope-open-text";
public $boximg = "object_bill";
public $boxlabel = "MahnungBoxOffeneRechnungen";
public $depends = array("facture", "mahnung");
@ -51,8 +52,10 @@ class box_mahnung_offen extends ModeleBoxes
$facturestatic = new Facture($this->db);
$societestatic = new Societe($this->db);
$textHead = $langs->trans("MahnungBoxOffeneRechnungen", $this->max);
$this->info_box_head = array(
'text' => $langs->trans("MahnungBoxOffeneRechnungen", $this->max),
'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>',
'limit' => dol_strlen($textHead),
);
if (!$user->hasRight('facture', 'lire')) {
@ -63,20 +66,20 @@ class box_mahnung_offen extends ModeleBoxes
return;
}
// Offene Rechnungen mit optionalem LEFT JOIN auf letzte aktive Mahnung
$sql = "SELECT s.rowid as socid, s.nom as name, s.logo, s.email, s.entity,";
$sql .= " s.code_client, s.client,";
// Query wie box_factures_imp, plus Mahnstufe per Subquery
$sql = "SELECT s.rowid as socid, s.nom as name, s.code_client, s.client,";
$sql .= " s.logo, s.email, s.entity,";
$sql .= " f.rowid as facid, f.ref, f.type, f.datef as date,";
$sql .= " f.date_lim_reglement as datelimit,";
$sql .= " f.total_ht, f.total_tva, f.total_ttc,";
$sql .= " f.paye, f.fk_statut as status,";
$sql .= " COALESCE(SUM(pf.amount), 0) as am,";
// Letzte Mahnstufe per Subquery
$sql .= " SUM(pf.amount) as am,";
// Letzte aktive Mahnstufe
$sql .= " (SELECT m2.stufe FROM ".MAIN_DB_PREFIX."mahnung_mahnung as m2";
$sql .= " WHERE m2.fk_facture = f.rowid AND m2.status NOT IN (".Mahnung::STATUS_STORNIERT.")";
$sql .= " WHERE m2.fk_facture = f.rowid AND m2.status != ".((int) Mahnung::STATUS_STORNIERT);
$sql .= " ORDER BY m2.stufe DESC LIMIT 1) as mahnstufe,";
$sql .= " (SELECT m3.date_mahnung FROM ".MAIN_DB_PREFIX."mahnung_mahnung as m3";
$sql .= " WHERE m3.fk_facture = f.rowid AND m3.status NOT IN (".Mahnung::STATUS_STORNIERT.")";
$sql .= " WHERE m3.fk_facture = f.rowid AND m3.status != ".((int) Mahnung::STATUS_STORNIERT);
$sql .= " ORDER BY m3.stufe DESC LIMIT 1) as mahndatum";
$sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
@ -84,15 +87,13 @@ class box_mahnung_offen extends ModeleBoxes
$sql .= " WHERE f.entity IN (".getEntity('invoice').")";
$sql .= " AND f.paye = 0";
$sql .= " AND f.fk_statut = 1";
$sql .= " AND f.date_lim_reglement IS NOT NULL";
$sql .= " AND f.date_lim_reglement < '".$this->db->idate(dol_now())."'";
if (empty($user->socid) && !$user->hasRight('societe', 'client', 'voir')) {
$sql .= " AND s.rowid IN (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_user = ".((int) $user->id).")";
$sql .= " AND s.rowid = (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."societe_commerciaux as sc WHERE sc.fk_soc = s.rowid AND sc.fk_user = ".((int) $user->id)." LIMIT 1)";
}
if ($user->socid) {
$sql .= " AND s.rowid = ".((int) $user->socid);
}
$sql .= " GROUP BY s.rowid, s.nom, s.logo, s.email, s.entity, s.code_client, s.client,";
$sql .= " GROUP BY s.rowid, s.nom, s.code_client, s.client, s.logo, s.email, s.entity,";
$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";
@ -110,13 +111,11 @@ class box_mahnung_offen extends ModeleBoxes
$num = $this->db->num_rows($result);
$line = 0;
$l_due_date = $langs->trans('Late').' ('.strtolower($langs->trans('DateDue')).': %s)';
$totalHt = 0;
while ($line < min($num, $this->max)) {
$objp = $this->db->fetch_object($result);
$datelimit = $this->db->jdate($objp->datelimit);
$tageVerzug = (int) floor((dol_now() - $datelimit) / 86400);
$facturestatic->id = $objp->facid;
$facturestatic->ref = $objp->ref;
@ -156,7 +155,7 @@ class box_mahnung_offen extends ModeleBoxes
$label = $labels[$stufe] ?? 'Stufe '.$stufe;
$mahnDatum = $objp->mahndatum ? dol_print_date($this->db->jdate($objp->mahndatum), 'day') : '';
$tooltip = $label.($mahnDatum ? ' vom '.$mahnDatum : '');
$mahnBadge = ' <span class="badge" style="background-color:'.$color.';color:#fff;font-size:0.75em;" title="'.dol_escape_htmltag($tooltip).'">'.$label.'</span>';
$mahnBadge = '<span class="badge" style="background-color:'.$color.';color:#fff;font-size:0.75em;" title="'.dol_escape_htmltag($tooltip).'">'.$label.'</span>';
}
// Spalte 1: Rechnung + Warnung
@ -186,20 +185,19 @@ class box_mahnung_offen extends ModeleBoxes
'text' => dol_print_date($datelimit, 'day', 'tzuserrel'),
);
// Spalte 5: Tage Verzug
// Spalte 5: Status (wie Original)
$this->info_box_contents[$line][] = array(
'td' => 'class="center nowraponall"',
'text' => $tageVerzug.' T.',
'td' => 'class="right" width="18"',
'text' => $facturestatic->LibStatut($objp->paye, $objp->status, 3, $objp->am, $objp->type),
);
// Spalte 6: Mahnstufe
$this->info_box_contents[$line][] = array(
'td' => 'class="center nowraponall"',
'text' => !empty($mahnBadge) ? $mahnBadge : '<span class="opacitymedium">—</span>',
'text' => !empty($mahnBadge) ? $mahnBadge : '',
'asis' => 1,
);
$totalHt += (float) $objp->total_ht;
$line++;
}
@ -209,7 +207,23 @@ class box_mahnung_offen extends ModeleBoxes
}
if ($num > 0) {
// Summenzeile
// Summe (wie Original: separate Query ohne LIMIT)
$sql2 = "SELECT SUM(f.total_ht) as total_ht";
$sql2 .= " FROM ".MAIN_DB_PREFIX."facture as f";
$sql2 .= " INNER JOIN ".MAIN_DB_PREFIX."societe as s ON s.rowid = f.fk_soc";
$sql2 .= " WHERE f.entity IN (".getEntity('invoice').")";
$sql2 .= " AND f.paye = 0 AND f.fk_statut = 1";
if ($user->socid) {
$sql2 .= " AND s.rowid = ".((int) $user->socid);
}
$resTotal = $this->db->query($sql2);
$totalHt = 0;
if ($resTotal) {
$objTotal = $this->db->fetch_object($resTotal);
$totalHt = (float) $objTotal->total_ht;
$this->db->free($resTotal);
}
$this->info_box_contents[$line][] = array(
'tr' => 'class="liste_total"',
'td' => 'class="liste_total"',