Vorschlagsliste UX: B2B/B2C-Filter wirkt direkt auf Kunden-Dropdown, Skip-Grund-Zelle harmonisiert [deploy]
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s

Kundentyp filtert das Kunden-Dropdown:
- select_company bekommt SQL-Filter "s.tva_intra IS NOT NULL AND s.tva_intra <> ''"
  bzw. "s.tva_intra IS NULL OR s.tva_intra = ''" je nach B2B/B2C-Wahl.
- Das Kundentyp-Select hat onchange=this.form.submit, sodass das Dropdown
  ohne extra Klick auf "Suche" direkt neu geladen wird.

Skip-Grund-Zelle:
- opacitymedium-Klasse von td auf inneres span verschoben. Manche Themes
  rendern td.opacitymedium mit eigenem Border-Verhalten — das hatte zu
  sichtbarem Rahmen-Unterschied in der Uebersprungen-Tabelle gefuehrt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Eduard Wisch 2026-05-11 12:34:57 +02:00
parent 3a016ce999
commit 3e67a876c1
2 changed files with 18 additions and 5 deletions

View file

@ -2,6 +2,11 @@
## [Unreleased]
### UX-Fixes (Vorschlagsliste)
- Kundentyp-Filter (B2B/B2C) wird jetzt direkt an `select_company()` durchgereicht — wenn B2C gewaehlt ist, zeigt das Kunden-Dropdown nur noch Drittparteien ohne TVA-Nummer (entsprechend umgekehrt fuer B2B).
- Auto-Submit beim Wechsel des Kundentyps, damit das Dropdown ohne extra "Suche"-Klick aktualisiert wird.
- Skip-Grund-Spalte in der Uebersprungen-Tabelle: `opacitymedium` jetzt am inneren `span` statt am `td`, damit Theme-spezifisches Zellen-Border-Verhalten konsistent bleibt.
### Versand-Reminder (Cron + Ntfy)
- Neuer Cron-Job `MahnungCronVersandReminder` (taeglich): sucht Mahnungen mit Status `ERSTELLT` deren PDF seit > N Tagen erstellt aber noch nicht versendet wurde, schickt Ntfy-Push und (falls aktiv) GlobalNotify-Badge.
- Schwellenwert konfigurierbar via Konstante `MAHNUNG_VERSAND_REMINDER_DAYS` (Default 2).

View file

@ -116,8 +116,8 @@ print '<td><input type="number" name="filter_minverzug" value="'.dol_escape_html
// Mindestbetrag (in EUR, Komma erlaubt)
print '<td><input type="text" name="filter_minbetrag" value="'.dol_escape_htmltag((string) $filter_minbetrag).'" size="6" placeholder="0,00"> €</td>';
// Kundentyp
print '<td><select name="filter_kundentyp">';
// Kundentyp — Auto-Submit beim Wechsel, damit das Kunden-Dropdown direkt gefiltert wird
print '<td><select name="filter_kundentyp" onchange="this.form.submit();">';
print '<option value="">— '.$langs->trans('All').' —</option>';
print '<option value="B2B"'.($filter_kundentyp === 'B2B' ? ' selected' : '').'>B2B</option>';
print '<option value="B2C"'.($filter_kundentyp === 'B2C' ? ' selected' : '').'>B2C</option>';
@ -125,12 +125,20 @@ print '</select></td>';
// Kunden-Auswahl: Dolibarr-Standard select_company (Ajax wenn COMPANY_USE_SEARCH_TO_SELECT,
// sonst klassisches Dropdown). htmlname='search_socid' bleibt = Backward-Kompatibilitaet
// zu Direkt-Links (?search_socid=74) von der Kundenkarte.
// zu Direkt-Links (?search_socid=74) von der Kundenkarte. Wenn Kundentyp-Filter
// gesetzt ist, schraenken wir die Dropdown-Liste passend ein (B2B = TVA gesetzt,
// B2C = TVA leer); der Filter wird im SQL-WHERE als zusaetzliche Condition genutzt.
$socFilter = '';
if ($filter_kundentyp === 'B2B') {
$socFilter = "s.tva_intra IS NOT NULL AND s.tva_intra <> ''";
} elseif ($filter_kundentyp === 'B2C') {
$socFilter = "(s.tva_intra IS NULL OR s.tva_intra = '')";
}
print '<td>';
print $form->select_company(
$filter_socid, // selected
'search_socid', // htmlname (Hidden-Input-Name)
'', // filter
$socFilter, // filter (SQL-Condition, von Dolibarr in WHERE eingebunden)
'SelectThirdParty', // showempty (Translation-Key)
0, 0, array(), 0, 'minwidth250'
);
@ -268,7 +276,7 @@ function renderUebersprungeneTabelle($skipped)
print '<td class="right">'.((int) $r['tage_verzug']).'</td>';
print '<td class="right">'.price($r['betrag_offen']).'</td>';
print '<td>'.($r['letzte_mahnung_stufe'] ? 'Stufe '.((int) $r['letzte_mahnung_stufe']).' am '.dol_print_date($r['letzte_mahnung_datum'], 'day') : '—').'</td>';
print '<td class="opacitymedium">'.dol_escape_htmltag((string) $r['skip_reason']).'</td>';
print '<td><span class="opacitymedium">'.dol_escape_htmltag((string) $r['skip_reason']).'</span></td>';
print '</tr>';
}
print '</table>';