All checks were successful
Deploy mahnung / deploy (push) Successful in 14s
Umlaute in allen lang-Dateien korrigiert. Alle hardcodierten deutschen Strings
in 22 PHP-Dateien durch $langs->trans('Key') ersetzt. Neue Schlüssel für
Cron-Meldungen, Dokument-Aktionen, Bonität, Vorschlag-Status, Template-Vars u.a.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
651 lines
19 KiB
PHP
651 lines
19 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, version 3.
|
|
*/
|
|
|
|
/**
|
|
* \file htdocs/custom/mahnung/class/mahnung.class.php
|
|
* \ingroup mahnung
|
|
* \brief CRUD-Klasse für Mahnvorgänge (llx_mahnung_mahnung).
|
|
*/
|
|
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
|
|
|
|
/**
|
|
* Klasse Mahnung — repräsentiert einen Mahnvorgang zu einer Kundenrechnung.
|
|
*/
|
|
class Mahnung extends CommonObject
|
|
{
|
|
const STATUS_ENTWURF = 0;
|
|
const STATUS_ERSTELLT = 1;
|
|
const STATUS_VERSENDET = 2;
|
|
const STATUS_ERLEDIGT = 3;
|
|
const STATUS_STORNIERT = 9;
|
|
|
|
const VERSAND_PDF = 'pdf';
|
|
const VERSAND_MAIL = 'mail';
|
|
const VERSAND_DRUCK = 'druck';
|
|
const VERSAND_NONE = 'none';
|
|
|
|
const KUNDENTYP_B2C = 'B2C';
|
|
const KUNDENTYP_B2B = 'B2B';
|
|
|
|
/** @var string */
|
|
public $element = 'mahnung';
|
|
|
|
/** @var string */
|
|
public $table_element = 'mahnung_mahnung';
|
|
|
|
/** @var int */
|
|
public $entity;
|
|
|
|
/** @var string */
|
|
public $ref;
|
|
|
|
/** @var int */
|
|
public $fk_facture;
|
|
|
|
/** @var int */
|
|
public $fk_soc;
|
|
|
|
/** @var int 1, 2, 3 */
|
|
public $stufe;
|
|
|
|
/** @var int Unix-Zeit */
|
|
public $date_mahnung;
|
|
|
|
/** @var int Unix-Zeit */
|
|
public $date_lim_reglement_alt;
|
|
|
|
/** @var int Unix-Zeit */
|
|
public $date_lim_reglement_neu;
|
|
|
|
/** @var float */
|
|
public $betrag_offen = 0;
|
|
|
|
/** @var float */
|
|
public $mahngebuehr = 0;
|
|
|
|
/** @var float */
|
|
public $pauschale_b2b = 0;
|
|
|
|
/** @var float */
|
|
public $verzugszinsen = 0;
|
|
|
|
/** @var float */
|
|
public $summe_mahnung = 0;
|
|
|
|
/** @var string pdf|mail|druck|none */
|
|
public $versandart = self::VERSAND_PDF;
|
|
|
|
/** @var string B2C|B2B */
|
|
public $customertype;
|
|
|
|
/** @var float */
|
|
public $basiszins_snapshot;
|
|
|
|
/** @var string */
|
|
public $pdf_path;
|
|
|
|
/** @var string */
|
|
public $note_private;
|
|
|
|
/** @var string Aktuelles Dokumentenmodell */
|
|
public $model_pdf;
|
|
|
|
/** @var int 0..9 */
|
|
public $status = self::STATUS_ENTWURF;
|
|
|
|
/** @var int Unix-Zeit — Versanddatum (per Hand erfasst oder beim Mail-Versand) */
|
|
public $date_versand;
|
|
|
|
/** @var string post|einschreiben|dhl|dpd|hermes|ups|fax|email|persoenlich|eigen */
|
|
public $versandweg;
|
|
|
|
/** @var string Rohe Sendungsnummer wie ausgedruckt */
|
|
public $tracking_nr;
|
|
|
|
/** @var string dhl|dpag|hermes|dpd|ups|custom — für URL-Template */
|
|
public $tracking_provider;
|
|
|
|
/** @var int Unix-Zeit */
|
|
public $datec;
|
|
|
|
/** @var int Unix-Zeit */
|
|
public $tms;
|
|
|
|
/** @var int */
|
|
public $fk_user_creat;
|
|
|
|
/** @var int */
|
|
public $fk_user_modif;
|
|
|
|
/**
|
|
* @param DoliDB $db Datenbank-Handler
|
|
*/
|
|
public function __construct($db)
|
|
{
|
|
global $conf;
|
|
$this->db = $db;
|
|
$this->entity = $conf->entity;
|
|
}
|
|
|
|
/**
|
|
* Nächste freie Mahnungs-Referenz für das aktuelle Jahr.
|
|
* Format: MAHN<YYYY>-<NNNN>
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getNextRef()
|
|
{
|
|
$year = (int) dol_print_date(dol_now(), '%Y');
|
|
$prefix = 'MAHN'.$year.'-';
|
|
|
|
$sql = "SELECT MAX(CAST(SUBSTRING(ref, ".(strlen($prefix) + 1).") AS UNSIGNED)) AS maxnum";
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."mahnung_mahnung";
|
|
$sql .= " WHERE entity = ".((int) $this->entity);
|
|
$sql .= " AND ref LIKE '".$this->db->escape($prefix)."%'";
|
|
|
|
$resql = $this->db->query($sql);
|
|
$next = 1;
|
|
if ($resql) {
|
|
$obj = $this->db->fetch_object($resql);
|
|
$next = ((int) $obj->maxnum) + 1;
|
|
$this->db->free($resql);
|
|
}
|
|
return $prefix.str_pad((string) $next, 4, '0', STR_PAD_LEFT);
|
|
}
|
|
|
|
/**
|
|
* Mahnvorgang anlegen.
|
|
*
|
|
* @param User $user Anlegender User
|
|
* @return int <0 bei Fehler, sonst neue rowid
|
|
*/
|
|
public function create($user)
|
|
{
|
|
$now = dol_now();
|
|
|
|
if (empty($this->ref)) {
|
|
$this->ref = $this->getNextRef();
|
|
}
|
|
|
|
$this->db->begin();
|
|
|
|
$sql = "INSERT INTO ".MAIN_DB_PREFIX."mahnung_mahnung (";
|
|
$sql .= "entity, ref, fk_facture, fk_soc, stufe, date_mahnung,";
|
|
$sql .= " date_lim_reglement_alt, date_lim_reglement_neu,";
|
|
$sql .= " betrag_offen, mahngebuehr, pauschale_b2b, verzugszinsen, summe_mahnung,";
|
|
$sql .= " versandart, customertype, basiszins_snapshot, pdf_path, note_private,";
|
|
$sql .= " status, datec, fk_user_creat";
|
|
$sql .= ") VALUES (";
|
|
$sql .= ((int) $this->entity).",";
|
|
$sql .= "'".$this->db->escape($this->ref)."',";
|
|
$sql .= ((int) $this->fk_facture).",";
|
|
$sql .= ((int) $this->fk_soc).",";
|
|
$sql .= ((int) $this->stufe).",";
|
|
$sql .= "'".$this->db->idate($this->date_mahnung ?: $now)."',";
|
|
$sql .= ($this->date_lim_reglement_alt ? "'".$this->db->idate($this->date_lim_reglement_alt)."'" : "NULL").",";
|
|
$sql .= ($this->date_lim_reglement_neu ? "'".$this->db->idate($this->date_lim_reglement_neu)."'" : "NULL").",";
|
|
$sql .= ((float) $this->betrag_offen).",";
|
|
$sql .= ((float) $this->mahngebuehr).",";
|
|
$sql .= ((float) $this->pauschale_b2b).",";
|
|
$sql .= ((float) $this->verzugszinsen).",";
|
|
$sql .= ((float) $this->summe_mahnung).",";
|
|
$sql .= "'".$this->db->escape($this->versandart ?: self::VERSAND_PDF)."',";
|
|
$sql .= ($this->customertype ? "'".$this->db->escape($this->customertype)."'" : "NULL").",";
|
|
$sql .= ($this->basiszins_snapshot !== null ? ((float) $this->basiszins_snapshot) : "NULL").",";
|
|
$sql .= ($this->pdf_path ? "'".$this->db->escape($this->pdf_path)."'" : "NULL").",";
|
|
$sql .= ($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL").",";
|
|
$sql .= ((int) $this->status).",";
|
|
$sql .= "'".$this->db->idate($now)."',";
|
|
$sql .= ((int) $user->id);
|
|
$sql .= ")";
|
|
|
|
dol_syslog(get_class($this).'::create', LOG_DEBUG);
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
|
|
$this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.'mahnung_mahnung');
|
|
$this->datec = $now;
|
|
$this->fk_user_creat = $user->id;
|
|
|
|
$this->db->commit();
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* @param int $id rowid
|
|
* @return int -1 Fehler, 0 nicht gefunden, >0 OK
|
|
*/
|
|
public function fetch($id)
|
|
{
|
|
$sql = "SELECT t.* FROM ".MAIN_DB_PREFIX."mahnung_mahnung as t";
|
|
$sql .= " WHERE t.rowid = ".((int) $id);
|
|
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$this->error = $this->db->lasterror();
|
|
return -1;
|
|
}
|
|
if (!$this->db->num_rows($resql)) {
|
|
$this->db->free($resql);
|
|
return 0;
|
|
}
|
|
|
|
$obj = $this->db->fetch_object($resql);
|
|
$this->id = $obj->rowid;
|
|
$this->entity = $obj->entity;
|
|
$this->ref = $obj->ref;
|
|
$this->fk_facture = $obj->fk_facture;
|
|
$this->fk_soc = $obj->fk_soc;
|
|
$this->stufe = $obj->stufe;
|
|
$this->date_mahnung = $this->db->jdate($obj->date_mahnung);
|
|
$this->date_lim_reglement_alt = $this->db->jdate($obj->date_lim_reglement_alt);
|
|
$this->date_lim_reglement_neu = $this->db->jdate($obj->date_lim_reglement_neu);
|
|
$this->betrag_offen = $obj->betrag_offen;
|
|
$this->mahngebuehr = $obj->mahngebuehr;
|
|
$this->pauschale_b2b = $obj->pauschale_b2b;
|
|
$this->verzugszinsen = $obj->verzugszinsen;
|
|
$this->summe_mahnung = $obj->summe_mahnung;
|
|
$this->versandart = $obj->versandart;
|
|
$this->customertype = $obj->customertype;
|
|
$this->basiszins_snapshot = $obj->basiszins_snapshot;
|
|
$this->pdf_path = $obj->pdf_path;
|
|
$this->note_private = $obj->note_private;
|
|
$this->status = (int) $obj->status;
|
|
$this->date_versand = isset($obj->date_versand) ? $this->db->jdate($obj->date_versand) : null;
|
|
$this->versandweg = $obj->versandweg ?? null;
|
|
$this->tracking_nr = $obj->tracking_nr ?? null;
|
|
$this->tracking_provider = $obj->tracking_provider ?? null;
|
|
$this->datec = $this->db->jdate($obj->datec);
|
|
$this->tms = $this->db->jdate($obj->tms);
|
|
$this->fk_user_creat = $obj->fk_user_creat;
|
|
$this->fk_user_modif = $obj->fk_user_modif;
|
|
|
|
// Alias für CommonObject::fetch_thirdparty()
|
|
$this->socid = $this->fk_soc;
|
|
|
|
$this->db->free($resql);
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Dokument generieren über das Dolibarr-Dokumentenmodell-System.
|
|
*
|
|
* @param string $modele Modellname ('standard_mahnung', 'generic_mahnung_odt')
|
|
* @param Translate $outputlangs Ausgabesprache
|
|
* @param int $hidedetails Details ausblenden
|
|
* @param int $hidedesc Beschreibung ausblenden
|
|
* @param int $hideref Referenz ausblenden
|
|
* @param array $moreparams Weitere Parameter
|
|
* @return int >0 OK, <=0 Fehler
|
|
*/
|
|
public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0, $moreparams = null)
|
|
{
|
|
global $conf, $langs;
|
|
|
|
$langs->load("mahnung@mahnung");
|
|
|
|
if (!dol_strlen($modele)) {
|
|
$modele = 'standard_mahnung';
|
|
if (!empty($this->model_pdf)) {
|
|
$modele = $this->model_pdf;
|
|
} elseif (getDolGlobalString('MAHNUNG_ADDON_PDF')) {
|
|
$modele = getDolGlobalString('MAHNUNG_ADDON_PDF');
|
|
}
|
|
}
|
|
|
|
$modelpath = "core/modules/mahnung/doc/";
|
|
|
|
return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref, $moreparams);
|
|
}
|
|
|
|
/**
|
|
* Mehrere Mahnungen laden.
|
|
*
|
|
* @param string $sortfield
|
|
* @param string $sortorder
|
|
* @param int $limit
|
|
* @param int $offset
|
|
* @param array $filter Schlüssel: fk_facture, fk_soc, stufe, status, ref_like
|
|
* @param string $mode 'list' | 'count'
|
|
* @return Mahnung[]|int Liste, Anzahl oder -1 bei Fehler
|
|
*/
|
|
public function fetchAll($sortfield = 'date_mahnung', $sortorder = 'DESC', $limit = 0, $offset = 0, $filter = array(), $mode = 'list')
|
|
{
|
|
$sql = "SELECT t.rowid FROM ".MAIN_DB_PREFIX."mahnung_mahnung as t";
|
|
$sql .= " WHERE t.entity = ".((int) $this->entity);
|
|
|
|
if (!empty($filter['fk_facture'])) {
|
|
$sql .= " AND t.fk_facture = ".((int) $filter['fk_facture']);
|
|
}
|
|
if (!empty($filter['fk_soc'])) {
|
|
$sql .= " AND t.fk_soc = ".((int) $filter['fk_soc']);
|
|
}
|
|
if (isset($filter['stufe']) && $filter['stufe'] !== '') {
|
|
$sql .= " AND t.stufe = ".((int) $filter['stufe']);
|
|
}
|
|
if (isset($filter['status']) && $filter['status'] !== '') {
|
|
$sql .= " AND t.status = ".((int) $filter['status']);
|
|
}
|
|
if (!empty($filter['ref_like'])) {
|
|
$sql .= " AND t.ref LIKE '%".$this->db->escape($filter['ref_like'])."%'";
|
|
}
|
|
|
|
if ($mode === 'count') {
|
|
$sqlcount = preg_replace('/SELECT t\.rowid/', 'SELECT COUNT(*) as total', $sql);
|
|
$resqlcount = $this->db->query($sqlcount);
|
|
if (!$resqlcount) {
|
|
return -1;
|
|
}
|
|
$objcount = $this->db->fetch_object($resqlcount);
|
|
$this->db->free($resqlcount);
|
|
return (int) $objcount->total;
|
|
}
|
|
|
|
$sql .= $this->db->order($sortfield, $sortorder);
|
|
if ($limit > 0) {
|
|
$sql .= $this->db->plimit($limit, $offset);
|
|
}
|
|
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$this->error = $this->db->lasterror();
|
|
return -1;
|
|
}
|
|
|
|
$result = array();
|
|
while ($obj = $this->db->fetch_object($resql)) {
|
|
$m = new self($this->db);
|
|
$m->fetch($obj->rowid);
|
|
$result[] = $m;
|
|
}
|
|
$this->db->free($resql);
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Mahnvorgang aktualisieren.
|
|
*
|
|
* @param User $user Bearbeitender User
|
|
* @return int <0 bei Fehler, sonst id
|
|
*/
|
|
public function update($user)
|
|
{
|
|
if (empty($this->id)) {
|
|
$this->error = 'Mahnung::update — id missing';
|
|
return -1;
|
|
}
|
|
|
|
$this->db->begin();
|
|
|
|
$sql = "UPDATE ".MAIN_DB_PREFIX."mahnung_mahnung SET";
|
|
$sql .= " stufe = ".((int) $this->stufe);
|
|
$sql .= ", date_mahnung = '".$this->db->idate($this->date_mahnung ?: dol_now())."'";
|
|
$sql .= ", date_lim_reglement_alt = ".($this->date_lim_reglement_alt ? "'".$this->db->idate($this->date_lim_reglement_alt)."'" : "NULL");
|
|
$sql .= ", date_lim_reglement_neu = ".($this->date_lim_reglement_neu ? "'".$this->db->idate($this->date_lim_reglement_neu)."'" : "NULL");
|
|
$sql .= ", betrag_offen = ".((float) $this->betrag_offen);
|
|
$sql .= ", mahngebuehr = ".((float) $this->mahngebuehr);
|
|
$sql .= ", pauschale_b2b = ".((float) $this->pauschale_b2b);
|
|
$sql .= ", verzugszinsen = ".((float) $this->verzugszinsen);
|
|
$sql .= ", summe_mahnung = ".((float) $this->summe_mahnung);
|
|
$sql .= ", versandart = '".$this->db->escape($this->versandart)."'";
|
|
$sql .= ", customertype = ".($this->customertype ? "'".$this->db->escape($this->customertype)."'" : "NULL");
|
|
$sql .= ", basiszins_snapshot = ".($this->basiszins_snapshot !== null ? ((float) $this->basiszins_snapshot) : "NULL");
|
|
$sql .= ", pdf_path = ".($this->pdf_path ? "'".$this->db->escape($this->pdf_path)."'" : "NULL");
|
|
$sql .= ", note_private = ".($this->note_private ? "'".$this->db->escape($this->note_private)."'" : "NULL");
|
|
$sql .= ", status = ".((int) $this->status);
|
|
$sql .= ", date_versand = ".($this->date_versand ? "'".$this->db->idate($this->date_versand)."'" : "NULL");
|
|
$sql .= ", versandweg = ".($this->versandweg ? "'".$this->db->escape($this->versandweg)."'" : "NULL");
|
|
$sql .= ", tracking_nr = ".($this->tracking_nr ? "'".$this->db->escape($this->tracking_nr)."'" : "NULL");
|
|
$sql .= ", tracking_provider = ".($this->tracking_provider ? "'".$this->db->escape($this->tracking_provider)."'" : "NULL");
|
|
$sql .= ", fk_user_modif = ".((int) $user->id);
|
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
|
|
|
dol_syslog(get_class($this).'::update', LOG_DEBUG);
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
|
|
$this->fk_user_modif = $user->id;
|
|
$this->db->commit();
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* Mahnvorgang löschen. Verknüpftes PDF wird mitgelöscht falls vorhanden.
|
|
*
|
|
* @param User $user Loeschender User
|
|
* @return int <0 bei Fehler, sonst 1
|
|
*/
|
|
public function delete($user)
|
|
{
|
|
$this->db->begin();
|
|
|
|
if ($this->pdf_path && file_exists($this->pdf_path)) {
|
|
@unlink($this->pdf_path);
|
|
}
|
|
|
|
$sql = "DELETE FROM ".MAIN_DB_PREFIX."mahnung_mahnung WHERE rowid = ".((int) $this->id);
|
|
dol_syslog(get_class($this).'::delete', LOG_DEBUG);
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql) {
|
|
$this->error = $this->db->lasterror();
|
|
$this->db->rollback();
|
|
return -1;
|
|
}
|
|
|
|
$this->db->commit();
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* Status auf "erledigt" setzen (Trigger nach Zahlungseingang).
|
|
*
|
|
* @param User $user
|
|
* @return int <0 bei Fehler, sonst 1
|
|
*/
|
|
public function setErledigt($user)
|
|
{
|
|
$this->status = self::STATUS_ERLEDIGT;
|
|
$res = $this->update($user);
|
|
return $res > 0 ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Versand-Daten setzen: Datum, Weg, optional Tracking-Nr/Provider.
|
|
* Setzt Status automatisch auf VERSENDET, wenn er noch <= ERSTELLT war.
|
|
*
|
|
* @param User $user
|
|
* @param int $dateVersand Unix-Zeit
|
|
* @param string $weg z.B. 'dhl', 'post', 'einschreiben', ...
|
|
* @param string|null $trackingNr
|
|
* @param string|null $trackingProvider
|
|
* @return int <0 Fehler, sonst 1
|
|
*/
|
|
public function setVersand($user, $dateVersand, $weg, $trackingNr = null, $trackingProvider = null)
|
|
{
|
|
$this->date_versand = $dateVersand;
|
|
$this->versandweg = $weg;
|
|
$this->tracking_nr = $trackingNr !== null && $trackingNr !== '' ? $trackingNr : null;
|
|
$this->tracking_provider = $trackingProvider !== null && $trackingProvider !== '' ? $trackingProvider : null;
|
|
if ((int) $this->status < self::STATUS_VERSENDET) {
|
|
$this->status = self::STATUS_VERSENDET;
|
|
}
|
|
$res = $this->update($user);
|
|
return $res > 0 ? 1 : -1;
|
|
}
|
|
|
|
/**
|
|
* Mapping versandweg → tracking_provider (Default-Provider je Versandweg).
|
|
*
|
|
* @param string $weg
|
|
* @return string|null
|
|
*/
|
|
public static function defaultProviderForWeg($weg)
|
|
{
|
|
switch ($weg) {
|
|
case 'dhl': return 'dhl';
|
|
case 'einschreiben': return 'dpag';
|
|
case 'dpd': return 'dpd';
|
|
case 'hermes': return 'hermes';
|
|
case 'ups': return 'ups';
|
|
default: return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Baut einen Sendungsverfolgungs-Deep-Link aus Provider + Tracking-Nr.
|
|
*
|
|
* @param string $provider dhl|dpag|hermes|dpd|ups|custom
|
|
* @param string $nr
|
|
* @return string Vollständige URL oder leer bei unbekanntem Provider
|
|
*/
|
|
public static function trackingUrl($provider, $nr)
|
|
{
|
|
$nr = trim((string) $nr);
|
|
if ($nr === '') {
|
|
return '';
|
|
}
|
|
$enc = rawurlencode($nr);
|
|
switch ((string) $provider) {
|
|
case 'dhl':
|
|
return 'https://www.dhl.de/de/privatkunden/dhl-sendungsverfolgung.html?piececode='.$enc;
|
|
case 'dpag':
|
|
return 'https://www.deutschepost.de/sendung/simpleQuery.html?form.sendungsnummer='.$enc;
|
|
case 'dpd':
|
|
return 'https://tracking.dpd.de/status/de_DE/parcel/'.$enc;
|
|
case 'hermes':
|
|
return 'https://www.myhermes.de/empfangen/sendungsverfolgung/sendungsinformation/#'.$enc;
|
|
case 'ups':
|
|
return 'https://www.ups.com/track?tracknum='.$enc;
|
|
default:
|
|
return '';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Lokalisiertes Versandweg-Label.
|
|
*
|
|
* @param string|null $weg Override (sonst $this->versandweg)
|
|
* @return string
|
|
*/
|
|
public function getVersandwegLabel($weg = null)
|
|
{
|
|
global $langs;
|
|
$w = $weg ?? $this->versandweg;
|
|
if (empty($w)) {
|
|
return '';
|
|
}
|
|
$key = 'MahnungVersandweg'.ucfirst(strtolower((string) $w));
|
|
$trans = $langs->trans($key);
|
|
return $trans !== $key ? $trans : (string) $w;
|
|
}
|
|
|
|
/**
|
|
* Letzten Mahnvorgang zu einer Rechnung holen (höchste Stufe, neuestes Datum).
|
|
*
|
|
* @param int $factureId
|
|
* @return Mahnung|null
|
|
*/
|
|
public function fetchLastByFacture($factureId)
|
|
{
|
|
$sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."mahnung_mahnung";
|
|
$sql .= " WHERE fk_facture = ".((int) $factureId);
|
|
$sql .= " AND entity = ".((int) $this->entity);
|
|
$sql .= " AND status NOT IN (".self::STATUS_STORNIERT.")";
|
|
$sql .= " ORDER BY stufe DESC, date_mahnung DESC, rowid DESC";
|
|
$sql .= " LIMIT 1";
|
|
|
|
$resql = $this->db->query($sql);
|
|
if (!$resql || !$this->db->num_rows($resql)) {
|
|
return null;
|
|
}
|
|
$obj = $this->db->fetch_object($resql);
|
|
$this->db->free($resql);
|
|
|
|
$m = new self($this->db);
|
|
if ($m->fetch($obj->rowid) > 0) {
|
|
return $m;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Verzugszinsen tagesgenau nach BGB §288 berechnen.
|
|
* Formel: zinsen = betrag_offen * (basiszins + aufschlag) / 100 * tage / 365
|
|
*
|
|
* @param float $betragOffen
|
|
* @param int $tageVerzug
|
|
* @param string $kundentyp B2C|B2B
|
|
* @param float $basiszins in Prozent (z.B. 1.27)
|
|
* @param float|null $zinssatzOverride Override aus Stufen-Konfig (Prozent)
|
|
* @return float Zinsen in EUR (gerundet 2 Nachkomma)
|
|
*/
|
|
public static function berechneVerzugszinsen($betragOffen, $tageVerzug, $kundentyp, $basiszins, $zinssatzOverride = null)
|
|
{
|
|
$tage = max(0, (int) $tageVerzug);
|
|
if ($tage <= 0 || $betragOffen <= 0) {
|
|
return 0.0;
|
|
}
|
|
|
|
if ($zinssatzOverride !== null) {
|
|
$satz = (float) $zinssatzOverride;
|
|
} else {
|
|
$aufschlag = ($kundentyp === self::KUNDENTYP_B2B)
|
|
? (float) getDolGlobalString('MAHNUNG_AUFSCHLAG_B2B', '9.0')
|
|
: (float) getDolGlobalString('MAHNUNG_AUFSCHLAG_B2C', '5.0');
|
|
$satz = (float) $basiszins + $aufschlag;
|
|
}
|
|
|
|
$zinsen = ((float) $betragOffen) * $satz / 100.0 * $tage / 365.0;
|
|
return round($zinsen, 2);
|
|
}
|
|
|
|
/**
|
|
* Setzt $summe_mahnung = betrag_offen + mahngebuehr + pauschale_b2b + verzugszinsen.
|
|
*
|
|
* @return float Neue Summe
|
|
*/
|
|
public function rechneSumme()
|
|
{
|
|
$this->summe_mahnung = round(
|
|
(float) $this->betrag_offen
|
|
+ (float) $this->mahngebuehr
|
|
+ (float) $this->pauschale_b2b
|
|
+ (float) $this->verzugszinsen,
|
|
2
|
|
);
|
|
return $this->summe_mahnung;
|
|
}
|
|
|
|
/**
|
|
* Lokalisiertes Status-Label.
|
|
*
|
|
* @param int|null $status Override (sonst $this->status)
|
|
* @return string
|
|
*/
|
|
public function getStatusLabel($status = null)
|
|
{
|
|
global $langs;
|
|
$s = $status ?? $this->status;
|
|
switch ((int) $s) {
|
|
case self::STATUS_ENTWURF: return $langs->trans('MahnungStatusEntwurf');
|
|
case self::STATUS_ERSTELLT: return $langs->trans('MahnungStatusErstellt');
|
|
case self::STATUS_VERSENDET: return $langs->trans('MahnungStatusVersendet');
|
|
case self::STATUS_ERLEDIGT: return $langs->trans('MahnungStatusErledigt');
|
|
case self::STATUS_STORNIERT: return $langs->trans('MahnungStatusStorniert');
|
|
default: return (string) $s;
|
|
}
|
|
}
|
|
}
|