mahnung/core/triggers/interface_99_modMahnung_MahnungTriggers.class.php
Eduard Wisch 80d92042bc
All checks were successful
Deploy mahnung / deploy (push) Successful in 13s
Fix: Menü-Navigation, GlobalNotify-URL, Dokument-Upload + -Löschen [deploy]
- GlobalNotify-URL: relativer Pfad statt absoluter (DOL_MAIN_URL_ROOT ohne
  Protokoll führte zu kaputten Seiten-URLs im Browser); buildAbsoluteUrl()
  prüft jetzt auf fehlendes http(s)://
- Menü-Navigation: mainmenu=billing&leftmenu=mahnung in allen list.php-Links
  ergänzt (createmahnung.php Redirect, Filter-Form, Hook-Links, Cron-Pfade)
- card.php Dokumente: Lupe direkt neben Dateinamen, Löschen-Button pro Datei
- card.php Upload: actions_linkedfiles.inc.php eingebunden (vor llxHeader),
  upload_dir korrekt gesetzt — showdocuments() zeigt jetzt Upload-Formular
- Redundante Variablen-Definitionen (mahnungSafeRef, files.lib require) entfernt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-13 15:36:58 +02:00

178 lines
5.5 KiB
PHP

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*/
/**
* \file core/triggers/interface_99_modMahnung_MahnungTriggers.class.php
* \ingroup mahnung
* \brief Trigger: setzt offene Mahnvorgaenge nach Zahlungseingang auf "erledigt".
*
* Klassenname: Interface<Suffix>Triggers — Suffix muss zu Dateinamen passen.
* Datei muss in core/triggers/ liegen, wird durch DolibarrModules->loadtriggers
* (module_parts['triggers']=1) beim Modul-Aktivieren registriert.
*/
require_once DOL_DOCUMENT_ROOT.'/core/triggers/dolibarrtriggers.class.php';
class InterfaceMahnungTriggers extends DolibarrTriggers
{
/**
* @param DoliDB $db Datenbank-Handler
*/
public function __construct($db)
{
parent::__construct($db);
$this->family = 'financial';
$this->description = 'Mahnung-Trigger: erledigt offene Mahnvorgaenge bei Zahlungseingang.';
$this->version = self::VERSIONS['dev'];
$this->picto = 'fa-envelope-open-text';
}
/**
* Wird bei jedem Dolibarr-Event aufgerufen.
*
* @param string $action z.B. PAYMENT_CUSTOMER_CREATE, BILL_PAYED
* @param CommonObject $object Event-Subjekt
* @param User $user aktueller User
* @param Translate $langs Sprache
* @param Conf $conf Konfig
* @return int <0 Fehler, 0 nichts getan, >0 OK
*/
public function runTrigger($action, $object, User $user, Translate $langs, Conf $conf)
{
if (!isModEnabled('mahnung')) {
return 0;
}
switch ($action) {
case 'BILL_PAYED':
case 'BILL_VALIDATE':
// $object ist Facture
if (!empty($object) && !empty($object->id) && !empty($object->paye)) {
return $this->onRechnungBezahlt((int) $object->id, $user);
}
return 0;
case 'PAYMENT_CUSTOMER_CREATE':
// $object ist Paiement; eventuell auch ohne paye=1 Status — pro betroffener Rechnung pruefen
return $this->onPaiementErzeugt($object, $user);
default:
return 0;
}
}
/**
* Setzt alle offenen Mahnvorgaenge zur Rechnung auf STATUS_ERLEDIGT.
*
* @param int $factureId
* @param User $user
* @return int >=0 Anzahl aktualisierter Mahnungen, <0 Fehler
*/
private function onRechnungBezahlt($factureId, User $user)
{
require_once DOL_DOCUMENT_ROOT.'/custom/mahnung/class/mahnung.class.php';
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."mahnung_mahnung";
$sql .= " WHERE fk_facture = ".((int) $factureId);
$sql .= " AND status NOT IN (".Mahnung::STATUS_ERLEDIGT.", ".Mahnung::STATUS_STORNIERT.")";
$resql = $this->db->query($sql);
if (!$resql) {
return -1;
}
$count = 0;
while ($obj = $this->db->fetch_object($resql)) {
$m = new Mahnung($this->db);
if ($m->fetch((int) $obj->rowid) > 0 && $m->setErledigt($user) > 0) {
$count++;
}
}
$this->db->free($resql);
// Wenn Mahnungen erledigt wurden: pruefen ob noch offene uebrig sind.
// Falls nicht, GlobalNotify-Badge raeumen.
if ($count > 0 && !$this->hatOffeneMahnungen()) {
require_once DOL_DOCUMENT_ROOT.'/custom/mahnung/class/mahnungcron.class.php';
MahnungCron::clearGlobalNotify();
}
return $count;
}
/**
* Bei Zahlungs-Erzeugung: alle betroffenen Rechnungen pruefen, ob sie nun
* vollstaendig bezahlt sind. paye-Flag wird in Dolibarr typischerweise erst
* gesetzt, wenn Summe der Zahlungen >= total_ttc — wir pruefen pessimistisch:
* sobald ueberhaupt eine Zahlung kommt + offene Mahnung existiert -> erledigen,
* wenn die Zahlung den offenen Betrag deckt.
*
* @param CommonObject $payment
* @param User $user
* @return int
*/
private function onPaiementErzeugt($payment, User $user)
{
if (empty($payment) || empty($payment->amounts) || !is_array($payment->amounts)) {
return 0;
}
$total = 0;
foreach ($payment->amounts as $factureId => $amount) {
$factureId = (int) $factureId;
if ($factureId <= 0) {
continue;
}
// Pruefen, ob die Rechnung jetzt voll bezahlt ist
if ($this->istRechnungVollBezahlt($factureId)) {
$total += $this->onRechnungBezahlt($factureId, $user);
}
}
return $total;
}
/**
* Prueft ob noch offene Mahnvorgaenge existieren (Status weder erledigt noch storniert).
*
* @return bool true wenn mindestens eine offene Mahnung existiert
*/
private function hatOffeneMahnungen()
{
$sql = "SELECT COUNT(*) AS nb FROM ".MAIN_DB_PREFIX."mahnung_mahnung";
$sql .= " WHERE status NOT IN (".Mahnung::STATUS_ERLEDIGT.", ".Mahnung::STATUS_STORNIERT.")";
$resql = $this->db->query($sql);
if (!$resql) {
return true; // Im Zweifel Badge stehen lassen
}
$obj = $this->db->fetch_object($resql);
$this->db->free($resql);
return (int) $obj->nb > 0;
}
/**
* @param int $factureId
* @return bool
*/
private function istRechnungVollBezahlt($factureId)
{
$sql = "SELECT f.total_ttc, COALESCE(SUM(pf.amount), 0) AS gezahlt";
$sql .= " FROM ".MAIN_DB_PREFIX."facture as f";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."paiement_facture as pf ON pf.fk_facture = f.rowid";
$sql .= " WHERE f.rowid = ".((int) $factureId);
$sql .= " GROUP BY f.rowid, f.total_ttc";
$resql = $this->db->query($sql);
if (!$resql || !$this->db->num_rows($resql)) {
return false;
}
$obj = $this->db->fetch_object($resql);
$this->db->free($resql);
return (float) $obj->gezahlt + 0.005 >= (float) $obj->total_ttc;
}
}