Hotfix: 500-Error beim Kundentyp-Filter — select_company-Filter muss USC-Syntax sein [deploy]
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s

Bug:
- Mein letzter Commit hat einen plain-SQL-Filter an select_company uebergeben.
  Dolibarrs select_thirdparty_list reicht den Filter durch
  forgeSQLFromUniversalSearchCriteria, das erwartet aber USC-Syntax
  feld:operator:wert in Klammern. Plain-SQL fuehrt zu SQL-Syntax-Error
  und 500-Antwort.

Fix:
- B2B-Filter: (s.tva_intra:isnot:NULL) AND (s.tva_intra:!=:'')
- B2C-Filter: (s.tva_intra:is:NULL) OR (s.tva_intra:=:'')

Zusatz-Fixes aus dem Log:
- search_socid=-1 (von select_company als "nichts ausgewaehlt" gerendert)
  wurde irrtuemlich als Filter auf fk_soc=-1 angewendet. Jetzt nur als
  Filter genutzt wenn > 0.
- Beim Auto-Submit des Kundentyp-Selects wird search_socid auf "" gesetzt,
  damit eine zuvor ausgewaehlte (jetzt evtl. ausgefilterte) Kunden-ID
  nicht stehen bleibt.

KB-Eintrag #602 zur USC-Syntax angelegt.

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

View file

@ -3,8 +3,9 @@
## [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.
- 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). Filter nutzt Dolibarrs **Universal-Search-Criteria-Syntax** `(feld:operator:wert)` — plain SQL wuerde durch `forgeSQLFromUniversalSearchCriteria` fehlschlagen.
- Auto-Submit beim Wechsel des Kundentyps + automatisches Reset von `search_socid`, damit das Dropdown ohne extra "Suche"-Klick aktualisiert wird und keine ungueltige (im neuen Filter nicht enthaltene) Kunden-ID stehen bleibt.
- `search_socid=-1` (von `select_company` als "nichts ausgewaehlt" geliefert) wird jetzt korrekt ignoriert statt als Filter auf `fk_soc=-1` zu wirken.
- 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)

View file

@ -67,7 +67,8 @@ if ($filter_minverzug !== '' && $filter_minverzug !== null) {
$filter['min_tage_verzug'] = (int) $filter_minverzug;
}
$filter_socid = GETPOST('search_socid', 'int');
if (!empty($filter_socid)) {
// select_company liefert -1 fuer "nichts ausgewaehlt" — nur positive IDs als Filter werten
if ((int) $filter_socid > 0) {
$filter['soc_id'] = (int) $filter_socid;
}
$filter_minbetrag = GETPOST('filter_minbetrag', 'alpha'); // Komma/Punkt zugelassen
@ -116,8 +117,12 @@ 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 — Auto-Submit beim Wechsel, damit das Kunden-Dropdown direkt gefiltert wird
print '<td><select name="filter_kundentyp" onchange="this.form.submit();">';
// Kundentyp — Auto-Submit beim Wechsel + Kunden-Auswahl zuruecksetzen, damit das
// Kunden-Dropdown direkt mit dem neuen Typ-Filter neu geladen wird (alte Auswahl
// koennte im neuen Filter gar nicht mehr enthalten sein).
print '<td><select name="filter_kundentyp" onchange="';
print 'var s=this.form.elements[\'search_socid\']; if(s){s.value=\'\';} this.form.submit();';
print '">';
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>';
@ -126,13 +131,16 @@ 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. 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.
// gesetzt ist, schraenken wir die Dropdown-Liste passend ein.
//
// WICHTIG: select_thirdparty_list erwartet $filter im Universal-Search-Criteria-Format
// (siehe forgeSQLFromUniversalSearchCriteria), NICHT plain SQL.
// Syntax: (feld:operator:wert) mit AND/OR; Operatoren: =, !=, <, >, like, is, isnot, in, notin.
$socFilter = '';
if ($filter_kundentyp === 'B2B') {
$socFilter = "s.tva_intra IS NOT NULL AND s.tva_intra <> ''";
$socFilter = "(s.tva_intra:isnot:NULL) AND (s.tva_intra:!=:'')";
} elseif ($filter_kundentyp === 'B2C') {
$socFilter = "(s.tva_intra IS NULL OR s.tva_intra = '')";
$socFilter = "(s.tva_intra:is:NULL) OR (s.tva_intra:=:'')";
}
print '<td>';
print $form->select_company(