Kunden und Adressen auf Prepared Statements umgebaut

incs/saveNchange.php neu geschrieben: Adressen, Telefonnummern, Kontakte,
Notizen und Konten laufen ueber db_abfrage() mit Platzhaltern, mehrschrittiges
Speichern in einer Transaktion. Weil sich die Speicherfunktionen gegenseitig
aufrufen, klammern beginneSpeichern()/beendeSpeichern() die Verschachtelung;
incs/rechnung.php nutzt sie ebenfalls.

Kunden- und Lieferantenseiten waren zwei fast gleiche Kopien und teilen sich
jetzt partnerAddSeite(), partnerChangeSeite() und partnerShowDaten().

Dabei behoben:
- SQL-Injektion ueber die Suchbegriffe der Kunden-, Lieferanten-, Adress-,
  Kommissions- und Projektsuche sowie ueber die Artikel-Autovervollstaendigung
- gespeichertes XSS: Notizen (nl2br escapt nicht), Bankname, Dokumenttyp,
  Namen und Adressen in allen Trefferlisten
- sites/liefershow.php war unter PHP 8 ein Fatal ($kdnres.id)
- "Telefonnummer loeschen" im Kundenbereich lief in einen Fatal, die Nummern
  einer geloeschten Adresse blieben stehen (Spalte hiess adress_id statt
  adresse_id, mysql_fetch_assoc gibt es nicht mehr)
- Geburtstag ohne Jahr wurde im Formular verschluckt, die IBAN kam beim
  Bearbeiten aus $_GET statt aus dem Konto
- die Versionskette eines Kunden brach nach einem Schritt ab
- Kommissionsadressen speicherten die Ortsangabe der Adresse statt der des
  Telefonformulars und einen Adresstyp als Telefontyp
- Blaettern in den Trefferlisten: ohne ORDER BY konnte dieselbe Zeile zweimal
  oder gar nicht erscheinen; ajax_searchadress() bekam die Seite nicht
- Hauptadresse laesst sich nicht mehr loeschen, Kundendaten nicht mehr ueber
  die Lieferantenseite (und umgekehrt)
- ajax/auto/* baute JSON von Hand zusammen, ein Anfuehrungszeichen im Ort
  machte die Liste unbrauchbar

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-21 19:47:01 +02:00
co-authored by Claude Opus 5
parent 3f7d070d7f
commit 3dfbf1c9c7
40 changed files with 1706 additions and 2194 deletions
+9
View File
@@ -119,6 +119,15 @@ function db_sql_text($dbconn, $sql, $params = array())
return $text;
}
/*
* Text als Praefix-Suchmuster fuer LIKE. % und _ waeren darin sonst
* Platzhalter; das Fluchtzeichen ist der Backslash.
*/
function db_like_praefix($text)
{
return str_replace(array("\\", "%", "_"), array("\\\\", "\%", "\_"), (string)$text)."%";
}
/* Erste Spalte der ersten Zeile, null ohne Treffer, bei Fehlern false. */
function db_wert($dbconn, $sql, $params = array())
{
+7
View File
@@ -36,6 +36,9 @@ function rrmdir($dir) {
function del_files($path, $pattern) {
$matches = Array();
$entries = Array();
// Fehlt das Verzeichnis, gibt es auch nichts zu loeschen
if(!is_dir($path))
return;
$dir = dir($path);
while ($entry = $dir->read())
{
@@ -51,6 +54,10 @@ function del_files($path, $pattern) {
function search_file($path, $pattern) {
$matches = Array();
$entries = Array();
$ret = "";
// Fehlt das Verzeichnis, gibt es auch nichts zu finden
if(!is_dir($path))
return $ret;
$dir = dir($path);
while ($entry = $dir->read())
{
+151 -200
View File
@@ -1,182 +1,100 @@
<?php
/*
* Die Suchbedingung der Kunden-, Lieferanten- und Adresssuche. $fields
* waehlt aus, worin gesucht wird, $src sind die einzelnen Suchbegriffe.
* Die Werte kommen als Platzhalter dazu, die Spaltennamen stehen fest.
*/
function partnerSuchbedingung($src, $combiner, $fields, &$params)
{
$spalten = array(
"all" => array("vname", "nname", "vname2", "nname2", "firma", "ort", "str", "plz", "partner.id"),
"kdnr" => array("partner.id"),
"name" => array("vname", "nname", "vname2", "nname2", "firma"),
"str" => array("str"),
"plz" => array("plz"),
"ort" => array("ort"),
"tel" => array("tel.nr"),
"kont" => array("kontakt"),
);
if(!isset($spalten[$fields]))
return "";
$combiner = $combiner == "OR" ? "OR" : "AND";
$bedingung = "";
foreach($src AS $tag)
{
$teile = array();
foreach($spalten[$fields] as $spalte)
{
$teile[] = "$spalte LIKE ?";
$params[] = "%".$tag."%";
}
$bedingung .= " $combiner (".implode(" OR ", $teile).")";
}
return $bedingung;
}
/*
* Kunden- bzw. Lieferantensuche, eine Zeile je Partner. $typ ist 1 fuer
* Kunden, 2 fuer Lieferanten. Mit $full kommen auch veraltete Versionen
* dazu; ihre Namen, Adressen und Telefonnummern stehen dann untereinander
* in einer Zelle (siehe zeilenHtml()).
* Rueckgabe: array("all" => sql, "limited" => sql mit LIMIT, "params" => Werte).
*/
function createPartQry($page,$pagesize,$src,$combiner,$fields,$full=0,$typ=1)
{
$joins = "FROM partner
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN strasse ON strasse.id = str_id
LEFT JOIN ort ON ort.id = ort_id
LEFT JOIN tel ON tel.partner_id = partner.id
LEFT JOIN kontakt ON kontakt.partner_id = partner.id";
if(!$full)
{
$query = "SELECT partner.id AS kdnr,firma,vname,nname,vname2,nname2,ort,plz,str,hnr, tel.nr AS tel FROM partner
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN strasse ON strasse.id = str_id
LEFT JOIN ort ON ort.id = ort_id
LEFT JOIN tel ON tel.partner_id = partner.id
LEFT JOIN kontakt ON kontakt.partner_id = partner.id
WHERE updated_by = 0 and adresse.typ_id = 1 AND partner.typ_id = $typ";
}
$query = "SELECT partner.id AS kdnr,firma,vname,nname,vname2,nname2,ort,plz,str,hnr, tel.nr AS tel
$joins
WHERE updated_by = 0 AND adresse.typ_id = 1 AND partner.typ_id = ?";
else
{
$query = "SELECT partner.id AS kdnr,firma,GROUP_CONCAT(CONCAT(vname,' ',nname) SEPARATOR '<br />') AS nname, '' AS vname,GROUP_CONCAT(CONCAT(vname2,' ',nname2) SEPARATOR '<br />') AS nname2,'' AS vname2,'' AS ort,GROUP_CONCAT(CONCAT(plz,' ',ort) SEPARATOR '<br />') AS plz,GROUP_CONCAT(CONCAT(str,' ',hnr) SEPARATOR '<br />') AS str,'' AS hnr, GROUP_CONCAT(tel.nr SEPARATOR '<br />') AS tel FROM partner
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN strasse ON strasse.id = str_id
LEFT JOIN ort ON ort.id = ort_id
LEFT JOIN tel ON tel.partner_id = partner.id
LEFT JOIN kontakt ON kontakt.partner_id = partner.id
WHERE partner.typ_id = $typ";
}
switch($fields)
{
case "all":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (vname LIKE '$tag' OR nname LIKE '$tag' OR vname2 LIKE '$tag' OR nname2 LIKE '$tag' OR firma LIKE '$tag' OR ort LIKE '$tag' OR str LIKE '$tag' OR plz LIKE '$tag' OR partner.id LIKE '$tag')";
}
break;
case "kdnr":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (partner.id LIKE '$tag')";
}
break;
case "name":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (vname LIKE '$tag' OR nname LIKE '$tag' OR vname2 LIKE '$tag' OR nname2 LIKE '$tag' OR firma LIKE '$tag')";
}
break;
case "str":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (str LIKE '$tag')";
}
break;
case "plz":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (plz LIKE '$tag')";
}
break;
case "ort":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (ort LIKE '$tag')";
}
break;
case "tel":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (tel.nr LIKE '$tag')";
}
break;
case "kont":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (kontakt LIKE '$tag')";
}
break;
}
$query .= " GROUP BY partner.id";
$query = "SELECT partner.id AS kdnr,firma,
GROUP_CONCAT(CONCAT(vname,' ',nname) ORDER BY adresse.id, tel.id SEPARATOR '\n') AS nname, '' AS vname,
GROUP_CONCAT(CONCAT(vname2,' ',nname2) ORDER BY adresse.id, tel.id SEPARATOR '\n') AS nname2,'' AS vname2,'' AS ort,
GROUP_CONCAT(CONCAT(plz,' ',ort) ORDER BY adresse.id, tel.id SEPARATOR '\n') AS plz,
GROUP_CONCAT(CONCAT(str,' ',hnr) ORDER BY adresse.id, tel.id SEPARATOR '\n') AS str,'' AS hnr,
GROUP_CONCAT(tel.nr ORDER BY adresse.id, tel.id SEPARATOR '\n') AS tel
$joins
WHERE partner.typ_id = ?";
$params = array((int)$typ);
$query .= partnerSuchbedingung($src, $combiner, $fields, $params);
// Ohne feste Reihenfolge kann dieselbe Zeile beim Blaettern zweimal
// oder gar nicht auftauchen
$query .= " GROUP BY partner.id ORDER BY partner.id";
$ret["all"] = $query;
$query .= " LIMIT ".(intval($page)*$pagesize).", $pagesize";
$ret["limited"] = $query;
$ret["limited"] = $query." LIMIT ".((int)$page*(int)$pagesize).", ".(int)$pagesize;
$ret["params"] = $params;
return $ret;
}
/*
* Adresssuche: wie createPartQry(), aber eine Zeile je Adresse statt je
* Partner. Damit laesst sich fuer ein Dokument eine Nebenadresse auswaehlen.
*/
function createAdressQry($page,$pagesize,$src,$combiner,$fields,$full=0,$typ=1)
{
if(!$full)
{
$query = "SELECT partner.id AS kdnr,firma,vname,nname,vname2,nname2,ort,plz,str,hnr,adresse.id AS adrid, tel.nr AS tel
FROM partner
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN strasse ON strasse.id = str_id
LEFT JOIN ort ON ort.id = ort_id
LEFT JOIN tel ON tel.partner_id = partner.id
LEFT JOIN kontakt ON kontakt.partner_id = partner.id
WHERE updated_by = 0 AND partner.typ_id = $typ";
}
else
{
$query = "SELECT partner.id AS kdnr,firma,vname,nname,vname2,nname2,ort,plz,str,hnr,adresse.id AS adrid, tel.nr AS tel
FROM partner
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN strasse ON strasse.id = str_id
LEFT JOIN ort ON ort.id = ort_id
LEFT JOIN tel ON tel.partner_id = partner.id
LEFT JOIN kontakt ON kontakt.partner_id = partner.id
WHERE partner.typ_id = $typ";
}
switch($fields)
{
case "all":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (vname LIKE '$tag' OR nname LIKE '$tag' OR vname2 LIKE '$tag' OR nname2 LIKE '$tag' OR firma LIKE '$tag' OR ort LIKE '$tag' OR str LIKE '$tag' OR plz LIKE '$tag' OR partner.id LIKE '$tag')";
}
break;
case "kdnr":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (partner.id LIKE '$tag')";
}
break;
case "name":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (vname LIKE '$tag' OR nname LIKE '$tag' OR vname2 LIKE '$tag' OR nname2 LIKE '$tag' OR firma LIKE '$tag')";
}
break;
case "str":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (str LIKE '$tag')";
}
break;
case "plz":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (plz LIKE '$tag')";
}
break;
case "ort":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (ort LIKE '$tag')";
}
break;
case "tel":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (tel.nr LIKE '$tag')";
}
break;
case "kont":
foreach($src AS $tag)
{
$tag = "%".$tag."%";
$query .= " $combiner (kontakt LIKE '$tag')";
}
break;
}
$query .= " GROUP BY adresse.id";
$query = "SELECT partner.id AS kdnr,firma,vname,nname,vname2,nname2,ort,plz,str,hnr,adresse.id AS adrid, tel.nr AS tel
FROM partner
LEFT JOIN adresse ON adresse.partner_id = partner.id
LEFT JOIN strasse ON strasse.id = str_id
LEFT JOIN ort ON ort.id = ort_id
LEFT JOIN tel ON tel.partner_id = partner.id
LEFT JOIN kontakt ON kontakt.partner_id = partner.id
WHERE ".($full ? "" : "updated_by = 0 AND ")."partner.typ_id = ?";
$params = array((int)$typ);
$query .= partnerSuchbedingung($src, $combiner, $fields, $params);
$query .= " GROUP BY adresse.id ORDER BY adresse.id";
$ret["all"] = $query;
$query .= " LIMIT ".$page*$pagesize.", $pagesize";
$ret["limited"] = $query;
$ret["limited"] = $query." LIMIT ".((int)$page*(int)$pagesize).", ".(int)$pagesize;
$ret["params"] = $params;
return $ret;
}
@@ -240,53 +158,62 @@ function createKdnRechQry($page,$pagesize,$src,$combiner,$id,$typ,$sks=0)
return $ret;
}
/* Projekte eines Kunden, Rueckgabe wie createKdnRechQry(). */
function createKdnProjectQry($page,$pagesize,$src,$combiner,$id)
{
$query = "SELECT project.id, project.name,
$combiner = $combiner == "OR" ? "OR" : "AND";
$params = array($id);
$query = "SELECT project.id, project.name,
DATE_FORMAT(project.datetime, '%d.%m.%Y') AS date,
SUM(CASE WHEN rechn = 0 THEN work.std ELSE 0 END) AS work
FROM project
FROM project
JOIN work ON project.id = work.project_id
AND partner_id='".$id."'";
AND partner_id = ?";
foreach($src AS $tag)
{
$tag .= "%";
$query .= " $combiner (work.bezeichn LIKE '$tag' OR project.name LIKE '$tag' OR DATE_FORMAT(project.datetime, '%d.%m.%Y') LIKE '$tag')";
$query .= " $combiner (work.bezeichn LIKE ? OR project.name LIKE ? OR DATE_FORMAT(project.datetime, '%d.%m.%Y') LIKE ?)";
array_push($params, $tag, $tag, $tag);
}
$query .= " GROUP BY project.id ORDER BY project.datetime DESC ";
$ret["all"] = $query;
$query .= " LIMIT ".$page*$pagesize.", $pagesize";
$ret["limited"] = $query;
$ret["limited"] = $query." LIMIT ".((int)$page*(int)$pagesize).", ".(int)$pagesize;
$ret["params"] = $params;
return $ret;
}
/* Kommissionsadressen (adresstyp 5) eines Kunden, Rueckgabe wie createKdnRechQry(). */
function createKommQry($page,$pagesize,$src,$combiner,$id)
{
$query = "SELECT adresse.id, adresse.partner_id, firma, vname, nname, vname2, nname2, titel_id, titel2_id, anrede_id, anrede2_id, str, hnr, ort, ortsteil,plz,ort,nr AS tel,vwahl
$combiner = $combiner == "OR" ? "OR" : "AND";
$params = array($id);
$query = "SELECT adresse.id, adresse.partner_id, firma, vname, nname, vname2, nname2, titel_id, titel2_id, anrede_id, anrede2_id, str, hnr, ort, ortsteil,plz,ort,nr AS tel,vwahl
FROM adresse
LEFT JOIN strasse ON adresse.str_id = strasse.id
LEFT JOIN ort ON ort_id = ort.id
LEFT JOIN strasse ON adresse.str_id = strasse.id
LEFT JOIN ort ON ort_id = ort.id
LEFT JOIN tel ON adresse.id = tel.adresse_id
WHERE adresse.partner_id='".$id."' AND adresse.typ_id = '5' ";
WHERE adresse.partner_id = ? AND adresse.typ_id = 5 ";
foreach($src AS $tag)
{
$tag .= "%";
$query .= " $combiner (ort LIKE '$tag'
OR str LIKE '$tag'
OR nr LIKE '$tag'
OR vname LIKE '$tag'
OR nname LIKE '$tag'
OR vname2 LIKE '$tag'
OR nname2 LIKE '$tag'
OR firma LIKE '$tag')";
$query .= " $combiner (ort LIKE ?
OR str LIKE ?
OR nr LIKE ?
OR vname LIKE ?
OR nname LIKE ?
OR vname2 LIKE ?
OR nname2 LIKE ?
OR firma LIKE ?)";
for($i = 0; $i < 8; $i++)
$params[] = $tag;
}
$query .= " GROUP BY adresse.id ORDER BY adresse.id DESC ";
$ret["all"] = $query;
$query .= " LIMIT ".$page*$pagesize.", $pagesize";
$ret["limited"] = $query;
$ret["limited"] = $query." LIMIT ".((int)$page*(int)$pagesize).", ".(int)$pagesize;
$ret["params"] = $params;
return $ret;
}
@@ -461,10 +388,29 @@ function createMsgQry($page,$pagesize,$src,$combiner,$user)
return $ret;
}
/* Artikelliste aus createRechQry()/createKdnRechQry() als escaptes HTML, eine Zeile je Artikel */
function artikelListeHtml($artikel)
/*
* Zahl der Treffer einer Suche. Die Abfragen aus create*Qry() gruppieren,
* deshalb wird die ungekuerzte Abfrage ausgefuehrt und gezaehlt, statt mit
* COUNT(*) zu arbeiten.
*/
function zaehleTreffer($dbconn, $queries)
{
return implode("<br />", array_map("htmlspecialchars", explode("\n", (string)$artikel)));
$res = isset($queries["params"])
? db_abfrage($dbconn, $queries["all"], $queries["params"])
: mysqli_query($dbconn, $queries["all"]);
if(!$res)
die("Datenbank fehler: ".htmlspecialchars(mysqli_error($dbconn)));
return mysqli_num_rows($res);
}
/*
* Mit \n verbundene Werte aus GROUP_CONCAT als escaptes HTML, eine Zeile
* je Wert. Zusammengebaut wird erst hier, damit Daten aus der Datenbank
* nicht als HTML durchschlagen.
*/
function zeilenHtml($text)
{
return implode("<br />", array_map("htmlspecialchars", explode("\n", (string)$text)));
}
function displayPages($pagesize,$currpage,$numentries,$refreshfunc,$ad_params = "")
@@ -585,25 +531,30 @@ function displayList($header,$entries,$speciallines=array(),$colors=array())
echo "</table>";
}
/*
* Bausteine fuer die Trefferlisten. Sie liefern fertiges HTML und escapen
* die Werte aus der Datenbank deshalb selbst.
*/
function makenameline($adresse)
{
$ret = $adresse["vname"]." ".$adresse["nname"];
if($adresse["firma"])
$ret .= "<br /><i><u>".$adresse["firma"]."</u></i>";
$ret = zeilenHtml(trim($adresse["vname"]." ".$adresse["nname"]));
if(!empty($adresse["firma"]))
$ret .= "<br /><i><u>".zeilenHtml($adresse["firma"])."</u></i>";
return $ret;
}
function makeadressline($adresse)
{
$ret["ort"] = $adresse["plz"]." ".$adresse["ort"];
$ret["str"] = $adresse["str"]." ".$adresse["hnr"];
$ret["ort"] = zeilenHtml(trim($adresse["plz"]." ".$adresse["ort"]));
$ret["str"] = zeilenHtml(trim($adresse["str"]." ".$adresse["hnr"]));
return $ret;
}
function maketelline($tel)
{
$ret="";
if(isset($tel["vwahl"]) && !stristr($tel["tel"], "-") && !stristr($tel["tel"], "/"))
$ret = $tel["vwahl"]."-";
$ret .= $tel["tel"];
$nr = isset($tel["tel"]) ? (string)$tel["tel"] : "";
$ret = "";
if(!empty($tel["vwahl"]) && !str_contains($nr, "-") && !str_contains($nr, "/"))
$ret = zeilenHtml($tel["vwahl"])."-";
$ret .= zeilenHtml($nr);
return $ret;
}
+13 -48
View File
@@ -1,36 +1,10 @@
<?php
require_once("saveNchange.php");
/* ---------------------------------------------------------------------
* Hilfsfunktionen für Formularwerte
* ------------------------------------------------------------------ */
/* Getrimmter Text aus $_POST, fehlend oder kein Text ergibt "" */
function formularText($name)
{
return isset($_POST[$name]) && is_string($_POST[$name]) ? trim($_POST[$name]) : "";
}
/*
* Zahl aus $_POST in deutscher Schreibweise. Steht ein Komma darin, ist es
* der Dezimaltrenner und Punkte sind Tausendertrenner ("1.234,50"). Ohne
* Komma gilt ein Punkt als Dezimaltrenner ("12.50", so liefert ihn die
* Artikel-Autovervollständigung). Leere oder ungültige Eingaben werden 0 -
* so hat sie der frühere, nicht strikte Modus gespeichert.
* Rechnungen, Angebote, Lieferscheine und Briefe. Die Hilfsfunktionen für
* Formularwerte (formularText(), formularZahl(), formularGanzzahl()) stehen
* in saveNchange.php, weil beide Module sie brauchen.
*/
function formularZahl($name)
{
$wert = str_replace(" ", "", formularText($name));
if(str_contains($wert, ","))
$wert = str_replace(array(".", ","), array("", "."), $wert);
return is_numeric($wert) ? $wert : "0";
}
/* Ganzzahl aus $_POST, gerundet wie MariaDB beim Speichern */
function formularGanzzahl($name)
{
return (int)round((float)formularZahl($name));
}
require_once("saveNchange.php");
/* Die zwölf Ankreuzfelder für den Adressblock als 0/1-Zeichenkette */
function formularAdressfelder()
@@ -423,7 +397,7 @@ function saveRechnung($dbconn,$update)
// Alles oder nichts: bricht ein Schritt ab, bleibt keine halbe Rechnung
// zurück. Der Entwurf in tmp_rechnung bleibt dann erhalten.
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
$err = 0;
if($update)
@@ -536,13 +510,9 @@ function saveRechnung($dbconn,$update)
if(!$err)
$err = loescheEntwurf($dbconn, $type);
if(!$err)
beendeSpeichern($dbconn, $err);
if($err)
{
mysqli_commit($dbconn);
}
else
{
mysqli_rollback($dbconn);
$err = error("Es ist ein Fehler beim Speichern aufgetreten, <br />
Ihre Rechnung ist aber noch vorhanden, <br />
Bitte gehen Sie <a href='?action=rechnungadd&type=$type'>zurück zum Rechnungsformular</a> <br />
@@ -598,7 +568,7 @@ function saveTmpRechnung($dbconn, $nurAktive)
);
$set = implode(", ", array_map(function($spalte) { return "`$spalte` = ?"; }, array_keys($felder)));
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
$err = 0;
$progressid = db_wert($dbconn, "SELECT id FROM tmp_rechnung WHERE user_id = ? AND typ_id = ? ORDER BY id LIMIT 1", array($_SESSION["user"], $type));
if($progressid === false)
@@ -649,17 +619,14 @@ function saveTmpRechnung($dbconn, $nurAktive)
$i++;
}
if($err)
mysqli_rollback($dbconn);
else
mysqli_commit($dbconn);
beendeSpeichern($dbconn, $err);
return array($progressid, $err);
}
function delRechnung($dbconn,$id)
{
$err = 0;
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
db_abfrage($dbconn, "DELETE FROM artikel_rechn WHERE rech_id = ?", array($id)) or $err = error("Fehler beim löschen der Artikel-Rechnung Beziehung <br />".mysqli_error($dbconn));
if(!$err)
db_abfrage($dbconn, "DELETE FROM artikel_eigensch WHERE rech_id = ?", array($id)) or $err = error("Fehler beim löschen der Artikel-Eigenschaften Beziehung <br />".mysqli_error($dbconn));
@@ -667,8 +634,7 @@ function delRechnung($dbconn,$id)
db_abfrage($dbconn, "DELETE FROM rechnung WHERE id = ? LIMIT 1", array($id)) or $err = error("Fehler beim löschen der Rechnung <br />".mysqli_error($dbconn));
if(!$err)
$err = saveLog($dbconn, db_sql_text($dbconn, "DELETE FROM rechnung WHERE id = ? LIMIT 1", array($id))." [rechnung DEL]", "", "löschen");
$err ? mysqli_rollback($dbconn) : mysqli_commit($dbconn);
return $err;
return beendeSpeichern($dbconn, $err);
}
/* Storno setzen (1) oder zurücknehmen (0) */
@@ -717,7 +683,7 @@ function copyRech($dbconn,$id,$adrid)
if($partnerid === false)
return error("Fehler beim ermitteln der Adressdaten <br />".mysqli_error($dbconn));
mysqli_begin_transaction($dbconn);
beginneSpeichern($dbconn);
list($rechnr, $err) = neueRechnungsnummer($dbconn, $res["typ_id"]);
if(!$err)
{
@@ -746,8 +712,7 @@ function copyRech($dbconn,$id,$adrid)
if(!$err)
$err = saveLog($dbconn, db_sql_text($dbconn, $sql, array($rechid, $id))." [rechnung copy]", "DELETE FROM artikel_eigensch WHERE rech_id = $rechid", "anlegen");
}
$err ? mysqli_rollback($dbconn) : mysqli_commit($dbconn);
return $err;
return beendeSpeichern($dbconn, $err);
}
function calculateRechnungsSum($dbconn, $rechid, $inclmwst)
+1141 -679
View File
File diff suppressed because it is too large Load Diff