Browse Source

Neue Struktur mit kunde_aufgabe und 7-Tage-Rückblick

gc-server6 1 year ago
parent
commit
97458e2a24

+ 259 - 256
app/ImportController.php

@@ -1,260 +1,263 @@
 <?php
+
 class ImportController
 {
-	public $fail;
-
-	private $dbh;
-	private $imap;
-
-	private $customers;
-	private $version;
-
-	private $currentErrorCount;
-
-
-	public function __construct ($database, $imap)
-	{
-		$this->dbh = new PDO($database['connect'], $database['user'], $database['password']);
-		$this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
-		$this->imap = $imap;
-
-		$this->loadCustomers();
-	}
-
-	public function Workflow ()
-	{
-		$this->connectToServer();
-		$this->importMails();
-		$this->closeConnection();
-	}
-
-
-	private function findAdditionalErrors ($fb, $whiteList)
-	{
-		$fb = str_replace("\r\`", "`", str_replace("\r\"", "\"", str_replace("\r\n", "", $fb)));
-		$report = json_decode($fb, true);
-
-		if (!$report) {
-			return addslashes($fb);
-		}
-
-		if ($whiteList) {
-			if (!isset($whiteList['Layer'])) $whiteList['Layer'] = array();
-			if (!isset($whiteList['Report'])) $whiteList['Report'] = array();
-			if (!isset($whiteList['User'])) $whiteList['User'] = array();
-		}
-
-		foreach ($report as $i => $log) {
-			if (preg_match("/\.bat$/", $log['Name'])) {
-				$report[$i]['Errors'][0] = htmlentities($report[$i]['Errors'][0]);
-				$report[$i]['Errors'][0] = preg_replace("/!! Bitte E-Mailadresse fuer Statusbericht angeben !!/im", "! Bitte E-Mailadresse fuer Statusbericht angeben !", $report[$i]['Errors'][0]);
-				$report[$i]['Errors'][0] = preg_replace("/!! SMTP-Konfiguration bitte anpassen !!/im", "! SMTP-Konfiguration bitte anpassen !", $report[$i]['Errors'][0]);
-				$count = 0;
-				$report[$i]['Errors'][0] = preg_replace("/(!![^\n]*!!)/im", "<b>$1</b>", $report[$i]['Errors'][0], -1, $count);
-				$count2 = 0;
-				$report[$i]['Errors'][0] = preg_replace("/\((\w{2}\d{4})\)( [^\r]*)/im", "<b><a href='http://gc-server1/wiki/$1' target='_blank'>($1)</a>$2</b>", $report[$i]['Errors'][0], -1, $count2);
-				//die(print($log['Errors'][0]));
-				if ($count > 0 || $count2 > 0) {
-					$report[$i]['ErrorLevel'] = 2;
-					for ($j = 1; $j < $count; $j++) {
-						$report[$i]['Errors'][] = "";
-					}
-					$this->currentErrorCount += 1;
-				}
-			} else if ($whiteList && count($report[$i]['Errors']) > 0 && ($report[$i]['Type'] == 'Versand' || $report[$i]['Type'] == 'Portal')) {
-				$report[$i]['Errors2'] = array();
-				foreach ($report[$i]['Errors'] as $j => $e) {
-					if (in_array($e['Layer'], $whiteList['Layer']) || in_array($e['Report'], $whiteList['Report']) || in_array($e['User'], $whiteList['User'])) {
-						$report[$i]['Errors2'][] = $report[$i]['Errors'][$j];
-						unset($report[$i]['Errors'][$j]);
-					}
-				}
-				if (count($report[$i]['Errors']) == 0) {
-					$report[$i]['ErrorLevel'] = 3;
-					$this->currentErrorCount -= 1;
-				}
-			}
-		}
-		return addslashes(json_encode($report));
-	}
-
-	private function loadCustomers ()
-	{
-		$q = $this->dbh->query("SELECT kunde, whitelist, version FROM kunden");
-		$customerQuery = $q->fetchAll(PDO::FETCH_ASSOC);
-		$this->customers = array();
-		$this->version = array();
-		foreach ($customerQuery as $c) {
-			$this->customers[$c['kunde']] = json_decode(stripslashes($c['whitelist']), true);
-			$this->version[$c['kunde']] = $c['version'];
-		}
-	}
-
-	private function connectToServer ()
-	{
-		$this->fail = false;
-		$this->imap['connect'] = imap_open($this->imap['server'], $this->imap['user'], $this->imap['password']) or die("Could not open Mailbox - try again later!");
-		$this->imap['message_count'] = imap_num_msg($this->imap['connect']);
-		if ($this->imap['message_count'] > 40) {
-			$this->imap['message_count'] = 40;
-			$this->fail = true;
-		}
-	}
-
-	private function importMails ()
-	{
-		for ($m = 1; $m <= $this->imap['message_count']; $m++) {
-			$this->currentErrorCount = 0;
-			$header = imap_headerinfo($this->imap['connect'], $m);
-			$rec = explode(";", $header->Subject);
-			
-			if ($rec[0] == "=?iso-8859-1?Q?L=B3ckenotto") {
-				$rec[0] = "Lueckenotto";
-			}
-
-			if (count($rec) < 5) continue;
-			if (count($rec) < 6) {
-				$rec[] = "";
-			}
-
-			$attachments = $this->getAttachments($m, @$this->customers[$rec[0]]);
-
-			$rec[] = $attachments['fehlerbericht'];
-			$rec[4] += $this->currentErrorCount;
-
-			/** @noinspection SqlInsertValues */
-			$insertQuery = "INSERT INTO status_meldung (kunde, start, ende, datum, anzahl, aufgabe, fehlerbericht) VALUES ('" . implode("','", $rec) . "')";
-			$c = $this->dbh->query($insertQuery);
-			if ($c) {
-				imap_delete($this->imap['connect'], $m);
-			} else {
-				if (strtotime($header->MailDate) < strtotime("-5 days")) {
-					imap_delete($this->imap['connect'], $m);
-				}
-				$error = $this->dbh->errorInfo();
-				if ($error[0] != "23000") {
-					print_r($error);					
-				}
-			}
-
-
-			if (!isset($this->customers[$rec[0]])) {
-				$this->dbh->query("INSERT INTO kunden (kunde) VALUES ('{$rec[0]}')");
-				$this->customers[$rec[0]] = array();
-			}
-
-			if (substr($rec[5], -4) == ".bat" && !isset($this->customers[$rec[0]][$rec[5]])) {
-				$this->dbh->query("INSERT INTO kunden_aufgabe (kunde,aufgabe,start_soll,ende_soll,erster_status) 
+  public $fail;
+
+  private $dbh;
+  private $imap;
+
+  private $customers;
+  private $version;
+
+  private $currentErrorCount;
+
+
+  public function __construct($database, $imap)
+  {
+    $this->dbh = new PDO($database['connect'], $database['user'], $database['password']);
+    $this->dbh->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
+    $this->imap = $imap;
+
+    $this->loadCustomers();
+  }
+
+  public function Workflow()
+  {
+    $this->connectToServer();
+    $this->importMails();
+    $this->closeConnection();
+  }
+
+
+  private function findAdditionalErrors($fb, $whiteList)
+  {
+    $fb = str_replace("\r\`", "`", str_replace("\r\"", "\"", str_replace("\r\n", "", $fb)));
+    $report = json_decode($fb, true);
+
+    if (!$report) {
+      return addslashes($fb);
+    }
+
+    if ($whiteList) {
+      if (!isset($whiteList['Layer'])) $whiteList['Layer'] = array();
+      if (!isset($whiteList['Report'])) $whiteList['Report'] = array();
+      if (!isset($whiteList['User'])) $whiteList['User'] = array();
+    }
+
+    foreach ($report as $i => $log) {
+      if (preg_match("/\.bat$/", $log['Name'])) {
+        $report[$i]['Errors'][0] = htmlentities($report[$i]['Errors'][0]);
+        $report[$i]['Errors'][0] = preg_replace("/!! Bitte E-Mailadresse fuer Statusbericht angeben !!/im", "! Bitte E-Mailadresse fuer Statusbericht angeben !", $report[$i]['Errors'][0]);
+        $report[$i]['Errors'][0] = preg_replace("/!! SMTP-Konfiguration bitte anpassen !!/im", "! SMTP-Konfiguration bitte anpassen !", $report[$i]['Errors'][0]);
+        $count = 0;
+        $report[$i]['Errors'][0] = preg_replace("/(!![^\n]*!!)/im", "<b>$1</b>", $report[$i]['Errors'][0], -1, $count);
+        $count2 = 0;
+        $report[$i]['Errors'][0] = preg_replace("/\((\w{2}\d{4})\)( [^\r]*)/im", "<b><a href='http://gc-server1/wiki/$1' target='_blank'>($1)</a>$2</b>", $report[$i]['Errors'][0], -1, $count2);
+        //die(print($log['Errors'][0]));
+        if ($count > 0 || $count2 > 0) {
+          $report[$i]['ErrorLevel'] = 2;
+          for ($j = 1; $j < $count; $j++) {
+            $report[$i]['Errors'][] = "";
+          }
+          $this->currentErrorCount += 1;
+        }
+      } else if ($whiteList && count($report[$i]['Errors']) > 0 && ($report[$i]['Type'] == 'Versand' || $report[$i]['Type'] == 'Portal')) {
+        $report[$i]['Errors2'] = array();
+        foreach ($report[$i]['Errors'] as $j => $e) {
+          if (in_array($e['Layer'], $whiteList['Layer']) || in_array($e['Report'], $whiteList['Report']) || in_array($e['User'], $whiteList['User'])) {
+            $report[$i]['Errors2'][] = $report[$i]['Errors'][$j];
+            unset($report[$i]['Errors'][$j]);
+          }
+        }
+        if (count($report[$i]['Errors']) == 0) {
+          $report[$i]['ErrorLevel'] = 3;
+          $this->currentErrorCount -= 1;
+        }
+      }
+    }
+    return addslashes(json_encode($report));
+  }
+
+  private function loadCustomers()
+  {
+    $q = $this->dbh->query("SELECT * FROM kunden_aufgabe");
+    $customerQuery = $q->fetchAll(PDO::FETCH_ASSOC);
+    $this->customers = array();
+    $this->version = array();
+    foreach ($customerQuery as $c) {
+      $this->customers[$c['kunde']][$c['aufgabe']] = $c;
+      $this->customers[$c['kunde']][$c['aufgabe']]['whitelist'] = json_decode(stripslashes($c['whitelist']), true);
+    }
+  }
+
+  private function connectToServer()
+  {
+    $this->fail = false;
+    $this->imap['connect'] = imap_open($this->imap['server'], $this->imap['user'], $this->imap['password']) or die("Could not open Mailbox - try again later!");
+    $this->imap['message_count'] = imap_num_msg($this->imap['connect']);
+    if ($this->imap['message_count'] > 40) {
+      $this->imap['message_count'] = 40;
+      $this->fail = true;
+    }
+  }
+
+  private function importMails()
+  {
+    for ($m = 1; $m <= $this->imap['message_count']; $m++) {
+      $this->currentErrorCount = 0;
+      $header = imap_headerinfo($this->imap['connect'], $m);
+      $rec = explode(";", $header->Subject);
+
+      if (count($rec) < 5) continue;
+      if (count($rec) < 6) {
+        $rec[] = "";
+      }
+      $currentTask = array('whitelist' => false);
+      if (isset($this->customers[$rec[0]]) && isset($this->customers[$rec[0]][$rec[5]])) {
+        $currentTask = $this->customers[$rec[0]][$rec[5]];
+      }
+
+      $attachments = $this->getAttachments($m, @$currentTask['whitelist']);
+
+      $rec[] = $attachments['fehlerbericht'];
+      $rec[4] += $this->currentErrorCount;
+
+      /** @noinspection SqlInsertValues */
+      $insertQuery = "INSERT INTO status_meldung (kunde, start, ende, datum, anzahl, aufgabe, fehlerbericht) VALUES ('" . implode("','", $rec) . "')";
+      $c = $this->dbh->query($insertQuery);
+      if ($c) {
+        imap_delete($this->imap['connect'], $m);
+      } else {
+        if (strtotime($header->MailDate) < strtotime("-5 days")) {
+          imap_delete($this->imap['connect'], $m);
+        }
+        $error = $this->dbh->errorInfo();
+        if ($error[0] != "23000") {
+          print_r($error);
+        }
+      }
+
+
+      if (!isset($this->customers[$rec[0]])) {
+        $this->dbh->query("INSERT INTO kunden (kunde) VALUES ('{$rec[0]}')");
+        $this->customers[$rec[0]] = array();
+      }
+
+      if (substr($rec[5], -4) == ".bat" && !isset($this->customers[$rec[0]][$rec[5]])) {
+        $this->dbh->query("INSERT INTO kunden_aufgabe (kunde,aufgabe,start_soll,ende_soll,erster_status) 
 											VALUES ('{$rec[0]}', '{$rec[5]}', '{$rec[1]}', '{$rec[2]}', '{$rec[3]}')");
-				$this->customers[$rec[0]][$rec[5]]['whitelist'] = false;
-			}
-
-			$ver = "";
-			if (preg_match("/Version:\s*(\d{4}-\d{2}-\d{2})_?(\w*)?/", $attachments['fehlerbericht'], $ver) && (!isset($version[$rec[0]]) || $version[$rec[0]] != $ver[1])) {
-				$beta = ($ver[2] == "beta") ? '1' : '0';
-				$this->dbh->query("UPDATE kunden SET version = '{$ver[1]}', beta_version = '{$beta}' WHERE kunde = '{$rec[0]}'");
-			}
-
-			if ($attachments['info']) {
-				$q = $this->dbh->query("SELECT * FROM kunden_config WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
-				$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
-				if (!$last || addslashes($last['info']) != $attachments['info']) {
-					$this->dbh->query("INSERT INTO kunden_config (kunde, datum, info) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['info']}')");
-				}
-			}
-
-			if ($attachments['starter']) {
-				$q = $this->dbh->query("SELECT * FROM kunden_gcstarter WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
-				$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
-				if (!$last || addslashes($last['gcstarter']) != $attachments['starter']) {
-					$this->dbh->query("INSERT INTO kunden_gcstarter (kunde, datum, gcstarter) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['starter']}')");
-				}
-			}
-
-			if ($attachments['struct']) {
-				$q = $this->dbh->query("SELECT * FROM kunden_gcstruct WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
-				$last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
-				if (!$last || addslashes($last['gcstruct']) != $attachments['struct']) {
-					$this->dbh->query("INSERT INTO kunden_gcstruct (kunde, datum, gcstruct) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['struct']}')");
-				}
-			}
-		}
-	}
-
-	private function closeConnection () {
-		imap_expunge($this->imap['connect']);
-		imap_close($this->imap['connect']);
-	}
-
-	private function getAttachments ($m, $customer = null)
-	{
-		$structure = imap_fetchstructure($this->imap['connect'], $m);
-		$attachments = array();
-		if (isset($structure->parts) && count($structure->parts)) {
-
-			for ($i = 0; $i < count($structure->parts); $i++) {
-
-				$attachments[$i] = array(
-					'is_attachment' => false,
-					'filename' => '',
-					'name' => '',
-					'attachment' => ''
-				);
-
-				if ($structure->parts[$i]->ifdparameters) {
-					foreach ($structure->parts[$i]->dparameters as $object) {
-						if (strtolower($object->attribute) == 'filename') {
-							$attachments[$i]['is_attachment'] = true;
-							$attachments[$i]['filename'] = $object->value;
-						}
-					}
-				}
-
-				if ($structure->parts[$i]->ifparameters) {
-					foreach ($structure->parts[$i]->parameters as $object) {
-						if (strtolower($object->attribute) == 'name') {
-							$attachments[$i]['is_attachment'] = true;
-							$attachments[$i]['name'] = $object->value;
-						}
-					}
-				}
-
-				if ($attachments[$i]['is_attachment']) {
-					$attachments[$i]['attachment'] = imap_fetchbody($this->imap['connect'], $m, $i + 1);
-					if ($structure->parts[$i]->encoding == 3) { // 3 = BASE64
-						$attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
-					} elseif ($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
-						$attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
-					}
-				}
-			}
-		}
-
-		$result = array(
-			'fehlerbericht' => 0,
-			'info' => 0,
-			'starter' => 0,
-			'struct' => 0
-		);
-
-		$result['fehlerbericht'] = addslashes(trim(imap_fetchbody($this->imap['connect'], $m, '1')));
-
-		foreach ($attachments as $key => $attachment) {
-			if ($attachment['is_attachment']) {
-				if ($attachment['filename'] == "info.json") {
-					$result['info'] = addslashes($attachment['attachment']);
-				}
-				if ($attachment['filename'] == "gcstarter.json") {
-					$result['starter'] = addslashes($attachment['attachment']);
-				}
-				if ($attachment['filename'] == "gcstruct.json") {
-					$result['struct'] = addslashes($attachment['attachment']);
-				}
-				if ($attachment['filename'] == "fehlerbericht.json") {
-					$result['fehlerbericht'] = $this->findAdditionalErrors($attachment['attachment'], $customer);
-				}
-			}
-		}
-		return $result;
-	}
-}
+        $this->customers[$rec[0]][$rec[5]]['whitelist'] = false;
+      }
+
+
+      $ver = "";
+      if (preg_match("/Version:\s*(\d{4}-\d{2}-\d{2})_?(\w*)?/", $attachments['fehlerbericht'], $ver) && (!isset($this->version[$rec[0]]) || $this->version[$rec[0]] != $ver[1])) {
+        $beta = ($ver[2] == "beta") ? '1' : '0';
+        $this->dbh->query("UPDATE kunden SET version = '{$ver[1]}', beta_version = '{$beta}' WHERE kunde = '{$rec[0]}'");
+      }
+
+      if ($attachments['info']) {
+        $q = $this->dbh->query("SELECT * FROM kunden_config WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
+        $last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
+        if (!$last || addslashes($last['info']) != $attachments['info']) {
+          $this->dbh->query("INSERT INTO kunden_config (kunde, datum, info) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['info']}')");
+        }
+      }
+
+      if ($attachments['starter']) {
+        $q = $this->dbh->query("SELECT * FROM kunden_gcstarter WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
+        $last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
+        if (!$last || addslashes($last['gcstarter']) != $attachments['starter']) {
+          $this->dbh->query("INSERT INTO kunden_gcstarter (kunde, datum, gcstarter) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['starter']}')");
+        }
+      }
+
+      if ($attachments['struct']) {
+        $q = $this->dbh->query("SELECT * FROM kunden_gcstruct WHERE kunde = '{$rec[0]}' ORDER BY datum DESC LIMIT 1");
+        $last = ($q && $q->rowCount() == 1) ? $q->fetch(PDO::FETCH_ASSOC) : false;
+        if (!$last || addslashes($last['gcstruct']) != $attachments['struct']) {
+          $this->dbh->query("INSERT INTO kunden_gcstruct (kunde, datum, gcstruct) VALUES ('{$rec[0]}', '{$rec[3]}', '{$attachments['struct']}')");
+        }
+      }
+    }
+  }
+
+  private function closeConnection()
+  {
+    imap_expunge($this->imap['connect']);
+    imap_close($this->imap['connect']);
+  }
+
+  private function getAttachments($m, $customer = null)
+  {
+    $structure = imap_fetchstructure($this->imap['connect'], $m);
+    $attachments = array();
+    if (isset($structure->parts) && count($structure->parts)) {
+
+      for ($i = 0; $i < count($structure->parts); $i++) {
+
+        $attachments[$i] = array(
+          'is_attachment' => false,
+          'filename' => '',
+          'name' => '',
+          'attachment' => ''
+        );
+
+        if ($structure->parts[$i]->ifdparameters) {
+          foreach ($structure->parts[$i]->dparameters as $object) {
+            if (strtolower($object->attribute) == 'filename') {
+              $attachments[$i]['is_attachment'] = true;
+              $attachments[$i]['filename'] = $object->value;
+            }
+          }
+        }
+
+        if ($structure->parts[$i]->ifparameters) {
+          foreach ($structure->parts[$i]->parameters as $object) {
+            if (strtolower($object->attribute) == 'name') {
+              $attachments[$i]['is_attachment'] = true;
+              $attachments[$i]['name'] = $object->value;
+            }
+          }
+        }
+
+        if ($attachments[$i]['is_attachment']) {
+          $attachments[$i]['attachment'] = imap_fetchbody($this->imap['connect'], $m, $i + 1);
+          if ($structure->parts[$i]->encoding == 3) { // 3 = BASE64
+            $attachments[$i]['attachment'] = base64_decode($attachments[$i]['attachment']);
+          } elseif ($structure->parts[$i]->encoding == 4) { // 4 = QUOTED-PRINTABLE
+            $attachments[$i]['attachment'] = quoted_printable_decode($attachments[$i]['attachment']);
+          }
+        }
+      }
+    }
+
+    $result = array(
+      'fehlerbericht' => 0,
+      'info' => 0,
+      'starter' => 0,
+      'struct' => 0
+    );
+
+    $result['fehlerbericht'] = addslashes(trim(imap_fetchbody($this->imap['connect'], $m, '1')));
+
+    foreach ($attachments as $key => $attachment) {
+      if ($attachment['is_attachment']) {
+        if ($attachment['filename'] == "info.json") {
+          $result['info'] = addslashes($attachment['attachment']);
+        }
+        if ($attachment['filename'] == "gcstarter.json") {
+          $result['starter'] = addslashes($attachment['attachment']);
+        }
+        if ($attachment['filename'] == "gcstruct.json") {
+          $result['struct'] = addslashes($attachment['attachment']);
+        }
+        if ($attachment['filename'] == "fehlerbericht.json") {
+          $result['fehlerbericht'] = $this->findAdditionalErrors($attachment['attachment'], $customer);
+        }
+      }
+    }
+    return $result;
+  }
+}

+ 50 - 75
app/db.php

@@ -1,5 +1,5 @@
 <?php
-header('Access-Control-Allow-Origin: *');
+// header('Access-Control-Allow-Origin: *');
 header('Access-Control-Allow-Methods: GET, POST, PUT');
 header('Access-Control-Allow-Headers: accept, content-type');
 header('Cache-Control: no-cache, must-revalidate');
@@ -17,33 +17,36 @@ switch ($_REQUEST['a']) {
 		$datum = $_REQUEST['datum'];
 		$start = ($_REQUEST['start'] == "null") ? '00:00:00' : $_REQUEST['start'];
 
-		$q = $dbh->query("SELECT sm.*, k.whitelist FROM status_meldung sm
-						  INNER JOIN kunden k USING (kunde)
-						  WHERE sm.datum = '{$datum}' AND sm.kunde = '{$kunde}' AND sm.start = '{$start}' LIMIT 1");
-		$result = $q->fetch(PDO::FETCH_ASSOC);
-		if ($result) {
-			$result['fehlerbericht'] = str_replace("\r\`", "`", str_replace("\r\"", "\"", str_replace("\r\n", "", $result['fehlerbericht'])));
-			$fehlerbericht = json_decode($result['fehlerbericht'], true);
-			if ($fehlerbericht != "") {
-				$result['fehlerbericht'] = $fehlerbericht;
-			}
+		if (count($data) > 0) {
 
-			$result['whitelist'] = (isset($result['whitelist'])) ? json_decode(stripslashes($result['whitelist']), true) : null;
 		} else {
-			$result = array();
-		}
-		if (isset($result['kommentar_id']) && $result['kommentar_id'] > 0) {
-			$q = $dbh->query("SELECT sk.* FROM status_kommentar sk
-							  WHERE sk.id = '{$result['kommentar_id']}' ");
-			$comment = $q->fetch(PDO::FETCH_ASSOC);	
-		} else {
-			$q = $dbh->query("SELECT sk.* FROM status_kommentar sk
-							  WHERE sk.datum = '{$datum}' AND sk.kunde = '{$kunde}' AND sk.start = '{$start}' 
-							  ORDER BY cdate DESC LIMIT 1");
-			$comment = $q->fetch(PDO::FETCH_ASSOC);
-		}
-		$result['kommentar'] = ($comment) ? $comment : array();
+			$q = $dbh->query("SELECT sm.*, k.whitelist FROM status_meldung sm
+			 				  INNER JOIN kunden k USING (kunde)
+							  WHERE sm.datum = '{$datum}' AND sm.kunde = '{$kunde}' AND sm.start = '{$start}' LIMIT 1");
+			$result = $q->fetch(PDO::FETCH_ASSOC);
+			if ($result) {
+				$result['fehlerbericht'] = str_replace("\r\`", "`", str_replace("\r\"", "\"", str_replace("\r\n", "", $result['fehlerbericht'])));
+				$fehlerbericht = json_decode($result['fehlerbericht'], true);
+				if ($fehlerbericht) {
+					$result['fehlerbericht'] = $fehlerbericht;
+				}
 
+				$result['whitelist'] = (isset($result['whitelist'])) ? json_decode(stripslashes($result['whitelist']), true) : null;
+			} else {
+				$result = array();
+			}
+			if (isset($result['kommentar_id']) && $result['kommentar_id'] > 0) {
+				$q = $dbh->query("SELECT sk.* FROM status_kommentar sk
+							      WHERE sk.id = '{$result['kommentar_id']}' ");
+				$comment = $q->fetch(PDO::FETCH_ASSOC);	
+			} else {
+				$q = $dbh->query("SELECT sk.* FROM status_kommentar sk
+							      WHERE sk.datum = '{$datum}' AND sk.kunde = '{$kunde}' AND sk.start = '{$start}' 
+								  ORDER BY cdate DESC LIMIT 1");
+				$comment = $q->fetch(PDO::FETCH_ASSOC);
+			}
+			$result['kommentar'] = ($comment) ? $comment : array();
+		}
 		break;
 
 	case 'zeit':
@@ -116,7 +119,7 @@ switch ($_REQUEST['a']) {
 
 		break;
 	case 'kunden':
-		if ($data != null && count($data) > 0) {
+		if (count($data) > 0) {
 			foreach ($data as $kunde) {
 				if (isset($kunde['kunde'])) {
 					$q = $dbh->exec("UPDATE kunden SET system = '{$kunde['system']}', start_soll = '{$kunde['start_soll']}', ende_soll = '{$kunde['ende_soll']}',
@@ -134,7 +137,7 @@ switch ($_REQUEST['a']) {
 		break;
 
 	case 'tickets':
-		if ($data != null && count($data) > 0) {
+		if (count($data) > 0) {
 			if ($data['id'] == '') {
 				$q = $dbh->exec("INSERT INTO tickets (datum, benutzer, kunde, kontakt, beschreibung, termin, dauer, status, prioritaet, fortschritt, kategorie, programm, kommentar)
 									VALUES ('{$data['datum']}', '{$data['benutzer']}', '{$data['kunde']}', '{$data['kontakt']}', '{$data['beschreibung']}', '{$data['termin']}', '{$data['dauer']}',
@@ -149,7 +152,6 @@ switch ($_REQUEST['a']) {
 		}
 		$q = $dbh->query("SELECT * FROM tickets");
 		$result = $q->fetchAll(PDO::FETCH_ASSOC);
-		//print_r($result);
 		break;
 
 	case 'config':
@@ -178,7 +180,7 @@ switch ($_REQUEST['a']) {
 	case 'kommentar':
 		$id = (isset($_REQUEST['id']) && $_REQUEST['id'] != "undefined") ? $_REQUEST['id'] : '';
 
-		if ($data != null && count($data) > 0) {
+		if (count($data) > 0) {
 			if ($id == '') {
 				$now = date('Y-m-d H:i:s');
 				$q = $dbh->exec("INSERT INTO status_kommentar (kunde, datum, start, benutzer, fehler, status, kommentar, cdate)
@@ -210,50 +212,23 @@ switch ($_REQUEST['a']) {
 		break;
 	default:
 	case 'liste':
-		$datum = (!isset($_REQUEST['datum']) || $_REQUEST['datum'] == '') ? "a.datum > date_add(now(), INTERVAL -32 DAY)" : "a.datum >= '{$_REQUEST['datum']}' ";
-		$datum_bis = (!isset($_REQUEST['datum_bis']) || $_REQUEST['datum_bis'] == '') ? "a.datum > date_add(now(), INTERVAL -32 DAY)" : "a.datum <= '{$_REQUEST['datum_bis']}' ";
-		$kunde = (!isset($_REQUEST['kunde']) || $_REQUEST['kunde'] == '') ? "1" : "k.kunde LIKE '%{$_REQUEST['kunde']}%'";
-
-		$q = $dbh->query("SELECT DISTINCT a.datum, k.kunde, sm.aufgabe, k.system, a.bundesland, a.feiertag, k.start_soll, k.ende_soll, sm.start, sm.ende, sm.anzahl, if(sk2.id IS NULL, sm.bearbeitet, '1') as bearbeitet,
-								case
-								 when woche = 'Mo-Fr' then mofr
-								 when woche = 'Mo-Sa' then mosa
-								 when woche = 'Mo-So' then moso
-								 when woche = 'Di-So' then diso
-								 else 1
-								end * if(sk.status <= 1, 0, 1) * if(sm.anzahl > 0 or (sm.anzahl is null and now() > date_add(concat(a.datum, ' ', k.ende_soll), INTERVAL 1 HOUR)), 1, 0) as fehler,
-								if(sm.anzahl is null and now() > date_add(concat(a.datum, ' ', k.ende_soll), INTERVAL 1 HOUR), 1, 0) as fehlend,
-								ifnull(sk.benutzer, '') as benutzer
-							FROM arbeitstage a
-							INNER JOIN kunden k USING (bundesland)
-							LEFT JOIN status_meldung sm USING (datum, kunde)
-							LEFT JOIN status_kommentar sk ON sm.kommentar_id = sk.id
-							LEFT JOIN status_kommentar as sk2 ON a.datum = sk2.datum AND k.kunde = sk2.kunde
-
-							WHERE {$datum} AND {$datum_bis} AND {$kunde} AND a.datum <= now() AND k.erster_status <= a.datum
-							AND k.aktiv = 1
-							ORDER BY a.datum, k.ende_soll");
-		$result = $q->fetchAll(PDO::FETCH_ASSOC);
-
-		if (isset($_REQUEST['events'])) {
-			$color = array("green", "#bb0", "#b80", "#d55", "#c33", "#a00", '?' => "#999");
-
-			$events = array();
-			foreach ($result as $e) {
-				if ($e['anzahl'] != '0') {
-					$event = array();
-					$anzahl = (!is_null($e['anzahl'])) ? $e['anzahl'] : "?";
-					$ende = ($e['ende']) ? $e['ende'] : $e['ende_soll'];
-					$event['title'] = "{$e['kunde']} ({$anzahl})";
-					$event['start'] = "{$e['datum']}T{$ende}";
-					$event['end'] = date("Y-m-d H:i:s", strtotime("+1 hour", strtotime($event['start'])));
-					$event['color'] = ($anzahl > 4) ? "darkred" : $color[$anzahl];
-					$events[] = $event;
-				}
-			}
-			$result = $events;
-		}
+		$query = file_get_contents(dirname(__FILE__)."/../queries/status_tag.sql");
+
+		if (isset($_REQUEST['datum']) && $_REQUEST['datum'] != '' && $_REQUEST['datum'] != 'today') {
+		  $query = str_replace("now()", "'" . $_REQUEST['datum'] . " 23:59:59'", $query);
+    }
+    //echo $query;
+    $q = $dbh->query($query);
+
+    while ($row = $q->fetch(PDO::FETCH_ASSOC)) {
+      $ka = $row['kunde'] . "-" . $row['aufgabe'];
+      if (!isset($result[$ka])) {
+        $result[$ka][0]['status'] = 'egal';
+      }
+      $result[$ka][$row['datum_diff']] = $row;
+    }
 }
-echo json_encode($result); 
-// print_r($result);
-// echo json_last_error();
+$json = json_encode($result);
+$hash = sha1($json);
+echo '{"result":'.$json.',"hash":"'.$hash.'"}';
+// echo json_last_error();

+ 4 - 110
app/index.html

@@ -5,109 +5,10 @@
     <title>Global Cube ITS</title>
     <meta name="description" content="">
     <meta name="viewport" content="width=device-width">
-    <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
-    <!-- build:css(.) styles/vendor.css -->
-    <!-- bower:css -->
     <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
+    <link rel="stylesheet" href="bower_components/bootstrap-datepicker/css/bootstrap-datepicker.css" />
     <link rel="stylesheet" href="bower_components/fullcalendar/dist/fullcalendar.css" />
-    <!-- endbower -->
-    <!-- endbuild -->
-    <!-- build:css(.tmp) styles/main.css -->
     <link rel="stylesheet" href="styles/main.css">
-    <!-- endbuild -->
-    <style type="text/css">
-        .table tr.middle > td, .table tr.middle > th {
-            vertical-align: middle;
-        }
-
-        .label-ARI {
-            background-color: #248;
-            color: #fff;
-        }
-
-        .label-AUDEV {
-            background-color: #fa0;
-            color: #000;
-        }
-
-        .label-AUTOLINE {
-            background-color: #285;
-            color: #eee;
-        }
-
-        .label-CARLO {
-            background-color: #79c;
-            color: #eee;
-        }
-
-        .label-HS {
-            background-color: #659;
-            color: #eee;
-        }
-
-        .label-LOCOSOFT {
-            background-color: #f66;
-            color: #000;
-        }
-
-        .label-NAVISION {
-            background-color: #36a;
-            color: #eee;
-        }
-
-        .label-OPTIMA {
-            background-color: #3a4;
-            color: #000;
-        }
-		
-		.label-WERWISO {
-            background-color: #a14;
-            color: #eee;
-        }
-		
-		.label-Autosys {
-            background-color: #ee1;
-            color: #000;
-        }
-        
-		.label-Filaks {
-            background-color: #888;
-            color: #eee;
-        }
-        
-		.label-O21-Light {
-            background-color: #be3;
-            color: #000;
-        }
-
-		.label-? {
-            background-color: #aaa;
-            color: #000;
-        }
-
-        .closed-tab {
-            display: none;
-        }
-
-        .caret-up {
-            border-bottom: 10px solid #000000;
-            border-left: 6px solid rgba(0, 0, 0, 0);
-            border-right: 6px solid rgba(0, 0, 0, 0);
-            content: "";
-            display: inline-block;
-            height: 0;
-            vertical-align: top;
-            width: 0;
-        }
-
-        .red {
-            color: #cc0000;
-        }
-
-        pre b {
-            background-color: #ee5555;
-        }
-    </style>
 </head>
 <body ng-app="fehlerberichtApp">
 <!--[if lt IE 7]>
@@ -115,14 +16,12 @@
     improve your experience.</p>
 <![endif]-->
 
-<!-- Add your site or application content here -->
 <div class="container-fluid">
     <div class="header">
         <h3 class="text-muted pull-left"><a ng-href="#">Global Cube ITS</a></h3>
         <ul class="nav nav-tabs">
             <li><a ng-href="#">Fehlerberichte</a></li>
             <li><a ng-href="#/tickets">Aufgaben</a></li>
-            <li><a ng-href="#/calendar">Kalender</a></li>
             <li><a ng-href="#/customers">Kundenliste</a></li>
             <li><a ng-href="#/config">Konfiguration</a></li>
             <li><a ng-href="#/stats/Altermann">Statistik</a></li>
@@ -136,19 +35,17 @@
 </div>
 
 
-<!-- build:js(.) scripts/oldieshim.js -->
 <!--[if lt IE 9]>
 <script src="bower_components/es5-shim/es5-shim.js"></script>
 <script src="bower_components/json3/lib/json3.min.js"></script>
 <![endif]-->
-<!-- endbuild -->
 
-<!-- build:js(.) scripts/vendor.js -->
-<!-- bower:js -->
 <script src="bower_components/jquery/dist/jquery.js"></script>
 <script src="bower_components/angular/angular.js"></script>
 <script src="bower_components/json3/lib/json3.js"></script>
 <script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
+<script src="bower_components/bootstrap-datepicker/js/bootstrap-datepicker.js"></script>
+<script src="bower_components/bootstrap-datepicker/locales/bootstrap-datepicker.de.min.js"></script>
 <script src="bower_components/angular-resource/angular-resource.js"></script>
 <script src="bower_components/angular-cookies/angular-cookies.js"></script>
 <script src="bower_components/angular-sanitize/angular-sanitize.js"></script>
@@ -164,9 +61,6 @@
 <script src="bower_components/fullcalendar/dist/lang/de.js"></script>
 <script src="bower_components/underscore/underscore.js"></script>
 
-<!-- endbower -->
-<!-- endbuild -->
-
 <script src="scripts/amcharts/amcharts.js" type="text/javascript"></script>
 <script src="scripts/amcharts/serial.js" type="text/javascript"></script>
 <script src="scripts/amcharts/pie.js" type="text/javascript"></script>
@@ -183,6 +77,6 @@
 <script src="scripts/controllers/overview.js"></script>
 <script src="scripts/controllers/stats.js"></script>
 <script src="scripts/controllers/tickets.js"></script>
-<!-- endbuild -->
+
 </body>
 </html>

+ 10 - 27
app/scripts/controllers/customers.js

@@ -14,34 +14,17 @@ angular.module('fehlerberichtApp')
             },
             'system': [
                 '?',
-				'ARI',
-                'AUDEV',
-				'AUTOLINE',
-				'CARLO',
-				'HS',
-				'LOCOSOFT',
-				'NAVISION',
-				'OPTIMA',
-				'WERWISO',
-				'Autosys',
-				'Filaks',
-				'O21-Light'
+                'Autosys',
+                'Autosys-Light',
+                'CarIT-Audev',
+                'EDS',
+                'Filaks',
+                'GlobalCube',
+                'Locosoft',
+                'Navision',
+                'Optima',
+                'Optima-Light'
             ],
-			'sys': {
-                '?': '?',
-				'ARI': 'AI',
-                'AUDEV_CARIT': 'AC',
-				'AUTOLINE': 'AL',
-				'CARLO': 'C',
-				'HS': 'HS',
-				'LOCOSOFT': 'LO',
-				'NAVISION': 'NV',
-				'OPTIMA': 'O',
-				'WERWISO': 'W',
-				'Autosys': 'AS',
-				'Filaks': 'F',
-				'Optima-Light': 'OL'
-            },
             'woche': [
                 'Mo-Fr',
                 'Mo-Sa',

+ 112 - 88
app/scripts/controllers/overview.js

@@ -8,7 +8,7 @@
  * Controller of the fehlerberichtApp
  */
 angular.module('fehlerberichtApp')
-    .controller('OverviewCtrl', function ($scope, $http, $routeParams, $interval) {
+    .controller('OverviewCtrl', function ($scope, $http, $routeParams, $interval, $timeout) {
         var webservice = 'db.php?';
 
         var PERIOD_VISIBLE = 60 * 1000;
@@ -52,41 +52,39 @@ angular.module('fehlerberichtApp')
             },
             'system': [
                 '?',
-				'ARI',
-                'AUDEV',
-				'AUTOLINE',
-				'CARLO',
-				'HS',
-				'LOCOSOFT',
-				'NAVISION',
-				'OPTIMA',
-				'WERWISO',
-				'Autosys',
-				'Filaks',
-				'O21-Light'
+                'Autosys',
+                'Autosys-Light',
+                'CarIT-Audev',
+                'EDS',
+                'Filaks',
+                'GlobalCube',
+                'Locosoft',
+                'Navision',
+                'Optima',
+                'Optima-Light'
             ],
-			'sys': {
-                '?': '?',
-				'ARI': 'AI',
-                'AUDEV_CARIT': 'AC',
-				'AUTOLINE': 'AL',
-				'CARLO': 'C',
-				'HS': 'HS',
-				'LOCOSOFT': 'LO',
-				'NAVISION': 'NV',
-				'OPTIMA': 'O',
-				'WERWISO': 'W',
-				'Autosys': 'AS',
-				'Filaks': 'F',
-				'Optima-Light': 'OL'
-            },
             'datum': {},
             'kunde': {},
-            'status': {
-                'errors': '1',
-                'all': '',
-                'missing': '',
-                'flawless': '0'
+          'status': [
+            'fehlerhaft',
+            'fehlend',
+            'verspaetet',
+            'anstehend',
+            'manuell',
+            'bearbeitet',
+            'fehlerfrei',
+            'undefiniert'
+          ],
+            'statusinfo': {
+              'fehlerhaft': 'glyphicon-exclamation-sign',
+              'fehlend': 'glyphicon-question-sign',
+              'verspaetet': 'glyphicon-time',
+              'anstehend': 'glyphicon-retweet',
+              'manuell': 'glyphicon-wrench',
+              'bearbeitet': 'glyphicon-ok',
+              'fehlerfrei': 'glyphicon-eye-close',
+              'fehlerfrei-bearbeitet': 'glyphicon-check',
+              'undefiniert': ''
             },
             'fehlend': {
                 '1': 'fehlt',
@@ -103,7 +101,12 @@ angular.module('fehlerberichtApp')
         $scope.benutzer = window.localStorage.getItem("Benutzer");
         $scope.benutzer2 = 'bitte auswählen';
 
-        $scope.overview = [];
+        $scope.overview = {
+          'all': [],
+          'hash': "",
+          'status': [],
+          'system': []
+        };
         $scope.comments = {};
         $scope.comments2 = {};
 
@@ -120,11 +123,14 @@ angular.module('fehlerberichtApp')
 
         $scope.Filter = {
             'kunde': ($routeParams.customer === 'all' || _.contains($scope.domain.system, $routeParams.customer)) ? '' : $routeParams.customer,
-            'fehler': $scope.domain.status[$routeParams.status],
-            'fehlend': ($routeParams.status === 'missing') ? '1' : '',
             'system': (_.contains($scope.domain.system, $routeParams.customer)) ? $routeParams.customer : '',
-            'benutzer': ''
-        };
+            'benutzer': '',
+            'status': ''
+          };
+
+        $scope.getFilter = function () {
+          return true;
+        }
 
         $scope.DatumFilter = {
             'von': (moment($routeParams.date, 'YYYY-MM-DD').isValid()) ? $routeParams.date : $scope.domain.date[$routeParams.date],
@@ -154,42 +160,26 @@ angular.module('fehlerberichtApp')
         };
 
         $http.get(webservice + 'a=benutzer').success(function (data) {
-            $scope.domain.benutzer = _.unique(_.pluck(data, 'benutzer'));
+            $scope.domain.benutzer = _.unique(_.pluck(data.result, 'benutzer'));
         });
 
         $http.get(webservice + 'a=kommentar&kunde=' + $scope.Filter.kunde + '&datum=' + $scope.DatumFilter.von + '&datum_bis=' + $scope.DatumFilter.bis).success(function (data) {
-            $scope.comments = _.groupBy(data, 'kunde');
-            $scope.comments2 = _.indexBy(data, 'id');
+            $scope.comments = _.groupBy(data.result, 'kunde');
+            $scope.comments2 = _.indexBy(data.result, 'id');
         });
 
         $scope.refresh = function () {
-            $http.get(webservice + 'a=liste&kunde=' + $scope.Filter.kunde + '&datum=' + $scope.DatumFilter.von + '&datum_bis=' + $scope.DatumFilter.bis).success(function (data) {
-                if (JSON.stringify($scope.overview) !== JSON.stringify(data)) {
-                    $scope.overview = data;
-                }
-                //$scope.domain.benutzer = _.unique(_.pluck(data, 'benutzer'));
-            });
-        };
+            $http.get(webservice + 'a=liste&datum=' + $scope.DatumFilter.von).success(function (data) {
+                if ($scope.overview.hash !== data.hash) {
+                    $('.loading').show();
+                    $scope.overview.all = data.result;
+                    $scope.overview.hash = data.hash;
+                    $scope.overview.status = _.groupBy(data.result, function (row) { return row[0].status; });
+                    $scope.overview.system = _.groupBy(data.result, function (row) { return row[0].system; });
+                    $timeout(function () { $('.loading').hide(); }, 500);
 
-        $scope.importData = function () {
-            $scope.error.level = 0;
-            $scope.error.message = "Aktualisierung läuft!";
-            $http.get('http://rbs06/GlobalCube/Fehlerbericht/app/import.php').success(function (data) {
-                if (Array.isArray(data)) {
-                    $scope.error.info = data;
-                    if (data.length === 0) {
-                        $scope.error.level = 0;
-                        $scope.error.message = "Keine neuen Datensätze!";
-                    } else {
-                        $scope.error.message = "Neue Datensätze:";
-                        $scope.error.level = 0;
-                        $scope.refresh();
-                    }
-                } else {
-                    $scope.error.info = [];
-                    $scope.error.level = 1;
-                    $scope.error.message = data;
                 }
+                //$scope.domain.benutzer = _.unique(_.pluck(data, 'benutzer'));
             });
         };
 
@@ -280,6 +270,13 @@ angular.module('fehlerberichtApp')
             return t;
         };
 
+      $scope.timeFormat2 = function (t) {
+        if (t === null) {
+          return '';
+        }
+        return t.substring(0, 5) + ' Uhr';
+      };
+
         $scope.mailFormat = function (t) {
             if (t === undefined) {
                 return '';
@@ -299,20 +296,9 @@ angular.module('fehlerberichtApp')
             if (e === null) {
                 return '0';
             }
-            if (e.LastChangedDays > 0) {
+            if (e.Errors.length === 0 || e.Errors.length === 1 && e.Errors[0] === '') {
                 return $scope.daysCount(e);
             }
-			if (e.Errors.length === 0) {
-				if(e.Sources.length === 0) {
-					return "Transformer-Protokollierung unvollständig";
-				}
-				else if (e.Summary === null) {
-					return "Cube nicht erstellt, Protokoll fehlerhaft";
-				}
-			} 
-			if (e.Errors.length === 1 && e.Type === "Modell" && e.Errors[0].Message !== null && e.Errors[0].Message.indexOf("has been deployed") > 0) {
-				return "Transformer-Protokollierung im falschen Format (englisch)";
-			}
             var type = 'Info';
             if (e.ErrorLevel < 3) {
                 type = 'Fehler';
@@ -320,6 +306,34 @@ angular.module('fehlerberichtApp')
             return _.values(e.Errors).length + ' ' + type;
         };
 
+        $scope.getCount = function (e) {
+          if (e == null || e < 0) {
+            return 'X';
+          }
+          return e;
+        };
+
+      $scope.getCount2 = function (e) {
+        if (e == null || e < 0) {
+          return 'X';
+        }
+        if (e > 9) {
+          return '9';
+        }
+        if (e > 5) {
+          return '5';
+        }
+        return e;
+      };
+
+      $scope.getStatusIcon = function (e) {
+        return $scope.domain.statusinfo[e.status];
+      };
+
+      $scope.toggleErrorStatus = function (e) {
+        $('.row-'+ e).toggle();
+      };
+
         $scope.daysCount = function (e) {
             if (e.LastChangedDays === 0) {
                 return '0';
@@ -352,11 +366,16 @@ angular.module('fehlerberichtApp')
                 'benutzer2': ''
             };
 
-            $http.get(webservice + 'a=liste&kunde=' + $scope.current.zeile.kunde + '&datum=').success(function (data) {
-                $scope.current.overview = data;
+            $http.get(webservice + 'a=liste&kunde=' + $scope.current.zeile.kunde).success(function (data) {
+                $scope.current.overview = data.result;
             });
 
-            $http.get(webservice + 'a=fehlerbericht&kunde=' + $scope.current.zeile.kunde + '&datum=' + $scope.current.zeile.datum + '&start=' + $scope.current.zeile.start).success(function (data) {
+            $http.get(webservice + 'a=fehlerbericht&kunde=' + $scope.current.zeile.kunde + '&datum=' + $scope.current.zeile.datum + '&start=' + $scope.current.zeile.start).success(function (d) {
+              if (d.result === undefined) {
+                console.log(d);
+                return false;
+              }
+              var data = d.result;
                 $scope.current.fehler = data;
                 if (data.whitelist === undefined || data.whitelist === null) {
                     data.whitelist = {
@@ -366,7 +385,7 @@ angular.module('fehlerberichtApp')
                     };
                 }
 
-				if (data.kommentar.id !== undefined) {
+				if (data.kommentar !== undefined && data.kommentar.id !== undefined) {
                     $scope.current.kommentar = data.kommentar;
                     $scope.current.kommentar.fehler = parseInt(data.kommentar.fehler, 10);
                 } else {
@@ -420,12 +439,12 @@ angular.module('fehlerberichtApp')
             return false;
         };
 
-        $scope.getCommentsInfo = function (comment_id) {
+        $scope.getCommentsInfo = function (comment_id, kunde, datum) {
             if ($scope.comments2[comment_id] !== undefined) {
                 var c = $scope.comments2[comment_id];
                 return '<i>' + $scope.domain.bearbeitet[c.status] + '</i><br/>' + c.kommentar;
             }
-            return 'blubb';
+            return '<b>' + $scope.dateFormat(datum) + '</b>: ' + comment_id;
         };
 
         $scope.getCommentIcon = function (c) {
@@ -475,7 +494,7 @@ angular.module('fehlerberichtApp')
 
         $scope.saveComments = function () {
             $http.put(webservice + 'a=kommentar&id=' + $scope.current.kommentar.id, $scope.current.kommentar).success(function (data) {
-                $scope.comments = _.groupBy(data, 'kunde');
+                $scope.comments = _.groupBy(data.result, 'kunde');
 
                 if ($scope.current.kommentar.id === '') {
                     $scope.refresh();
@@ -507,8 +526,8 @@ angular.module('fehlerberichtApp')
         $scope.whitelistToggle = function (key, value) {
             var flag = (!$scope.inWhitelist(key, value)) ? "J" : "N";
             $http.put(webservice + 'a=whitelist&kunde=' + $scope.current.zeile.kunde + '&typ=' + key + '&wert=' + value + "&aktiv=" + flag).success(function (data) {
-                if (data.whitelist !== undefined) {
-                    $scope.current.fehler.whitelist = data.whitelist;
+                if (data.result.whitelist !== undefined) {
+                    $scope.current.fehler.whitelist = data.result.whitelist;
                 }
             });
         };
@@ -516,4 +535,9 @@ angular.module('fehlerberichtApp')
         $scope.inWhitelist = function (key, value) {
             return $scope.current.fehler.whitelist[key] !== undefined && _.contains($scope.current.fehler.whitelist[key], value);
         };
-    });
+
+      $('#datum .input-append.date').datepicker({
+        language: "de"
+      });
+
+    });

+ 249 - 1
app/styles/main.css

@@ -71,6 +71,27 @@
   color: #cc0000;
 }
 
+.headline td, .headline th {
+  font-size: 12pt;
+  font-weight: bold;
+
+}
+
+.kunde a {
+  color: #000000;
+  font-weight: bold;
+  font-size: 14pt;
+}
+
+.aufgabe {
+
+}
+
+#datum input {
+  font-size: 20pt;
+  font-weight: bold;
+}
+
 pre b {
   background-color: #ee5555;
 }
@@ -160,4 +181,231 @@ body {
 .bisher {
     text-decoration: line-through;
     color: #aa0000;
-}
+}
+
+
+.table tbody tr td {
+  vertical-align: middle;
+}
+
+
+.history button.btn-default {
+  font-weight: bold;
+}
+
+.label2, .label3 {
+  width: 24px;
+  height: 24px;
+  border-radius: .25em;
+  text-align: center;
+  color: #ffffff;
+}
+
+.label3 {
+  width: 50px;
+  height: 30px;
+  font-weight: bold;
+  font-size: 14px;
+}
+
+.label-X {
+  background-color: #999999;
+}
+
+.label-0 {
+  background-color: #008800;
+}
+
+.label-1 {
+  background-color: #bbaa00;
+}
+
+.label-2 {
+  background-color: #bb8800;
+}
+
+.label-3, .label-4 {
+  background-color: #bb0000;
+}
+
+.label-5 {
+  background-color: #880000;
+}
+
+.label-9 {
+  background-color: #330000;
+}
+
+.row-bearbeitet, .row-fehlerfrei {
+  display: none;
+}
+
+table.ft {
+  border: 1px solid #888;
+}
+
+table.ft td {
+  padding: 3px 5px;
+  margin: 2px;
+  background-color: #ddd;
+}
+
+.logdatei {
+  margin: 10px 5px 20px 5px;
+  padding: 0 20px 10px 20px;
+  background-color: #eee;
+  border: 1px solid #888;
+}
+
+.modell {
+  font-weight: bold;
+  background-color: #ccc;
+  padding: 10px;
+  margin: 0 -20px;
+}
+
+.rot {
+  background-color: #e88;
+}
+
+.number {
+  font-weight: bold;
+  background-color: #ccc;
+  border: 1px solid #888888;
+}
+
+.strich {
+  border-bottom: 1px solid #888888;
+}
+
+.table>tbody>tr.headline>td, .table>tbody>tr.headline>th, .table>tbody>tr>td.headline,
+.table>tbody>tr>th.headline, .table>tfoot>tr.headline>td, .table>tfoot>tr.headline>th,
+.table>tfoot>tr>td.headline, .table>tfoot>tr>th.headline, .table>thead>tr.headline>td,
+.table>thead>tr.headline>th, .table>thead>tr>td.headline, .table>thead>tr>th.headline {
+  background-color: #888888;
+  color: #eeeeee;
+}
+
+
+/* Absolute Center Spinner */
+.loading {
+  position: fixed;
+  z-index: 999;
+  height: 2em;
+  width: 2em;
+  overflow: visible;
+  margin: auto;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+
+/* Transparent Overlay */
+.loading:before {
+  content: '';
+  display: block;
+  position: fixed;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  background: radial-gradient(rgba(20, 20, 20,.8), rgba(0, 0, 0, .8));
+
+  background: -webkit-radial-gradient(rgba(20, 20, 20,.8), rgba(0, 0, 0,.8));
+}
+
+/* :not(:required) hides these rules from IE9 and below */
+.loading:not(:required) {
+  /* hide "loading..." text */
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.loading:not(:required):after {
+  content: '';
+  display: block;
+  font-size: 10px;
+  width: 1em;
+  height: 1em;
+  margin-top: -0.5em;
+  -webkit-animation: spinner 1500ms infinite linear;
+  -moz-animation: spinner 1500ms infinite linear;
+  -ms-animation: spinner 1500ms infinite linear;
+  -o-animation: spinner 1500ms infinite linear;
+  animation: spinner 1500ms infinite linear;
+  border-radius: 0.5em;
+  -webkit-box-shadow: rgba(255,255,255, 0.75) 1.5em 0 0 0, rgba(255,255,255, 0.75) 1.1em 1.1em 0 0, rgba(255,255,255, 0.75) 0 1.5em 0 0, rgba(255,255,255, 0.75) -1.1em 1.1em 0 0, rgba(255,255,255, 0.75) -1.5em 0 0 0, rgba(255,255,255, 0.75) -1.1em -1.1em 0 0, rgba(255,255,255, 0.75) 0 -1.5em 0 0, rgba(255,255,255, 0.75) 1.1em -1.1em 0 0;
+  box-shadow: rgba(255,255,255, 0.75) 1.5em 0 0 0, rgba(255,255,255, 0.75) 1.1em 1.1em 0 0, rgba(255,255,255, 0.75) 0 1.5em 0 0, rgba(255,255,255, 0.75) -1.1em 1.1em 0 0, rgba(255,255,255, 0.75) -1.5em 0 0 0, rgba(255,255,255, 0.75) -1.1em -1.1em 0 0, rgba(255,255,255, 0.75) 0 -1.5em 0 0, rgba(255,255,255, 0.75) 1.1em -1.1em 0 0;
+}
+
+/* Animation */
+
+@-webkit-keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@-moz-keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@-o-keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@keyframes spinner {
+  0% {
+    -webkit-transform: rotate(0deg);
+    -moz-transform: rotate(0deg);
+    -ms-transform: rotate(0deg);
+    -o-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    -moz-transform: rotate(360deg);
+    -ms-transform: rotate(360deg);
+    -o-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+

+ 622 - 515
app/views/overview.html

@@ -1,552 +1,659 @@
+<div class="loading">Loading&#8230;</div>
+
+
+
 <div class="container-fluid">
-    <ul class="nav nav-pills">
-        <li><a ng-href="#/overview/all/today/errors">Heutige Fehler</a></li>
-        <li><a ng-href="#/overview/all/today/all">Heutige Statusmeldungen</a></li>
-        <li><a ng-href="#/overview/all/all/missing">Alle Fehlenden</a></li>
-        <li><a ng-href="#/overview/all/all/errors">Alle Fehler</a></li>
+  <div class="row">
+    <div class="col-md-8">
+      <div id="datum">
+        <div class="input-append date">
+          <input type="text" class="span2" value="{{dateFormat(DatumFilter.von)}}"><span class="add-on"><i class="icon-th"></i></span>
+        </div>
+      </div>
 
+      <ul class="nav nav-pills">
         <li>
-            <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">Benutzer: {{benutzer||'bitte auswählen'}}&nbsp;<b class="caret"></b></a>
-                <ul class="dropdown-menu" role="menu">
-                    <li ng-repeat="val in domain.benutzer"><a ng-click="saveUser(val)">{{val}}</a></li>
-                </ul>
-            </div>
+          <div class="dropdown">
+            <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">Benutzer: {{benutzer||'bitte auswählen'}}&nbsp;<b
+              class="caret"></b></a>
+            <ul class="dropdown-menu" role="menu">
+              <li ng-repeat="val in domain.benutzer"><a ng-click="saveUser(val)">{{val}}</a></li>
+            </ul>
+          </div>
         </li>
-    </ul>
-
+      </ul>
+    </div>
+  </div>
 </div>
 
 <div class="row">
-    <div class="container-fluid col-md-8">
-<table class="table table-bordered table-striped">
-    <tr>
-        <th>
-            <label>
-                Datum <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='datum'"></i><br/>
-                <input ng-model="DatumFilter.von" type="date" ng-change="refresh()" /><br/>
-                <input ng-model="DatumFilter.bis" type="date" ng-change="refresh()" />
-            </label>
-        </th>
-        <th>
-            <label>
-                Kunde <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='kunde'"></i><br/>
-                <input ng-model="Filter.kunde" ng-change="refresh()" />
-            </label>
-        </th>
+  <div class="container-fluid col-md-8">
+    <table class="table table-bordered table-striped" id="list">
+      <tr>
+        <th>Kunde <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='kunde'"></i></th>
+        <th>Datei</th>
+        <th>System</th>
         <th>Info</th>
-        <th>Start Soll<br/>Ende Soll <i class="glyphicon glyphicon-sort-by-alphabet" ng-click="Predicate='ende_soll'"></i></th>
-        <th>Start Ist<br/>Ende Ist</th>
-        <th>Abweichung</th>
+        <th>Ende<br/>Abweichung</th>
         <th>Fehler / Statistik</th>
-        <th>Kommentar</th>
-    </tr>
-    <tr>
-        <td></td>
-		<td></td>
+      </tr>
+      <tr>
         <td>
-            <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.system||'alle'}}&nbsp;<b class="caret"></b></a>
-                <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="Filter.system=''">alle</a></li>
-                    <li class="divider"></li>
-                    <li ng-repeat="val in domain.system"><a ng-click="Filter.system=val">{{val}}</a></li>
-                </ul>
-            </div>
+          <label>
+            <input ng-model="Filter.kunde" />
+          </label>
         </td>
         <td></td>
         <td>
-            <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.fehlend[Filter.fehlend]||'alle'}}&nbsp;<b class="caret"></b></a>
-                <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="Filter.fehlend=''">alle</a></li>
-                    <li class="divider"></li>
-                    <li ng-repeat="(key,val) in domain.fehlend"><a ng-click="Filter.fehlend=key">{{val}}</a></li>
-                </ul>
-            </div>
+          <div class="dropdown">
+            <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.system||'alle'}}&nbsp;<b
+              class="caret"></b></a>
+            <ul class="dropdown-menu" role="menu">
+              <li><a ng-click="Filter.system=''">alle</a></li>
+              <li class="divider"></li>
+              <li ng-repeat="val in domain.system"><a ng-click="Filter.system=val">{{val}}</a></li>
+            </ul>
+          </div>
         </td>
         <td></td>
+        <td></td>
         <td>
-            <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{domain.fehler[Filter.fehler]||'alle'}}&nbsp;<b class="caret"></b></a>
-                <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="Filter.fehler=''">alle</a></li>
-                    <li class="divider"></li>
-                    <li ng-repeat="(key,val) in domain.fehler"><a ng-click="Filter.fehler=key">{{val}}</a></li>
-                </ul>
-            </div>
+          <div class="dropdown">
+            <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.benutzer||'alle'}}&nbsp;<b
+              class="caret"></b></a>
+            <ul class="dropdown-menu" role="menu">
+              <li><a ng-click="Filter.benutzer=''">alle</a></li>
+              <li class="divider"></li>
+              <li ng-repeat="val in domain.benutzer"><a ng-click="Filter.benutzer=val">{{val}}</a></li>
+            </ul>
+          </div>
         </td>
-        <td>
-            <div class="dropdown">
-                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{Filter.benutzer||'alle'}}&nbsp;<b class="caret"></b></a>
-                <ul class="dropdown-menu" role="menu">
-                    <li><a ng-click="Filter.benutzer=''">alle</a></li>
-                    <li class="divider"></li>
-                    <li ng-repeat="val in domain.benutzer"><a ng-click="Filter.benutzer=val">{{val}}</a></li>
-                </ul>
-            </div>
+      </tr>
+
+      <tbody ng-repeat="st in domain.status" ng-show="overview.status[st].length > 0">
+      <tr class="headline" ng-click="toggleErrorStatus(st)">
+        <td colspan="8">{{st}} ({{overview.status[st].length}})</td>
+      </tr>
+      <tr ng-repeat="zeile in overview.status[st] | filter:getFilter" class="row-{{st}}"  ng-init="c = getComments(zeile[0])">
+        <td class="kunde"><a data-toggle="modal" data-target="#kunde-modal"
+                             ng-click="setCurrent(zeile[0])">{{zeile[0].kunde}}</a></td>
+        <td class="aufgabe"><a data-toggle="modal" data-target="#aufgabe-modal"
+                               ng-click="setCurrent(zeile[0])">{{zeile[0].aufgabe}}</a></td>
+        <td><span class="label label-danger label-{{zeile[0].system}}">{{left(zeile[0].system, 1)}}</span> {{zeile[0].system}}</td>
+        <td><button type="button" class="btn btn-default" title="Konfiguration" data-toggle="modal" data-target="#config-modal"
+                ng-click="setCurrent(zeile[0])">
+              <span class="glyphicon glyphicon-wrench"></span>
+            </button>
+<!--
+            <button type="button" class="btn btn-default" title="Installationsdaten">
+              <span class="glyphicon glyphicon-folder-open"></span>
+            </button>-->
+
         </td>
-    </tr>
 
-    <tr ng-repeat="zeile in overview | filter:DatumFilter.datum | filter:Filter | orderBy:Predicate:Reverse" ng-class="{'danger':zeile.fehlend==1}">
-        <td>{{dateFormat(zeile.datum)}}</td>
-        <td><a ng-href="#/overview/{{zeile.kunde}}/all/all">{{zeile.kunde}}</a> {{zeile.aufgabe}}</td>
         <td>
-            <span class="label label-danger label-{{zeile.system}}">{{zeile.system}}</span>
+          <a ng-click="saveEndTime(zeile[0])">{{timeFormat2(zeile[0].ende)}}</a><br/>
+          {{timeDiff(zeile[0])}}
         </td>
-        <td>{{zeile.start_soll}}<br/>{{zeile.ende_soll}}</td>
+
+<!--
+        <td>{{zeile[0].start_soll}}<br/>{{zeile[0].ende_soll}}</td>
         <td>
-            <a ng-click="saveStartTime(zeile)">{{zeile.start}}</a><br/>
-            <a ng-click="saveEndTime(zeile)">{{zeile.ende}}</a>
+          <a ng-click="saveStartTime(zeile[0])">{{zeile[0].start}}</a><br/>
+          <a ng-click="saveEndTime(zeile[0])">{{zeile[0].ende}}</a>
         </td>
         <td>
-            {{timeDiffStart(zeile)}}<br/>
-            {{timeDiff(zeile)}}</td>
+          {{timeDiffStart(zeile[0])}}<br/>
+          {{timeDiff(zeile[0])}}
+        </td>
+
+        -->
         <td>
-            <!--<a ng-href="#/overview/{{zeile.kunde}}/all/all"><button type="button" class="btn btn-default" title="Fehlermeldungen"><span class="glyphicon glyphicon-exclamation-sign"></span></button></a>-->
-            <!--<a ng-href="#/stats/{{zeile.kunde}}"><button type="button" class="btn btn-default" title="Statistik"><span class="glyphicon glyphicon-stats"></span></button></a>-->
+          <!--<a ng-href="#/overview/{{zeile.kunde}}/all/all"><button type="button" class="btn btn-default" title="Fehlermeldungen"><span class="glyphicon glyphicon-exclamation-sign"></span></button></a>-->
+          <!--<a ng-href="#/stats/{{zeile.kunde}}"><button type="button" class="btn btn-default" title="Statistik"><span class="glyphicon glyphicon-stats"></span></button></a>-->
+
+          <!--<a ng-href="#/config/{{zeile.kunde}}/current"><button type="button" class="btn btn-default" title="Konfiguration"><span class="glyphicon glyphicon-list-alt"></span></button></a>-->
+
+          <div class="btn-group btn-group-xs history" role="group">
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[7].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[7])" data-placement="bottom" data-popover="{{zeile[7].status}}" data-kunde="{{zeile[7].kunde}}"
+                    data-datum="{{zeile[7].datum}}">{{getCount(zeile[7].anzahl)}}</button>
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[6].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[6])" data-placement="bottom" data-popover="{{zeile[6].status}}" data-kunde="{{zeile[6].kunde}}"
+                    data-datum="{{zeile[0].datum}}">{{getCount(zeile[6].anzahl)}}</button>
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[5].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[5])" data-placement="bottom" data-popover="{{zeile[5].status}}" data-kunde="{{zeile[5].kunde}}"
+                    data-datum="{{zeile[5].datum}}">{{getCount(zeile[5].anzahl)}}</button>
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[4].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[4])" data-placement="bottom" data-popover="{{zeile[4].status}}" data-kunde="{{zeile[4].kunde}}"
+                    data-datum="{{zeile[4].datum}}">{{getCount(zeile[4].anzahl)}}</button>
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[3].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[3])" data-placement="bottom" data-popover="{{zeile[3].status}}" data-kunde="{{zeile[3].kunde}}"
+                    data-datum="{{zeile[3].datum}}">{{getCount(zeile[3].anzahl)}}</button>
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[2].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[2])" data-placement="bottom" data-popover="{{zeile[2].status}}" data-kunde="{{zeile[2].kunde}}"
+                    data-datum="{{zeile[2].datum}}">{{getCount(zeile[2].anzahl)}}</button>
+            <button type="button" class="btn btn-default label2 label-{{getCount2(zeile[1].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                    ng-click="setCurrent(zeile[1])" data-placement="bottom" data-popover="{{zeile[1].status}}" data-kunde="{{zeile[1].kunde}}"
+                    data-datum="{{zeile[1].datum}}">{{getCount(zeile[1].anzahl)}}</button>
+          </div>
+          &nbsp;
+          <button type="button" class="btn btn-default btn-sm label3 label-{{getCount2(zeile[0].anzahl)}}" data-toggle="modal" data-target="#fehler-modal"
+                  ng-click="setCurrent(zeile[0])" data-placement="bottom" data-popover="{{zeile[0].status}}" data-kunde="{{zeile[0].kunde}}"
+                  data-datum="{{zeile[0].datum}}">
+            <span class="glyphicon {{getStatusIcon(zeile[0])}}"></span>
+            <span class=""> {{getCount(zeile[0].anzahl)}}</span>
+          </button>
+
+<!--
+          <button type="button" class="btn btn-default btn-sm"
+                  data-toggle="popover" data-placement="bottom"
+                  title="" data-content="" data-popover="{{c[0].id}}" data-kunde="{{c[0].kunde}}"
+                  data-datum="{{c[0].datum}}">
+            <span ng-show="c[0].datum != zeile.datum">{{dateFormat(c[0].datum)}}: </span>
+            <span class="glyphicon {{getCommentIcon(c)}}"></span>
+            <span class="label label-danger label-{{c[0].fehler}}"> {{c[0].fehler}}</span>
+            {{c[0].benutzer}}
+          </button>-->
+        </td>
+      </tr>
+      </tbody>
+    </table>
+  </div>
+</div>
 
-            <!--<a ng-href="#/config/{{zeile.kunde}}/current"><button type="button" class="btn btn-default" title="Konfiguration"><span class="glyphicon glyphicon-list-alt"></span></button></a>-->
+<!-- Modal -->
+<div class="modal fade" id="aufgabe-modal" tabindex="-1" role="dialog" aria-labelledby="aufgabe-modal-label"
+     aria-hidden="true">
+  <div class="modal-dialog modal-lg">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span
+          class="sr-only">Close</span></button>
+        <h4 class="modal-title" id="aufgabe-modal-label"><span class="glyphicon glyphicon-exclamation-sign"></span>&nbsp;
+          Aufgabe: {{current.zeile.kunde}} - {{current.zeile.aufgabe}}</h4>
+      </div>
+
+
+      <div class="modal-body">
+        <h3>Verschiedenen Einstellungen zur ausgewählten Batch-Datei</h3>
+      </div>
+    </div>
+  </div>
+</div>
 
-            <button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#fehler-modal" ng-click="setCurrent(zeile)" ng-show="zeile.anzahl != null">
-                <span class="glyphicon" ng-class="{'glyphicon-check': zeile.anzahl == 0 && zeile.bearbeitet == 1, 'glyphicon-eye-close': zeile.anzahl == 0 && zeile.bearbeitet == 0,  'glyphicon-exclamation-sign': zeile.anzahl > 0 && zeile.bearbeitet == 0,  'glyphicon-ok': zeile.anzahl > 0 && zeile.bearbeitet == 1}"></span>
-                <span class="label label-danger label-{{zeile.anzahl}}"> {{zeile.anzahl}}</span>
-            </button>
+<div class="modal fade" id="kunde-modal" tabindex="-1" role="dialog" aria-labelledby="kunde-modal-label"
+     aria-hidden="true">
+  <div class="modal-dialog modal-lg">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span
+          class="sr-only">Close</span></button>
+        <h4 class="modal-title" id="kunde-modal-label"><span class="glyphicon glyphicon-exclamation-sign"></span>&nbsp;
+          Kunde: {{current.zeile.kunde}}</h4>
+      </div>
+
+
+      <div class="modal-body">
+        <h3>Adresse und System-Infos des Kunden</h3>
+      </div>
+    </div>
+  </div>
+</div>
 
-            <button type="button" data-trigger="focus" class="btn btn-default btn-sm" data-toggle="modal" data-target="#fehler-modal" ng-click="setCurrent(zeile)" ng-show="zeile.anzahl == null">
-                <span class="glyphicon" ng-class="{'glyphicon-check': zeile.bearbeitet == 1, 'glyphicon-question-sign': zeile.bearbeitet != 1 }"></span>
-            </button>
-        </td>
-        <td>
-            <button type="button" class="btn btn-default btn-sm" ng-init="c = getComments(zeile)" ng-show="c" data-toggle="popover" data-placement="bottom"
-                    title="" data-content="" data-popover="{{c[0].id}}" data-kunde="{{c[0].kunde}}" data-datum="{{c[0].datum}}">
-                <span ng-show="c[0].datum != zeile.datum">{{dateFormat(c[0].datum)}}: </span>
+<div class="modal fade" id="config-modal" tabindex="-1" role="dialog" aria-labelledby="config-modal-label"
+     aria-hidden="true">
+  <div class="modal-dialog modal-lg">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span
+          class="sr-only">Close</span></button>
+        <h4 class="modal-title" id="config-modal-label"><span class="glyphicon glyphicon-exclamation-sign"></span>&nbsp;
+          Konfiguration: {{current.zeile.kunde}}</h4>
+      </div>
+
+
+      <div class="modal-body">
+        <h3>GAPS-Portal-Berichte und Versanddateien</h3>
+      </div>
+    </div>
+  </div>
+</div>
+
+
+
+<div class="modal fade" id="fehler-modal" tabindex="-1" role="dialog" aria-labelledby="fehler-modal-label"
+     aria-hidden="true">
+  <div class="modal-dialog modal-lg">
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span
+          class="sr-only">Close</span></button>
+        <h4 class="modal-title" id="fehler-modal-label"><span class="glyphicon glyphicon-exclamation-sign"></span>&nbsp;
+          {{current.zeile.kunde}} - {{dateFormat(current.zeile.datum)}}</h4>
+      </div>
+
+
+      <div class="modal-body">
+        <h3>Kommentar</h3>
+
+        <table class="table table-hover table-bordered">
+          <tr>
+            <th>Benutzer</th>
+            <td>
+              <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{current.kommentar.benutzer||'unbekannt'}}&nbsp;<b
+                  class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                  <li ng-repeat="val in domain.benutzer"><a ng-click="current.kommentar.benutzer=val">{{val}}</a></li>
+                </ul>
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <th>Bearbeitungsstand</th>
+            <td>
+              <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown"><span
+                  class="glyphicon {{getCommentIcon(current.kommentar)}}"></span>
+                  {{domain.bearbeitet[current.kommentar.status]||'unbekannt'}}&nbsp;<b class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                  <li ng-repeat="(key,val) in domain.bearbeitet"><a ng-click="current.kommentar.status=key"><span
+                    class="glyphicon {{domain.comment[key]}}"></span> {{val}}</a></li>
+                </ul>
+              </div>
+            </td>
+          </tr>
+          <tr ng-show="current.kommentar.status=='7'">
+            <th>Empfänger</th>
+            <td>
+              <div class="dropdown">
+                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{current.kommentar.benutzer2||'unbekannt'}}&nbsp;<b
+                  class="caret"></b></a>
+                <ul class="dropdown-menu" role="menu">
+                  <li ng-repeat="val in domain.benutzer"><a
+                    ng-click="current.kommentar.benutzer2=val;current.kommentar.kommentar='weitergeleitet an '+val">{{val}}</a>
+                  </li>
+                </ul>
+              </div>
+            </td>
+          </tr>
+          <tr>
+            <th>Anzahl Fehler
+              <span class="label label-danger label-{{current.fehler.anzahl}}"> {{current.fehler.anzahl}}</span>
+            </th>
+            <td>
+              <span class="label label-danger label-{{current.kommentar.fehler}}"> {{current.kommentar.fehler}}</span>
+              &nbsp;
+              <label>
+                <input type="range" name="Anzahl" min="0" max="10" ng-model="current.kommentar.fehler"/>
+              </label>
+            </td>
+          </tr>
+          <tr>
+            <th>Kommentar</th>
+            <td>
+              <label>
+                <textarea cols="60" rows="5" ng-model="current.kommentar.kommentar"></textarea>
+              </label>
+            </td>
+          </tr>
+          <tr>
+            <td></td>
+            <td>
+              <button type="button" class="btn btn-default" ng-click="saveComments()">Speichern</button>
+              <button type="button" class="btn btn-primary" ng-click="saveComments()" data-dismiss="modal">Speichern und
+                schließen
+              </button>
+            </td>
+          </tr>
+        </table>
+
+
+        <h3>Fehler</h3>
+
+        <div class="logdatei"
+             ng-repeat="e in current.fehler.fehlerbericht | filter: errorLevel | orderBy: 'ErrorLevel'">
+          <a href="" onclick="$(this).next().toggle()" ng-click="e.Errors3 = e.Errors">
+            <p class="modell" ng-class="{'rot':e.ErrorLevel < 3}">{{e.Type}}: {{e.Name}} ({{errorCount(e)}})</p>
+          </a>
+
+          <div class="closed-tab">
+            <ul class="fehler" ng-show="e.Type=='Modell'">
+              <li ng-repeat="error in e.Errors3"><a href="http://rbs06/wiki/{{error.Number}}" target="_blank">{{error.Number}}</a>:
+                ({{error.Level}}) {{error.Message}}
+              </li>
+            </ul>
+            <pre class="fehler" ng-show="e.Type=='Workflow'" ng-bind-html="e.Errors3[0]"></pre>
+            <table class="ft" ng-show="e.Type=='Portal'||e.Type=='Versand'">
+              <tbody ng-repeat="error in e.Errors3">
+              <tr>
+                <td rowspan="6" class="number">{{$index+1}}
+                <td>Datei:</td>
+                <td></td>
+                <td>{{error.Filename}}</td>
+              </tr>
+              <tr>
+                <td>Stand:</td>
+                <td></td>
+                <td>{{error.Modified}}</td>
+              </tr>
+              <tr>
+                <td>Benutzer:</td>
+                <td>
+                  <button class="btn btn-default btn-sm" ng-show="!inWhitelist('User', error.User)"
+                          ng-click="whitelistToggle('User', error.User)"><span
+                    class="glyphicon glyphicon-ban-circle"></span></button>
+                </td>
+                <td>{{error.User}}</td>
+              </tr>
+              <tr>
+                <td>Bericht:</td>
+                <td>
+                  <button class="btn btn-default btn-sm" ng-show="!inWhitelist('Report', error.Report)"
+                          ng-click="whitelistToggle('Report', error.Report)"><span
+                    class="glyphicon glyphicon-ban-circle"></span></button>
+                </td>
+                <td>{{error.Report}}</td>
+              </tr>
+              <tr>
+                <td>Schicht:</td>
+                <td>
+                  <button class="btn btn-default btn-sm" ng-show="!inWhitelist('Layer', error.Layer)"
+                          ng-click="whitelistToggle('Layer', error.Layer)"><span
+                    class="glyphicon glyphicon-ban-circle"></span></button>
+                </td>
+                <td>{{error.Layer}}</td>
+              </tr>
+              <tr class="strich">
+                <td>
+                  <div ng-show="e.Type=='Versand'">Empfänger:</div>
+                </td>
+                <td></td>
+                <td>
+                  <div ng-bind-html="mailFormat(error.MailTo)"></div>
+                </td>
+              </tr>
+              </tbody>
+              <tr ng-show="e.Errors2">
+                <td colspan="4"><a ng-click="e.Show=!e.Show;">Ausgeblendete Berichte</a></td>
+              </tr>
+              <tbody ng-repeat="error in e.Errors2" ng-show="e.Show">
+              <tr>
+                <td rowspan="6" class="number">{{$index+1}}
+                <td>Datei:</td>
+                <td></td>
+                <td>{{error.Filename}}</td>
+              </tr>
+              <tr>
+                <td>Stand:</td>
+                <td></td>
+                <td>{{error.Modified}}</td>
+              </tr>
+              <tr>
+                <td>Benutzer:</td>
+                <td>
+                  <button class="btn btn-default btn-sm" ng-show="!inWhitelist('User', error.User)"
+                          ng-click="whitelistToggle('User', error.User)"><span
+                    class="glyphicon glyphicon-ban-circle"></span></button>
+                </td>
+                <td>{{error.User}}</td>
+              </tr>
+              <tr>
+                <td>Bericht:</td>
+                <td>
+                  <button class="btn btn-default btn-sm" ng-show="!inWhitelist('Report', error.Report)"
+                          ng-click="whitelistToggle('Report', error.Report)"><span
+                    class="glyphicon glyphicon-ban-circle"></span></button>
+                </td>
+                <td>{{error.Report}}</td>
+              </tr>
+              <tr>
+                <td>Schicht:</td>
+                <td>
+                  <button class="btn btn-default btn-sm" ng-show="!inWhitelist('Layer', error.Layer)"
+                          ng-click="whitelistToggle('Layer', error.Layer)"><span
+                    class="glyphicon glyphicon-ban-circle"></span></button>
+                </td>
+                <td>{{error.Layer}}</td>
+              </tr>
+              <tr class="strich">
+                <td>
+                  <div ng-show="e.Type=='Versand'">Empfänger:</div>
+                </td>
+                <td></td>
+                <td>
+                  <div ng-bind-html="mailFormat(error.MailTo)"></div>
+                </td>
+              </tr>
+              </tbody>
+            </table>
+
+          </div>
+        </div>
+
+        <h3>Weitere Logdateien</h3>
+
+        <table class="table table-hover table-bordered">
+          <tr ng-repeat="(header, g) in current.fehler.weitere">
+            <th>{{header}}</th>
+
+            <td>
+              <ul>
+                <li ng-repeat="e in g">
+                  <a ng-click="current.fehlerdetails = e" ng-show="header != 'Modell'">{{e.Name}}</a>
+                  <span ng-show="header == 'Modell'">{{e.Name}}</span>
+                </li>
+              </ul>
+            </td>
+          </tr>
+        </table>
+
+        <div class="logdatei" ng-show="current.fehlerdetails != null">
+          <p class="modell">{{current.fehlerdetails.Type}}: {{current.fehlerdetails.Name}}
+            ({{errorCount(current.fehlerdetails)}})</p>
+          <pre class="fehler" ng-repeat="error in current.fehlerdetails.Errors">{{error}}</pre>
+          <table class="ft" ng-show="current.fehlerdetails.Errors2">
+            <tbody ng-repeat="error in current.fehlerdetails.Errors2">
+            <tr>
+              <td rowspan="6" class="number">{{$index+1}}
+              <td>Datei:</td>
+              <td></td>
+              <td>{{error.Filename}}</td>
+            </tr>
+            <tr>
+              <td>Stand:</td>
+              <td></td>
+              <td>{{error.Modified}}</td>
+            </tr>
+            <tr>
+              <td>Benutzer:</td>
+              <td>
+                <button class="btn btn-default btn-sm" ng-show="!inWhitelist('User', error.User)"
+                        ng-click="whitelistToggle('User', error.User)"><span
+                  class="glyphicon glyphicon-ban-circle"></span></button>
+              </td>
+              <td>{{error.User}}</td>
+            </tr>
+            <tr>
+              <td>Bericht:</td>
+              <td>
+                <button class="btn btn-default btn-sm" ng-show="!inWhitelist('Report', error.Report)"
+                        ng-click="whitelistToggle('Report', error.Report)"><span
+                  class="glyphicon glyphicon-ban-circle"></span></button>
+              </td>
+              <td>{{error.Report}}</td>
+            </tr>
+            <tr>
+              <td>Schicht:</td>
+              <td>
+                <button class="btn btn-default btn-sm" ng-show="!inWhitelist('Layer', error.Layer)"
+                        ng-click="whitelistToggle('Layer', error.Layer)"><span
+                  class="glyphicon glyphicon-ban-circle"></span></button>
+              </td>
+              <td>{{error.Layer}}</td>
+            </tr>
+            <tr class="strich">
+              <td>
+                <div ng-show="e.Type=='Versand'">Empfänger:</div>
+              </td>
+              <td></td>
+              <td>
+                <div ng-bind-html="mailFormat(error.MailTo)"></div>
+              </td>
+            </tr>
+            </tbody>
+          </table>
+        </div>
+
+        <div
+          ng-show="current.fehler.whitelist.User || current.fehler.whitelist.Report || current.fehler.whitelist.Layer">
+          <h3>Ausgeblendete Berichte</h3>
+
+          <table class="table table-hover table-bordered">
+            <tr ng-show="current.fehler.whitelist.User">
+              <th>Benutzer</th>
+              <td>
+                <ul>
+                  <li ng-repeat="val in current.fehler.whitelist.User"><a ng-click="whitelistToggle('User', val)">{{val}}</a>
+                  </li>
+                </ul>
+              </td>
+            </tr>
+            <tr ng-show="current.fehler.whitelist.Report">
+              <th>Bericht</th>
+              <td>
+                <ul>
+                  <li ng-repeat="val in current.fehler.whitelist.Report">
+                    <button ng-click="whitelistToggle('Report', val)"><span class="glyphicon glyphicon-trash"></span>
+                    </button>
+                    {{val}}
+                  </li>
+                </ul>
+              </td>
+            </tr>
+            <tr ng-show="current.fehler.whitelist.Layer">
+              <th>Schicht</th>
+              <td>
+                <ul>
+                  <li ng-repeat="val in current.fehler.whitelist.Layer"><a ng-click="whitelistToggle('Layer', val)">{{val}}</a>
+                  </li>
+                </ul>
+              </td>
+            </tr>
+          </table>
+        </div>
+
+        <h3>Historie</h3>
+
+        <table class="table table-hover table-bordered table-condensed">
+          <tr>
+            <th style="width: 140px;">Datum</th>
+            <th style="width: 100px;">Start<br/>Ende</th>
+            <th style="width: 110px;">Abweichung</th>
+            <th style="width: 120px;">Fehler</th>
+            <th style="width: 340px;">Kommentar</th>
+          </tr>
+          <tr ng-repeat="z in current.overview | orderBy: 'datum':true | limitTo: current.limit "
+              ng-class="{'danger':z.fehlend==1}">
+            <td>{{dateFormat(z.datum)}}</td>
+            <td>
+              <a ng-click="saveStartTime(z)">{{z.start}}</a><br/>
+              <a ng-click="saveEndTime(z)">{{z.ende}}</a>
+            </td>
+            <td>
+              {{timeDiffStart(z)}}<br/>
+              {{timeDiff(z)}}
+            </td>
+            <td>
+              <button type="button" class="btn btn-default btn-sm" ng-click="setCurrent(z)" ng-show="z.anzahl != null">
+                <span class="glyphicon"
+                      ng-class="{'glyphicon-check': z.anzahl == 0 && z.bearbeitet == 1, 'glyphicon-eye-close': z.anzahl == 0 && z.bearbeitet == 0,  'glyphicon-exclamation-sign': z.anzahl > 0 && z.bearbeitet == 0,  'glyphicon-ok': z.anzahl > 0 && z.bearbeitet == 1}"></span>
+                <span class="label label-danger label-{{z.anzahl}}"> {{z.anzahl}}</span>
+              </button>
+
+              <button type="button" data-trigger="focus" class="btn btn-default btn-sm" ng-click="setCurrent(zeile)"
+                      ng-show="z.anzahl == null">
+                <span class="glyphicon glyphicon-question-sign"></span>
+              </button>
+            </td>
+            <td>
+              <button type="button" class="btn btn-default btn-sm" ng-init="c = getComments(z, '1')" ng-show="c"
+                      data-toggle="popover" data-placement="bottom"
+                      title="" data-content="" data-popover="{{c.id}}">
+                <span ng-show="c[0].datum != z.datum">{{dateFormat(c[0].datum)}}: </span>
                 <span class="glyphicon {{getCommentIcon(c)}}"></span>
                 <span class="label label-danger label-{{c[0].fehler}}"> {{c[0].fehler}}</span>
                 {{c[0].benutzer}}
-            </button>
-        </td>
-    </tr>
-</table>
-    </div>
-</div>
+              </button>
 
-<!-- Modal -->
-<div class="modal fade" id="fehler-modal" tabindex="-1" role="dialog" aria-labelledby="fehler-modal-label" aria-hidden="true">
-    <div class="modal-dialog modal-lg">
-        <div class="modal-content">
-            <div class="modal-header">
-                <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
-                <h4 class="modal-title" id="fehler-modal-label"><span class="glyphicon glyphicon-exclamation-sign"></span>&nbsp; {{current.zeile.kunde}} - {{dateFormat(current.zeile.datum)}}</h4>
-            </div>
-
-
-            <div class="modal-body">
-                <h3>Kommentar</h3>
-
-                <table class="table table-hover table-bordered">
-                    <tr>
-                        <th>Benutzer</th>
-                        <td>
-                            <div class="dropdown">
-                                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{current.kommentar.benutzer||'unbekannt'}}&nbsp;<b class="caret"></b></a>
-                                <ul class="dropdown-menu" role="menu">
-                                    <li ng-repeat="val in domain.benutzer"><a ng-click="current.kommentar.benutzer=val">{{val}}</a></li>
-                                </ul>
-                            </div>
-                        </td>
-                    </tr>
-                    <tr>
-                        <th>Bearbeitungsstand</th>
-                        <td>
-                            <div class="dropdown">
-                                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown"><span class="glyphicon {{getCommentIcon(current.kommentar)}}"></span> {{domain.bearbeitet[current.kommentar.status]||'unbekannt'}}&nbsp;<b class="caret"></b></a>
-                                <ul class="dropdown-menu" role="menu">
-                                    <li ng-repeat="(key,val) in domain.bearbeitet"><a ng-click="current.kommentar.status=key"><span class="glyphicon {{domain.comment[key]}}"></span> {{val}}</a></li>
-                                </ul>
-                            </div>
-                        </td>
-                    </tr>
-                    <tr ng-show="current.kommentar.status=='7'">
-                        <th>Empfänger</th>
-                        <td>
-                            <div class="dropdown">
-                                <a class="btn dropdown-toggle" role="button" data-toggle="dropdown">{{current.kommentar.benutzer2||'unbekannt'}}&nbsp;<b class="caret"></b></a>
-                                <ul class="dropdown-menu" role="menu">
-                                    <li ng-repeat="val in domain.benutzer"><a ng-click="current.kommentar.benutzer2=val;current.kommentar.kommentar='weitergeleitet an '+val">{{val}}</a></li>
-                                </ul>
-                            </div>
-                        </td>
-                    </tr>
-                    <tr>
-                        <th>Anzahl Fehler
-                            <span class="label label-danger label-{{current.fehler.anzahl}}"> {{current.fehler.anzahl}}</span>
-                        </th>
-                        <td>
-                            <span class="label label-danger label-{{current.kommentar.fehler}}"> {{current.kommentar.fehler}}</span> &nbsp;
-                            <label>
-                                <input type="range" name="Anzahl" min="0" max="10" ng-model="current.kommentar.fehler" />
-                            </label>
-                        </td>
-                    </tr>
-                    <tr>
-                        <th>Kommentar</th>
-                        <td>
-                            <label>
-                                <textarea cols="60" rows="5" ng-model="current.kommentar.kommentar"></textarea>
-                            </label>
-                        </td>
-                    </tr>
-                    <tr>
-                        <td></td>
-                        <td>
-                            <button type="button" class="btn btn-default" ng-click="saveComments()">Speichern</button>
-                            <button type="button" class="btn btn-primary" ng-click="saveComments()" data-dismiss="modal">Speichern und schließen</button>
-                        </td>
-                    </tr>
-                </table>
-
-
-                <h3>Fehler</h3>
-
-                <div class="logdatei" ng-repeat="e in current.fehler.fehlerbericht | filter: errorLevel | orderBy: 'ErrorLevel'">
-                    <a href="" onclick="$(this).next().toggle()" ng-click="e.Errors3 = e.Errors">
-                        <p class="modell" ng-class="{'rot':e.ErrorLevel < 3}">{{e.Type}}: {{e.Name}} ({{errorCount(e)}})</p>
-                    </a>
-
-                    <div class="closed-tab">
-                        <ul class="fehler" ng-show="e.Type=='Modell'">
-                            <li ng-repeat="error in e.Errors3"><a href="http://rbs06/wiki/{{error.Number}}" target="_blank">{{error.Number}}</a>:
-                                ({{error.Level}}) {{error.Message}}</li>
-                        </ul>
-                        <pre class="fehler" ng-show="e.Type=='Workflow'" ng-bind-html="e.Errors3[0]"></pre>
-                        <table class="ft" ng-show="e.Type=='Portal'||e.Type=='Versand'">
-                            <tbody ng-repeat="error in e.Errors3">
-                                <tr>
-                                    <td rowspan="6" class="number">{{$index+1}}
-                                    <td>Datei:</td>
-                                    <td></td>
-                                    <td>{{error.Filename}}</td>
-                                </tr>
-                                <tr>
-                                    <td>Stand:</td>
-                                    <td></td>
-                                    <td>{{error.Modified}}</td>
-                                </tr>
-                                <tr>
-                                    <td>Benutzer:</td>
-                                    <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('User', error.User)" ng-click="whitelistToggle('User', error.User)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                                    <td>{{error.User}}</td>
-                                </tr>
-                                <tr>
-                                    <td>Bericht:</td>
-                                    <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('Report', error.Report)" ng-click="whitelistToggle('Report', error.Report)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                                    <td>{{error.Report}}</td>
-                                </tr>
-                                <tr>
-                                    <td>Schicht:</td>
-                                    <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('Layer', error.Layer)" ng-click="whitelistToggle('Layer', error.Layer)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                                    <td>{{error.Layer}}</td>
-                                </tr>
-                                <tr class="strich">
-                                    <td><div  ng-show="e.Type=='Versand'">Empfänger:</div></td>
-                                    <td></td>
-                                    <td><div ng-bind-html="mailFormat(error.MailTo)"></div></td>
-                                </tr>
-                            </tbody>
-                            <tr ng-show="e.Errors2">
-                                <td colspan="4"><a ng-click="e.Show=!e.Show;">Ausgeblendete Berichte</a></td>
-                            </tr>
-                            <tbody ng-repeat="error in e.Errors2" ng-show="e.Show">
-                            <tr>
-                                <td rowspan="6" class="number">{{$index+1}}
-                                <td>Datei:</td>
-                                <td></td>
-                                <td>{{error.Filename}}</td>
-                            </tr>
-                            <tr>
-                                <td>Stand:</td>
-                                <td></td>
-                                <td>{{error.Modified}}</td>
-                            </tr>
-                            <tr>
-                                <td>Benutzer:</td>
-                                <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('User', error.User)" ng-click="whitelistToggle('User', error.User)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                                <td>{{error.User}}</td>
-                            </tr>
-                            <tr>
-                                <td>Bericht:</td>
-                                <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('Report', error.Report)" ng-click="whitelistToggle('Report', error.Report)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                                <td>{{error.Report}}</td>
-                            </tr>
-                            <tr>
-                                <td>Schicht:</td>
-                                <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('Layer', error.Layer)" ng-click="whitelistToggle('Layer', error.Layer)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                                <td>{{error.Layer}}</td>
-                            </tr>
-                            <tr class="strich">
-                                <td><div  ng-show="e.Type=='Versand'">Empfänger:</div></td>
-                                <td></td>
-                                <td><div ng-bind-html="mailFormat(error.MailTo)"></div></td>
-                            </tr>
-                            </tbody>
-                        </table>
-
-                    </div>
-                </div>
-
-                <h3>Weitere Logdateien</h3>
-
-                <table class="table table-hover table-bordered">
-                    <tr ng-repeat="(header, g) in current.fehler.weitere">
-                        <th>{{header}}</th>
-
-                        <td>
-                            <ul>
-                                <li ng-repeat="e in g" >
-                                    <a ng-click="current.fehlerdetails = e" ng-show="header != 'Modell'">{{e.Name}}</a>
-                                    <span ng-show="header == 'Modell'">{{e.Name}}</span>
-                                </li>
-                            </ul>
-                        </td>
-                    </tr>
-                </table>
-
-                <div class="logdatei" ng-show="current.fehlerdetails != null">
-                    <p class="modell">{{current.fehlerdetails.Type}}: {{current.fehlerdetails.Name}} ({{errorCount(current.fehlerdetails)}})</p>
-                    <pre class="fehler" ng-repeat="error in current.fehlerdetails.Errors">{{error}}</pre>
-                    <table class="ft" ng-show="current.fehlerdetails.Errors2">
-                        <tbody ng-repeat="error in current.fehlerdetails.Errors2">
-                        <tr>
-                            <td rowspan="6" class="number">{{$index+1}}
-                            <td>Datei:</td>
-                            <td></td>
-                            <td>{{error.Filename}}</td>
-                        </tr>
-                        <tr>
-                            <td>Stand:</td>
-                            <td></td>
-                            <td>{{error.Modified}}</td>
-                        </tr>
-                        <tr>
-                            <td>Benutzer:</td>
-                            <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('User', error.User)" ng-click="whitelistToggle('User', error.User)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                            <td>{{error.User}}</td>
-                        </tr>
-                        <tr>
-                            <td>Bericht:</td>
-                            <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('Report', error.Report)" ng-click="whitelistToggle('Report', error.Report)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                            <td>{{error.Report}}</td>
-                        </tr>
-                        <tr>
-                            <td>Schicht:</td>
-                            <td><button class="btn btn-default btn-sm" ng-show="!inWhitelist('Layer', error.Layer)" ng-click="whitelistToggle('Layer', error.Layer)"><span class="glyphicon glyphicon-ban-circle"></span></button></td>
-                            <td>{{error.Layer}}</td>
-                        </tr>
-                        <tr class="strich">
-                            <td><div  ng-show="e.Type=='Versand'">Empfänger:</div></td>
-                            <td></td>
-                            <td><div ng-bind-html="mailFormat(error.MailTo)"></div></td>
-                        </tr>
-                        </tbody>
-                    </table>
-                </div>
-
-                <div ng-show="current.fehler.whitelist.User || current.fehler.whitelist.Report || current.fehler.whitelist.Layer">
-                    <h3>Ausgeblendete Berichte</h3>
-
-                    <table class="table table-hover table-bordered">
-                        <tr ng-show="current.fehler.whitelist.User">
-                            <th>Benutzer</th>
-                            <td>
-                                <ul>
-                                    <li ng-repeat="val in current.fehler.whitelist.User"><a ng-click="whitelistToggle('User', val)">{{val}}</a></li>
-                                </ul>
-                            </td>
-                        </tr>
-                        <tr ng-show="current.fehler.whitelist.Report">
-                            <th>Bericht</th>
-                            <td>
-                                <ul>
-                                    <li ng-repeat="val in current.fehler.whitelist.Report"><button ng-click="whitelistToggle('Report', val)"><span class="glyphicon glyphicon-trash"></span></button> {{val}}</li>
-                                </ul>
-                            </td>
-                        </tr>
-                        <tr ng-show="current.fehler.whitelist.Layer">
-                            <th>Schicht</th>
-                            <td>
-                                <ul>
-                                    <li ng-repeat="val in current.fehler.whitelist.Layer"><a ng-click="whitelistToggle('Layer', val)">{{val}}</a></li>
-                                </ul>
-                            </td>
-                        </tr>
-                    </table>
-                </div>
-
-                <h3>Historie</h3>
-
-                <table class="table table-hover table-bordered table-condensed">
-                    <tr>
-                        <th style="width: 140px;">Datum</th>
-                        <th style="width: 100px;">Start<br/>Ende</th>
-                        <th style="width: 110px;">Abweichung</th>
-                        <th style="width: 120px;">Fehler</th>
-                        <th style="width: 340px;">Kommentar</th>
-                    </tr>
-                    <tr ng-repeat="z in current.overview | orderBy: 'datum':true | limitTo: current.limit " ng-class="{'danger':z.fehlend==1}">
-                        <td>{{dateFormat(z.datum)}}</td>
-                        <td>
-                            <a ng-click="saveStartTime(z)">{{z.start}}</a><br/>
-                            <a ng-click="saveEndTime(z)">{{z.ende}}</a>
-                        </td>
-                        <td>
-                            {{timeDiffStart(z)}}<br/>
-                            {{timeDiff(z)}}
-                        </td>
-                        <td>
-                            <button type="button" class="btn btn-default btn-sm" ng-click="setCurrent(z)" ng-show="z.anzahl != null">
-                                <span class="glyphicon" ng-class="{'glyphicon-check': z.anzahl == 0 && z.bearbeitet == 1, 'glyphicon-eye-close': z.anzahl == 0 && z.bearbeitet == 0,  'glyphicon-exclamation-sign': z.anzahl > 0 && z.bearbeitet == 0,  'glyphicon-ok': z.anzahl > 0 && z.bearbeitet == 1}"></span>
-                                <span class="label label-danger label-{{z.anzahl}}"> {{z.anzahl}}</span>
-                            </button>
-
-                            <button type="button" data-trigger="focus" class="btn btn-default btn-sm" ng-click="setCurrent(zeile)" ng-show="z.anzahl == null">
-                                <span class="glyphicon glyphicon-question-sign"></span>
-                            </button>
-                        </td>
-                        <td>
-                            <button type="button" class="btn btn-default btn-sm" ng-init="c = getComments(z, '1')" ng-show="c" data-toggle="popover" data-placement="bottom"
-                                    title="" data-content="" data-popover="{{c.id}}">
-                                <span ng-show="c[0].datum != z.datum">{{dateFormat(c[0].datum)}}: </span>
-                                <span class="glyphicon {{getCommentIcon(c)}}"></span>
-                                <span class="label label-danger label-{{c[0].fehler}}"> {{c[0].fehler}}</span>
-                                {{c[0].benutzer}}
-                            </button>
-
-                        </td>
-                    </tr>
-                    <tr>
-                        <td>
-                            <button class="btn btn-default" ng-click="current.limit=100"><span class="glyphicon glyphicon-plus"></span></button>
-                        </td>
-                    </tr>
-                </table>
-
-                <h3>Statistik</h3>
-
-                <div>
-                    <div id="durationChart" style="width: 750px; height: 550px"></div>
-
-                    </div>
-                    <br/><br/>
-                    <table class="table table-bordered table-striped">
-                        <tr>
-                            <th>Name</th>
-                            <th>Datum</th>
-                            <th>Zeit</th>
-                            <th>Dauer</th>
-                            <th>Quellen</th>
-                            <th>Kategorien</th>
-                            <th>Datensätze</th>
-                        </tr>
-                        <tr ng-repeat="e in current.fehler.fehlerbericht" ng-show="e.Summary.Duration != null">
-                            <td>{{e.Type}}: <a href="" ng-click="showDetails(e)">{{e.Name}}</a></td>
-                            <td>{{dateFormat(e.Modified)}}</td>
-                            <td>{{timeFormat(e.Modified)}}</td>
-                            <td>{{e.Summary.Duration}}</td>
-                            <td>{{e.Sources.length}}</td>
-                            <td>{{e.Summary.Categories}}</td>
-                            <td>{{e.Summary.Entities}}</td>
-                        </tr>
-                    </table>
-
-                    <div ng-show="current.details!=null">
-                        <h3>Details zu {{current.details.Type}}: {{current.details.Name}}</h3>
-                        <div id="durationDetailsChart" style="width: 750px; height: 550px">
-
-                        </div>
-                        <br/><br/>
-                        <table class="table table-bordered table-striped">
-                            <tr>
-                                <th>Name</th>
-                                <th ng-show="current.details.Type!='Modell'">Report</th>
-                                <th ng-show="current.details.Type=='Modell'">Datensätze</th>
-                                <th>Dauer</th>
-                            </tr>
-                            <tr ng-repeat="e in current.details.Sources">
-                                <td>{{e.Filename}}</td>
-                                <td ng-show="current.details.Type!='Modell'">{{e.Report}} ({{e.Layer}})</td>
-                                <td ng-show="current.details.Type=='Modell'">{{e.Entities}}</td>
-                                <td>{{e.Duration}}</td>
-                            </tr>
-                        </table>
-                    </div>
-                </div>
-
-
-
-
-            </div>
+            </td>
+          </tr>
+          <tr>
+            <td>
+              <button class="btn btn-default" ng-click="current.limit=100"><span
+                class="glyphicon glyphicon-plus"></span></button>
+            </td>
+          </tr>
+        </table>
+
+        <h3>Statistik</h3>
+
+        <div>
+          <div id="durationChart" style="width: 750px; height: 550px"></div>
+
+        </div>
+        <br/><br/>
+        <table class="table table-bordered table-striped">
+          <tr>
+            <th>Name</th>
+            <th>Datum</th>
+            <th>Zeit</th>
+            <th>Dauer</th>
+            <th>Quellen</th>
+            <th>Kategorien</th>
+            <th>Datensätze</th>
+          </tr>
+          <tr ng-repeat="e in current.fehler.fehlerbericht" ng-show="e.Summary.Duration != null">
+            <td>{{e.Type}}: <a href="" ng-click="showDetails(e)">{{e.Name}}</a></td>
+            <td>{{dateFormat(e.Modified)}}</td>
+            <td>{{timeFormat(e.Modified)}}</td>
+            <td>{{e.Summary.Duration}}</td>
+            <td>{{e.Sources.length}}</td>
+            <td>{{e.Summary.Categories}}</td>
+            <td>{{e.Summary.Entities}}</td>
+          </tr>
+        </table>
+
+        <div ng-show="current.details!=null">
+          <h3>Details zu {{current.details.Type}}: {{current.details.Name}}</h3>
+          <div id="durationDetailsChart" style="width: 750px; height: 550px">
+
+          </div>
+          <br/><br/>
+          <table class="table table-bordered table-striped">
+            <tr>
+              <th>Name</th>
+              <th ng-show="current.details.Type!='Modell'">Report</th>
+              <th ng-show="current.details.Type=='Modell'">Datensätze</th>
+              <th>Dauer</th>
+            </tr>
+            <tr ng-repeat="e in current.details.Sources">
+              <td>{{e.Filename}}</td>
+              <td ng-show="current.details.Type!='Modell'">{{e.Report}} ({{e.Layer}})</td>
+              <td ng-show="current.details.Type=='Modell'">{{e.Entities}}</td>
+              <td>{{e.Duration}}</td>
+            </tr>
+          </table>
         </div>
+      </div>
+
+
     </div>
+  </div>
+</div>
 </div>
 
 <style>
-.table tbody tr td {
-    vertical-align: middle;
-}
-
-.label-0 {
-    background-color: #aaaaaa;
-}
-
-.label-1 {
-    background-color: #bbbb00;
-}
-
-.label-2 {
-    background-color: #bb8800;
-}
-
-.label-3 {
-    background-color: #bb0000;
-}
-
-table.ft {
-    border: 1px solid #888;
-}
-
-table.ft td {
-    padding: 3px 5px;
-    margin: 2px;
-    background-color: #ddd;
-}
-
-.logdatei {
-    margin: 10px 5px 20px 5px;
-    padding: 0 20px 10px 20px;
-    background-color: #eee;
-    border: 1px solid #888;
-}
-
-.modell {
-    font-weight: bold;
-    background-color: #ccc;
-    padding: 10px;
-    margin: 0 -20px;
-}
-
-.rot {
-    background-color: #e88;
-}
-
-.number {
-    font-weight: bold;
-    background-color: #ccc;
-    border: 1px solid #888888;
-}
-
-.strich {
-    border-bottom: 1px solid #888888;
-}
-
-</style>
+
+</style>

+ 67 - 58
queries/status_tag.sql

@@ -1,66 +1,75 @@
-SELECT sm.datum, sm.kunde, sm.aufgabe, sm.anzahl,
-IFNULL(s7.anzahl, 'X') AS anzahl_7, 
-IFNULL(s6.anzahl, 'X') AS anzahl_6,
-IFNULL(s5.anzahl, 'X') AS anzahl_5,
-IFNULL(s4.anzahl, 'X') AS anzahl_4,
-IFNULL(s3.anzahl, 'X') AS anzahl_3,
-IFNULL(s2.anzahl, 'X') AS anzahl_2,
-IFNULL(s1.anzahl, 'X') AS anzahl_1
+SELECT DISTINCT sm.kunde,
+                sm.aufgabe,
+                sm.datum,
+                datediff(now(), sm.datum) as datum_diff,
+                k.system,
+                k.bundesland,
+                sm.start,
+                sm.ende,
+                ka.start_soll,
+                ifnull(case
+                         when dayofweek(sm.datum) = 2 then ka.ende_mo
+                         when dayofweek(sm.datum) = 3 then ka.ende_di
+                         when dayofweek(sm.datum) = 4 then ka.ende_mi
+                         when dayofweek(sm.datum) = 5 then ka.ende_do
+                         when dayofweek(sm.datum) = 6 then ka.ende_fr
+                         when dayofweek(sm.datum) = 7 then ka.ende_sa
+                         else ka.ende_so
+                         end, ka.ende_soll)      as ende_soll,
+                sm.anzahl,
+                sm.bearbeitet,
+                ifnull(sk.benutzer, '')          as benutzer,
+                case
+                  when sm.bearbeitet = '1' then 'bearbeitet'
+                  when ka.start_soll is NULL then 'manuell'
+                  when sm.anzahl != 0 then 'fehlerhaft'
+                  when concat(sm.datum, ' ', sm.ende) > date_add(concat(sm.datum, ' ', ka.ende_soll), INTERVAL 1 HOUR) then 'verspaetet'
+                  when sm.anzahl = 0 then 'fehlerfrei'
+                  else 'undefiniert'
+                  end                            as `status`
 
-FROM `status_meldung` sm
-LEFT JOIN status_meldung AS s7 ON s7.datum = date_add(sm.datum, INTERVAL -7 DAY) AND s7.kunde = sm.kunde AND s7.aufgabe = sm.aufgabe
-LEFT JOIN status_meldung AS s6 ON s6.datum = date_add(sm.datum, INTERVAL -6 DAY) AND s6.kunde = sm.kunde AND s6.aufgabe = sm.aufgabe
-LEFT JOIN status_meldung AS s5 ON s5.datum = date_add(sm.datum, INTERVAL -5 DAY) AND s5.kunde = sm.kunde AND s5.aufgabe = sm.aufgabe
-LEFT JOIN status_meldung AS s4 ON s4.datum = date_add(sm.datum, INTERVAL -4 DAY) AND s4.kunde = sm.kunde AND s4.aufgabe = sm.aufgabe
-LEFT JOIN status_meldung AS s3 ON s3.datum = date_add(sm.datum, INTERVAL -3 DAY) AND s3.kunde = sm.kunde AND s3.aufgabe = sm.aufgabe
-LEFT JOIN status_meldung AS s2 ON s2.datum = date_add(sm.datum, INTERVAL -2 DAY) AND s2.kunde = sm.kunde AND s2.aufgabe = sm.aufgabe
-LEFT JOIN status_meldung AS s1 ON s1.datum = date_add(sm.datum, INTERVAL -1 DAY) AND s1.kunde = sm.kunde AND s1.aufgabe = sm.aufgabe
+FROM status_meldung sm
+       INNER JOIN kunden k USING (kunde)
+       LEFT JOIN kunden_aufgabe ka USING (kunde, aufgabe)
+       LEFT JOIN status_kommentar sk ON sm.kommentar_id = sk.id
+       LEFT JOIN status_kommentar as sk2 ON sm.datum = sk2.datum AND sm.kunde = sk2.kunde
+WHERE sm.datum <= now()
+  AND datediff(now(), sm.datum) <= 7
+  AND k.aktiv = 1
+  AND (ka.aktiv IS NULL OR ka.aktiv = 1)
 
-WHERE sm.datum = '2017-06-06'
+UNION
 
+SELECT DISTINCT k.kunde,
+                ka.aufgabe,
+                a.datum,
+                datediff(now(), a.datum) as datum_diff,
+                k.system,
+                a.bundesland,
+                NULL                            as start,
+                NULL                            as ende,
+                ka.start_soll,
+                ka.ende_soll,
+                -1                              as anzahl,
+                0                               as bearbeitet,
+                ''                              as benutzer,
+                case
+                  when now() > date_add(concat(a.datum, ' ', ka.ende_soll), INTERVAL 1 HOUR) then 'fehlend'
+                  else 'anstehend'
+                  end                           as `status`
 
 
+FROM arbeitstage a
+       INNER JOIN kunden k USING (bundesland)
+       INNER JOIN kunden_aufgabe ka USING (kunde)
+       LEFT JOIN status_meldung sm USING (datum, kunde, aufgabe)
 
-SELECT DISTINCT a.datum, a.wochentag, a.feiertag, k.kunde, ka.aufgabe, k.system, k.bundesland, ka.start_soll,
-	case
-	  when a.wochentag = 'Mo' and ka.ende_mo IS NOT NULL then ka.ende_mo
-	  when a.wochentag = 'Di' and ka.ende_di IS NOT NULL then ka.ende_di
-	  when a.wochentag = 'Mi' and ka.ende_mi IS NOT NULL then ka.ende_mi
-	  when a.wochentag = 'Do' and ka.ende_do IS NOT NULL then ka.ende_do
-	  when a.wochentag = 'Fr' and ka.ende_fr IS NOT NULL then ka.ende_fr
-	  when a.wochentag = 'Sa' and ka.ende_sa IS NOT NULL then ka.ende_sa
-	  when a.wochentag = 'So' and ka.ende_so IS NOT NULL then ka.ende_so
-	  else ka.ende_soll
-	end as 'ende_soll',
-	ka.woche,  
-	case
-	 when ka.woche = 'Mo-Fr' then a.mofr
-	 when ka.woche = 'Mo-Sa' then a.mosa
-	 when ka.woche = 'Mo-So' then a.moso
-	 when ka.woche = 'Di-So' then a.diso
-	 else 1
-	end
-	* ka.aktiv * if(a.datum >= ka.erster_status, 1, 0)  as 'anstehend'
-								
-FROM kunden k
-INNER JOIN arbeitstage a USING (bundesland)
-INNER JOIN kunden_aufgabe ka USING (kunde)
+WHERE a.datum <= now()
+  AND datediff(now(), a.datum) <= 7
+  AND k.aktiv = 1
+  AND ka.aktiv = 1
+  AND sm.start IS NULL
 
-WHERE a.datum <= date_add(now(), INTERVAL 1 DAY) 
-AND a.datum >= date_add(now(), INTERVAL -20 DAY)
-							
-							
-							
-							
-							LEFT JOIN status_meldung sm USING (datum, kunde)
-							LEFT JOIN status_kommentar sk ON sm.kommentar_id = sk.id
-							LEFT JOIN status_kommentar as sk2 ON a.datum = sk2.datum AND k.kunde = sk2.kunde
 
-							WHERE {$datum} AND {$datum_bis} AND {$kunde} AND a.datum <= now() AND k.erster_status <= a.datum
-							AND k.aktiv = 1
-							ORDER BY a.datum, k.ende_soll
-							
-							
-							end * if(sk.status <= 1, 0, 1) * if(sm.anzahl > 0 or (sm.anzahl is null and now() > date_add(concat(a.datum, ' ', k.ende_soll), INTERVAL 1 HOUR)), 1, 0) as fehler,
-								if(sm.anzahl is null and now() > date_add(concat(a.datum, ' ', k.ende_soll), INTERVAL 1 HOUR), 1, 0) as fehlend,
-							
+ORDER BY 1, 2, 4
+

+ 66 - 0
queries/status_test.sql

@@ -0,0 +1,66 @@
+SELECT sm.datum, sm.kunde, sm.aufgabe, sm.anzahl,
+IFNULL(s7.anzahl, 'X') AS anzahl_7, 
+IFNULL(s6.anzahl, 'X') AS anzahl_6,
+IFNULL(s5.anzahl, 'X') AS anzahl_5,
+IFNULL(s4.anzahl, 'X') AS anzahl_4,
+IFNULL(s3.anzahl, 'X') AS anzahl_3,
+IFNULL(s2.anzahl, 'X') AS anzahl_2,
+IFNULL(s1.anzahl, 'X') AS anzahl_1
+
+FROM `status_meldung` sm
+LEFT JOIN status_meldung AS s7 ON s7.datum = date_add(sm.datum, INTERVAL -7 DAY) AND s7.kunde = sm.kunde AND s7.aufgabe = sm.aufgabe
+LEFT JOIN status_meldung AS s6 ON s6.datum = date_add(sm.datum, INTERVAL -6 DAY) AND s6.kunde = sm.kunde AND s6.aufgabe = sm.aufgabe
+LEFT JOIN status_meldung AS s5 ON s5.datum = date_add(sm.datum, INTERVAL -5 DAY) AND s5.kunde = sm.kunde AND s5.aufgabe = sm.aufgabe
+LEFT JOIN status_meldung AS s4 ON s4.datum = date_add(sm.datum, INTERVAL -4 DAY) AND s4.kunde = sm.kunde AND s4.aufgabe = sm.aufgabe
+LEFT JOIN status_meldung AS s3 ON s3.datum = date_add(sm.datum, INTERVAL -3 DAY) AND s3.kunde = sm.kunde AND s3.aufgabe = sm.aufgabe
+LEFT JOIN status_meldung AS s2 ON s2.datum = date_add(sm.datum, INTERVAL -2 DAY) AND s2.kunde = sm.kunde AND s2.aufgabe = sm.aufgabe
+LEFT JOIN status_meldung AS s1 ON s1.datum = date_add(sm.datum, INTERVAL -1 DAY) AND s1.kunde = sm.kunde AND s1.aufgabe = sm.aufgabe
+
+WHERE sm.datum = '2017-06-06'
+
+
+
+
+SELECT DISTINCT a.datum, a.wochentag, a.feiertag, k.kunde, ka.aufgabe, k.system, k.bundesland, ka.start_soll,
+	case
+	  when a.wochentag = 'Mo' and ka.ende_mo IS NOT NULL then ka.ende_mo
+	  when a.wochentag = 'Di' and ka.ende_di IS NOT NULL then ka.ende_di
+	  when a.wochentag = 'Mi' and ka.ende_mi IS NOT NULL then ka.ende_mi
+	  when a.wochentag = 'Do' and ka.ende_do IS NOT NULL then ka.ende_do
+	  when a.wochentag = 'Fr' and ka.ende_fr IS NOT NULL then ka.ende_fr
+	  when a.wochentag = 'Sa' and ka.ende_sa IS NOT NULL then ka.ende_sa
+	  when a.wochentag = 'So' and ka.ende_so IS NOT NULL then ka.ende_so
+	  else ka.ende_soll
+	end as 'ende_soll',
+	ka.woche,  
+	case
+	 when ka.woche = 'Mo-Fr' then a.mofr
+	 when ka.woche = 'Mo-Sa' then a.mosa
+	 when ka.woche = 'Mo-So' then a.moso
+	 when ka.woche = 'Di-So' then a.diso
+	 else 1
+	end
+	* ka.aktiv * if(a.datum >= ka.erster_status, 1, 0)  as 'anstehend'
+								
+FROM kunden k
+INNER JOIN arbeitstage a USING (bundesland)
+INNER JOIN kunden_aufgabe ka USING (kunde)
+
+WHERE a.datum <= date_add(now(), INTERVAL 1 DAY) 
+AND a.datum >= date_add(now(), INTERVAL -20 DAY)
+							
+							
+							
+							
+							LEFT JOIN status_meldung sm USING (datum, kunde)
+							LEFT JOIN status_kommentar sk ON sm.kommentar_id = sk.id
+							LEFT JOIN status_kommentar as sk2 ON a.datum = sk2.datum AND k.kunde = sk2.kunde
+
+							WHERE {$datum} AND {$datum_bis} AND {$kunde} AND a.datum <= now() AND k.erster_status <= a.datum
+							AND k.aktiv = 1
+							ORDER BY a.datum, k.ende_soll
+							
+							
+							end * if(sk.status <= 1, 0, 1) * if(sm.anzahl > 0 or (sm.anzahl is null and now() > date_add(concat(a.datum, ' ', k.ende_soll), INTERVAL 1 HOUR)), 1, 0) as fehler,
+								if(sm.anzahl is null and now() > date_add(concat(a.datum, ' ', k.ende_soll), INTERVAL 1 HOUR), 1, 0) as fehlend,
+