Widget offene Rechnungen: Brutto-Summe zusaetzlich zur Netto-Summe [deploy]
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s
Summenzeile zeigt jetzt Netto und Brutto (aus f.total_ttc der Rechnung, nicht aus Netto hochgerechnet - damit bleiben Reverse-Charge, Steuer- befreiung und Kleinunternehmerregelung korrekt). Neue Lang-Keys MahnungBoxNetto/MahnungBoxBrutto in de_DE + en_US. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
84e9692ffe
commit
7532770599
5 changed files with 21 additions and 4 deletions
|
|
@ -27,7 +27,10 @@ Dolibarr Custom-Modul: 3-stufiges Mahnwesen nach BGB §288 + Versand-Tracking +
|
|||
- `box_mahnung_offen` basiert 1:1 auf `box_factures_imp.php` (Standard-Widget)
|
||||
- Zeigt ALLE offenen Rechnungen, nicht nur überfällige
|
||||
- Mahnstufe-Badge nur wenn Mahnung existiert, sonst Strich
|
||||
- **Zähler im Kopf**: Der Badge im Widget-Kopf zeigt die tatsächliche Gesamtzahl offener Rechnungen (verlinkt auf die Rechnungsliste). Titel-Lang-Key hat kein `(%s)` mehr — die Zahl steckt im Badge. Der Zähler wird erst NACH der Query gesetzt (wenn `$num` bekannt ist), damit die frühen Return-Pfade (fehlende Rechte / SQL-Fehler) ohne Zähler bleiben.
|
||||
- **Zeilenanzahl konfigurierbar** via Konstante `MAHNUNG_BOX_MAXLINES` (Admin-Select in `setup.php`: Alle/5/10/20/30/50, Default `0` = alle). Widget lädt IMMER alle offenen Rechnungen (für den korrekten Zähler), rendert aber nur `MAHNUNG_BOX_MAXLINES` Zeilen + eine `...`-Überlaufzeile. **Nicht** auf das von Dolibarr übergebene `$max` verlassen — das kommt aus `MAIN_SIZE_SHORTLIST_LIMIT` (Default 5) und gilt global für ALLE Home-Boxen. (KB #598)
|
||||
- **Empty-State Pflicht**: bei `$num == 0` Platzhalter-Zeile in `info_box_contents` einfügen — sonst rendert `ModeleBoxes::showBox()` gar nichts und das Widget verschwindet komplett (auch nach neuen Rechnungen sieht der User es nicht zurückkommen). Siehe KB #682.
|
||||
- **Summenzeile Netto+Brutto**: Betragszelle der `liste_total`-Zeile zeigt zweizeilig Netto (`SUM(f.total_ht)`) und Brutto (`SUM(f.total_ttc)`). Brutto kommt direkt aus `f.total_ttc` der Rechnung, NICHT aus Netto × Steuersatz hochgerechnet — sonst wären Reverse-Charge §13b, Steuerbefreiung und Kleinunternehmer §19 UStG falsch. Lang-Keys `MahnungBoxNetto`/`MahnungBoxBrutto`.
|
||||
|
||||
## Hooks-Stolperfallen
|
||||
- **`completeTabsHead`** wird bei jedem Aufruf von `complete_head_from_modules()` getriggert — pro Karte mehrfach (core + external + remove). Filter auf `mode=add` + `filterorigmodule=external`, sonst doppelter Tab. (KB #601)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ Version **0.2.0 + Phasen 1-6 (Unreleased)** — UX-Vorschlagsliste, Versand-Erfa
|
|||
| E-Mail-Versand mit PDF-Anhang | `CMailFile`, Subject/Body mit Platzhaltern |
|
||||
| Auto-Erledigung bei Zahlungseingang | Trigger `BILL_PAYED` + `PAYMENT_CUSTOMER_CREATE` |
|
||||
| Tab "Mahnungen (n)" auf Rechnungs- + Kundenkarte | Hook `completeTabsHead` (filtert auf add/external) |
|
||||
| Widget: Offene Rechnungen mit Mahnstufe | `box_mahnung_offen` |
|
||||
| Widget: Offene Rechnungen mit Mahnstufe (Zähler im Kopf, Zeilenanzahl einstellbar, Summenzeile Netto+Brutto) | `box_mahnung_offen`, Konstante `MAHNUNG_BOX_MAXLINES` |
|
||||
| **Vorschlagsliste-Filter** (Mahnstufe, Tage Verzug, Mindestbetrag, Kundentyp B2B/B2C, Kunden-Select2 mit Ajax) | `list.php` — Kundentyp-Wechsel filtert das Kunden-Dropdown sofort per Auto-Submit |
|
||||
| **Kontakt-Spalte** in Vorschlagsliste (Telefon-/Mail-Icons mit Direktlink) | tel:/mailto: aus `llx_societe.phone/email` |
|
||||
| **Versand-Erfassung** pro Mahnung (Datum, Versandweg, Sendungsnummer, Tracking-Provider) | `card.php` Versand-Block; setzt automatisch Status auf VERSENDET |
|
||||
|
|
@ -123,6 +123,7 @@ Vollständige Liste: **Setup → Mahnwesen → Verfügbare Template-Variablen**
|
|||
| `MAHNUNG_ADDON_PDF_ODT_PATH` | `DOL_DATA_ROOT/doctemplates/mahnung` | ODT-Template-Verzeichnis |
|
||||
| `MAHNUNG_NTFY_TOPIC` | `vk-builds` | Ntfy-Topic für Vorschlags-Push |
|
||||
| `MAHNUNG_VERSAND_REMINDER_DAYS` | `2` | Schwelle (Tage) für Versand-Reminder Ntfy-Push |
|
||||
| `MAHNUNG_BOX_MAXLINES` | `0` | Widget: max. angezeigte offene Rechnungen (`0` = alle) |
|
||||
|
||||
## Datenbank
|
||||
|
||||
|
|
|
|||
|
|
@ -240,8 +240,11 @@ class box_mahnung_offen extends ModeleBoxes
|
|||
}
|
||||
|
||||
if ($num > 0) {
|
||||
// Summe (wie Original: separate Query ohne LIMIT)
|
||||
$sql2 = "SELECT SUM(f.total_ht) as total_ht";
|
||||
// Summe (wie Original: separate Query ohne LIMIT).
|
||||
// Brutto direkt aus f.total_ttc der Rechnung, NICHT aus total_ht
|
||||
// hochgerechnet — so bleiben Sonderregelungen (Reverse-Charge §13b,
|
||||
// Steuerbefreiung, Kleinunternehmer §19 UStG) korrekt.
|
||||
$sql2 = "SELECT SUM(f.total_ht) as total_ht, SUM(f.total_ttc) as total_ttc";
|
||||
$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').")";
|
||||
|
|
@ -251,9 +254,11 @@ class box_mahnung_offen extends ModeleBoxes
|
|||
}
|
||||
$resTotal = $this->db->query($sql2);
|
||||
$totalHt = 0;
|
||||
$totalTtc = 0;
|
||||
if ($resTotal) {
|
||||
$objTotal = $this->db->fetch_object($resTotal);
|
||||
$totalHt = (float) $objTotal->total_ht;
|
||||
$totalTtc = (float) $objTotal->total_ttc;
|
||||
$this->db->free($resTotal);
|
||||
}
|
||||
|
||||
|
|
@ -266,9 +271,13 @@ class box_mahnung_offen extends ModeleBoxes
|
|||
'td' => 'class="liste_total"',
|
||||
'text' => ' ',
|
||||
);
|
||||
// Netto (wie bisher) + Brutto darunter, Brutto aus f.total_ttc der
|
||||
// Rechnung (Sonderregelungen wie §13b/§19 UStG bleiben korrekt).
|
||||
$this->info_box_contents[$line][] = array(
|
||||
'td' => 'class="nowraponall right liste_total"',
|
||||
'text' => price($totalHt, 0, $langs, 0, -1, -1, $conf->currency),
|
||||
'text' => '<span class="opacitymedium paddingright small">'.$langs->trans("MahnungBoxNetto").'</span>'.price($totalHt, 0, $langs, 0, -1, -1, $conf->currency)
|
||||
.'<br><span class="opacitymedium paddingright small">'.$langs->trans("MahnungBoxBrutto").'</span>'.price($totalTtc, 0, $langs, 0, -1, -1, $conf->currency),
|
||||
'asis' => 1,
|
||||
);
|
||||
$this->info_box_contents[$line][] = array(
|
||||
'td' => 'class="liste_total"',
|
||||
|
|
|
|||
|
|
@ -209,6 +209,8 @@ 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.
|
||||
MahnungBoxNetto = Netto
|
||||
MahnungBoxBrutto = Brutto
|
||||
|
||||
#
|
||||
# Dokumentenmodelle
|
||||
|
|
|
|||
|
|
@ -334,6 +334,8 @@ 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.
|
||||
MahnungBoxNetto = Net
|
||||
MahnungBoxBrutto = Gross
|
||||
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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue