Termine auf Prepared Statements umgebaut
Kalender, Terminliste, Terminformular und Terminzettel laufen ueber db_abfrage() mit Platzhaltern; das Anlegen einer mehrtaegigen Terminreihe liegt in einer Transaktion. Die Logik steckt jetzt in incs/termin.php, sites/termin*.php rufen sie nur noch auf. Dabei behoben: - SQL-Injektion ueber die Suchbegriffe der Terminliste, ueber die Mehrfachauswahl (Ankreuzfelder del<N>/erl<N> gingen roh in DELETE bzw. UPDATE), ueber die Wiedervorlage-Tage (INTERVAL $folgedays DAY) und ueber ?action=terminshow&id=... in maketerminarray(), maketerminadresse(), maketelnrn() und makegooglestring() - gespeichertes XSS: Beschreibung, Notiz, Termintyp, Ort, Kundenname und Mitarbeiterfarbe im Kalender, in der Terminliste und im Formular - "or $err=error(...)" stand innerhalb des Abfrage-Strings, dadurch wurden die Nebenzeilen einer Terminreihe beim Loeschen nie entfernt - die Abfrage zum Folgetermin las eine Spalte typ_id, die es in termin nicht gibt; Typ und Wiedervorlage fehlten deshalb beim Bearbeiten - ein Folgetermin wurde mit termtime='' und termdauer='' angelegt, ein Termin ohne Folgetermin mit followed_by='' - im strikten Modus Fehler - ein Termin ohne Datum landete auf dem 01.01.1970 und gab dabei "NICHTTERMINIERT!!" mitten in die Seite aus - die Ueberschneidungspruefung verglich ab dem zweiten Tag gegen das Ende des ersten Tages - eine unbekannte Registerkarte der Terminliste ergab ein leeres WHERE und damit einen SQL-Fehler; jetzt gilt die Standardansicht - terminshow.php pruefte den Typ mit = statt == - der Kalender haengt nicht mehr an der Locale de_DE (strftime) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+65
-44
@@ -285,60 +285,80 @@ function createRechQry($page,$pagesize,$src,$combiner,$sks=0)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Terminliste. $termtyp waehlt die Registerkarte:
|
||||
* 1 offene mit Datum, 2 offene ohne Datum, 3 erledigte,
|
||||
* 4 vorgemerkte (Wiedervorlage in der Zukunft), 5 ganztaegige.
|
||||
* Rueckgabe wie createKdnRechQry().
|
||||
*/
|
||||
function createTermQry($page,$pagesize,$src,$combiner,$termtyp)
|
||||
{
|
||||
|
||||
$query = "SELECT termin.id,termtyp.typ, termin.head, MIN(termtime) AS termtime, SEC_TO_TIME(SUM(TIME_TO_SEC(termdauer))) AS termdauer, user, user2, user3, user4, done, partner_id, adresse_id, termin.id, str, ort, ortsteil, plz, hnr, adresse.vname as vname, adresse.nname as nname,
|
||||
adresse.firma as firma,
|
||||
user.vname as uservname, user.nname as usernname, user.color as color,
|
||||
user2.vname as uservname2, user2.nname as usernname2,
|
||||
user3.vname as uservname3, user3.nname as usernname3,
|
||||
user4.vname as uservname4, user4.nname as usernname4,
|
||||
firma, vname2, nname2
|
||||
FROM termin
|
||||
LEFT JOIN termtyp ON termin.typ = termtyp.id
|
||||
LEFT JOIN adresse ON termin.adresse_id = adresse.id
|
||||
LEFT JOIN partner ON adresse.partner_id = partner.id
|
||||
LEFT JOIN strasse ON adresse.str_id = strasse.id
|
||||
LEFT JOIN ort ON strasse.ort_id = ort.id
|
||||
LEFT JOIN user ON termin.user = user.id
|
||||
LEFT JOIN user AS user2 ON termin.user2 = user2.id
|
||||
LEFT JOIN user AS user3 ON termin.user3 = user3.id
|
||||
LEFT JOIN user AS user4 ON termin.user4 = user4.id
|
||||
WHERE ";
|
||||
if($termtyp == 1)
|
||||
$query .= "termdauer != '24:00:00' AND termtime != '0000-00-00 00:00:00' AND done = 0 AND act_date < NOW()";
|
||||
elseif($termtyp == 2)
|
||||
$query .= "termdauer != '24:00:00' AND termtime = '0000-00-00 00:00:00' AND done = 0 AND act_date < NOW()";
|
||||
elseif($termtyp == 3)
|
||||
$query .= "termdauer != '24:00:00' AND done = 1 AND act_date < NOW()";
|
||||
elseif($termtyp == 4)
|
||||
$query .= "termdauer != '24:00:00' AND act_date > NOW()";
|
||||
elseif($termtyp == 5)
|
||||
$query .= "termdauer = '24:00:00'";
|
||||
$combiner = $combiner == "OR" ? "OR" : "AND";
|
||||
$params = array();
|
||||
$query = "SELECT termin.id, termtyp.typ, termin.head, MIN(termtime) AS termtime,
|
||||
SEC_TO_TIME(SUM(TIME_TO_SEC(termdauer))) AS termdauer,
|
||||
user, user2, user3, user4, done, partner_id, adresse_id, main_id,
|
||||
str, ort, ortsteil, plz, hnr, adresse.vname AS vname, adresse.nname AS nname,
|
||||
user.vname AS uservname, user.nname AS usernname, user.color AS color,
|
||||
user2.vname AS uservname2, user2.nname AS usernname2,
|
||||
user3.vname AS uservname3, user3.nname AS usernname3,
|
||||
user4.vname AS uservname4, user4.nname AS usernname4,
|
||||
firma, vname2, nname2
|
||||
FROM termin
|
||||
LEFT JOIN termtyp ON termin.typ = termtyp.id
|
||||
LEFT JOIN adresse ON termin.adresse_id = adresse.id
|
||||
LEFT JOIN partner ON adresse.partner_id = partner.id
|
||||
LEFT JOIN strasse ON adresse.str_id = strasse.id
|
||||
LEFT JOIN ort ON strasse.ort_id = ort.id
|
||||
LEFT JOIN user ON termin.user = user.id
|
||||
LEFT JOIN user AS user2 ON termin.user2 = user2.id
|
||||
LEFT JOIN user AS user3 ON termin.user3 = user3.id
|
||||
LEFT JOIN user AS user4 ON termin.user4 = user4.id
|
||||
WHERE ";
|
||||
switch((int)$termtyp)
|
||||
{
|
||||
case 2:
|
||||
$query .= "termdauer != '24:00:00' AND termtime = '0000-00-00 00:00:00' AND done = 0 AND act_date < NOW()";
|
||||
break;
|
||||
case 3:
|
||||
$query .= "termdauer != '24:00:00' AND done = 1 AND act_date < NOW()";
|
||||
break;
|
||||
case 4:
|
||||
$query .= "termdauer != '24:00:00' AND act_date > NOW()";
|
||||
break;
|
||||
case 5:
|
||||
$query .= "termdauer = '24:00:00'";
|
||||
break;
|
||||
// 1 ist die uebliche Ansicht und faengt zugleich unbekannte Werte ab
|
||||
default:
|
||||
$query .= "termdauer != '24:00:00' AND termtime != '0000-00-00 00:00:00' AND done = 0 AND act_date < NOW()";
|
||||
break;
|
||||
}
|
||||
foreach($src AS $tag)
|
||||
{
|
||||
$tag = "%".$tag."%";
|
||||
$query .= " $combiner (termin.head LIKE '$tag' OR
|
||||
termin.text LIKE '$tag' OR
|
||||
adresse.firma LIKE '$tag' OR
|
||||
adresse.vname LIKE '$tag' OR
|
||||
adresse.nname LIKE '$tag' OR
|
||||
ort LIKE '$tag' OR
|
||||
plz LIKE '$tag' OR
|
||||
str LIKE '$tag' OR
|
||||
DATE_FORMAT(termtime, '%d.%m.%Y %H:%i') LIKE '$tag')";
|
||||
$query .= " $combiner (termin.head LIKE ? OR
|
||||
termin.text LIKE ? OR
|
||||
adresse.firma LIKE ? OR
|
||||
adresse.vname LIKE ? OR
|
||||
adresse.nname LIKE ? OR
|
||||
ort LIKE ? OR
|
||||
plz LIKE ? OR
|
||||
str LIKE ? OR
|
||||
DATE_FORMAT(termtime, '%d.%m.%Y %H:%i') LIKE ?)";
|
||||
for($i = 0; $i < 9; $i++)
|
||||
$params[] = $tag;
|
||||
}
|
||||
if($termtyp == 2)
|
||||
if((int)$termtyp == 2)
|
||||
$query .= " GROUP BY main_id ORDER BY ort ASC, termtime DESC";
|
||||
elseif($termtyp != 5 && $termtyp != 3)
|
||||
elseif((int)$termtyp != 5 && (int)$termtyp != 3)
|
||||
$query .= " GROUP BY main_id ORDER BY termtime ASC";
|
||||
else
|
||||
$query .= " GROUP BY main_id ORDER BY termtime 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;
|
||||
}
|
||||
|
||||
@@ -502,7 +522,8 @@ function displayList($header,$entries,$speciallines=array(),$colors=array())
|
||||
echo "<tr style='background-color: #e2e2e2;'>";
|
||||
|
||||
if(isset($colors[$i]))
|
||||
echo "<td bgcolor='".$colors[$i]."' style='box-shadow: inset 0 0 0.7em #000; border: 1px solid black; border-top-left-radius: 0.5em; border-bottom-left-radius: 0.5em;'></td>";
|
||||
// die Farbe kommt aus der Benutzerverwaltung, nicht aus dem Code
|
||||
echo "<td bgcolor='".htmlspecialchars((string)$colors[$i])."' style='box-shadow: inset 0 0 0.7em #000; border: 1px solid black; border-top-left-radius: 0.5em; border-bottom-left-radius: 0.5em;'></td>";
|
||||
|
||||
foreach($entry AS $element)
|
||||
{
|
||||
|
||||
+57
-87
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
|
||||
require_once(__DIR__."/db.php");
|
||||
require_once('tcpdf/tcpdf.php');
|
||||
|
||||
// Unicode-Schriften statt der eingebauten PDF-Schriften Times/Helvetica: Die kennen
|
||||
@@ -1332,9 +1333,10 @@ function makesingleterminpage($pdf,$termin,$adresse,$telnrn,$anfahrt,$googleadre
|
||||
}
|
||||
}
|
||||
|
||||
/* Die Daten eines Termins fuer den Terminzettel */
|
||||
function maketerminarray($dbconn,$id)
|
||||
{
|
||||
$qry = mysqli_query($dbconn,"SELECT head, user, text, termin.id, termtime, termtyp.typ AS typ, termdauer, str, ort, hnr, plz, partner_id, land,
|
||||
$res = db_zeile($dbconn,"SELECT head, user, text, termin.id, termtime, termtyp.typ AS typ, termdauer, str, ort, hnr, plz, partner_id, land,
|
||||
adresse.vname AS vname, adresse.nname AS nname, titel_id, titel2_id, anrede_id, anrede2_id, vname2, nname2, zusatz,
|
||||
user.vname as uservname, user.nname as usernname,
|
||||
user2.vname as uservname2, user2.nname as usernname2,
|
||||
@@ -1350,72 +1352,38 @@ function maketerminarray($dbconn,$id)
|
||||
LEFT JOIN user AS user2 ON termin.user2 = user2.id
|
||||
LEFT JOIN user AS user3 ON termin.user3 = user3.id
|
||||
LEFT JOIN user AS user4 ON termin.user4 = user4.id
|
||||
WHERE termin.id = $id") or $err = error("Fehler beim ermitteln der Termindaten<br />".mysqli_error($dbconn));
|
||||
$res = mysqli_fetch_assoc($qry);
|
||||
|
||||
$qry = mysqli_query($dbconn,"SELECT anrede
|
||||
FROM anrede
|
||||
WHERE id = '".$res["anrede_id"]."'") or $err = error("Fehler beim ermitteln der Anrede<br />".mysqli_error($dbconn));
|
||||
$res2 = mysqli_fetch_assoc($qry);
|
||||
$res["anrede"] = $res2["anrede"];
|
||||
|
||||
$qry = mysqli_query($dbconn,"SELECT anrede
|
||||
FROM anrede
|
||||
WHERE id = '".$res["anrede2_id"]."'") or $err = error("Fehler beim ermitteln der Anrede2<br />".mysqli_error($dbconn));
|
||||
$res2 = mysqli_fetch_assoc($qry);
|
||||
$res["anrede2"] = $res2["anrede"];
|
||||
|
||||
$qry = mysqli_query($dbconn,"SELECT titel
|
||||
FROM titel
|
||||
WHERE id = '".$res["titel_id"]."'") or $err = error("Fehler beim ermitteln des Titels<br />".mysqli_error($dbconn));
|
||||
$res2 = mysqli_fetch_assoc($qry);
|
||||
$res["titel"] = $res2["titel"];
|
||||
|
||||
$qry = mysqli_query($dbconn,"SELECT titel
|
||||
FROM titel
|
||||
WHERE id = '".$res["titel2_id"]."'") or $err = error("Fehler beim ermitteln des Titel2<br />".mysqli_error($dbconn));
|
||||
$res2 = mysqli_fetch_assoc($qry);
|
||||
$res["titel2"] = $res2["titel"];
|
||||
|
||||
WHERE termin.id = ?", array($id));
|
||||
if(!$res)
|
||||
{
|
||||
error("Fehler beim ermitteln der Termindaten<br />".mysqli_error($dbconn));
|
||||
return array();
|
||||
}
|
||||
$anrs = db_zuordnung($dbconn, "SELECT id, anrede FROM anrede") ?: array();
|
||||
$titels = db_zuordnung($dbconn, "SELECT id, titel FROM titel") ?: array();
|
||||
$res["anrede"] = $anrs[$res["anrede_id"]] ?? "";
|
||||
$res["anrede2"] = $anrs[$res["anrede2_id"]] ?? "";
|
||||
$res["titel"] = $titels[$res["titel_id"]] ?? "";
|
||||
$res["titel2"] = $titels[$res["titel2_id"]] ?? "";
|
||||
return $res;
|
||||
}
|
||||
|
||||
function maketerminadresse($dbconn,$termid)
|
||||
{
|
||||
|
||||
$qry=mysqli_query($dbconn,"SELECT nname, titel_id, titel2_id, vname, nname2, vname2, str, ort, plz, hnr, land, firma, anrede_id, anrede2_id, partner_id, adresse_id
|
||||
FROM termin
|
||||
JOIN adresse ON termin.adresse_id = adresse.id
|
||||
JOIN strasse ON strasse.id = str_id
|
||||
$adresse = db_zeile($dbconn,"SELECT nname, titel_id, titel2_id, vname, nname2, vname2, str, ort, plz, hnr, land, firma, anrede_id, anrede2_id, partner_id, adresse_id
|
||||
FROM termin
|
||||
JOIN adresse ON termin.adresse_id = adresse.id
|
||||
JOIN strasse ON strasse.id = str_id
|
||||
JOIN ort ON ort.id = ort_id JOIN land ON land.id = land_id
|
||||
WHERE termin.id = $termid") or $err= error("Fehler beim ermitteln der Adressdaten<br />".mysqli_error($dbconn));
|
||||
|
||||
|
||||
$adresse = mysqli_fetch_assoc($qry);
|
||||
|
||||
$qry = mysqli_query($dbconn,"SELECT * FROM anrede");
|
||||
while($res=mysqli_fetch_assoc($qry))
|
||||
WHERE termin.id = ?", array($termid));
|
||||
if(!$adresse)
|
||||
{
|
||||
$anrs[$res["id"]] = $res["anrede"];
|
||||
error("Fehler beim ermitteln der Adressdaten<br />".mysqli_error($dbconn));
|
||||
$adresse = array();
|
||||
}
|
||||
|
||||
$qry = mysqli_query($dbconn,"SELECT * FROM titel");
|
||||
while($res=mysqli_fetch_assoc($qry))
|
||||
{
|
||||
$titels[$res["id"]] = $res["titel"];
|
||||
}
|
||||
|
||||
define("ADRFIELD_FIRMAANR", 0);
|
||||
define("ADRFIELD_FIRMA", 1);
|
||||
define("ADRFIELD_ANR1", 2);
|
||||
define("ADRFIELD_TITEL1", 3);
|
||||
define("ADRFIELD_NAME1", 4);
|
||||
define("ADRFIELD_ANR2", 5);
|
||||
define("ADRFIELD_TITEL2", 6);
|
||||
define("ADRFIELD_NAME2", 7);
|
||||
define("ADRFIELD_STR", 8);
|
||||
define("ADRFIELD_ORT", 9);
|
||||
define("ADRFIELD_LAND", 10);
|
||||
// ADRFIELD_* stehen in incs/constants.php
|
||||
$anrs = db_zuordnung($dbconn, "SELECT id, anrede FROM anrede") ?: array();
|
||||
$titels = db_zuordnung($dbconn, "SELECT id, titel FROM titel") ?: array();
|
||||
|
||||
$adressfields = "";
|
||||
if($adresse["firma"])
|
||||
@@ -1800,50 +1768,52 @@ define("ADRFIELD_LAND", 10);
|
||||
|
||||
function maketelnrn($dbconn,$termid)
|
||||
{
|
||||
$qry=mysqli_query($dbconn,"SELECT partner_id, adresse_id
|
||||
FROM termin
|
||||
$telstr = "";
|
||||
$adresse = db_zeile($dbconn,"SELECT partner_id, adresse_id
|
||||
FROM termin
|
||||
JOIN adresse ON termin.adresse_id = adresse.id
|
||||
WHERE termin.id = $termid") or $err= error("Fehler beim ermitteln der Adressdaten<br />".mysqli_error($dbconn));
|
||||
|
||||
|
||||
if($adresse = mysqli_fetch_assoc($qry))
|
||||
WHERE termin.id = ?", array($termid));
|
||||
if($adresse)
|
||||
{
|
||||
$qry = mysqli_query($dbconn,"SELECT name,typ,tel.id,nr,ort,ortsteil,plz,vwahl FROM tel LEFT JOIN teltyp ON typ_id = teltyp.id LEFT JOIN ort ON ort_id = ort.id WHERE partner_id='".$adresse["partner_id"]."' AND (tel.adresse_id = 0 OR tel.adresse_id = '".$adresse["adresse_id"]."') ORDER BY typ_id ASC");
|
||||
while($res=mysqli_fetch_assoc($qry))
|
||||
{
|
||||
$telstr .= trim($res["typ"]).": "." (".$res["vwahl"].") ".$res["nr"]." in ".$res["ort"]."(".$res["name"].")\n";
|
||||
}
|
||||
$qry = mysqli_query($dbconn,"SELECT kontakt,typ FROM kontakt LEFT JOIN kontakttyp ON typ_id = kontakttyp.id WHERE partner_id='".$adresse["partner_id"]."' ORDER BY typ_id ASC");
|
||||
while($res=mysqli_fetch_assoc($qry))
|
||||
{
|
||||
$telstr .= trim($res["typ"]).": ".$res["kontakt"]."\n";
|
||||
}
|
||||
$zeilen = db_zeilen($dbconn,"SELECT name, typ, tel.id, nr, ort, ortsteil, plz, vwahl FROM tel
|
||||
LEFT JOIN teltyp ON tel.typ_id = teltyp.id
|
||||
LEFT JOIN ort ON tel.ort_id = ort.id
|
||||
WHERE partner_id = ? AND (tel.adresse_id = 0 OR tel.adresse_id = ?)
|
||||
ORDER BY tel.typ_id ASC", array($adresse["partner_id"], $adresse["adresse_id"]));
|
||||
foreach((array)$zeilen as $res)
|
||||
$telstr .= trim($res["typ"]).": "." (".$res["vwahl"].") ".$res["nr"]." in ".$res["ort"]."(".$res["name"].")\\n";
|
||||
$zeilen = db_zeilen($dbconn,"SELECT kontakt, typ FROM kontakt
|
||||
LEFT JOIN kontakttyp ON kontakt.typ_id = kontakttyp.id
|
||||
WHERE partner_id = ? ORDER BY kontakt.typ_id ASC", array($adresse["partner_id"]));
|
||||
foreach((array)$zeilen as $res)
|
||||
$telstr .= trim($res["typ"]).": ".$res["kontakt"]."\\n";
|
||||
}
|
||||
return $telstr;
|
||||
}
|
||||
|
||||
function makeadrtelnrn($dbconn,$partnerid)
|
||||
{
|
||||
$qry = mysqli_query($dbconn,"SELECT name,typ,tel.id,nr,ort,ortsteil,plz,vwahl FROM tel LEFT JOIN teltyp ON typ_id = teltyp.id LEFT JOIN ort ON ort_id = ort.id WHERE partner_id='".$partnerid."' ORDER BY typ_id ASC");
|
||||
while($res=mysqli_fetch_assoc($qry))
|
||||
{
|
||||
$telstr .= trim($res["typ"]).": "."(".$res["vwahl"].")".$res["nr"].",".$res["ort"]."(".$res["name"].")\n";
|
||||
}
|
||||
$telstr = "";
|
||||
$zeilen = db_zeilen($dbconn,"SELECT name, typ, tel.id, nr, ort, ortsteil, plz, vwahl FROM tel
|
||||
LEFT JOIN teltyp ON tel.typ_id = teltyp.id
|
||||
LEFT JOIN ort ON tel.ort_id = ort.id
|
||||
WHERE partner_id = ? ORDER BY tel.typ_id ASC", array($partnerid));
|
||||
foreach((array)$zeilen as $res)
|
||||
$telstr .= trim($res["typ"]).": "."(".$res["vwahl"].")".$res["nr"].",".$res["ort"]."(".$res["name"].")\\n";
|
||||
return $telstr;
|
||||
}
|
||||
|
||||
function makegooglestring($dbconn,$termid)
|
||||
{
|
||||
|
||||
$qry=mysqli_query($dbconn,"SELECT nname, titel_id, titel2_id, vname, nname2, vname2, str, ort, plz, hnr, land, firma, anrede_id, anrede2_id
|
||||
FROM termin
|
||||
JOIN adresse ON termin.adresse_id = adresse.id
|
||||
JOIN strasse ON strasse.id = str_id
|
||||
$googlestr = "";
|
||||
$adresse = db_zeile($dbconn,"SELECT nname, titel_id, titel2_id, vname, nname2, vname2, str, ort, plz, hnr, land, firma, anrede_id, anrede2_id
|
||||
FROM termin
|
||||
JOIN adresse ON termin.adresse_id = adresse.id
|
||||
JOIN strasse ON strasse.id = str_id
|
||||
JOIN ort ON ort.id = ort_id JOIN land ON land.id = land_id
|
||||
WHERE termin.id = $termid") or $err= error("Fehler beim ermitteln der Adressdaten<br />".mysqli_error($dbconn));
|
||||
|
||||
|
||||
if($adresse = mysqli_fetch_assoc($qry))
|
||||
WHERE termin.id = ?", array($termid));
|
||||
if($adresse)
|
||||
{
|
||||
$googlestr = "http://maps.googleapis.com/maps/api/staticmap";
|
||||
$googlestr .= "?markers=color:blue|label:A|";
|
||||
|
||||
+554
@@ -0,0 +1,554 @@
|
||||
<?php
|
||||
/*
|
||||
* Termine: Kalenderansicht, Terminliste, Anlegen, Ändern und Löschen.
|
||||
*
|
||||
* Ein Termin über mehrere Tage wird als Reihe einzelner Zeilen gespeichert,
|
||||
* die alle dasselbe `main_id` tragen - die id der ersten Zeile. Der Kalender
|
||||
* zeigt die Zeilen einzeln, die Liste fasst sie über `main_id` zusammen.
|
||||
*
|
||||
* Urlaub und Krankheit sind Termine ohne Kunden. Ihre Typ-ids stehen seit
|
||||
* jeher fest im Code (auch in `incs/users.php` bei der Urlaubsberechnung und
|
||||
* in `templates/addtermin.tpl`).
|
||||
*/
|
||||
require_once(__DIR__."/db.php");
|
||||
require_once(__DIR__."/saveNchange.php");
|
||||
|
||||
define("TERMTYP_URLAUB", 0);
|
||||
define("TERMTYP_KRANKHEIT", 5);
|
||||
|
||||
/* Ganztägige Termine bekommen diese Dauer; die Terminliste filtert darauf */
|
||||
define("TERMIN_GANZTAG", "24:00:00");
|
||||
|
||||
/* Leerwerte der NOT-NULL-Spalten - der strikte Modus lehnt '' dort ab */
|
||||
define("TERMIN_KEIN_DATUM", "0000-00-00 00:00:00");
|
||||
define("TERMIN_KEINE_DAUER", "00:00:00");
|
||||
|
||||
/* Urlaub und Krankheit laufen immer über ganze Tage */
|
||||
function terminIstGanztaegig($typ)
|
||||
{
|
||||
return $typ == TERMTYP_URLAUB || $typ == TERMTYP_KRANKHEIT;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Formularwerte
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* Die Felder aus addtermin.tpl. `datetime_start` und `datetime_end` kommen
|
||||
* in deutscher Schreibweise ("24.12.2026 um 09:30") und werden hier schon
|
||||
* in das Datenbankformat gebracht.
|
||||
*/
|
||||
function terminFormularwerte()
|
||||
{
|
||||
return array(
|
||||
"head" => formularText("head"),
|
||||
"text" => formularText("text"),
|
||||
"typ" => formularGanzzahl("typ"),
|
||||
"done" => formularGanzzahl("done") ? 1 : 0,
|
||||
"user" => formularGanzzahl("user"),
|
||||
"user2" => formularGanzzahl("user2"),
|
||||
"user3" => formularGanzzahl("user3"),
|
||||
"user4" => formularGanzzahl("user4"),
|
||||
"folge" => formularGanzzahl("folge") ? 1 : 0,
|
||||
"folgetyp" => formularGanzzahl("folgetyp"),
|
||||
"folgedays" => formularGanzzahl("folgedays"),
|
||||
"start" => dispdate_to_mysql_date(formularText("datetime_start"), 0),
|
||||
"ende" => dispdate_to_mysql_date(formularText("datetime_end"), 1),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verteilt einen Termin auf Tage. Länger als zwölf Stunden oder Urlaub und
|
||||
* Krankheit werden zu ganzen Tagen: Rückgabe ist
|
||||
* array(erster Tag, Dauer je Tag, Anzahl Tage).
|
||||
*/
|
||||
function terminTageUndDauer($werte)
|
||||
{
|
||||
$start = $werte["start"];
|
||||
$dauer = mysql_dauer($start, $werte["ende"]);
|
||||
$stunden = (int)strtok($dauer, ":");
|
||||
if($stunden <= 12 && !terminIstGanztaegig($werte["typ"]))
|
||||
return array($start, $dauer, 1);
|
||||
|
||||
// ceil() rechnet mit der Stundenzahl, nicht mit dem ganzen Zeitstring
|
||||
$tage = max(1, (int)ceil($stunden / 24));
|
||||
if($start != TERMIN_KEIN_DATUM)
|
||||
$start = substr($start, 0, 11)."00:00:00";
|
||||
return array($start, TERMIN_GANZTAG, $tage);
|
||||
}
|
||||
|
||||
/* Der $i-te Tag einer Terminreihe, ohne Datum bleibt es ohne Datum */
|
||||
function terminTag($start, $i)
|
||||
{
|
||||
if($start == TERMIN_KEIN_DATUM)
|
||||
return TERMIN_KEIN_DATUM;
|
||||
return date("Y-m-d H:i:s", strtotime("+".$i." day", strtotime($start)));
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Überschneidungen
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* Sucht einen Termin, bei dem $benutzer schon zwischen $start und $ende
|
||||
* eingetragen ist. $ausserMain schließt die gerade bearbeitete Reihe aus.
|
||||
* Gibt die id des kollidierenden Termins zurück, sonst null (false bei
|
||||
* Fehlern).
|
||||
*/
|
||||
function terminUeberschneidung($dbconn, $benutzer, $start, $ende, $ausserMain)
|
||||
{
|
||||
if(!$benutzer || $start == TERMIN_KEIN_DATUM)
|
||||
return null;
|
||||
$params = array(TERMIN_KEIN_DATUM, $benutzer, $benutzer, $benutzer, $benutzer);
|
||||
// eine main_id von 0 gibt es nur bei Altdaten, dann darf nichts ausgenommen werden
|
||||
$eigene = "";
|
||||
if($ausserMain > 0)
|
||||
{
|
||||
$eigene = " AND main_id != ?";
|
||||
$params[] = (int)$ausserMain;
|
||||
}
|
||||
array_push($params, $start, $start, $ende, $ende, $start, $ende);
|
||||
$sql = "SELECT id FROM
|
||||
(SELECT id, main_id, user, user2, user3, user4, termtime,
|
||||
DATE_ADD(termtime, INTERVAL CONCAT(HOUR(termdauer),' ',MINUTE(termdauer)) HOUR_MINUTE) AS termend
|
||||
FROM termin WHERE termtime != ? AND done = 0) AS belegt
|
||||
WHERE (user = ? OR user2 = ? OR user3 = ? OR user4 = ?)$eigene
|
||||
AND ((? >= termtime AND ? < termend)
|
||||
OR (? > termtime AND ? <= termend)
|
||||
OR (? <= termtime AND ? >= termend))
|
||||
LIMIT 1";
|
||||
return db_wert($dbconn, $sql, $params);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prüft alle vier Mitarbeiter eines Termins für jeden Tag der Reihe.
|
||||
* Rückgabe 0, wenn nichts kollidiert, sonst die Fehlermeldung.
|
||||
*/
|
||||
function pruefeUeberschneidungen($dbconn, $werte, $start, $dauer, $tage, $ausserMain)
|
||||
{
|
||||
foreach(range(0, $tage - 1) as $i)
|
||||
{
|
||||
$tagStart = terminTag($start, $i);
|
||||
$tagEnde = dauer_to_date($tagStart, $dauer);
|
||||
foreach(array("user", "user2", "user3", "user4") as $feld)
|
||||
{
|
||||
$treffer = terminUeberschneidung($dbconn, $werte[$feld], $tagStart, $tagEnde, $ausserMain);
|
||||
if($treffer === false)
|
||||
return error("Fehler beim überprüfen von Überlappungen:<br />".mysqli_error($dbconn));
|
||||
if($treffer !== null)
|
||||
return error("Dieser Mitarbeiter hat zu der Zeit bereits einen Termin, er kann nicht an zwei Orten gleichzeitig sein.");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Speichern
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* Legt einen Folgetermin an: gleicher Kopf und dieselben Mitarbeiter, aber
|
||||
* ohne Datum und mit einem Wiedervorlagedatum in $tage Tagen. Gibt dessen
|
||||
* id zurück oder false.
|
||||
*/
|
||||
function legeFolgeterminAn($dbconn, $werte, $adressid)
|
||||
{
|
||||
$sql = "INSERT INTO termin SET head = ?, text = '', adresse_id = ?, typ = ?,
|
||||
changetime = NOW(), datetime = NOW(), done = 0,
|
||||
termtime = ?, termdauer = ?, followed_by = 0,
|
||||
user = ?, user2 = ?, user3 = ?, user4 = ?, changeuser = ?,
|
||||
act_date = DATE_ADD(CURDATE(), INTERVAL ? DAY)";
|
||||
$params = array($werte["head"], $adressid, $werte["folgetyp"],
|
||||
TERMIN_KEIN_DATUM, TERMIN_KEINE_DAUER,
|
||||
$werte["user"], $werte["user2"], $werte["user3"], $werte["user4"],
|
||||
$_SESSION["user"], $werte["folgedays"]);
|
||||
if(!db_abfrage($dbconn, $sql, $params))
|
||||
{
|
||||
error("Fehler beim anlegen des Folgetermins:<br />".mysqli_error($dbconn));
|
||||
return false;
|
||||
}
|
||||
$id = mysqli_insert_id($dbconn);
|
||||
// Ein Termin ohne eigene Reihe ist sein eigener Hauptsatz
|
||||
db_abfrage($dbconn, "UPDATE termin SET main_id = ? WHERE id = ?", array($id, $id));
|
||||
if(saveLog($dbconn, db_sql_text($dbconn, $sql, $params)." [folgetermin, hat ID $id]",
|
||||
"DELETE FROM termin WHERE id = $id", "anlegen"))
|
||||
return false;
|
||||
return $id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Legt einen Termin an oder ändert ihn. $terminid ist die id der Reihe
|
||||
* (0 = neu), $adressid die Kundenadresse (0 bei Urlaub und Krankheit).
|
||||
*
|
||||
* Wird aus einem eintägigen Termin ein mehrtägiger, wird die alte Reihe
|
||||
* verworfen und neu angelegt - anders lässt sich die Reihe nicht umbauen.
|
||||
*/
|
||||
function speichereTermin($dbconn, $terminid, $adressid)
|
||||
{
|
||||
$werte = terminFormularwerte();
|
||||
list($start, $dauer, $tage) = terminTageUndDauer($werte);
|
||||
|
||||
beginneSpeichern($dbconn);
|
||||
|
||||
$neuAnlegen = !$terminid;
|
||||
if($terminid && $tage > 1)
|
||||
{
|
||||
// aus einem Einzeltermin wird eine Reihe: alte Zeilen verwerfen
|
||||
$err = loescheTerminreihe($dbconn, $terminid);
|
||||
if($err)
|
||||
return beendeSpeichern($dbconn, $err);
|
||||
$neuAnlegen = true;
|
||||
$terminid = 0;
|
||||
}
|
||||
elseif($terminid)
|
||||
{
|
||||
// Zeilen der bisherigen Reihe bis auf die erste entfernen
|
||||
$sql = "DELETE FROM termin WHERE main_id = ? AND id != ?";
|
||||
db_abfrage($dbconn, $sql, array($terminid, $terminid))
|
||||
or $err = error("Konnte Nebentermine nicht löschen:<br />".mysqli_error($dbconn));
|
||||
if(!empty($err))
|
||||
return beendeSpeichern($dbconn, $err);
|
||||
}
|
||||
|
||||
if(!$werte["done"])
|
||||
{
|
||||
$err = pruefeUeberschneidungen($dbconn, $werte, $start, $dauer, $tage, $terminid);
|
||||
if($err)
|
||||
return beendeSpeichern($dbconn, $err);
|
||||
}
|
||||
|
||||
$alt = null;
|
||||
if(!$neuAnlegen)
|
||||
{
|
||||
$alt = db_zeile($dbconn, "SELECT * FROM termin WHERE id = ?", array($terminid));
|
||||
if($alt === false)
|
||||
return beendeSpeichern($dbconn, error("Fehler beim ermitteln des Termins:<br />".mysqli_error($dbconn)));
|
||||
if(!$alt)
|
||||
return beendeSpeichern($dbconn, error("Dieser Termin existiert nicht!"));
|
||||
}
|
||||
|
||||
// Folgetermin nur einmal und nur, wenn der Termin gerade erledigt wird
|
||||
$folgeId = $alt ? (int)$alt["followed_by"] : 0;
|
||||
if($werte["done"] && $werte["folge"] && !$folgeId)
|
||||
{
|
||||
$folgeId = legeFolgeterminAn($dbconn, $werte, $adressid);
|
||||
if($folgeId === false)
|
||||
return beendeSpeichern($dbconn, 1);
|
||||
}
|
||||
|
||||
$felder = array(
|
||||
"head" => $werte["head"],
|
||||
"text" => $werte["text"],
|
||||
"adresse_id" => $adressid,
|
||||
"typ" => $werte["typ"],
|
||||
"done" => $werte["done"],
|
||||
"termdauer" => $dauer,
|
||||
"changeuser" => $_SESSION["user"],
|
||||
"user" => $werte["user"],
|
||||
"user2" => $werte["user2"],
|
||||
"user3" => $werte["user3"],
|
||||
"user4" => $werte["user4"],
|
||||
"followed_by" => $folgeId,
|
||||
);
|
||||
$zuweisung = array();
|
||||
foreach(array_keys($felder) as $spalte)
|
||||
$zuweisung[] = "`$spalte` = ?";
|
||||
$set = implode(", ", $zuweisung);
|
||||
$err = 0;
|
||||
|
||||
if(!$neuAnlegen)
|
||||
{
|
||||
$sql = "UPDATE termin SET $set, termtime = ?, changetime = NOW() WHERE id = ?";
|
||||
$params = array_merge(array_values($felder), array(terminTag($start, 0), $terminid));
|
||||
if(!db_abfrage($dbconn, $sql, $params))
|
||||
return beendeSpeichern($dbconn, error("Fehler beim ändern des Termins:<br />".mysqli_error($dbconn)));
|
||||
$altWerte = array();
|
||||
foreach(array_keys($felder) as $spalte)
|
||||
$altWerte[] = $alt[$spalte];
|
||||
$err = saveLog($dbconn, db_sql_text($dbconn, $sql, $params)." [termin change]",
|
||||
db_sql_text($dbconn, $sql, array_merge($altWerte, array($alt["termtime"], $terminid))), "ändern");
|
||||
}
|
||||
else
|
||||
{
|
||||
$mainId = 0;
|
||||
foreach(range(0, $tage - 1) as $i)
|
||||
{
|
||||
if($err)
|
||||
break;
|
||||
$sql = "INSERT INTO termin SET $set, termtime = ?, main_id = ?, changetime = NOW(), datetime = NOW()";
|
||||
$params = array_merge(array_values($felder), array(terminTag($start, $i), $mainId));
|
||||
if(!db_abfrage($dbconn, $sql, $params))
|
||||
{
|
||||
$err = error("Fehler beim anlegen des Termins:<br />".mysqli_error($dbconn));
|
||||
break;
|
||||
}
|
||||
$id = mysqli_insert_id($dbconn);
|
||||
if(!$mainId)
|
||||
{
|
||||
// der erste Tag ist der Hauptsatz der Reihe
|
||||
$mainId = $id;
|
||||
db_abfrage($dbconn, "UPDATE termin SET main_id = ? WHERE id = ?", array($id, $id))
|
||||
or $err = error("Fehler beim verknüpfen der Terminreihe:<br />".mysqli_error($dbconn));
|
||||
}
|
||||
if(!$err)
|
||||
$err = saveLog($dbconn, db_sql_text($dbconn, $sql, $params)." [termin add, hat ID $id]",
|
||||
"DELETE FROM termin WHERE id = $id", "anlegen");
|
||||
}
|
||||
}
|
||||
return beendeSpeichern($dbconn, $err);
|
||||
}
|
||||
|
||||
/* Löscht eine Terminreihe samt Nebenzeilen */
|
||||
function loescheTerminreihe($dbconn, $id)
|
||||
{
|
||||
beginneSpeichern($dbconn);
|
||||
$err = 0;
|
||||
$beschreibung = db_wert($dbconn, "SELECT head FROM termin WHERE id = ?", array($id));
|
||||
if($beschreibung === false)
|
||||
return beendeSpeichern($dbconn, error("Fehler beim ermitteln des Termins:<br />".mysqli_error($dbconn)));
|
||||
if($beschreibung === null)
|
||||
return beendeSpeichern($dbconn, error("Dieser Termin existiert nicht!"));
|
||||
|
||||
// erst die Nebenzeilen, dann der Hauptsatz - sonst verliert main_id den Bezug
|
||||
$sql = "DELETE FROM termin WHERE main_id = ? AND id != ?";
|
||||
db_abfrage($dbconn, $sql, array($id, $id))
|
||||
or $err = error("Konnte Nebentermine nicht löschen:<br />".mysqli_error($dbconn));
|
||||
if(!$err)
|
||||
{
|
||||
$sql = "DELETE FROM termin WHERE id = ?";
|
||||
db_abfrage($dbconn, $sql, array($id))
|
||||
or $err = error("Konnte Haupttermin nicht löschen:<br />".mysqli_error($dbconn));
|
||||
}
|
||||
if(!$err)
|
||||
$err = saveLog($dbconn, db_sql_text($dbconn, "DELETE FROM termin WHERE main_id = ?", array($id))." [$beschreibung]", "", "löschen");
|
||||
return beendeSpeichern($dbconn, $err);
|
||||
}
|
||||
|
||||
/* Markiert eine Terminreihe als erledigt ($erledigt = 1) oder offen (0) */
|
||||
function setzeTerminErledigt($dbconn, $id, $erledigt)
|
||||
{
|
||||
$erledigt = $erledigt ? 1 : 0;
|
||||
$vorhanden = db_wert($dbconn, "SELECT id FROM termin WHERE id = ?", array($id));
|
||||
if($vorhanden === false)
|
||||
return error("Fehler beim ermitteln des Termins:<br />".mysqli_error($dbconn));
|
||||
if($vorhanden === null)
|
||||
return error("Dieser Termin existiert nicht!");
|
||||
|
||||
beginneSpeichern($dbconn);
|
||||
$err = 0;
|
||||
$sql = "UPDATE termin SET done = ?, changetime = NOW(), changeuser = ? WHERE main_id = ? OR id = ?";
|
||||
$params = array($erledigt, $_SESSION["user"], $id, $id);
|
||||
db_abfrage($dbconn, $sql, $params)
|
||||
or $err = error("Konnte den Termin nicht umstellen:<br />".mysqli_error($dbconn));
|
||||
if(!$err)
|
||||
$err = saveLog($dbconn, db_sql_text($dbconn, $sql, $params)." [termin erledigt]", "", "ändern");
|
||||
return beendeSpeichern($dbconn, $err);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Lesen
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
* Der Termin für das Formular: die Reihe zu einer Hauptsatz-id wird zu
|
||||
* einem Eintrag zusammengefasst, Anfang und Gesamtdauer eingeschlossen.
|
||||
*/
|
||||
function terminZumBearbeiten($dbconn, $id)
|
||||
{
|
||||
$res = db_zeile($dbconn, "SELECT MIN(termtime) AS termtime,
|
||||
SEC_TO_TIME(SUM(TIME_TO_SEC(termdauer))) AS termdauer,
|
||||
head, followed_by, MIN(id) AS id, main_id, typ, adresse_id,
|
||||
done, user, user2, user3, user4, changeuser, act_date, text
|
||||
FROM termin WHERE main_id = ? GROUP BY main_id", array($id));
|
||||
if($res === false)
|
||||
{
|
||||
error("Fehler beim ermitteln des Termins:<br />".mysqli_error($dbconn));
|
||||
return null;
|
||||
}
|
||||
if(!$res)
|
||||
return null;
|
||||
|
||||
if($res["followed_by"] > 0)
|
||||
{
|
||||
$folge = db_zeile($dbconn, "SELECT DATE_FORMAT(act_date,'%Y-%m-%d') AS act_date, typ FROM termin WHERE id = ?",
|
||||
array($res["followed_by"]));
|
||||
if($folge)
|
||||
{
|
||||
$res["folgetyp"] = $folge["typ"];
|
||||
$tage = (strtotime($folge["act_date"]) - strtotime(date("Y-m-d"))) / 86400;
|
||||
if($tage > 0)
|
||||
{
|
||||
$res["folge"] = 1;
|
||||
$res["folgedays"] = (int)$tage;
|
||||
}
|
||||
}
|
||||
}
|
||||
$res["termend"] = dauer_to_date($res["termtime"], $res["termdauer"]);
|
||||
if(str_contains($res["termend"], "00:00:00"))
|
||||
$res["termend"] = date("Y-m-d H:i:s", strtotime("-1 minutes", strtotime($res["termend"])));
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* Die Auswahllisten des Terminformulars */
|
||||
function terminAuswahllisten($dbconn, $smarty)
|
||||
{
|
||||
list($typids, $typs) = auswahlliste($dbconn, "SELECT id, typ FROM termtyp WHERE id > 0");
|
||||
$smarty->assign("typids", $typids);
|
||||
$smarty->assign("typs", $typs);
|
||||
|
||||
$benutzer = db_zeilen($dbconn, "SELECT id, vname, nname FROM user WHERE blocked = 0 AND id > 0 ORDER BY nname, vname");
|
||||
$ids = array();
|
||||
$namen = array();
|
||||
foreach((array)$benutzer as $b)
|
||||
{
|
||||
$ids[] = $b["id"];
|
||||
$namen[] = trim($b["vname"]." ".$b["nname"]);
|
||||
}
|
||||
$smarty->assign("userids", $ids);
|
||||
$smarty->assign("users", $namen);
|
||||
$ids[] = 0;
|
||||
$namen[] = "Keiner";
|
||||
$smarty->assign("optuserids", $ids);
|
||||
$smarty->assign("optusers", $namen);
|
||||
|
||||
$smarty->assign("days", range(0, 40));
|
||||
|
||||
list($urlaubIds, $urlaubNamen) = auswahlliste($dbconn, "SELECT id, typ FROM termtyp WHERE typ = 'Urlaub' OR typ = 'Krankheit'");
|
||||
$smarty->assign("vac_types_id", $urlaubIds);
|
||||
$smarty->assign("vac_types_name", $urlaubNamen);
|
||||
}
|
||||
|
||||
/* Die Adresse, an der ein Termin stattfindet - leer, wenn es keine gibt */
|
||||
function terminAdresse($dbconn, $adressid)
|
||||
{
|
||||
$res = db_zeile($dbconn, "SELECT plz, ortsteil, ort, str, hnr, vname, partner_id, nname, vname2, nname2,
|
||||
firma, adresse.id, land, anrede_id, titel_id, anrede2_id, titel2_id
|
||||
FROM adresse
|
||||
LEFT JOIN strasse ON str_id = strasse.id
|
||||
LEFT JOIN ort ON ort_id = ort.id
|
||||
LEFT JOIN land ON land_id = land.id
|
||||
WHERE adresse.id = ?", array($adressid));
|
||||
if($res === false)
|
||||
{
|
||||
error("Fehler beim abrufen der Daten:<br />".mysqli_error($dbconn));
|
||||
return array();
|
||||
}
|
||||
return $res ? $res : array();
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Kalender
|
||||
* ------------------------------------------------------------------ */
|
||||
|
||||
/* Deutsche Wochentagsnamen - unabhängig davon, ob die Locale vorhanden ist */
|
||||
function wochentag($zeitpunkt)
|
||||
{
|
||||
$namen = array("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag");
|
||||
return $namen[(int)date("w", $zeitpunkt)];
|
||||
}
|
||||
|
||||
/*
|
||||
* Die Termine eines Tages. $ganztags trennt die ganztägigen (Dauer über
|
||||
* zwölf Stunden) von den übrigen.
|
||||
*/
|
||||
function kalenderTermine($dbconn, $tag, $ganztags)
|
||||
{
|
||||
$vergleich = $ganztags ? ">" : "<";
|
||||
$sql = "SELECT termin.id, termtyp.typ, termin.head, termtime, termdauer,
|
||||
user, user2, user3, user4, done, partner_id, main_id,
|
||||
str, ort, ortsteil, plz, hnr, adresse.vname AS vname, adresse.nname AS nname,
|
||||
user.vname AS uservname, user.nname AS usernname,
|
||||
user2.vname AS uservname2, user2.nname AS usernname2,
|
||||
user3.vname AS uservname3, user3.nname AS usernname3,
|
||||
user4.vname AS uservname4, user4.nname AS usernname4,
|
||||
firma, vname2, nname2
|
||||
FROM termin
|
||||
LEFT JOIN termtyp ON termin.typ = termtyp.id
|
||||
LEFT JOIN adresse ON termin.adresse_id = adresse.id
|
||||
LEFT JOIN partner ON adresse.partner_id = partner.id
|
||||
LEFT JOIN strasse ON adresse.str_id = strasse.id
|
||||
LEFT JOIN ort ON strasse.ort_id = ort.id
|
||||
LEFT JOIN user ON termin.user = user.id
|
||||
LEFT JOIN user AS user2 ON termin.user2 = user2.id
|
||||
LEFT JOIN user AS user3 ON termin.user3 = user3.id
|
||||
LEFT JOIN user AS user4 ON termin.user4 = user4.id
|
||||
WHERE DATE(termtime) = ? AND termdauer $vergleich '12:00:00'
|
||||
ORDER BY termtime ASC";
|
||||
return db_zeilen($dbconn, $sql, array($tag)) ?: array();
|
||||
}
|
||||
|
||||
/* Die an einem Tag gebuchten Arbeiten aus der Projektverwaltung */
|
||||
function kalenderArbeiten($dbconn, $tag)
|
||||
{
|
||||
$sql = "SELECT work.id, project.id AS projectid, work.bezeichn AS head, work.rechn AS done,
|
||||
project.name AS projectname, work.datetime AS termtime, work.std AS termdauer,
|
||||
project.changeuser AS user, project.partner_id,
|
||||
adresse.vname AS vname, adresse.nname AS nname, adresse.firma AS firma
|
||||
FROM work
|
||||
LEFT JOIN project ON work.project_id = project.id
|
||||
LEFT JOIN partner ON project.partner_id = partner.id
|
||||
LEFT JOIN adresse ON adresse.partner_id = partner.id
|
||||
LEFT JOIN user ON work.changeuser = user.id
|
||||
WHERE adresse.typ_id = 1 AND DATE(work.datetime) = ?
|
||||
ORDER BY work.datetime ASC";
|
||||
return db_zeilen($dbconn, $sql, array($tag)) ?: array();
|
||||
}
|
||||
|
||||
/* Wer an einem Tag gestempelt hat und ob der Tag abgeschlossen ist */
|
||||
function kalenderAnwesenheit($dbconn, $tag)
|
||||
{
|
||||
$sql = "SELECT user.vname, user.nname, user.color,
|
||||
CASE MAX(zeiten.gehen) WHEN MAX(zeiten.kommen) THEN 0 ELSE 1 END AS complete
|
||||
FROM user
|
||||
LEFT JOIN zeiten ON user.id = zeiten.ma_id
|
||||
WHERE DATE(kommen) = ?
|
||||
GROUP BY user.id ORDER BY user.nname ASC";
|
||||
return db_zeilen($dbconn, $sql, array($tag)) ?: array();
|
||||
}
|
||||
|
||||
/*
|
||||
* Die acht Tage einer Kalenderseite, beginnend einen Tag vor dem
|
||||
* Seitenanfang (so ist der Vortag immer sichtbar).
|
||||
*/
|
||||
function kalenderTage($dbconn, $seite)
|
||||
{
|
||||
$heute = strtotime("today");
|
||||
$tage = array();
|
||||
for($i = $seite * 8 - 1; $i < $seite * 8 + 7; $i++)
|
||||
{
|
||||
$zeitpunkt = strtotime("+".$i." day", $heute);
|
||||
$datum = date("Y-m-d", $zeitpunkt);
|
||||
$feiertag = feiertag_bayern((int)date("d", $zeitpunkt), (int)date("m", $zeitpunkt), (int)date("Y", $zeitpunkt));
|
||||
$termine = array();
|
||||
if(($_SESSION["firma"] ?? "") == "Ingenieurbüro Wagner")
|
||||
$termine = kalenderArbeiten($dbconn, $datum);
|
||||
$termine = array_merge($termine, kalenderTermine($dbconn, $datum, false));
|
||||
|
||||
$tage[] = array(
|
||||
// am Feiertag steht der Name des Feiertags statt des Wochentags
|
||||
"weekday" => ($feiertag ? date("d.m.Y", $zeitpunkt)."<br/>" : wochentag($zeitpunkt)."<br/>".date("d.m.Y", $zeitpunkt)),
|
||||
"date" => date("Ymd", $zeitpunkt),
|
||||
"termine" => $termine,
|
||||
"fulldaytermine" => kalenderTermine($dbconn, $datum, true),
|
||||
"numfulldaytermine" => 0,
|
||||
"ma_check" => kalenderAnwesenheit($dbconn, $datum),
|
||||
"feiertag" => $feiertag ? $feiertag : "",
|
||||
);
|
||||
}
|
||||
return $tage;
|
||||
}
|
||||
|
||||
/* Die Mitarbeiter der Kalenderspalte samt Resturlaub */
|
||||
function kalenderBenutzer($dbconn)
|
||||
{
|
||||
$users = array();
|
||||
$zeilen = db_zeilen($dbconn, "SELECT id, vname, nname, color FROM user WHERE blocked = 0 AND nick != 'ALL'");
|
||||
foreach((array)$zeilen as $res)
|
||||
{
|
||||
$res["openvacation"] = urlaub_remaining($dbconn, $res["id"]);
|
||||
$users[$res["id"]] = $res;
|
||||
}
|
||||
return $users;
|
||||
}
|
||||
|
||||
?>
|
||||
Reference in New Issue
Block a user