new file mode 100644
--- /dev/null
+++ b/classes/bfw/mvc/model/TTicket.php
@@ -0,0 +1,196 @@
+<?php
+
+namespace bfw\mvc\model {
+
+ /**
+ * Class TTicket
+ *
+ * @method int getUser_Id()
+ * @method int getStatus_Id()
+ * @method string getSubject()
+ * @method string getMessage()
+ * @method bool getLocked()
+ * @method timestamp getLast_Access()
+ *
+ * @method setStatus_Id($param)
+ * @method setSubject($param)
+ * @method setMessage($param)
+ * @method setLocked($param)
+ * @method setLast_Access($param)
+ *
+ */
+ class TTicket extends Model {
+ private static $logger = null;
+
+ public function __construct() {
+ parent::__construct('t_ticket');
+
+ self::$logger = \Logger::getLogger('__CLASS__');
+
+ $this->data = array(
+ 'id' => NULL,
+ 'user_id' => 1,
+ 'status_id' => 1,
+ 'subject' => '',
+ 'message' => '',
+ 'locked' => 0,
+ 'last_access' => 'now()',
+ );
+ }
+
+ /**
+ * <b>Findet alle Tickets des angegebenen Nutzers</b>
+ *
+ *
+ * @param SERIAL $uid
+ * @return array|null
+ */
+ public function findAllTicketsByUserid($uid) {
+ return $this->findAllByField('user_id', $uid);
+ }
+
+ /**
+ * <b>Weisst frei gewordenen Tickets automatisiert zu.</b>
+ */
+ public function reassignFreeTickets() {
+ $tickets = $this->findAllByField('user_id', 1);
+
+ $tUser = new TUser();
+ foreach ($tickets as $ticket) {
+ $freeSupporterId = $tUser->getFreeSupporterId();
+
+ /**
+ * Niemals vergessen: Nur aktualisieren, wenn auch
+ * aktualisiert werden muss.
+ *
+ */
+ if ($freeSupporterId > 1) {
+ $ticket->setUser_Id($freeSupporterId);
+ if ($ticket->store($ticket->getId(), $ticket)) {
+ self::$logger->info(sprintf("TICKET %d wurde neu zugewiesen.", $ticket->getId()));
+ }
+ }
+ }
+ }
+
+ public function lockTicket($ticket, $user) {
+ if ($user->getGroup_id() == TGroup::SUPPORTER) {
+ if ($ticket->getLocked() == false) {
+ $ticket->setLocked(1);
+ $ticket->setLast_Access(date('Y-m-d H:i:s'));
+
+ if ($this->store($ticket->getId(), $ticket)) {
+ self::$logger->info(sprintf("TICKET %d wurde gesperrt", $ticket->getId()));
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * <b>Das Ticket wird automatisch entsperrt nach 2 Stunden</b>
+ *
+ * @param $tTicket
+ * @return bool
+ */
+ public function unlockTickets($tTicket) {
+ $tickets = $tTicket->findAll(false);
+ $user = new TUser();
+
+ foreach ($tickets as $ticket) {
+ if ($ticket->getStatus_Id() == TStatus::GESCHLOSSEN) {
+ continue;
+ }
+
+ // Ticketalter
+ $ticketAge = time() - strtotime($ticket->getLast_Access());
+
+ // Die Bearbeitungszeit beträgt 2 Stunden pro Supporter
+ $deadLine = 3600 * 2;
+
+ self::$logger->info('Ticket-Alter: ' . $ticketAge);
+ self::$logger->info('Deadline: ' . $deadLine);
+
+ if ($ticketAge > $deadLine) {
+ self::$logger->info('Time is up: Daten werden geändert.');
+ $freeSupporterId = $user->getFreeSupporterId();
+
+ if ($freeSupporterId > 1) {
+ $ticket->setUser_Id($freeSupporterId);
+ $ticket->setLocked(0);
+
+ if ($this->store($ticket->getId(), $ticket)) {
+ continue;
+ }
+ } else {
+ // Es existieren keine Supporter
+ self::$logger->info(sprintf("%s(): Es existieren keine Supporter!", __METHOD__));
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * <b>Überladene find Methode</b>
+ *
+ * In früheren Versionen wurde hier das Ticket 'on the fly' modifiziert.
+ * Da das aber nicht Sinn und Zweck einer 'find' Methode ist, wurde das
+ * wieder entfernt und die Modifizierung erfolgt außerhalb...
+ *
+ * <b>Sinn und Zweck dieser Methode ist: 'Ticket-ID: nnn' ins Log zu schreiben...</b>
+ *
+ * @param $id
+ *
+ * @return array|null
+ */
+ public function find($id) {
+ self::$logger->info(sprintf("Ticket-ID: %d", $id));
+
+ return parent::find($id);
+ }
+
+ /**
+ * <b>Prüft, ob der übergebene Nutzer überhaupt die Berechtigung für das übergebene Ticket besitzt.</b>
+ *
+ * @param $ticket
+ * @param $user
+ * @return bool
+ */
+ public function hasPrivilege($ticket, $user, $write = true) {
+
+ // NULL Tickets: Kein Zugriff
+ if (!is_object($ticket)) {
+ self::$logger->warn(sprintf("%s(): Ticket wurde nicht initialisiert!", __METHOD__));
+ return false;
+ }
+
+ // NULL User: Kein Zugriff
+ if (!is_object($user)) {
+ self::$logger->warn(sprintf("%s(): Benutzer wurde nicht initialisiert!", __METHOD__));
+ return false;
+ }
+
+ // ADMIN UND MANAGER: Zugriff per Default
+ switch ($user->getGroup_Id()) {
+ case TGroup::ADMIN:
+ case TGroup::MANAGER:
+ return true;
+ }
+
+ if ($write == false) {
+ // System-Datensatz herausfiltern
+ if ($ticket->getId() > 1) {
+ return true;
+ }
+ }
+
+ // Ticketbasierter Zugriff: Ticket-Owner == Angemeldeter Benutzer?
+ return ($ticket->getUser_Id() == $user->getId());
+ }
+
+ }
+}
\ No newline at end of file