<?php
/*
 * SPDX-FileCopyrightText: 2024 OpenXE-org
 * SPDX-FileCopyrightText: 2022 Andreas Palm
 * SPDX-FileCopyrightText: 2019 Xentral (c) Xentral ERP Software GmbH, Fuggerstrasse 11, D-86150 Augsburg, Germany
 *
 * SPDX-License-Identifier: LicenseRef-EGPL-3.1
 */

/*
**** COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
* 
* Xentral (c) Xentral ERP Sorftware GmbH, Fuggerstrasse 11, D-86150 Augsburg, * Germany 2019
*
* This file is licensed under the Embedded Projects General Public License *Version 3.1. 
*
* You should have received a copy of this license from your vendor and/or *along with this file; If not, please visit www.wawision.de/Lizenzhinweis 
* to obtain the text of the corresponding license version.  
*
**** END OF COPYRIGHT & LICENSE NOTICE *** DO NOT REMOVE ****
*/
?>
<?php
use Xentral\Components\MailClient\Client\MimeMessageFormatterInterface;
use Xentral\Core\LegacyConfig\ConfigLoader;
use Xentral\Modules\SystemMailClient\MailClientConfigProvider;
use Xentral\Modules\SystemMailClient\MailClientProvider;
use Xentral\Modules\SystemMailer\Data\EmailBackupAccount;
use Xentral\Components\Mailer\Data\EmailRecipient;
use Xentral\Modules\SuperSearch\Scheduler\SuperSearchFullIndexTask;

class erpAPI
{
  var $verbrauchslagervorhanden = null;
  var $commonreadonly=0;
  var $menucounter=0;
  var $mail_error=0;
  var $beschriftung_sprache="";
  var $check_column_missing_run=false;
  var $check_column_missing=array();
  var $check_index_missing=array();
  var $logtime;
  var $firstlogtime;
  var $firmendaten;
  var $cache;
  var $menuquery;
  var $BriefpapierHintergrunddisable;
  var $kurzueberschrift;
  var $kurzueberschrifturl;
  var $kurzueberschrift1;
  var $kurzueberschrift2;
  var $backlink;
  var $CheckColumnTableCache;
  var $Changelog;
  var $aktprozessstarter;
  private static $license;

  private $modulvorhandenlist = null;

  public static $lasttime = 0;
  public $uebersetzungId;
  public $uebersetzungBeschriftung;
  /** @var array $moduleActions */
  protected $moduleActions = [];
  /** @var string $cronjobObjDb */
  protected $cronjobObjDb;

  /** @var array $appList */
  protected $appList = [];

  /** @var ApplicationCore $app */

  public function __construct($app)
  {
    $this->app=$app;
    if(empty($this->app->erp)){
      $this->app->erp = $this;
    }
    $this->firstlogtime = microtime(true);
    $this->logtime = microtime(true);

    if(defined('SCRIPT_START_TIME'))
    {
      $this->firstlogtime = SCRIPT_START_TIME;
    }
    $this->cache = null;
    $this->menuquery = null;
    $this->BriefpapierHintergrunddisable = false;
  }

  /**
   * @param string $category
   * @param string $name
   * @param string $status
   * @param string $message
   */
  public function setSystemHealth($category, $name, $status, $message = '') {
    /** @var Systemhealth $obj */
    $obj = $this->LoadModul('systemhealth');
    if(empty($obj)) {
      return;
    }
    $obj->changeStatus($category, $name, $status, $message);
  }

  public function loadCronjobObj()
  {
    $dbName = $this->app->Conf->WFdbname;
    /** @var Prozessstarter cronjobObj */
    if(empty($this->cronjobObj) || empty($this->cronjobObjDb) || $this->cronjobObjDb !== $dbName) {
      $this->cronjobObj = $this->app->loadModule('prozessstarter', true);
      $this->cronjobObjDb = $this->app->Conf->WFdbname;
    }
  }

  /**
   * @param string   $status
   * @param null|int $prozessstarter
   */
  public function ProzessstarterStatus($status, $prozessstarter = null)
  {
    $this->loadCronjobObj();
    if(empty($this->cronjobObj)) {
      return;
    }
    if(method_exists($this->cronjobObj,'setCronjobStatus')) {
      $this->cronjobObj->setCronjobStatus($status, $prozessstarter);
    }
  }

  /**
   * @param array $output
   * @param array $task
   */
  public function checkCronjobMemory($output, $task)
  {
    $this->loadCronjobObj();
    if(method_exists($this->cronjobObj,'checkCronjobMemory')) {
      $this->cronjobObj->checkCronjobMemory($output, $task);
    }
  }

  public function checkIfCronjobRunning($uid, $task)
  {
    $this->loadCronjobObj();
    if(method_exists($this->cronjobObj,'checkIfCronjobRunning')) {
      $this->cronjobObj->checkIfCronjobRunning($uid, $task);
    }
  }

  public function checkCronjobRunning($uid, $task) {
    $this->loadCronjobObj();
    if(empty($this->cronjobObj)) {
      return;
    }
    if(method_exists($this->cronjobObj,'checkCronjobRunning')) {
      return $this->cronjobObj->checkCronjobRunning($uid, $task);
    }
    return true;
  }

  public function closeAndLogCronjob($uid, $fromStarter2 = false)
  {
    $this->loadCronjobObj();
    if(method_exists($this->cronjobObj,'closeAndLogCronjob')) {
      $this->cronjobObj->closeAndLogCronjob($uid, $fromStarter2);
    }
  }

  public function setCronjobRunning($uid, $task = null, $active = true) {
    $this->loadCronjobObj();
    if(empty($this->cronjobObj)) {
      return;
    }
    if(method_exists($this->cronjobObj,'setCronjobRunning')) {
      $this->cronjobObj->setCronjobRunning($uid, $task, $active);
    }
  }

  // @bruno
  public function TrackingCSV($datei, $versand, $append = false, $uebertragung = 0)
  {
    if((int)$versand <= 0 || $datei == ''){
      return false;
    }
    $arr = $this->app->DB->SelectRow("SELECT ".($uebertragung?" am.id_ext as auftragextid, ":"")." v.tracking, l.belegnr, if(ifnull(l.sprache,'') = '',ifnull(a.sprache,''),l.sprache) as tracking_sprache, l.name, v.versandart FROM versand v INNER JOIN lieferschein l ON v.lieferschein = l.id AND v.id = '$versand'
    LEFT JOIN auftrag a ON l.auftragid = a.id
    ".($uebertragung?"
    LEFT JOIN api_mapping am ON am.tabelle = 'auftrag' AND am.uebertragung_account = '$uebertragung' AND id_int = a.id
    ":"")."
    LIMIT 1");
    if($arr)
    {
      $file_ex = @is_file($datei);
      $handle = @fopen($datei, $append?'a':'w');
      if($handle)
      {
        if(!$append || !$file_ex)
        {
          $output = "";
          foreach($arr as $k => $v)$output .= $k.';';
          $output .= "\r\n";
          fputs($handle, $output);
        }
        $output = "";
        foreach($arr as $k2 => $v2)
        {
          $output .= '"'.$v2.'"'.';';
        }
        $output .= "\r\n";
        fputs($handle, $output);
        fclose($handle);
        return true;
      }
    }
    return false;
  }

/**
 * @bruno Prüfen ob es weg kann
 *
 * @deprecated
 *
 * @param $beleg
 *
 * @return void
 */
public function checkPDFClass($beleg)
{
  if(empty($beleg))
  {
    return;
  }
  $classcustom = ucfirst($beleg).'PDFCustom';
  $class = ucfirst($beleg).'PDF';
  if(class_exists($classcustom) || class_exists($class) || !file_exists(__DIR__.'/dokumente/class.'.$beleg.'.php')){
    return;
  }
  if(!defined('FPDF_FONTPATH')){
    define('FPDF_FONTPATH',__DIR__.'/pdf/font/');
  }
  if(!class_exists('FPDFWAWISION'))
  {
    if(file_exists(dirname(dirname(__DIR__)).'/conf/user_defined.php')){
      include_once dirname(dirname(__DIR__)).'/conf/user_defined.php';
    }
    if(defined('USEFPDF3') && USEFPDF3 && file_exists(__DIR__ .'/pdf/fpdf_3.php'))
    {
      require_once __DIR__ .'/pdf/fpdf_3.php';
    }
    else if(defined('USEFPDF2') && USEFPDF2 && file_exists(__DIR__ .'/pdf/fpdf_2.php'))
    {
      require_once __DIR__ .'/pdf/fpdf_2.php';
    } else {
      require_once __DIR__ .'/pdf/fpdf.php';
    }
  }
  if(!class_exists('PDF_EPS')){
    include_once __DIR__.'/pdf/fpdf_final.php';
  }
  if(!class_exists('SuperFPDF')){
    require_once __DIR__.'/dokumente/class.superfpdf.php';
  }

  if(!class_exists('Briefpapier'))
  {
    if(file_exists(__DIR__.'/dokumente/class.briefpapier_custom.php'))
    {
      require_once __DIR__.'/dokumente/class.briefpapier_custom.php';
    }else{
      require_once __DIR__.'/dokumente/class.briefpapier.php';
    }
  }

  if(file_exists(__DIR__.'/dokumente/class.'.$beleg.'_custom.php'))
  {
    include_once __DIR__.'/dokumente/class.'.$beleg.'_custom.php';
  }elseif(file_exists(__DIR__.'/dokumente/class.'.$beleg.'.php'))
  {
    include_once __DIR__.'/dokumente/class.'.$beleg.'.php';
  }
  if(!class_exists('image')){
    require __DIR__ . '/class.image.php';
  }
}

  function ArtikelUebertragen($datei, $artikelarr, $uebertragung = 0)
  {
    /** @var Uebertragungen $obj */
    $obj = $this->app->erp->LoadModul('uebertragungen');
    if(!empty($obj) && method_exists($obj, 'ArtikelUebertragen')) {
      return $obj->ArtikelUebertragen($datei, $artikelarr, $uebertragung);
    }
    return false;
  }

  /** @deprecated */
  function LagerzahlenCSV($datei, $artikel, $lager = 0, $lager_platz = 0, $append = false)
  {
    if((int)$artikel <= 0 || $datei == '')return false;
    if($lager || $lager_platz)
    {
      $artikelarr = $this->app->DB->SelectRow("SELECT art.nummer, art.herstellernummer, art.ean, ifnull(lag.menge,0) as lager_menge_total,  lag.lager_platz
      FROM artikel art 
      LEFT JOIN (
        SELECT lpi.artikel,lp.kurzbezeichnung as lager_platz, trim(ifnull(sum(lpi.menge),0))+0 as menge FROM lager_platz_inhalt lpi
        INNER JOIN lager_platz lp ON lpi.lager_platz = lp.id AND lp.geloescht = 0 ".($lager_platz?" AND lp.id = '$lager_platz' ":"")."
        ".($lager?" AND lp.lager = '$lager' ":"")."
        WHERE lpi.artikel = '$artikel' GROUP BY lp.id
      ) lag ON art.id = lag.artikel  WHERE art.id = '$artikel' LIMIT 1");
    }else{
      $artikelarr = $this->app->DB->SelectRow("SELECT art.nummer, art.herstellernummer, art.ean FROM artikel art
      WHERE art.id = '$artikel' LIMIT 1");
      if($artikelarr)$artikelarr['lager_menge_total'] = floor($this->ArtikelAnzahlVerkaufbar($artikel));
    }
    if($artikelarr){
      $file_ex = @is_file($datei);
      $handle = @fopen($datei, $append?'a':'w');
      if($handle)
      {
        if(!$append || !$file_ex)
        {
          $output = "";
          foreach($artikelarr as $k => $v)$output .= $k.';';
          $output .= "\r\n";
          fputs($handle, $output);
        }
        $output = "";
        foreach($artikelarr as $k2 => $v2)
        {
          $output .= '"'.$v2.'"'.';';
        }
        $output .= "\r\n";
        fputs($handle, $output);
        fclose($handle);
        return true;
      }
    }
    return false;
  }

// @todo
function Belegeexport($datei, $doctype, $doctypeid, $append = false, $optionen = null)
{
  if($doctype == '' || (int)$doctypeid <= 0 || $datei == '') {
    return false;
  }

  $arr = [
    'adresse','artikel','art','status','beleg_status','beleg_datum','beleg_lieferdatum','beleg_tatsaechlicheslieferdatum','beleg_versandart','beleg_zahlungsweise','beleg_belegnr','beleg_hauptbelegnr','beleg_kundennummer','beleg_name','beleg_abteilung',
     'beleg_unterabteilung','beleg_adresszusatz','beleg_ansprechpartner','beleg_telefon','beleg_email','beleg_land','beleg_strasse','beleg_plz','beleg_ort','beleg_projekt','beleg_aktion',
     'beleg_internebemerkung','beleg_internebezeichnung','beleg_freitext','beleg_ihrebestellnummer','beleg_lieferbedingung','beleg_art','artikel_nummer','artikel_bezeichnung','artikel_beschreibung',
     'artikel_menge','artikel_preis','artikel_rabatt','artikel_waehrung','artikel_lieferdatum','artikel_sort','artikel_umsatzsteuer','artikel_einheit','artikel_zolltarifnummer',
     'artikel_herkunftsland','artikel_artikelnummerkunde',
     'artikel_freifeld1','artikel_freifeld2','artikel_freifeld3','artikel_freifeld4','artikel_freifeld5','artikel_freifeld6','artikel_freifeld7','artikel_freifeld8','artikel_freifeld9','artikel_freifeld10',
     'artikel_freifeld11','artikel_freifeld12','artikel_freifeld13','artikel_freifeld14','artikel_freifeld15','artikel_freifeld16','artikel_freifeld17','artikel_freifeld18','artikel_freifeld19','artikel_freifeld20','artikel_freifeld21','artikel_freifeld22','artikel_freifeld23','artikel_freifeld24','artikel_freifeld25','artikel_freifeld26','artikel_freifeld27','artikel_freifeld28','artikel_freifeld29','artikel_freifeld30','artikel_freifeld31','artikel_freifeld32','artikel_freifeld33','artikel_freifeld34','artikel_freifeld35','artikel_freifeld36','artikel_freifeld37','artikel_freifeld38','artikel_freifeld39','artikel_freifeld40',
    'beleg_unterlistenexplodieren'
  ];

  if($doctype === 'bestellung') {
    $arr[] = 'beleg_lieferantennummer';
  }

  $colsa[] = 't.adresse';
  if($doctype !== 'verbindlichkeit'){
    $colsa[] = 'p.artikel';
  }
  $colsa[] = 'pr.abkuerzung as beleg_projekt';
  if(isset($optionen['art']) && $optionen['art'] != '') {
    $colsa[] = "'".$optionen['art']."' as art";
  }
  else{
    $colsa[] = "'$doctype' as art";
  }

  $checkfields = $this->app->DB->SelectRow("SELECT * FROM $doctype LIMIT 1");
  $checkfieldsposition = $doctype === 'verbindlichkeit'
    ?null: $this->app->DB->SelectRow("SELECT * FROM ".$doctype."_position LIMIT 1");
  foreach($arr as $v) {
    if(strpos($v,'beleg_') === 0) {
      $k = substr($v, 6);
      if($k !== 'projekt' && $k !== 'hauptbelegnr') {
        if(($k !== 'tatsaechlicheslieferdatum' && $k !== 'aktion' && $k !== 'art' && $k !== 'ihrebestellnummer') || $doctype === 'auftrag') {
          if(($doctype !== 'auftrag' && $doctype !== 'lieferschein') || $k !== 'lieferdatum') {
            if(array_key_exists($k,$checkfields)) {
              $colsa[] = 't.'.$k.' as '.$v;
            }
          }
        }
      }
    }
    elseif(strpos($v,'artikel_') === 0) {
      $k = substr($v, 8);
      if($k !== 'preisfuermenge' || $doctype === 'auftrag') {
        if(($k !== 'rabatt'
            || ($doctype !== 'bestellung' && $doctype !== 'lieferschein' && $doctype !== 'retoure' && $doctype!=='produktion'))
          && (($k !== 'preis' && $k !== 'waehrung' && $k !== 'umsatzsteuer') ||
        ($doctype !== 'lieferschein' && $doctype!=='produktion' && $doctype !== 'retoure'))) {
          if($doctype === 'bestellung' && $k === 'nummer') {
            $k = 'bestellnummer';
          }
          if($doctype === 'bestellung' && $k === 'bezeichnung') {
            $k = 'bezeichnunglieferant';
          }
          if($doctype === 'verbindlichkeit') {
            $colsa[] = " '' as " . $v;
            continue;
          }
          if(array_key_exists($k,$checkfieldsposition) && $k !== 'projekt') {
            if($k=='preis')
            {
              $colsa[] = $this->app->erp->FormatPreis('p.'.$k).' as '.$v;
            }
            else if($k=='menge')
            {
              $colsa[] = $this->app->erp->FormatMenge('p.'.$k).' as '.$v;
            }
            else {
              $colsa[] = 'p.' . $k . ' as ' . $v;
            }
          }
        }
      }
    }
  }
  if($doctype === 'auftrag') {
    $colsa[] = 't2.belegnr as beleg_hauptbelegnr';
  }
  if($doctype !== 'verbindlichkeit') {
    $colsa[] = " art.ean as artikel_ean ";
  }

  $colsa[] = "'1' as artikel_preisfuermenge ";
  $cols = implode(',', $colsa);
  switch($doctype) {
    case 'verbindlichkeit':
      $arr = $this->app->DB->SelectArr(
        sprintf(
          "SELECT %s 
          FROM `verbindlichkeit` AS `t` 
          LEFT JOIN `projekt` AS `pr` ON t.projekt = pr.id 
          WHERE t.id = %d",
          $cols, $doctypeid
        )
      );
      break;
    case 'auftrag':
      $arr = $this->app->DB->SelectArr(
        sprintf(
          "SELECT %s 
          FROM `auftrag` AS `t` 
          INNER JOIN `auftrag_position` AS `p` ON t.id = p.auftrag 
          INNER JOIN `artikel` AS `art` ON p.artikel = art.id 
          LEFT JOIN `projekt` AS `pr` ON t.projekt = pr.id 
          LEFT JOIN `auftrag` AS `t2` ON t.teillieferungvon = t2.id
          WHERE t.id = %d",
          $cols, $doctypeid
        )
      );
      break;
    default:
      $arr = $this->app->DB->SelectArr(
        sprintf(
          "SELECT %s
          FROM `%s` AS `t` 
          INNER JOIN `%s` AS `p` ON t.id = p.%s 
          INNER JOIN `artikel` AS `art` ON p.artikel = art.id
          LEFT JOIN `projekt` AS `pr` ON t.projekt = pr.id 
          WHERE t.id = %d",
          $cols, $doctype, $doctype.'_position',$doctype, $doctypeid
        )
      );
        break;
  }

  if($arr) {
    $file_ex = @is_file($datei);
    $handle = @fopen($datei, $append?'a':'w');
    if($handle) {
      if(!$append || !$file_ex) {
        $output = '';
        foreach($arr[0] as $k => $v) {
          $output .= $k.';';
        }
        $output .= "\r\n";
        fwrite($handle, $output);
      }
      $output = '';
      foreach($arr as $k => $v) {
        foreach($v as $k2 => $v2) {
          if(($k2 === 'belegnr' || $k2 === 'beleg_belegnr')) {
            if($k > 0) {
              if((isset($optionen['new']) && $optionen['new'] ) || $v2 == '' || !(isset($optionen['noparent']) && $optionen['noparent'])){
                $v2 = 'PARENT';
              }
            }
            else {
              if(isset($optionen['new']) && $optionen['new']) {
                $v2 = 'NEW';
              }
            }
          }
          $v3 = str_replace(array('&uuml;','&ouml;','&auml;','&Uuml;','&Ouml;','&Auml;','&szlig;','"'),array('ü','ö','ä','Ü','Ö','Ä','ß','"'.'"'),$v2);
          if(isset($optionen['nowrap'])) {
            $v3 = str_replace(array("\r","\n"),'', $v3);
          }
          $output .= '"'.$v3.'"'.';';
        }
        $output .= "\r\n";
      }
      fwrite($handle, $output);
      fclose($handle);
      return true;
    }
  }
  return false;
}

  // $app->Module()->Warehouse()->Gateway()->isConsumptionWarehouseAvailable()
  // $app->Warehouse()->
  function Verbrauchslagervorhanden()
  {
    if(is_null($this->verbrauchslagervorhanden))
    {
      $this->verbrauchslagervorhanden = $this->app->DB->Select("SELECT id FROM lager_platz WHERE verbrauchslager = 1 LIMIT 1")?true:false;
    }
    return $this->verbrauchslagervorhanden;
  }

  public function ExitWawi($status = 0)
  {
    if(method_exists($this->app, 'ExitXentral')) {
      $this->app->ExitXentral($status);
    }
    exit($status);
  }

  // @refactor Module OrderPicking
  public function GetNextKommissionierung($bezeichnung = '')
  {
    $this->app->DB->Insert("INSERT INTO kommissionierung (bearbeiter, bezeichnung) values ('".$this->app->DB->real_escape_string($this->app->User->GetName())."','".$bezeichnung."')");
    return $this->app->DB->GetInsertID();
  }

  // @refactor in DevTools
  function LogWithTime($message, $json = false)
  {
    if(defined('SCRIPT_START_TIME'))
    {
      $akttime = microtime(true);
      $aktmemory = number_format(memory_get_usage()/1024.0/1024.0,2);
      $peakmemory = number_format(memory_get_peak_usage()/1024.0/1024.0,2);
      $runtime = number_format($akttime - $this->logtime,3);
      $runtimeall = number_format($akttime - $this->firstlogtime,3);
      $this->LogFile('Time all '.$runtimeall."s last: ".$runtime."s Memakt:".$aktmemory."MB peak:".$peakmemory."MB ".$this->app->DB->real_escape_string( $json?json_encode($message):$message));
      $this->logtime = $akttime;
    }
  }

  /**
   * @deprecated Secure-Klasse verwenden
   *
   * @param $data
   *
   * @return mixed|null|string|string[]
   */
  function xss_clean($data)
  {
    // Fix &entity\n;
    $data = str_replace(array('&amp;','&lt;','&gt;'), array('&amp;amp;','&amp;lt;','&amp;gt;'), $data);
    $data = preg_replace('/(&#*\w+)[\x00-\x20]+;/u', '$1;', $data);
    $data = preg_replace('/(&#x*[0-9A-F]+);*/iu', '$1;', $data);
    $data = html_entity_decode($data, ENT_COMPAT, 'UTF-8');

    // Remove any attribute starting with "on" or xmlns
    $data = preg_replace('#(<[^>]+?[\x00-\x20"\'])(?:on|xmlns)[^>]*+>#iu', '$1>', $data);

    // Remove javascript: and vbscript: protocols
    $data = preg_replace('#([a-z]*)[\x00-\x20]*=[\x00-\x20]*([`\'"]*)[\x00-\x20]*j[\x00-\x20]*a[\x00-\x20]*v[\x00-\x20]*a[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2nojavascript...', $data);
    $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*v[\x00-\x20]*b[\x00-\x20]*s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:#iu', '$1=$2novbscript...', $data);
    $data = preg_replace('#([a-z]*)[\x00-\x20]*=([\'"]*)[\x00-\x20]*-moz-binding[\x00-\x20]*:#u', '$1=$2nomozbinding...', $data);

    // Only works in IE: <span style="width: expression(alert('Ping!'));"></span>
    $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?expression[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
    $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?behaviour[\x00-\x20]*\([^>]*+>#i', '$1>', $data);
    $data = preg_replace('#(<[^>]+?)style[\x00-\x20]*=[\x00-\x20]*[`\'"]*.*?s[\x00-\x20]*c[\x00-\x20]*r[\x00-\x20]*i[\x00-\x20]*p[\x00-\x20]*t[\x00-\x20]*:*[^>]*+>#iu', '$1>', $data);

    // Remove namespaced elements (we do not need them)
    $data = preg_replace('#</*\w+:\w[^>]*+>#i', '', $data);

    do
    {
        // Remove really unwanted tags
        $old_data = $data;
        $data = preg_replace('#</*(?:applet|b(?:ase|gsound|link)|embed|frame(?:set)?|i(?:frame|layer)|l(?:ayer|ink)|meta|object|s(?:cript|tyle)|title|xml)[^>]*+>#i', '', $data);
    }
    while ($old_data !== $data);

    return $data;
  }

  // @refactor in Benutzer Modul

  /**
   * @return array
   */
  public function getEncModullist()
  {
    if(file_exists(__DIR__.'/modulliste.php')) {
      $erg = [];
      include __DIR__.'/modulliste.php';
      return $erg;
    }
    return [];
  }

  /**
   * @return array|null
   */
  public function getAppList()
  {
    if(!isset($this->appList[$this->app->Conf->WFdbname])) {
      $this->appList[$this->app->Conf->WFdbname] = $this->app->getAppList();
    }

    return $this->appList[$this->app->Conf->WFdbname];
  }

  function getApps()
  {
    /** @var Appstore $obj */
    $obj = $this->LoadModul('appstore');
    if(!empty($obj) && method_exists($obj,'getAppsList'))
    {
      return $obj->getAppsList();
    }

    return null;
  }

  function StartseiteMenu()
  {
    /** @var Welcome $obj */
    $obj = $this->LoadModul('welcome');
    if(!empty($obj) && method_exists($obj,'StartseiteMenu'))
    {
      $obj->StartseiteMenu();
    }
  }

  function EventAPIAdd($eventname,$parameter,$module,$action,$kommentar="", $api = 0)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'EventAPIAdd'))
    {
      return $obj->EventAPIAdd($eventname,$parameter,$module,$action,$kommentar, $api);
    }
  }

  function EventCall($id)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'EventCall'))
    {
      return $obj->EventCall($id);
    }
  }

  function EventSendRequest($methodname,$xml,$hash,$parameter="",&$result_body="", $api = 0)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'EventSendRequest'))
    {
      return $obj->EventSendRequest($methodname,$xml,$hash,$parameter,$result_body, $api);
    }
  }

// @refactor Hook Komponente
function RemoveNavigationHook($module, $action = null)
{
  if(empty($module)) {
    return;
  }
  if($action)
  {
    $this->app->DB->Delete("DELETE FROM `hook_navigation` WHERE `module` = '".$this->app->DB->real_escape_string($module)."' AND `action` = '".$this->app->DB->real_escape_string($action)."'");
  }else{
    $this->app->DB->Delete("DELETE FROM `hook_navigation` WHERE `module` = '".$this->app->DB->real_escape_string($module)."'");
  }
}

  /**
   * @param string $table
   * @param string $uniqeCol
   */
public function repairNullIds($table, $uniqeCol = 'name')
{
  $doppelteids = $this->app->DB->SelectArr(
    sprintf(
      'SELECT `id`, count(*) as `co` FROM `%s` GROUP BY `id` HAVING COUNT(*) > 1',
      $table
    )
  );
  if(empty($doppelteids)) {
    $this->CheckAlterTable(sprintf("ALTER TABLE `%s` ADD PRIMARY KEY(`id`);", $table));
    $maxid = 1+(int)$this->app->DB->Select(sprintf("SELECT max(id) FROM `%s`", $table));
    $this->CheckAlterTable(
      sprintf(
        "ALTER TABLE `%s` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=%d",
        $table,
        $maxid
      )
    );
    return;
  }

  foreach($doppelteids as $val) {
    $maxid = 1+(int)$this->app->DB->Select(
        sprintf("SELECT max(id) FROM `%s`", $table)
      );
    if(empty($uniqeCol)) {
      for($i = 1; $i <= $val['co']; $i++) {
        $this->app->DB->Update(
          sprintf(
            'UPDATE `%s` 
            SET `id` = %d WHERE `id` = %d 
            LIMIT 1',
            $table, $maxid, $val['id']
          )
        );
      }
      continue;
    }
    $doppelte = $this->app->DB->SelectArr(
      sprintf('SELECT * FROM `%s` WHERE id = %d', $table, $val['id'])
    );
    foreach($doppelte as $row) {
      $this->app->DB->Update(
        sprintf(
          "UPDATE `%s` 
          SET id = %d WHERE id = %d AND `%s` = '%s' 
          LIMIT 1",
          $table, $maxid, $val['id'], $uniqeCol, $val[$uniqeCol]
        )
      );
      $maxid++;
    }
  }
  $this->CheckAlterTable(sprintf("ALTER TABLE `%s` ADD PRIMARY KEY(`id`);", $table));
  $maxid = 1+(int)$this->app->DB->Select(sprintf("SELECT max(id) FROM `%s`", $table));
  $this->CheckAlterTable(
    sprintf(
      "ALTER TABLE `%s` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=%d",
      $table,
      $maxid
    )
  );
}

// @refactor Hook Komponente
function RegisterNavigationHook($module, $action, $first, $sec, $aftersec = '', $position = 0)
{
  if(empty($module) || empty($action) || (String)$first === '') {
    return;
  }

  $check = $this->app->DB->SelectRow(
    "SELECT hn.id 
    FROM `hook_navigation` AS `hn` 
    WHERE hn.module = '".$this->app->DB->real_escape_string($module)."' AND hn.action = '".$this->app->DB->real_escape_string($action)."' 
    ORDER by hn.aktiv DESC 
    LIMIT 1"
  );
  if(!empty($check) && $check['id'] == 0) {
    $this->repairNullIds('hook_navigation');
    $check = $this->app->DB->SelectRow(
      "SELECT hn.id 
      FROM `hook_navigation` AS `hn` 
      WHERE hn.module = '".$this->app->DB->real_escape_string($module)."' AND hn.action = '".$this->app->DB->real_escape_string($action)."' 
      ORDER by hn.aktiv DESC 
      LIMIT 1"
    );
  }
  if($check) {
    $this->app->DB->Update("UPDATE `hook_navigation` SET `aktiv` = 1, `first` = '".$this->app->DB->real_escape_string($first)."', `sec` = '".$this->app->DB->real_escape_string($sec)."', `aftersec` = '".$this->app->DB->real_escape_string($aftersec)."', `position` = '".$this->app->DB->real_escape_string($position)."' WHERE `id` = ".(int)$check['id'].' LIMIT 1');
  }
  else {
    $this->app->DB->Insert("INSERT INTO `hook_navigation` (`module`, `action`, `first`, `sec`, `aftersec`, `position`, `aktiv`) 
    VALUES ('".$this->app->DB->real_escape_string($module)."','".$this->app->DB->real_escape_string($action)."',
    '".$this->app->DB->real_escape_string($first)."','".$this->app->DB->real_escape_string($sec)."','".$this->app->DB->real_escape_string($aftersec)."','".$this->app->DB->real_escape_string($position)."','1') 
    ");
  }
}

// @refactor Hook Komponente

  /**
   * @param array $menu
   */
public function NavigationHooks(&$menu)
{
  $hook_navigation = $this->app->DB->SelectArr(
    "SELECT hn.* 
    FROM `hook_navigation` AS `hn` 
    WHERE hn.aktiv = 1 AND hn.first != '' AND hn.module != '' AND hn.action != '' 
    ORDER BY hn.first, hn.aftersec DESC, hn.position, hn.sec"
  );

  if(!$hook_navigation) {
    return;
  }
  if($hook_navigation[0]['id'] === 0) {
    $this->repairNullIds('hook_navigation');
    $hook_navigation = $this->app->DB->SelectArr(
      "SELECT hn.* 
      FROM `hook_navigation` AS `hn` 
      WHERE hn.aktiv = 1 AND hn.first != '' AND hn.module != '' AND hn.action != '' 
      ORDER BY hn.first, hn.aftersec DESC, hn.position, hn.sec"
    );
  }

  foreach($menu as $k => $v) {
    if(isset($v['first'])) {
      $first[$v['first'][0]] = $k;
    }
  }

  foreach($hook_navigation as $k => $v) {
    if($k > 0 && $v['id'] > 0 && !empty($hook_navigation[$k-1]) && $hook_navigation[$k-1]['id'] > 0) {
      if(
          $v['module'] === $hook_navigation[$k-1]['module']
          && $v['action'] === $hook_navigation[$k-1]['action']
          && $v['sec'] === $hook_navigation[$k-1]['sec']
          && $v['first'] === $hook_navigation[$k-1]['first']
          && $v['aftersec'] === $hook_navigation[$k-1]['aftersec']
      ) {
        $this->app->DB->Delete(sprintf('DELETE FROM `hook_navigation` WHERE `id` = %d LIMIT 1', $v['id']));
        unset($hook_navigation[$k]);
        continue;
      }
    }
    if(!$this->RechteVorhanden($v['module'], $v['action'])) {
      continue;
    }
    if($v['sec'] !== '' || !isset($first[$v['first']])) {
      if($v['sec'] == '') {
        $menu[] = array('first'=>array($v['first'], $v['module'],$v['action']));
        $first[$v['first']] = (!empty($menu)?count($menu):0)-1;
      }
      elseif($v['sec'] != '' && !isset($first[$v['first']])){
        $menu[] = array('first'=>array($v['first'], '',''),'sec'=>array(array($v['sec'],$v['module'],$v['action'])));
        $first[$v['first']] = (!empty($menu)?count($menu):0)-1;
      }
      else{
        if(isset($menu[$first[$v['first']]])) {
          if($v['aftersec']) {
            if(empty($menu[$first[$v['first']]]['sec'])) {
              $ind = 0;
              $menu[$first[$v['first']]]['sec'][$ind] = array($v['sec'],$v['module'],$v['action']);
            }
            else{
              $found = false;
              foreach($menu[$first[$v['first']]]['sec'] as $k2 => $v2) {
                if($v2[0] == $v['aftersec']) {
                  $c = count($menu[$first[$v['first']]]['sec']);
                  for($k3 = $c; $k3 > $k2; $k3--)  {
                    $menu[$first[$v['first']]]['sec'][$k3] = $menu[$first[$v['first']]]['sec'][$k3-1];
                  }
                  $ind = $k2 + 1;
                  $menu[$first[$v['first']]]['sec'][$ind] = array($v['sec'],$v['module'],$v['action']);
                  $found = true;
                  break;
                }
              }
              if(!$found) {
                $ind = empty($menu[$first[$v['first']]]['sec'])?0:count($menu[$first[$v['first']]]['sec']);
                $menu[$first[$v['first']]]['sec'][$ind] = array($v['sec'],$v['module'],$v['action']);
              }
            }
          }
          else{
            $ind = empty($menu[$first[$v['first']]]['sec'])?0:count($menu[$first[$v['first']]]['sec']);
            $menu[$first[$v['first']]]['sec'][$ind] = array($v['sec'],$v['module'],$v['action']);
          }
        }
      }
    }
  }
}

// @refactor ModuleRenderer Komponente

  /**
   * @param string       $headline
   * @param string       $headline1
   * @param string|array $headline2
   */
  public function Headlines($headline = '', $headline1 = '', $headline2 = '')
{
  if($headline) {
    $this->kurzueberschrift = $headline;
    $this->app->Tpl->Set('KURZUEBERSCHRIFT', $headline);
  }
  if($headline1) {
    $this->kurzueberschrift1 = htmlspecialchars($headline1);
    $this->app->Tpl->Set('KURZUEBERSCHRIFT1', ' '.$headline1);
  }
  if($this->kurzueberschrift && $this->backlink && $this->kurzueberschrift1) {
    $this->app->Tpl->Set('KURZUEBERSCHRIFT', '<a href="'.$this->backlink.'">'.$this->kurzueberschrift.'</a>');
  }
  if($headline2) {
    if(is_string($headline2)) {
      $this->kurzueberschrift2 = ' <b>'.(stripos($headline2,'</a>')?$headline2:htmlspecialchars($headline2)).'</b>';
      $this->app->Tpl->Set('KURZUEBERSCHRIFT2', $this->kurzueberschrift2);
    }
    elseif(is_array($headline2)) {
      $this->kurzueberschrift2 = ' ';
      $first = true;
      foreach($headline2 as $k => $v) {
        if((String)$v !== '') {
          if(!$first) {
            $this->kurzueberschrift2 .= ' ';
          }
          $first = false;
          if(!is_numeric($k)) {
            $this->kurzueberschrift2 .=  $k.' ';
          }
          $this->kurzueberschrift2 .=  '<b>'.htmlspecialchars($v).'</b>';
        }
      }
      $this->app->Tpl->Add('KURZUEBERSCHRIFT2', $this->kurzueberschrift2);
    }
  }
  if(empty($headline) && !empty($this->kurzueberschrift)) {
    $headline = $this->kurzueberschrift;
  }
  if(empty($headline1) && !empty($this->kurzueberschrift1)) {
    $headline1 = $this->kurzueberschrift1;
  }

  $this->RunHook('HeadLines', 3, $headline, $headline1, $headline2);
}

  function generateHash($id = 0)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'generateHashFromApi'))
    {
      return $obj->generateHashFromApi($id);
    }
    return '';
  }

  function XMLGruppe($id, $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLGruppe'))
    {
      return $obj->XMLGruppe($id, $cdata);
    }
    return '';
  }

  function XMLAdresseKontakt($id, $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLAdresseKontakt'))
    {
      return $obj->XMLAdresseKontakt($id, $cdata);
    }
    return '';
  }

  function XMLAdresse($id, $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLAdresse'))
    {
      return $obj->XMLAdresse($id, $cdata);
    }
  }

  function XMLAuftrag($id, $doctype = 'auftrag', $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLAuftrag'))
    {
      return $obj->XMLAuftrag($id,$doctype, $cdata);
    }
    return '';
  }

  function XMLBenutzer($id, $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLBenutzer'))
    {
      return $obj->XMLBenutzer($id, $cdata);
    }
  }

  function XMLAdresseAccounts($filter=array(), $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLAdresseAccounts'))
    {
      return $obj->XMLAdresseAccounts($filter, $cdata);
    }
  }

  function XMLBerichte($id, $cdata = false){
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLBerichte'))
    {
      return $obj->XMLBerichte($id, $cdata);
    }
  }


  function XMLArtikelkontingente($filter=array(), $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLArtikelkontingente'))
    {
      return $obj->XMLArtikelkontingente($filter, $cdata);
    }
  }

  // @refactor PhysicalDimension Komponente
  function GetGewichtbezeichnung()
  {
    $gewichtbezeichnung = $this->Firmendaten('gewichtbezeichnung');
    if((String)$gewichtbezeichnung !== '')return $gewichtbezeichnung;
    return 'kg';
  }

  // @refactor PhysicalDimension Komponente
  function GewichtzuKgFaktor()
  {
    $faktor = (float)str_replace(',',',',$this->Firmendaten('gewichtzukgfaktor'));
    if($faktor > 0)return $faktor;
    return 1;
  }

  // @refactor DbHelper Komponente
  function FormatGewicht($spalte)
  {
    return 'concat('.$spalte.",' ".$this->GetGewichtbezeichnung()."')";
  }

  // @refactor DbHelper Komponente
  function FormatPreis($spalte, $stellen = null, $punkt = false)
  {
    if(is_null($stellen))return "if(trim(round( $spalte *100))+0 <> trim($spalte*100)+0, format($spalte,  length( trim($spalte)+0)-length(round($spalte))-1 ".($punkt?"":" ,'de_DE'")."),format($spalte,2".($punkt?"":" ,'de_DE'")."))";
    return "format($spalte,$stellen".($punkt?"":" ,'de_DE'").")";
  }

  /**
   * @deprecated
   *
   * @param $value
   *
   * @return mixed
   */
  function FromFormatZahlToDB($value)
  {
    $poskomma = strrpos($value, ',');
    $pospunkt = strrpos($value, '.');
    if($poskomma === false) {
      return $value;
    }
    if($pospunkt === false) {
      return str_replace(',','.', $value);
    }

    if($poskomma > $pospunkt) {
      return str_replace(['.', ','], ['', '.'], $value);
    }

    return str_replace(',','', $value);
  }

  // @refactor Formater Komponente
  function number_format_variable($value, $stellen = null)
  {
    if(is_null($stellen)) {
      $ret = rtrim(number_format($value,8,',','.'),'0');
      if(substr($ret,-1) === ',') {
        $ret .= '0';
      }

      return $ret;
    }

    return number_format($value, $stellen,',','.');
  }

  // @refactor DbHelper Komponente
  function BelegnummerSortierung($prefix = '')
  {
    $belegnummersortierungint = $this->Firmendaten('belegnummersortierungint');
    if($belegnummersortierungint) {
      if($prefix == '') {
        return 'cast(belegnr as UNSIGNED)';
      }
      return 'cast('.$prefix.'.belegnr as UNSIGNED)';
    }
    if($prefix == '') {
      return 'belegnr';
    }
    return $prefix.'.'.'belegnr';
  }

  // @refactor DbHelper Komponente
  function FormatMenge($spalte, $decimals = 0)
  {
    return ('FORMAT('.$spalte.','.$decimals.',\'de_DE\')');
  }

  function FormatMengeFuerFormular($spalte) {
    return "trim($spalte)+0";
  }

  function FormatUCfirst($spalte)
  {
    return ('CONCAT(UCASE(LEFT('.$spalte.', 1)),SUBSTRING('.$spalte.', 2))');
  }

  static function add_alias(string $text, $alias = false) {
    if (empty($alias)) {
        return($text);
    }
    else {
        return ($text." as `$alias`");
    }
  }

  // @refactor DbHelper Komponente
  function FormatDate(string $spalte, string $alias = null)
  {
    return $this->add_alias("DATE_FORMAT($spalte,'%d.%m.%Y')", $alias);
  }

  // @refactor DbHelper Komponente
  function FormatDateShort(string $spalte, string $alias = null)
  {
    return $this->add_alias("DATE_FORMAT($spalte,'%d.%m.%y')", $alias);
  }

  // @refactor DbHelper Komponente
  function FormatDateTimeShort(string $spalte, string $alias = null)
  {
    return $this->add_alias("DATE_FORMAT($spalte,'%d.%m.%y %H:%i')", $alias);
  }

  // @refactor DbHelper Komponente
  function FormatDateTime(string $spalte, string $alias = null)
  {
    return $this->add_alias("DATE_FORMAT($spalte,'%d.%m.%Y %H:%i:%s')", $alias);
  }

  public function XMLExportVorlage($id,$filter=array(), $cdata = false)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLExportVorlage'))
    {
      return $obj->XMLExportVorlage($id, $filter, $cdata);
    }
  }

  /**
   * Es werden Werte nur hinzugefuegt falls der Wert noch nicht existiert bzw. leer ist
   *
   * @refactor in ShopImporter Module
   *
   * @param int $shop Shopid
   * @param int $artikel Artikelid
   * @param array $arr Array zum Einfuegen / Updaten
   * @param bool $escape Werte werden fuer DB escaped
   *
   * @return bool wenn Daten OK true sonst falsch
   */
  public function AddShopArtikelIfEmpty($shop, $artikel, $arr, $escape = true)
  {
   if(empty($artikel) || empty($shop) || empty($arr)){
      return false;
    }
    $bearbeiter = $this->GetBearbeiter(true);
    $oldarr = array();
    $old = $this->app->DB->SelectArr("SELECT min(id) as id, name,wert  FROM shopexport_artikel 
      WHERE shopid = '$shop' AND artikel = '$artikel' GROUP BY name,wert");
    if(!empty($old))
    {
      foreach($old as $v)
      {
        $oldarr[$v['name']] = array('id'=>$v['id'],'wert'=>$v['wert']);
      }
    }

    foreach($arr as $k => $v)
    {
      if($k)
      {
        $check = !empty($oldarr[$k])?$oldarr[$k]['id']:0;
        if(!$check)
        {
          $this->app->DB->Insert("INSERT INTO shopexport_artikel (shopid, artikel, name) VALUES ('$shop','$artikel','".$this->app->DB->real_escape_string($k)."')");
          $new = $this->app->DB->GetInsertID();
          $check = $new;
        }else{
          $new = null;
        }
        if(!empty($new) || ($oldarr[$k]['wert'] != $v && empty($oldarr[$k]['wert']))){
          if($escape){
            $this->app->DB->Update("UPDATE shopexport_artikel SET bearbeiter = '$bearbeiter', wert = '" . $this->app->DB->real_escape_string($v) . "' WHERE id = '$check' LIMIT 1");
          }else{
            $this->app->DB->Update("UPDATE shopexport_artikel SET bearbeiter = '$bearbeiter', wert = '$v' WHERE id = '$check' LIMIT 1");
          }
        }
      }
    }
    return true;
  }

  /**
   * @deprecated
   * @refactor in User Klasse
   *
   * @param bool $escaped wenn true real_escaped zurueck
   *
   * @return string gibt Username oder Cronjob zurueck
   */
  public function GetBearbeiter($escaped = false)
  {
    $bearbeiter = 'Cronjob';
    if(!empty($this->app->User) && method_exists($this->app->User,'GetName'))
    {
      $bearbeiter = $this->app->User->GetName();
      if($escaped)
      {
        $bearbeiter = $this->app->DB->real_escape_string($bearbeiter);
      }
    }
    return $bearbeiter;
  }

  /**
   * @refactor in ShopImport Module
   *
   * @param int $shop Shopid
   * @param int $artikel Artikelid
   * @param array $arr Array das Geaendert / Eingefuegt werden soll
   * @param bool $escape Escapen fuer DB
   *
   * @return bool
   */
  public function SaveShopArtikel($shop, $artikel, $arr, $escape = true)
  {
    if(empty($artikel) || empty($shop) || empty($arr)){
      return false;
    }
    $bearbeiter = $this->GetBearbeiter(true);
    $oldarr = array();
    $old = $this->app->DB->SelectArr(
      sprintf(
        "SELECT MIN(id) as id, MAX(id) AS `maxid`, `name`, `wert`  
        FROM `shopexport_artikel` 
        WHERE `shopid` = %d AND `artikel` = %d 
        GROUP BY `name`, `wert`",
        $shop, $artikel
      )
    );
    if(!empty($old)) {
      foreach($old as $v) {
        $oldarr[
            $this->app->DB->real_escape_string($v['name'])
        ] = array('id'=>$v['id'],'wert'=>$v['wert'],'maxid' => $v['maxid']);
      }
    }

    foreach($arr as $k => $v) {
      if(empty($k)) {
        continue;
      }

        $nameForDb = $k;
        $valueForDb = $v;
        if($escape){
          $nameForDb = $this->app->DB->real_escape_string($k);
          $valueForDb = $this->app->DB->real_escape_string($v);
        }
        $check = !empty($oldarr[$k])?$oldarr[$k]['id']:0;
        $new = null;
        if(!$check) {
          $this->app->DB->Insert(
            sprintf(
              "INSERT INTO `shopexport_artikel` (shopid, artikel, `name`,wert) 
              VALUES (%d,%d,'%s','%s')",
              $shop, $artikel, $nameForDb, $valueForDb
            )
          );

          $new = $this->app->DB->GetInsertID();
        }

        if($check && (!empty($new) || $oldarr[$k]['wert'] != $v)) {
          $this->app->DB->Delete(
            sprintf(
              "DELETE FROM `shopexport_artikel` 
              WHERE `artikel` = %d AND `shopid` = %d AND `name` = '%s' AND `id` <> %d",
              $artikel, $shop, $nameForDb, $check
            )
          );

          $this->app->DB->Update(
              "UPDATE shopexport_artikel SET bearbeiter = '$bearbeiter', wert = '$valueForDb' WHERE id = '$check' LIMIT 1"
          );
        }
        elseif($check && $oldarr[$k]['id'] != $oldarr[$k]['maxid']) {
          $this->app->DB->Delete(
            sprintf(
              "DELETE FROM `shopexport_artikel` 
              WHERE `artikel` = %d AND `shopid` = %d AND `name` = '%s' AND `id` <> %d",
              $artikel, $shop, $nameForDb, $check
            )
          );
        }

    }

    return true;
  }

  // @refactor in Placetel Module
  function GetPhoneLink($adresse=0,$ansprechpartner=0,$telefon="")
  {
    $username = $this->app->User->GetUsername();
    $accounts = $this->app->erp->GetKonfiguration("placetel_list_accounts");

    $tmp = explode(PHP_EOL,trim($accounts));
    $sipuid = false;
    if($this->app->erp->RechteVorhanden('placetel','call'))
    {
      $this->app->Tpl->Set('JSPLACETEL','
          function call(id, dummy)
          {
            $.ajax({
                url: \'index.php?module=placetel&action=call&id=\'+id,
                type: \'POST\',
                dataType: \'json\',
                data: {},
                success: function(data) {
                  if(data)
                  {
                  
                  }
                }
            });

          }
      ');

      $ctmp = !empty($tmp)?count($tmp):0;
      for($i=0;$i<$ctmp;$i++)
      {
        $subtmp = explode(':',trim($tmp[$i]));

        if((!empty($subtmp)?count($subtmp):0)>0)
        {
          $subtmp[0] = trim($subtmp[0]);
          $subtmp[1] = !empty($subtmp[1])?trim($subtmp[1]):'';

          if($subtmp[0]==$username)
          {
            $sipuid = $subtmp[1];
            break;
          }
        }
      }
    }

    if($ansprechpartner <=0)
    {
      $typ = $this->app->DB->Select("SELECT if(telefon='$telefon' AND telefon!='','1',if(mobil='$telefon' AND mobil!='','2','')) FROM adresse WHERE id='$adresse' LIMIT 1");
      if($typ==1 OR $typ==2){
        $typid = $adresse;
      }
    } else {
      $typ = $this->app->DB->Select("SELECT if(telefon='$telefon' AND telefon!='','3',if(mobil='$telefon' AND mobil!='','4','')) FROM ansprechpartner WHERE id='$ansprechpartner' LIMIT 1");
      if($typ==3 OR $typ==4){
        $typid = $ansprechpartner;
      }
    }
    // 1 = telefon adresse, 2 = mobil adresse, 3 telefon ansprechpartner, 4 mobil ansprechpartner

    if($telefon!='') {
      $telefon = str_replace('/','',$telefon);
      $telefon = str_replace(' ','',$telefon);
      if($sipuid) {
        return "<a href=\"#\" onclick=call(\"".$typ."-".$typid."\") ><img border=\"0\" width=\"20\" src=\"./themes/".$this->app->Conf->WFconf['defaulttheme']."/images/phone.png\" class=\"iconininput\" alt=\"anrufen\" /></a>";
      }
      return "<a href=\"tel://$telefon\"><img border=\"0\" width=\"20\" src=\"./themes/".$this->app->Conf->WFconf['defaulttheme']."/images/phone.png\" class=\"iconininput\" alt=\"anrufen\" /></a>";
    }
  }

  public function GetArtikelunterbaumids($id, &$arr, $lvl = 0)
  {
    /** @var Artikelbaum $obj */
    $obj = $this->LoadModul('artikelbaum');
    if(!empty($obj) && method_exists($obj, 'getArticleSubtreeIds')) {
      $obj->getArticleSubtreeIds($id, $arr, $lvl);
    }
  }

  // @refactor in Shopimport Module
  public function GetShopArtikel($shop, $artikel, $name = '')
  {
    $ret = null;
    if((int)$artikel <= 0 || (int)$shop <= 0){
      return $ret;
    }
    $arr = $this->app->DB->SelectArr('SELECT `name`, `wert` FROM shopexport_artikel WHERE shopid = '.(int)$shop.' AND artikel = '.(int)$artikel." AND name <> ''".(!empty($name)?" AND name = '".$this->app->DB->real_escape_string($name)."' ":''));
    if(!empty($arr))
    {
      foreach($arr as $v){
        $ret[$v['name']] = $v['wert'];
      }
    }
    if(!empty($name))
    {
      return !empty($ret[$name])?$ret[$name]:'';
    }
    return $ret;
  }

  public function XMLArtikel($id, $api = 0)
  {
    /** @var Api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj,'XMLArtikel'))
    {
      return $obj->XMLArtikel($id, $api);
    }
  }

  // @refactor in Uservorlage Modul
  function AbgleichBenutzerVorlagen($userid=0, $vorlage = 0, $module = '', $action = '')
  {
    $bezeichnung = '';
    if($vorlage != 0)
    {
      $bezeichnung = $this->app->DB->Select("SELECT bezeichnung FROM uservorlage WHERE id = '$vorlage' LIMIT 1");
    }

    if($userid == 0 && $vorlag > 0 && $module != '' && $action != '')
    {
      $permission = $this->app->DB->Select("SELECT permission FROM uservorlagerights WHERE vorlage = '".$id_vorlage."'  AND module = '$module'  AND action = '$action' LIMIT 1");
    }


    // alle vorlagen ind ei Leute kopieren
    if($userid<=0){
      $user = $this->app->DB->SelectArr("SELECT * FROM user" . ($bezeichnung != '' ? " WHERE vorlage like '$bezeichnung' " : ''));
    }
    else{
      $user = $this->app->DB->SelectArr("SELECT * FROM user WHERE id='$userid'");
    }
    $startzeit = microtime(true);
    $cuser = !empty($user)?count($user):0;

    $grantingUserId = $this->app->User->GetID();
    $grantingUserName = $this->app->DB->Select("SELECT username FROM user WHERE id=$grantingUserId");
    $userPermission = $this->app->Container->get('UserPermissionService');

    for($i=0;$i<$cuser;$i++)
    {
      $user[$i]['vorlage'] = strtolower($user[$i]['vorlage']);
      if($vorlage)
      {
        $id_vorlage = $vorlage;
      }else{
        $id_vorlage = $this->app->DB->Select("SELECT id FROM uservorlage WHERE bezeichnung LIKE '".$user[$i]['vorlage']."' LIMIT 1");
      }
      if($id_vorlage == $vorlage || $vorlage == 0)
      {
        $receivingUserId = $user[$i]['id'];
        $receivingUserName = $this->app->DB->Select("SELECT username FROM user WHERE id=$receivingUserId");

        // neue eintraege
        if($userid == 0 && $vorlag > 0 && $module != '' && $action != '')
        {
          $this->app->DB->Delete("DELETE FROM userrights WHERE user = '".$user[$i]['id']."' AND module='$module' AND action = '$action'");
          try {
            $userPermission->log($grantingUserId,$grantingUserName,$receivingUserId,$receivingUserName,$module,$action,false);
          }catch (Exception $ex){
            $this->app->erp->LogFile('Fehler bei Zuweisung Rechtehistore',$ex->getMessage());
          }
          $this->app->DB->Insert("INSERT INTO userrights (user, module, action, permission) VALUES ('".$user[$i]['id']."','$module','$action','$permission')");
          try {
            $userPermission->log($grantingUserId,$grantingUserName,$receivingUserId,$receivingUserName,$module,$action,true);
          }catch (Exception $ex){
            $this->app->erp->LogFile('Fehler bei Zuweisung Rechtehistore',$ex->getMessage());
          }
        }else{
            $permissions = $this->app->DB->SelectArr("SELECT module, action,permission
            FROM uservorlagerights WHERE vorlage = '".$id_vorlage."' ".($module != ''?" AND module = '$module' ":"").($action != ''?" AND action = '$action'":''));
            foreach($permissions as $permission){
              try {
                $userPermission->log($grantingUserId,$grantingUserName,$receivingUserId,$receivingUserName,$permission['module'],$permission['action'],$permission['permission']);
              }catch (Exception $ex){
                $this->app->erp->LogFile('Fehler bei Zuweisung Rechtehistore',$ex->getMessage());
              }
            }
          $this->app->DB->Update("REPLACE INTO userrights (user, module,action,permission) (SELECT '".$user[$i]['id']."',module, action,permission
            FROM uservorlagerights WHERE vorlage = '".$id_vorlage."' ".($module != ''?" AND module = '$module' ":"").($action != ''?" AND action = '$action'":'').")   ");
          $neuesquery = $this->app->DB->Query("Select * from userrights where user = ".$user[$i]['id']." ".($module != ''?" AND module = '$module' ":"").($action != ''?" AND action = '$action'":'')." order by module, action, id desc");
          if($neuesquery)
          {
            $aktmodule = false;
            $aktaction = false;
            while($v = $this->app->DB->Fetch_Array($neuesquery))
            {
              if($aktaction != $v['action'] || $aktmodule != $v['module'])
              {
                $aktaction = $v['action'];
                $aktmodule = $v['module'];
              } else {
                $this->app->DB->Delete("DELETE FROM userrights where id = ".$v['id']);

              }
            }
            $this->app->DB->free($neuesquery);
          }
        }
      }
    }
  }

  // @refactor in Poll Komponente (oder Welcome Modul)
  // @refactor replace stringcleaner? also validate options_json
  function UserEvent($invisible = false)
  {
    /** @var \Xentral\Modules\SystemNotification\Service\NotificationInterface $notifyService */
    $notifyService= $this->app->Container->get('NotificationService');

    /** @var \Xentral\Modules\SystemNotification\Gateway\NotificationGateway $notifyGateway */
    $notifyGateway = $this->app->Container->get('NotificationGateway');
    $messages = $notifyGateway->findByUserId($this->app->User->GetID(), 0, 5);

    $result = array();
    if((!empty($messages)?count($messages):0) > 0) {

      $cleaner = new Stringcleaner($this->app);

      foreach ($messages as $message) {
        // xss prevention
        $message['title'] = $cleaner->CleanString($message['title'], 'nojs');
        $message['message'] = $cleaner->CleanString($message['message'], 'nojs');
        $message['options'] = [];
        $messageOptions = !empty($message['options_json']) ? json_decode($message['options_json'], true) : null;
        if (!empty($messageOptions['id'])) {
          $message['options']['id'] = strip_tags($messageOptions['id']);
        }
        if (!empty($messageOptions['buttons'])) {
          $message['options']['buttons'] = [];
          foreach ($messageOptions['buttons'] as $messageButton) {
            $messageButtonAttrs = [];
            foreach ($messageButton as $buttonAttrName => $buttonAttrValue) {
              if ($buttonAttrName === 'link') {
                $messageButtonAttrs[htmlspecialchars($buttonAttrName)] = $cleaner->CleanString($buttonAttrValue, 'nojs');
              } else{
                $messageButtonAttrs[htmlspecialchars($buttonAttrName)] = htmlspecialchars($buttonAttrValue);
              }
            }
            $message['options']['buttons'][] = $messageButtonAttrs;
          }
        }
        // END xss prevention

        $result[] = [
          'event' => 'notification',
          'type' => $message['type'],
          'title' => $message['title'],
          'message' => $message['message'],
          'options' => !empty($message['options']) ? $message['options'] : null,
          'priority' => (int)$message['priority'] === 1,
        ];
        // Delete processed messages
        $notifyService->delete($message['id']);
      }
    }

    if($this->app->erp->RechteVorhanden('chat','list')) {
      $userId = $this->app->User->GetID();
      $registrierDatum = $this->app->DB->Select("SELECT u.logdatei FROM `user` AS u WHERE u.id='".$userId."'");

      $ungelesenOeffentlich = (int)$this->app->DB->Select(
        "SELECT COUNT(c.id) 
          FROM chat AS c 
          LEFT JOIN chat_gelesen AS g ON c.id = g.message AND (g.user = '".$userId."' OR g.user = 0)
          WHERE c.user_to='0' AND c.zeitstempel > '".$registrierDatum."' 
          AND g.id IS NULL"
      );
      $ungelesenPrivat = (int)$this->app->DB->Select(
        "SELECT COUNT(c.id) 
          FROM chat AS c
          INNER JOIN `user` AS u ON c.user_from = u.id 
          LEFT JOIN chat_gelesen AS g ON c.id = g.message  
          WHERE u.activ = 1 AND c.user_to='".$userId."' 
          AND g.id IS NULL"
      );
      $anzchat = $ungelesenOeffentlich + $ungelesenPrivat;

      if($anzchat>0) {
        $result[] = array('event'=>'chatbox','sound'=>0, 'message'=>$anzchat);
      }
    }

    if((!empty($result)?count($result):0)>0){
      return $result;
    }
    return false;
  }

  /**
   * @deprecated
   *
   * @param bool $delete
   *
   * @return array|void
   */
  function UserEventNachrichten($delete = false)
  {
    $user = (int)$this->app->User->GetID();
    if(!$user)return;
    $adresse = (int)$this->app->DB->Select("SELECT adresse FROM user WHERE id = '".$user."' LIMIT 1");
    if($adresse)
    {
      $_gruppen = $this->app->DB->SelectArr("SELECT distinct parameter as gruppe FROM adresse_rolle WHERE adresse = '$adresse' AND subjekt = 'Mitglied' AND (bis = '0000-00-00' OR bis >= date(now())) AND parameter > 0");
      if($_gruppen)
      {
        foreach($_gruppen as $gruppe)
        {
          $gruppen[] = " b.gruppe = '".(int)$gruppe['gruppe']."' ";
        }
      }
    }
    if(!empty($gruppen))
    {
      $subwhere = implode(' OR ',$gruppen);
      $nachrichten = $this->app->DB->SelectArr("SELECT b.* FROM boxnachrichten b WHERE (b.user = '$user' OR ($subwhere)) AND (ablaufzeit = 0 OR
      TIME_TO_SEC(
       TIMEDIFF(
        now(),
        zeitstempel
       ) <= ablaufzeit
      )
      ) ORDER BY ablaufzeit > 0 DESC, prio DESC, zeitstempel");

    }else{
      $nachrichten = $this->app->DB->SelectArr("SELECT b.* FROM boxnachrichten b WHERE user = '$user' AND (ablaufzeit = 0 OR
      TIME_TO_SEC(
       TIMEDIFF(
        now(),
        zeitstempel
       ) <= ablaufzeit
      )
      ) ORDER BY ablaufzeit > 0 DESC, prio DESC, zeitstempel");
    }
    if($nachrichten)
    {
      if($delete)$this->app->DB->Delete("DELETE from boxnachrichten WHERE id = '".$nachrichten[0]['id']."' LIMIT 1");
      return array('anzahl'=>(!empty($nachrichten)?count($nachrichten):0),'nachricht'=>reset($nachrichten));
    }
    return array('anzahl'=>0);
  }

  /**
   * @deprecated
   *
   * @param $user
   * @param $gruppe
   * @param $bezeichnung
   * @param string $nachricht
   * @param int $prio
   * @param int $ablaufzeit
   * @param int $beep
   * @param string $objekt
   * @param int $parameter
   * @param bool $delete
   *
   * @return void
   */
  function AddUserGruppenNachricht($user, $gruppe, $bezeichnung, $nachricht = '', $prio = 0,$ablaufzeit = 0, $beep = 0, $objekt = '', $parameter = 0, $delete = false)
  {
    $parameter = (int)$parameter;
    $beep = (int)$beep;
    $objekt = $this->app->DB->real_escape_string($objekt);
    if($delete == true)
    {
      if(!empty($objekt) && !empty($parameter))$this->app->DB->Delete("DELETE FROM boxnachrichten WHERE objekt like '".$objekt."' AND parameter = '$parameter' ");
      return;
    }
    if($delete && is_numeric($delete))
    {
      $delete = (int)$delete;
      $this->app->DB->Delete("DELETE FROM boxnachrichten WHERE id = '$delete' LIMIT 1");
      return;
    }
    $user = (int)$user;
    $gruppe = (int)$gruppe;
    $prio = (int)$prio;
    $ablaufzeit = (int)$ablaufzeit;
    $bezeichnung = $this->app->DB->real_escape_string($bezeichnung);
    $nachricht = $this->app->DB->real_escape_string($nachricht);
    $this->app->DB->Insert("INSERT INTO boxnachrichten (user, gruppe, bezeichnung, nachricht, prio, ablaufzeit, objekt, parameter, beep) VALUES (
    '$user','$gruppe','$bezeichnung','$nachricht','$prio','$ablaufzeit','$objekt','$parameter','$beep'
    )");
    return $this->app->DB->GetInsertID();
  }

  // @refactor FileLock Komponente
  function ProzessLock($name)
  {
    $fp = @fopen($this->GetTMP()."lock_". $name . '.lock', 'w+');

    if($fp)
    {
      if (flock($fp, LOCK_EX)) {
        ftruncate($fp, 0);
        fwrite($fp, "Write something here\n");
        return $fp;
      }
      @fclose($fp);
    }
    return false;
  }

  // @refactor FileLock Komponente
  function ProzessUnlock($fp)
  {
    if(gettype($fp) != 'resource') return;
    fflush($fp); // leere Ausgabepuffer bevor die Sperre frei gegeben wird
    flock($fp, LOCK_UN); // Gib Sperre frei
    fclose($fp);
  }

  // @refactor Formater Komponente
  function ConvertToBytes($tmp)
  {
    $tmp = trim($tmp);
    $last = strtolower($tmp[strlen($tmp)-1]);
    switch($last)
    {
        case 'g':
        $tmp *= 1024;
        case 'm':
        $tmp *= 1024;
        case 'k':
        $tmp *= 1024;
    }
    return $tmp;
  }

  // @refactor SystemInformation Komponente
  function MaxUploadFileSize()
  {
    //select maximum upload size
    $max_upload = $this->ConvertToBytes(ini_get('upload_max_filesize'));
    $max_post = $this->ConvertToBytes(ini_get('post_max_size'));
    $memory_limit = $this->ConvertToBytes(ini_get('memory_limit'));
    return min($max_upload, $max_post, $memory_limit);
  }

  // @refactor Document Komponente
  public function GetSpracheBeleg($type, $id)
  {
    if(!empty($this->sprachen) && !empty($this->sprachen[$type]) && !empty($this->sprachen[$type][$id]))
    {
      return $this->sprachen[$type][$id];
    }
    $docArr = $this->app->DB->SelectRow(sprintf('SELECT sprache, adresse FROM `%s` WHERE id = %d', $type, $id));
    $sprache = !empty($docArr)?$docArr['sprache']:$this->app->DB->Select("SELECT sprache FROM $type WHERE id='$id' LIMIT 1");
    if($sprache=='') {
      $adresse = !empty($docArr)?$docArr['adresse']:$this->app->DB->Select("SELECT adresse FROM $type WHERE id='$id' LIMIT 1");
      $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    }
    if($sprache=='') {
      $sprache="de";
    }
    $this->sprachen[$type][$id] = $sprache;
    return $sprache;
  }

  public function GetSpracheBelegISO($type, $id)
  {
    $language = $this->GetSpracheBeleg($type, $id);
    if(strlen($language) > 2)
    {
      $language = $this->app->DB->Select("SELECT iso FROM sprachen WHERE alias='$language' ORDER by aktiv=1 LIMIT 1");
    }
    return $language;
  }



  // @refactor Document Komponente
  function BelegVersand($typ,$id,$versandart,$drucker="")
  {
    if($typ!="rechnung" && $typ!="angebot" && $typ!="auftrag" && $typ!="gutschrift" && $typ!="lieferschein" && $typ!="reisekosten")
      return;

    if($versandart!="email" && $versandart!="brief")
      return;

    $projekt = $this->app->DB->Select("SELECT projekt FROM $typ WHERE id='$id' LIMIT 1");
    $name = $this->app->DB->Select("SELECT name FROM $typ WHERE id='$id' LIMIT 1");
    $email = $this->app->DB->Select("SELECT email FROM $typ WHERE id='$id' LIMIT 1");
    $adresse = $this->app->DB->Select("SELECT adresse FROM $typ WHERE id='$id' LIMIT 1");

    // pruefe ob immer per per Papier oder immer per mail
    $rechnung_papier = $this->app->DB->Select("SELECT rechnung_papier FROM adresse WHERE id='$adresse' LIMIT 1");
    $rechnung_permail = $this->app->DB->Select("SELECT rechnung_permail FROM adresse WHERE id='$adresse' LIMIT 1");
    $rechnung_anzahlpapier = $this->app->DB->Select("SELECT rechnung_anzahlpapier FROM adresse WHERE id='$adresse' LIMIT 1");

    if($rechnung_papier=="1" && $typ=="rechnung") $versandart="brief";
    if($rechnung_permail=="1" && $typ=="rechnung") $versandart="email";


    $sprache = $this->app->DB->Select("SELECT sprache FROM $typ WHERE id='$id' LIMIT 1");
    if($sprache=="")
      $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

    if($sprache=='') {
      $sprache='deutsch';
    }

    $emailtext = $this->Geschaeftsbriefvorlage($sprache,$typ,$projekt,$name,$id);
    $idvorlage = $this->GetGeschaeftsBriefID($typ,$sprache,$projekt);

    $footer = $this->Grussformel($projekt,$sprache);
    if($footer!="") $emailtext['text'] = $emailtext['text']."\r\n".$footer;

    $this->BriefpapierHintergrundDisable($drucker);

    switch($typ)
    {
      case "rechnung":
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?true:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('RechnungPDFCustom'))
        {
          $Brief = new RechnungPDFCustom($this->app,$projekt);
        }else{
          $Brief = new RechnungPDF($this->app,$projekt);
        }
        $Brief->GetRechnung($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?false:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('RechnungPDFCustom'))
        {
          $Brief = new RechnungPDFCustom($this->app,$projekt);
        }else{
          $Brief = new RechnungPDF($this->app,$projekt);
        }
        $Brief->GetRechnung($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        break;
      case "angebot":
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?true:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AngebotPDFCustom'))
        {
          $Brief = new AngebotPDFCustom($this->app,$projekt);
        }else{
          $Brief = new AngebotPDF($this->app,$projekt);
        }
        $Brief->GetAngebot($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?false:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AngebotPDFCustom'))
        {
          $Brief = new AngebotPDFCustom($this->app,$projekt);
        }else{
          $Brief = new AngebotPDF($this->app,$projekt);
        }
        $Brief->GetAngebot($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        break;
      case "auftrag":
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?true:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AuftragPDFCustom'))
        {
          $Brief = new AuftragPDFCustom($this->app,$projekt);
        }else{
          $Brief = new AuftragPDF($this->app,$projekt);
        }
        $Brief->GetAuftrag($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?false:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AuftragPDFCustom'))
        {
          $Brief = new AuftragPDFCustom($this->app,$projekt);
        }else{
          $Brief = new AuftragPDF($this->app,$projekt);
        }
        $Brief->GetAuftrag($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        break;
      case "bestellung":
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?true:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('BestellungPDFCustom'))
        {
          $Brief = new BestellungPDFCustom($this->app,$projekt);
        }else{
          $Brief = new BestellungPDF($this->app,$projekt);
        }
        $Brief->GetBestellung($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?false:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('BestellungPDFCustom'))
        {
          $Brief = new BestellungPDFCustom($this->app,$projekt);
        }else{
          $Brief = new BestellungPDF($this->app,$projekt);
        }
        $Brief->GetBestellung($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        break;
      case "preisanfrage":
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?true:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('PreisanfragePDFCustom'))
        {
          $Brief = new PreisanfragePDFCustom($this->app,$projekt);
        }else{
          $Brief = new PreisanfragePDF($this->app,$projekt);
        }
        $Brief->GetPreisanfrage($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?false:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('PreisanfragePDFCustom'))
        {
          $Brief = new PreisanfragePDFCustom($this->app,$projekt);
        }else{
          $Brief = new PreisanfragePDF($this->app,$projekt);
        }
        $Brief->GetPreisanfrage($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        break;
      case "produktion":
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?true:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ProduktionPDFCustom'))
        {
          $Brief = new ProduktionPDFCustom($this->app,$projekt);
        }else{
          $Brief = new ProduktionPDF($this->app,$projekt);
        }
        $Brief->GetProduktion($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = $versandart === 'email'?false:!$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ProduktionPDFCustom'))
        {
          $Brief = new ProduktionPDFCustom($this->app,$projekt);
        }else{
          $Brief = new ProduktionPDF($this->app,$projekt);
        }
        $Brief->GetProduktion($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        break;

    }

    if($rechnung_anzahlpapier > 1 && $typ==='rechnung' && $versandart==='brief')
    {
      for($ra_i=0;$ra_i<$rechnung_anzahlpapier;$ra_i++)
      {
        $sendtmp[]=$tmpfile;
      }
    } else {
      $sendtmp = array($tmpfile);
    }

    //$this->LogFile("BelegeVersand T $typ I $id V $versandart Email $email Name $name betreff ".$emailtext['betreff']);

    if($drucker<0)
      $drucker = $this->app->DB->Select("SELECT standarddrucker FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
    else
      $drucker = $this->app->DB->Select("SELECT id FROM drucker WHERE id='".$drucker."' LIMIT 1");

    if($drucker <=0)
      $drucker = $this->Firmendaten('standardversanddrucker');

    if($versandart==='email') {
      if(!$this->isHTML($emailtext['text'])){
        $emailtext['text'] = nl2br($emailtext['text']);//str_replace("\r\n", "<br>", $emailtext['text']);
      }
      if(
        in_array(
          $typ,
          ['auftrag', 'rechnung','gutschrift','angebot','bestellung','retoure','proformarechnung','lieferschein']
        )
      ) {
        $dateien = [$tmpfile];

        if($typ === 'auftrag'){
          $stichwoerter = $this->app->DB->SelectArr("SELECT * FROM datei_stichwoerter WHERE objekt='geschaeftsbrief_vorlagen' AND parameter='$idvorlage' AND parameter > 0");
          if($stichwoerter){
            foreach ($stichwoerter as $v) {
              $dateiname = str_replace(' ', '_', $this->app->erp->GetDateiName($v['datei']));
              if($dateiname){
                $dateiinhalt = $this->app->erp->GetDatei($v['datei']);

                if($handle = fopen(rtrim($this->app->erp->GetTMP(), '/') . "/" . $dateiname, "wb")){
                  fwrite($handle, $dateiinhalt);
                  fclose($handle);
                  $dateien[] = rtrim($this->app->erp->GetTMP(), '/') . "/" . $dateiname;
                  $dateienIds[] = $v['datei'];
                }
              }
            }
          }
        }

        $stichwoerterAnhaenge = $this->app->DB->SelectArr("SELECT * FROM datei_stichwoerter WHERE subjekt = 'Anhang' AND objekt = '$typ' AND parameter = '$id' AND parameter > 0");
        if($stichwoerterAnhaenge)
        {
          foreach($stichwoerterAnhaenge as $v)
          {
            $dateiname = str_replace(' ','_',$this->app->erp->GetDateiName($v['datei']));

            if($dateiname && !in_array($v['datei'], $dateienIds))
            {
              $dateiinhalt = $this->app->erp->GetDatei($v['datei']);

              if($handle = fopen (rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname, "wb"))
              {
                fwrite($handle, $dateiinhalt);
                fclose($handle);
                $dateien[] = rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname;
              }
            }
          }
        }
        
        $this->DokumentSend($adresse,$typ, $id, $versandart,$emailtext['betreff'],$emailtext['text'],$dateien,"","",$projekt,$email, $name);
        if($dateien && (!empty($dateien)?count($dateien):0) > 1)
        {
          for($i = 1; $i < (!empty($dateien)?count($dateien):0); $i++)
          {
            if(@is_file($dateien[$i])){
              @unlink($dateien[$i]);
            }
          }
        }
      }else{
        $this->DokumentSend($adresse,$typ, $id, $versandart,$emailtext['betreff'],$emailtext['text'],array($tmpfile),"","",$projekt,$email, $name);
      }
    }
    else{
      $this->DokumentSend($adresse, $typ, $id, $versandart, $emailtext['betreff'], $emailtext['text'], $sendtmp, $drucker, "", $projekt, $email, $name);
    }


    if($this->Firmendaten("belegeinanhang")=="1") {
      $fileid = $this->CreateDateiWithStichwort($tmpfile, $module,'','',$tmpfile, $this->app->User->GetName() ,$typ,$typ, $id, "",false);
    }
    /*
    $fileid = $this->CreateDatei($tmpfile,$module,"","",$tmpfile,$this->app->User->GetName());
    $this->AddDateiStichwort($fileid,$typ,$typ,$id,false);
    */

    $ansprechpartner = $name." <".$email.">";

    $this->app->DB->Insert("INSERT INTO dokumente_send
        (id,dokument,zeit,bearbeiter,adresse,parameter,art,betreff,text,projekt,ansprechpartner,versendet,dateiid)
        VALUES ('','$typ',NOW(),'".$this->app->User->GetName()."',
          '$adresse','$id','$versandart','".$emailtext['betreff']."','".$emailtext['text']."','$projekt','$ansprechpartner',1,'$fileid')");

    unlink($tmpfile);

    if($typ==='rechnung' || $typ==='angebot' || $typ==='gutschrift')
    {
      if($typ === 'rechnung')
      {
        $this->closeInvoice($id,'freigegeben');
      }
      $this->app->DB->Update("UPDATE $typ SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
    }

    $this->app->DB->Update("UPDATE $typ SET versendet=1, versendet_am=NOW(),
        versendet_per='$versandart',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");



    $this->BriefpapierHintergrundEnable();


    switch($typ)
    {
      case "angebot": $this->AngebotProtokoll($id,"Angebot versendet"); break;
      case "auftrag": $this->AuftragProtokoll($id,"Auftrag versendet"); break;
      case "rechnung": $this->RechnungProtokoll($id,"Rechnung versendet"); break;
      case "lieferschein": $this->LieferscheinProtokoll($id,"Lieferschein versendet"); break;
      case "gutschrift": $this->GutschriftProtokoll($id,"Gutschrift versendet"); break;
      case "reisekosten": $this->ReisekostenProtokoll($id,"Reisekosten versendet"); break;
      case "proformarechnung": $this->ProformarechnungProtokoll($id,"Proformarechnung versendet"); break;
    }
  }

  // @refactor DocumentPdf Komponente
  public function PDFArchivieren($type,$id, $force = false)
  {
    $id = (int)$id;
    if($id <= 0){
      return false;
    }
    $types = array("auftrag","angebot","rechnung","lieferschein","gutschrift","bestellung","reisekosten","anfrage","preisanfrage","proformarechnung","arbeitsnachweis");
    if(!in_array($type, $types)){
      return false;
    }
    $class = ucfirst($type).'PDFCustom';
    if(!class_exists($class)){
      $class = ucfirst($type).'PDF';
    }
    if(class_exists($class)) {
      $projekt = $this->app->DB->Select("SELECT projekt FROM $type WHERE id = '$id' LIMIT 1");
      $Brief = new $class($this->app,$projekt);
      $get = 'Get'.ucfirst($type);
      if(method_exists($Brief, $get)) {
        $tmpfile = '';
        try {
          $Brief->$get($id);
          $tmpfile = $Brief->displayTMP();
          $Brief->ArchiviereDocument($force, $force);
          unlink($tmpfile);
          $tmpfile = '';
        }
        catch(Exception $e) {
          if($tmpfile !== '' && is_file($tmpfile)) {
            unlink($tmpfile);
            $tmpfile = '';
          }
          $this->LogFile($this->app->DB->real_escape_string($e->getMessage()));
          return false;
        }
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        try {
          $Brief = new $class($this->app, $projekt);
          $Brief->$get($id);
          $tmpfile = $Brief->displayTMP();
          $Brief->ArchiviereDocument($force, $force);
          unlink($tmpfile);
          $tmpfile = '';
        }
        catch(Exception $e) {
          if($tmpfile !== '' && is_file($tmpfile)) {
            unlink($tmpfile);
          }
          $this->LogFile($this->app->DB->real_escape_string($e->getMessage()));
          $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
          return false;
        }
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if($force) {
          $this->app->DB->Update("UPDATE `{$type}` SET `zuarchivieren` = 0 WHERE `id` = {$id}");
        }
        return true;
      }
    }
    return false;
  }

    // Rechnung special treatment because of XML
    function RechnungArchivieren($id) {
        $sql = "SELECT xmlrechnung FROM rechnung WHERE id = '".$id."' LIMIT 1";
        $xmlrechnung = $this->app->DB->Select($sql);
        if ($xmlrechnung) {
            $rechnungsmodul = $this->app->loadModule('rechnung', false);
            return($rechnungsmodul->RechnungArchiviereXML($id));
        } else {
            $this->PDFArchivieren('rechnung',$id,true);
        }
    }

  // @refactor in Location Klasse
  function UrlOrigin($s, $use_forwarded_host=false)
  {
    $ssl = (!empty($s['HTTPS']) && $s['HTTPS'] == 'on') ? true:false;
    $sp = strtolower($s['SERVER_PROTOCOL']);
    $protocol = substr($sp, 0, strpos($sp, '/')) . (($ssl) ? 's' : '');
    $port = $s['SERVER_PORT'];
    $port = ((!$ssl && $port=='80') || ($ssl && $port=='443')) ? '' : ':'.$port;
    $host = ($use_forwarded_host && isset($s['HTTP_X_FORWARDED_HOST'])) ? $s['HTTP_X_FORWARDED_HOST'] : (isset($s['HTTP_HOST']) ? $s['HTTP_HOST'] : null);
    $host = isset($host) ? $host : $s['SERVER_NAME'] . $port;

    $path = str_replace('/index.php','',$s['SCRIPT_NAME']);

    return $protocol . '://' . $host.$path;
  }

  // @refactor Formater Komponente
  function ZeitInStundenMinuten($number, $format = "%h:%i") {

     $number = str_replace(",",'.',$number);
     $h = floor($number);
     $i = round(($number - $h) * 60);

     $h = str_pad($h, 2, "0", STR_PAD_LEFT);
     $i = str_pad($i, 2, "0", STR_PAD_LEFT);
     $format = preg_replace("/%h/", $h, $format);
     $format = preg_replace("/%i/", $i, $format);
     return $format;
  }

  // @refactor Formater Komponente

  /**
   * @param string $text
   *
   * @return string
   */
  public function UmlauteEntfernen($text)
  {
    $text = $this->ReadyForPDF($text);
    $text = str_replace ("ä", "ae", $text);
    $text = str_replace ("Ä", "Ae", $text);
    $text = str_replace ("ö", "oe", $text);
    $text = str_replace ("Ö", "Oe", $text);
    $text = str_replace ("ü", "ue", $text);
    $text = str_replace ("Ü", "Ue", $text);
    $text = str_replace ("ß", "ss", $text);
    $text = str_replace(
      array('&uuml;','&Uuml;','&auml;','&Auml;','&ouml;','&Ouml;','&szlig;'),
      array('ue','Ue','ae','Ae','oe','Oe','ss'),
      $text
    );
    $text = str_replace ("&", "u", $text);
    $text = str_replace ("`", "", $text);
    $text = str_replace ("'", "", $text);

    return $text;
  }

  // @refactor DbHelper Komponente
  function Stroke($fieldstroke, $field) {
    return "if(" . $fieldstroke . ",CONCAT('<s>'," . $field . ",'</s>')," . $field . ")";
  }

    // @refactor DbHelper Komponente
    // creates a CONCAT sql statement with strings or sql expressions
    // Use like this: ConcatSQL('<a href=index.php?id=',['sql'] => 'id','>','click here</a>');
    function ConcatSQL(array $fields) {
        $result = "CONCAT(";
        $comma = "";    
        foreach ($fields as $field) {
            if (gettype($field) == 'array') {
                $result .= $comma.$field['sql'];
            } else {
                $result .= $comma."'".$field."'";
            }
            $comma = ",";
        }
        $result .= ")";
        return($result);
    }

  // @refactor Formater Komponente
  function Dateinamen($text) {
    $text = $this->UmlauteEntfernen($text);
    $text = str_replace(' ', '_', $text);
    $text = preg_replace('#[^-_.A-Za-z0-9]#', '', $text);
    return $text;
  }

  // @refactor in Dateien Modul
  function AnzahlDateien($objekt,$id)
  {
    return $this->app->DB->Select("SELECT COUNT(ds.id) FROM datei_stichwoerter ds INNER JOIN datei d ON d.id = ds.datei WHERE ds.objekt='$objekt' AND ds.parameter='$id' AND d.geloescht <> 1");
  }


  // @refactor in Service Modul
  function AnzahlOffeneSupport()
  {
    return 0;
  }


  // @refactor in Aufgaben Modul
  function AnzahlOffeneAufgaben()
  {
    return (int)$this->app->DB->Select("SELECT COUNT(a.id) FROM aufgabe a WHERE  (a.adresse='" . $this->app->User->GetAdresse() . "') AND a.startdatum='0000-00-00' AND a.status!='abgeschlossen' AND ( abgabe_bis='0000-00-00' OR abgabe_bis<=NOW())");
  }


  public function AnzahlOffeneTickets($eigene=true)
  {

    if ($eigene) {
        $sql = "SELECT COUNT(t.id) FROM ticket t WHERE t.status = 'neu' AND (t.warteschlange IN (SELECT w.label FROM warteschlangen w WHERE w.adresse = '".$this->app->User->GetAdresse()."'))";
    } else
    {
       $sql = "SELECT COUNT(t.id) FROM ticket t WHERE t.status = 'neu' AND (t.warteschlange = '')";
    }
    
    return (int)$this->app->DB->Select($sql);
  }


  // @refactor UiHelper Komponente
  function UserDevice()
  {
    return 'desktop';
  }

  // @refactor in Acl oder Login Modul
  function Startseite($weiterleitung = "")
  {
    if($this->app->User->GetID()!="")
    {
      if($this->UserDevice()=="desktop")
      {
        $startseite = (string)$weiterleitung !== ''?'':$this->app->DB->Select("SELECT startseite FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        $startseite = $this->ReadyForPDF($startseite);
        if(strpos($startseite,'action=logout') !== false && strpos($startseite,'module=welcome') !== false) {
          $startseite= '';
        }
        // wenn die GPS Stechuhr da ist
        if((string)$weiterleitung !== '')
        {
          header("Location: $weiterleitung");
        }
        elseif($startseite!=''){
          $this->app->Location->execute((String)$startseite);
        }
        else{
          header("Location: index.php?module=welcome&action=start");
        }
        exit;
      } else
      {
        header("Location: index.php?module=welcome&action=start");
        exit;
      }
    }
    header("Location: index.php?module=welcome&action=login");
    exit;
  }

  // @refactor in Kalender Modul @prüfen
  function getFirstDayOfWeek($year, $weeknr)
  {
    $offset = date('w', mktime(0,0,0,1,1,$year));
    $offset = ($offset < 5) ? 1-$offset : 8-$offset;
    $monday = mktime(0,0,0,1,1+$offset,$year);

    return date('Y-m-d',strtotime('+' . ($weeknr - 1) . ' weeks', $monday));
  }

  // @refactor in SystemInformation Modul
  function IsWindows()
  {
    return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
  }

  /**
   * Returns the absolute path to installation directory; without trailing slash
   *
   * @return string
   */
  public function GetRootPath()
  {
    return dirname(dirname(__DIR__));
  }

  // @refactor in SystemInformation Modul
  function GetTMP()
  {
    $userdata = $this->app->Conf->WFuserdata;
    $dbname = $this->app->Conf->WFdbname;

    if ($this->IsWindows()) {
      $tmp = $userdata."\\tmp\\".$dbname."\\";
    } else {
      $tmp = $userdata."/tmp/".$dbname."/";
    }

    $tmp = str_replace('//','/',$tmp);

    if(!is_dir($tmp)){
      mkdir($tmp, 0777, true);
    }

    return $tmp;
  }

  // @refactor in SystemInformation Modul
  function GetUSERDATA()
  {
    return $this->app->Conf->WFuserdata;
  }



  /** @deprecated */
  function RetoureSeriennummernberechnen($id)
  {

  }

    function LieferscheinSeriennummernberechnen($id)
    {
      /** @var Seriennummern $obj */
      $obj = $this->LoadModul('seriennummern');
      if(!empty($obj) && method_exists($obj, 'LieferscheinSeriennummernberechnen')) {
        $obj->LieferscheinSeriennummernberechnen($id);
      }
    }

    function SeriennummernCheckBenachrichtigung(int $artikel_id) {
        $obj = $this->LoadModul('seriennummern');
        return($obj->seriennummern_check_and_notification_stock_added($artikel_id));
    }  
    
    function SeriennummernCheckLieferscheinBenachrichtigung(int $lieferschein_id) {
        $obj = $this->LoadModul('seriennummern');
        return($obj->seriennummern_check_and_notification_delivery_note($lieferschein_id));
    }

    function SeriennummernCheckLieferscheinWarnung(int $lieferschein_id) {
        $obj = $this->LoadModul('seriennummern');
        return($obj->seriennummern_check_and_message_delivery_notes($lieferschein_id));
    }

    function SeriennummernCheckLieferschein($lieferschein_id = null, $ignore_date = false, $only_missing = true, $group_lieferschein = false) {
        $obj = $this->LoadModul('seriennummern');       
        return ($obj->seriennummern_check_delivery_notes($lieferschein_id, $ignore_date, $only_missing, $group_lieferschein));
    }
    
    function SeriennummernCheckWareneingangWarnung(int $wareneingang_id) {
        $obj = $this->LoadModul('seriennummern');
        return($obj->seriennummern_check_and_message_incoming_goods($wareneingang_id));
    }

    function SeriennummernCheckWareneingang($wareneingang_id = null, $ignore_date = false, $only_missing = true, $group_wareneingang = false) {
        $obj = $this->LoadModul('seriennummern');       
        return ($obj->seriennummern_check_incoming_goods($wareneingang_id, $ignore_date, $only_missing, $group_wareneingang));
    }


// @refactor in Lager Modul
function ArtikelAnzahlLagerPlatzMitSperre($artikel,$lager_platz)
{
  $result =  $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi
      LEFT JOIN lager_platz lp ON lp.id=lpi.lager_platz
      WHERE lpi.artikel='$artikel' AND lpi.lager_platz='$lager_platz'");
  if($result <=0) $result=0;
  return $result;
}


// @refactor LagerBeleg Modul
function LieferscheinEinlagern($id,$grund="Lieferschein Einlagern", $lpiids = null)
{
  if(!$id)return;
  $belegnr = $this->app->DB->Select("SELECT belegnr FROM lieferschein WHERE id = '$id' LIMIT 1");
  $bearbeiter = '';
  if(isset($this->app->User) && $this->app->User && method_exists($this->app->User,'GetName'))$bearbeiter = $this->app->User->GetName();
  $objekt_lager_platz = $this->app->DB->SelectArr("SELECT olp.id, olp.menge, olp.lager_platz, olp.artikel, olp.parameter, lp.id as lpid FROM 
  lieferschein_position lp INNER JOIN  objekt_lager_platz olp ON lp.id = olp.parameter AND olp.objekt = 'lieferschein' AND lp.lieferschein = '$id'");
  if($objekt_lager_platz)
  {
    $projekt = $this->app->DB->Select("SELECT projekt FROM lieferschein WHERE id = '$id' LIMIT 1");
    foreach($objekt_lager_platz as $olp)
    {
      $lpiid = null;
      if(isset($lpiids[$olp['lpid']]))$lpiid = $lpiids[$olp['lpid']];

      $this->app->erp->LagerEinlagern($olp['artikel'],$olp['menge'],$olp['lager_platz'],$projekt,
            "Stornierung Lieferschein $belegnr",$bearbeiter,"",'lieferschein', $id, $lpiid);
      $beleg_chargesnmhd = $this->app->DB->SelectArr("SELECT * FROM `beleg_chargesnmhd` WEHRE doctype = 'lieferschein' AND doctypeid = '$id' AND pos = '".$olp['parameter']."'");
      $seriennummern = $this->app->DB->SelectArr("SELECT * FROM seriennummern WHERE lieferschein = '$id' AND lieferscheinpos = '".$olp['parameter']."'");
      if($seriennummern)
      {
        foreach($seriennummern as $sn)
        {
          $belegesnarr['sn'][] = array('menge'=>1, 'value'=>$sn['seriennummer'],'table'=>'seriennummern','id'=>$sn['id']);
        }
      }
      if($beleg_chargesnmhd)
      {
        $belegesnarr = null;
        foreach($beleg_chargesnmhd as $bc)
        {
          $belegesnarr[$bc['typ']][] = array('menge'=>$bc['menge'], 'value'=>$bc['wert'],'table'=>'beleg_chargesnmhd','id'=>$bc['id']);
        }
      }
      if(isset($belegesnarr['sn']))
      {
        foreach($belegesnarr['sn'] as $v)
        {
          if(isset($belegesnarr['charge']) && isset($belegesnarr['mhd']))
          {
            $charge = '';
            $mhd = '';
            foreach($belegesnarr['charge'] as $k2 => $v2)
            {
              if($v2['menge'] > 1)
              {
                $charge = $v2['value'];
                $belegesnarr['charge'][$k2]['menge'] -= 1;
                break;
              }elseif($v2['menge'] == 1)
              {
                $charge = $v2['value'];
                unset($belegesnarr['charge'][$k2]);
                break;
              }
            }
            foreach($belegesnarr['mhd'] as $k2 => $v2)
            {
              if($v2['menge'] > 1)
              {
                $mhd = $v2['value'];
                $belegesnarr['mhd'][$k2]['menge'] -= 1;
                break;
              }elseif($v2['menge'] == 1)
              {
                $mhd = $v2['value'];
                unset($belegesnarr['mhd'][$k2]);
                break;
              }
            }
            if(isset($v['table']) &&  $v['table'] == 'seriennummern' && !empty($v['id']))
            {
// Xentral Legacy              $this->app->DB->Delete("DELETE FROM seriennummern WHERE id = '".$v['id']."' LIMIT 1");
            }elseif(isset($v['table']) && $v['table'] == 'beleg_chargesnmhd' && !empty($v['id'])){
              $this->app->DB->Delete("DELETE FROM beleg_chargesnmhd WHERE id = '".$v['id']."' LIMIT 1");
            }
            if(method_exists($this->app->erp,'AddSeriennummerLager'))$this->app->erp->AddSeriennummerLager($olp['artikel'], $olp['lager_platz'], $v['value'],"Stornierung Lieferschein $belegnr",  "", $mhd, $charge,'lieferschein', $id);
            if(method_exists($this->app->erp,'AddMindesthaltbarkeitsdatumLagerOhneBewegung'))$this->app->erp->AddMindesthaltbarkeitsdatumLagerOhneBewegung($olp['artikel'], 1,$olp['lager_platz'], $mhd, $charge);
            if(method_exists($this->app->erp,'AddChargeLagerOhneBewegung'))$this->app->erp->AddChargeLagerOhneBewegung($olp['artikel'],1, $olp['lager_platz'],$mhd,$charge,$grund);
          }elseif(isset($belegesnarr['charge']))
          {
            $charge = '';
            $mhd = '';
            foreach($belegesnarr['charge'] as $k2 => $v2)
            {
              if($v2['menge'] > 1)
              {
                $charge = $v2['value'];
                $belegesnarr['charge'][$k2]['menge'] -= 1;
                break;
              }elseif($v2['menge'] == 1)
              {
                $charge = $v2['value'];
                unset($belegesnarr['charge'][$k2]);
                break;
              }
            }
            if(isset($v['table']) &&  $v['table'] == 'seriennummern' && !empty($v['id']))
            {
// Xentral Legacy              $this->app->DB->Delete("DELETE FROM seriennummern WHERE id = '".$v['id']."' LIMIT 1");
            }elseif(isset($v['table']) && $v['table'] == 'beleg_chargesnmhd' && !empty($v['id'])){
              $this->app->DB->Delete("DELETE FROM beleg_chargesnmhd WHERE id = '".$v['id']."' LIMIT 1");
            }
            if(method_exists($this->app->erp,'AddSeriennummerLager'))$this->app->erp->AddSeriennummerLager($olp['artikel'],1, $olp['lager_platz'], $v['value'],$grund,  "", $mhd, $charge,'lieferschein', $id);
            if(method_exists($this->app->erp,'AddChargeLagerOhneBewegung'))$this->app->erp->AddChargeLagerOhneBewegung($olp['artikel'], 1,$olp['lager_platz'],$mhd,$charge,"", 'lieferschein', $id,$grund);
          }elseif(isset($belegesnarr['mhd']))
          {
            $charge = '';
            $mhd = '';
            foreach($belegesnarr['mhd'] as $k2 => $v2)
            {
              if($v2['menge'] > 1)
              {
                $mhd = $v2['value'];
                $belegesnarr['mhd'][$k2]['menge'] -= 1;
                break;
              }elseif($v2['menge'] == 1)
              {
                $mhd = $v2['value'];
                unset($belegesnarr['mhd'][$k2]);
                break;
              }
            }
            if(isset($v['table']) &&  $v['table'] == 'seriennummern' && !empty($v['id']))
            {
// Xentral Legacy              $this->app->DB->Delete("DELETE FROM seriennummern WHERE id = '".$v['id']."' LIMIT 1");
            }elseif(isset($v['table']) && $v['table'] == 'beleg_chargesnmhd' && !empty($v['id'])){
              $this->app->DB->Delete("DELETE FROM beleg_chargesnmhd WHERE id = '".$v['id']."' LIMIT 1");
            }
            if(method_exists($this->app->erp,'AddSeriennummerLager'))$this->app->erp->AddSeriennummerLager($olp['artikel'], $olp['lager_platz'], $v['value'],$grund,  "", $mhd, $charge);
            if(method_exists($this->app->erp,'AddMindesthaltbarkeitsdatumLagerOhneBewegung'))$this->app->erp->AddMindesthaltbarkeitsdatumLagerOhneBewegung($olp['artikel'],1, $olp['lager_platz'], $mhd, $charge, "", "lieferschein", $id, $grund);
          }else{
            if(isset($v['table']) &&  $v['table'] == 'seriennummern' && !empty($v['id']))
            {
// Xentral Legacy              $this->app->DB->Delete("DELETE FROM seriennummern WHERE id = '".$v['id']."' LIMIT 1");
            }elseif(isset($v['table']) && $v['table'] == 'beleg_chargesnmhd' && !empty($v['id'])){
              $this->app->DB->Delete("DELETE FROM beleg_chargesnmhd WHERE id = '".$v['id']."' LIMIT 1");
            }
            if(method_exists($this->app->erp,'AddSeriennummerLager'))$this->app->erp->AddSeriennummerLager($olp['artikel'], $olp['lager_platz'], $v['value'],$grund,  "", $mhd, $charge);
          }
        }
      }else{
        if(isset($belegesnarr['charge']) && isset($belegesnarr['mhd']))
        {
          foreach($belegesnarr['charge'] as $v2)
          {
            $nochmenge = $v2['value'];
            foreach($belegesnarr['mhd'] as $k3 => $v3)
            {
              if($nochmenge <= 0)break;
              if($nochmenge == $v3['menge'])
              {
                $mhd = $v3['value'];
                $charge = $v2['value'];
                if(method_exists($this->app->erp,'AddMindesthaltbarkeitsdatumLagerOhneBewegung'))$this->app->erp->AddMindesthaltbarkeitsdatumLagerOhneBewegung($olp['artikel'], $nochmenge,$olp['lager_platz'], $mhd, $charge, "", "lieferschein", $id, $grund);
                if(method_exists($this->app->erp,'AddChargeLagerOhneBewegung'))$this->app->erp->AddChargeLagerOhneBewegung($olp['artikel'],$nochmenge, $olp['lager_platz'],$mhd,$charge,"", 'lieferschein', $id,$grund);
                unset($belegesnarr['mhd'][$k3]);
                break;
              }elseif($nochmenge > $v3['menge'])
              {
                $mhd = $v3['value'];
                $charge = $v2['value'];
                if(method_exists($this->app->erp,'AddMindesthaltbarkeitsdatumLagerOhneBewegung'))$this->app->erp->AddMindesthaltbarkeitsdatumLagerOhneBewegung($olp['artikel'], $v3['menge'],$olp['lager_platz'], $mhd, $charge, "", "lieferschein", $id, $grund);
                if(method_exists($this->app->erp,'AddChargeLagerOhneBewegung'))$this->app->erp->AddChargeLagerOhneBewegung($olp['artikel'],$v3['menge'], $olp['lager_platz'],$mhd,$charge,"", 'lieferschein', $id,$grund);
                unset($belegesnarr['mhd'][$k3]);
                $nochmenge -= $v3['menge'];
              }elseif($nochmenge < $v3['menge'])
              {
                $mhd = $v3['value'];
                $charge = $v2['value'];
                if(method_exists($this->app->erp,'AddMindesthaltbarkeitsdatumLagerOhneBewegung'))$this->app->erp->AddMindesthaltbarkeitsdatumLagerOhneBewegung($olp['artikel'], $nochmenge,$olp['lager_platz'], $mhd, $charge, "", "lieferschein", $id, $grund);
                if(method_exists($this->app->erp,'AddChargeLagerOhneBewegung'))$this->app->erp->AddChargeLagerOhneBewegung($olp['artikel'],$nochmenge, $olp['lager_platz'],$mhd,$charge,"", 'lieferschein', $id,$grund);
                $belegesnarr['mhd'][$k3]['menge'] -= $nochmenge;
                break;
              }
            }
          }
        }elseif($belegesnarr['charge'])
        {
          foreach($belegesnarr['charge'] as $v2)
          {
            if(method_exists($this->app->erp,'AddChargeLagerOhneBewegung'))$this->app->erp->AddChargeLagerOhneBewegung($olp['artikel'],$v2['menge'], $olp['lager_platz'],'',$v2['value'],"", 'lieferschein', $id,$grund);
          }
        }elseif($belegesnarr['mhd'])
        {
          if(method_exists($this->app->erp,'AddMindesthaltbarkeitsdatumLagerOhneBewegung'))$this->app->erp->AddMindesthaltbarkeitsdatumLagerOhneBewegung($olp['artikel'],$v2['menge'], $olp['lager_platz'], $v2['value'], "", "lieferschein", $id, $grund);
        }
      }
      $this->app->DB->Delete("DELETE FROM objekt_lager_platz WHERE id = '".$olp['id']."' LIMIT 1");
    }
  }
}

  // @refactor LagerBeleg Modul
  // Returns Array:
  // storageMovements => array('lager_platz', 'artikel', 'menge');
  function LieferscheinAuslagern($lieferschein,$anzeige_lagerplaetze_in_lieferschein=false, $standardlager = 0, $belegtyp = 'lieferschein', $chargenmhdnachprojekt = 0, $forceseriennummerngeliefertsetzen = false,$nurrestmenge = false, $lager_platz_vpe = 0, $lpiid = 0, $simulieren = false)
  {
    if($lieferschein <= 0) {
      return;
    }
    if(!$anzeige_lagerplaetze_in_lieferschein) {
      $anzeige_lagerplaetze_in_lieferschein = true;
    }
    $artikelarr = $this->app->DB->SelectArr(
      sprintf(
        "SELECT * FROM `%s` WHERE `%s` = %d ORDER BY sort",
        $belegtyp.'_position', $belegtyp, (int)$lieferschein
      )
    );

    $belegarr = $this->app->DB->SelectRow(
      sprintf(
        'SELECT * FROM `%s` WHERE id=%d LIMIT 1',
        $belegtyp, (int)$lieferschein
      )
    );
    $kommissionskonsignationslager = 0;
    if($belegtyp === 'lieferschein'){
      $kommissionskonsignationslager = $belegarr['kommissionskonsignationslager'];
    }
    $chargenerfassen = 0;
    $mhderfassen = 0;
    $seriennummernerfassen = 0;
    $kommissionierverfahren = '';
    $projekt = 0;
    $belegnr = '';
    if(!empty($belegarr)) {
      $projekt = (int)$belegarr['projekt'];
      $projektarr = $this->app->DB->SelectRow(
        sprintf(
          'SELECT * FROM projekt WHERE id = %d LIMIT 1',
          $projekt
        )
      );
      if(!empty($projektarr)) {
        $chargenerfassen = $projektarr['chargenerfassen'];
        $mhderfassen = $projektarr['mhderfassen'];
        $seriennummernerfassen = $projektarr['seriennummernerfassen'];
        if(!empty($projektarr['multiorderpicking']) && $this->ModulVorhanden('multiorderpicking')) {
          $chargenerfassen = 1;
          $mhderfassen = 1;
          $seriennummernerfassen = 1;
        }
        $kommissionierverfahren = $projektarr['kommissionierverfahren'];
      }
      $belegnr = $belegarr['belegnr'];
    }

    $chargenauslagern = 1;
    $mhdauslagern = 1;
    $seriennummernauslagern = 1;
    if($chargenmhdnachprojekt && $chargenerfassen){
      $chargenauslagern = 0;
    }
    if($chargenmhdnachprojekt && $mhderfassen){
      $mhdauslagern = 0;
    }
    if($chargenmhdnachprojekt && $seriennummernerfassen && $kommissionierverfahren !== 'kommissionierverfahren'){
      $seriennummernauslagern = 0;
    }
    $sortreihenfolge = 'ASC';
    if($belegtyp === 'produktion') {
      $sortreihenfolge = 'DESC';
    }

    if($belegtyp === 'produktion') {
      if($standardlager > 0 && !$this->app->DB->Select(
        sprintf(
          "SELECT id FROM lager WHERE id = %d AND bezeichnung <> '' AND IFNULL(geloescht,0) = 0 LIMIT 1",
          (int)$standardlager)
        )
      ) {
        $standardlager = (int)$this->app->DB->Select(
          sprintf(
            "SELECT l.id 
            FROM projekt AS p 
            INNER JOIN lager AS l ON p.standardlagerproduktion = l.id 
            WHERE p.id = %d AND l.bezeichnung <> '' AND IFNULL(l.geloescht,0) = 0 
            LIMIT 1",
            (int)$projekt
          )
        );
      }
    }
    else{
      if($standardlager > 0 && !$this->app->DB->Select(
        sprintf(
            "SELECT id FROM lager WHERE id = %d AND bezeichnung <> '' AND IFNULL(geloescht,0) = 0 LIMIT 1",
            (int)$standardlager)
        )){
        $standardlager = (int)$this->app->DB->Select(
          sprintf(
            "SELECT l.id 
            FROM projekt AS p 
            INNER JOIN lager AS l ON p.standardlager = l.id 
            WHERE p.id = %d AND l.bezeichnung <> '' AND IFNULL(l.geloescht,0) = 0
            LIMIT 1",
            $projekt
          )
        );
      }
    }
    if($standardlager == 0) {
      if($projekt > 0){
        $projektlager = $this->app->DB->Select("SELECT projektlager FROM projekt WHERE id='$projekt'");
      }
    }
    $storageLocations = [];
    $storageMovements = [];
    $cartikel = $artikelarr?count($artikelarr):0;
    for($i= ($belegtyp==='produktion'?1:0) ;$i<$cartikel;$i++) {
      $beschreibung = $artikelarr[$i]['beschreibung'];
      $artikel = $artikelarr[$i]['artikel'];
      $menge = $artikelarr[$i]['menge'];
      if($nurrestmenge && $belegtyp=='produktion')
      {
        $menge = $artikelarr[$i]['menge'] - $artikelarr[$i]['geliefert_menge'];
      }
      $subid = $artikelarr[$i]['id'];
      $lager_string = '';

      $arcticleRow = $this->app->DB->SelectRow(
        sprintf(
          "SELECT lagerartikel, mindesthaltbarkeitsdatum, chargenverwaltung, seriennummern 
          FROM artikel WHERE id=%d LIMIT 1",
          (int)$artikel
        )
      );
      $lagerartikel = $arcticleRow['lagerartikel'];
      $seriennummern = $arcticleRow['seriennummern'] === 'keine'?'':$arcticleRow['seriennummern'];
      $regal = 0;

      $sperrlagerWhere = ' lp.sperrlager <> 1 ';
      if($belegtyp=='produktion') {
        $sperrlagerWhere = ' (lp.sperrlager <> 1 OR lp.allowproduction = 1) ';
      }

      if($lagerartikel > 0)
      {
        $this->LagerArtikelZusammenfassen($artikel);
        // lager platz suchen eins abziehen und namen in lieferschein
        // kleinster lager leer machen
        $regal = 0;
        $timeout=0;
        $restmenge = $menge;
        $lager_string = '';
        $mindesthaltbarkeitsdatum = $arcticleRow['mindesthaltbarkeitsdatum'];
        $chargenverwaltung = $arcticleRow['chargenverwaltung'];
        while($restmenge > 0)
        {
          $timeout++;
          if($restmenge <= 0){
            break;
          }
          //if($timeout > 1000) break;

          $extraorder = '';
          $maxAuslagern = $restmenge;
          if(!empty($seriennummern) && $belegtyp !== 'produktion') {
            $snDeliveryNoteStorage = $this->app->DB->SelectArr(
              sprintf(
                'SELECT bc.lagerplatz AS storage_location_id, COUNT(bc.id) - IFNULL(olp.menge, 0) AS amount
                FROM `beleg_chargesnmhd` AS bc
                LEFT JOIN (
                  SELECT SUM(menge) AS menge, lager_platz 
                  FROM `objekt_lager_platz` 
                  WHERE objekt = \'lieferschein\' AND parameter = %d
                  GROUP BY lager_platz
                ) AS olp ON bc.lagerplatz = olp.lager_platz 
                WHERE bc.type = \'sn\' AND bc.doctype = \'lieferschein\' AND bc.doctypeid = %d AND bc.pos = %d AND bc.wert <> \'\'
                GROUP BY bc.lagerplatz
                HAVING amount > 0
                ORDER BY COUNT(bc.id) - IFNULL(olp.menge, 0) = %f DESC, COUNT(bc.id) - IFNULL(olp.menge, 0)
                ',
                (int)$subid, (int)$lieferschein, (int)$subid, (float)$restmenge
              )
            );
            if(!empty($snDeliveryNoteStorage)) {
              $extraorder = sprintf(' lpi.lager_platz = %d DESC, ', $snDeliveryNoteStorage[0]['storage_location_id']);
              if($snDeliveryNoteStorage[0]['amount'] < $restmenge && $snDeliveryNoteStorage[0]['amount'] > 0 && (!empty($snDeliveryNoteStorage)?count($snDeliveryNoteStorage):0) > 1) {
                $maxAuslagern = $snDeliveryNoteStorage[0]['amount'];
              }
            }
          }

          $this->app->erp->RunHook('lieferscheinauslagern', 6, $belegtyp, $subid, $artikel, $mindesthaltbarkeitsdatum, $chargenverwaltung, $extraorder);

          if($mindesthaltbarkeitsdatum) {
            if($standardlager > 0) {
              $lager_max = $this->app->DB->SelectArr(
                sprintf(
                  "SELECT lpi.lager_platz, if(lpi.menge > lm.menge, lm.menge,lpi.menge) as menge, lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> %d 
                  INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                  INNER JOIN (
                    SELECT lager_platz, sum(menge) as menge,min(mhddatum) as mhddatum 
                    FROM lager_mindesthaltbarkeitsdatum 
                    WHERE artikel = %d 
                    GROUP BY lager_platz 
                  ) AS lm ON lp.id = lm.lager_platz 
                  WHERE lpi.artikel=%d AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1  AND '.$sperrlagerWhere)." AND `lag`.id='$standardlager' 
                  ORDER by ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." `lag`.id='$standardlager' DESC, $extraorder lm.mhddatum ASC, lpi.menge $sortreihenfolge 
                  LIMIT 1",
                  (int)$kommissionskonsignationslager,(int)$artikel, (int)$artikel
                )
              );
              if(!$lager_max) {
                $lager_max = $this->app->DB->SelectArr(
                  sprintf(
                    "SELECT lpi.lager_platz, lpi.menge, lpi.id 
                    FROM lager_platz_inhalt AS lpi
                    INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id 
                    INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                    LEFT JOIN lager_mindesthaltbarkeitsdatum lm ON lm.artikel=lpi.artikel AND lp.id = lm.lager_platz 
                    WHERE lpi.artikel=%d AND lpi.menge > 0
                    ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." AND `lag`.id='$standardlager' 
                    ORDER by ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." lag.id='$standardlager' DESC, $extraorder lm.mhddatum ASC, lpi.menge $sortreihenfolge 
                    LIMIT 1",
                    (int)$artikel
                  )
                );
              }
            }
            elseif($projektlager > 0) {
              // Hole nach und nach bis alles da ist
              $lager_max = $this->app->DB->SelectArr(
                "SELECT lpi.lager_platz, if(lpi.menge > lm.menge, lm.menge,lpi.menge) as menge,lpi.id 
                FROM lager_platz_inhalt AS lpi
                INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                INNER JOIN (
                  SELECT lager_platz, sum(menge) as menge,min(mhddatum) as mhddatum 
                  FROM lager_mindesthaltbarkeitsdatum 
                  WHERE artikel = '$artikel' AND menge > 0
                  GROUP BY lager_platz 
                ) AS lm  ON lp.id = lm.lager_platz 
                WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  AND `lag`.projekt='$projekt' 
                ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lm.mhddatum ASC, lpi.menge $sortreihenfolge 
                LIMIT 1"
              );
              if(!$lager_max) {
                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, lpi.menge,lpi.id
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id 
                  INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                  LEFT JOIN lager_mindesthaltbarkeitsdatum AS lm ON lm.artikel=lpi.artikel AND lp.id = lm.lager_platz 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  AND `lag`.projekt='$projekt' 
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lm.mhddatum ASC, lpi.menge $sortreihenfolge 
                  LIMIT 1");
              }
            }
            else {
              // Hole nach und nach bis alles da ist
              $lager_max = $this->app->DB->SelectArr(
                sprintf(
                  "SELECT lpi.lager_platz, if(lpi.menge > lm.menge, lm.menge,lpi.menge) as menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager'
                  INNER JOIN (
                    SELECT lager_platz, sum(menge) as menge,min(mhddatum) as mhddatum 
                    FROM lager_mindesthaltbarkeitsdatum 
                    WHERE artikel = %d AND menge > 0
                    GROUP BY lager_platz 
                  ) AS lm  ON lp.id = lm.lager_platz 
                  WHERE lpi.artikel=%d AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." 
                  ORDER by ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lm.mhddatum ASC, lpi.menge $sortreihenfolge 
                  LIMIT 1",
                  (int)$artikel, (int)$artikel
                )
              );
              if(!$lager_max) {
                $lager_max = $this->app->DB->SelectArr("SELECT lpi.lager_platz, lpi.menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id 
                  INNER JOIN lager_mindesthaltbarkeitsdatum AS lm ON lm.artikel=lpi.artikel AND lp.id = lm.lager_platz 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  
                  ORDER by ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lm.mhddatum ASC, lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
              }
            }
          }
          else {
            if($chargenverwaltung) {
              if($standardlager > 0) {
                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, if(lpi.menge > lm.menge, lm.menge,lpi.menge) as menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id 
                  INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                  INNER JOIN (
                    SELECT lager_platz, sum(menge) as menge 
                    FROM lager_charge 
                    WHERE artikel = '$artikel' AND menge > 0
                    GROUP BY lager_platz 
                  ) AS lm ON lp.id = lm.lager_platz 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  AND `lag`.id='$standardlager' 
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." `lag`.id='$standardlager' DESC, $extraorder lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
                if(!$lager_max)
                {
                  $lager_max = $this->app->DB->SelectArr(
                    "SELECT lpi.lager_platz, lpi.menge,lpi.id 
                    FROM lager_platz_inhalt AS lpi
                    INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id 
                    INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                    WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                    ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." AND `lag`.id='$standardlager' 
                    ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." `lag`.id='$standardlager' DESC, $extraorder lpi.menge $sortreihenfolge 
                    LIMIT 1"
                  );
                }
              }
              elseif($projektlager > 0){

                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, if(lpi.menge > lm.menge, lm.menge,lpi.menge) as menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                  INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                  INNER JOIN (
                    SELECT lager_platz, sum(menge) as menge 
                    FROM lager_charge 
                    WHERE artikel = '$artikel' AND menge > 0
                    GROUP BY lager_platz 
                  ) AS lm ON lp.id = lm.lager_platz 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  AND `lag`.projekt='$projekt' 
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
                if(!$lager_max) {
                  $lager_max = $this->app->DB->SelectArr(
                    "SELECT lpi.lager_platz, lpi.menge,lpi.id 
                    FROM lager_platz_inhalt AS lpi
                    INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                    INNER JOIN lager AS `lag` ON `lag`.id=lp.lager
                    WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                    ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  AND `lag`.projekt='$projekt' 
                    ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lpi.menge $sortreihenfolge 
                    LIMIT 1"
                  );
                }
              }
              else {
                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, if(lpi.menge > lm.menge, lm.menge,lpi.menge) as menge,lpi.id  
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager'
                  INNER JOIN (
                    SELECT lager_platz, sum(menge) as menge 
                    FROM lager_charge 
                    WHERE artikel = '$artikel' AND menge > 0
                    GROUP BY lager_platz 
                  ) AS lm  ON lp.id = lm.lager_platz 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)."  
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
                if(!$lager_max) {
                  $lager_max = $this->app->DB->SelectArr(
                    "SELECT lpi.lager_platz, lpi.menge,lpi.id 
                    FROM lager_platz_inhalt AS lpi
                    INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                    WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                    ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." 
                    ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lpi.menge $sortreihenfolge 
                    LIMIT 1"
                  );
                }
              }
            }
            else{
              if($standardlager > 0) {
                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, lpi.menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                  INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." AND `lag`.id='$standardlager' 
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." `lag`.id='$standardlager' DESC, $extraorder lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
              }
              elseif($projektlager > 0) {
                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, lpi.menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                  INNER JOIN lager AS `lag` ON `lag`.id=lp.lager 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." AND `lag`.projekt='$projekt' 
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')."  $extraorder lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
              }
              else {
                $lager_max = $this->app->DB->SelectArr(
                  "SELECT lpi.lager_platz, lpi.menge,lpi.id 
                  FROM lager_platz_inhalt AS lpi
                  INNER JOIN lager_platz AS lp ON lpi.lager_platz=lp.id AND lp.id <> '$kommissionskonsignationslager' 
                  WHERE lpi.artikel='$artikel' AND lpi.menge > 0
                  ".($lpiid?'':' AND lp.autolagersperre!=1 AND '.$sperrlagerWhere)." 
                  ORDER BY ".($lpiid?" lpi.id = '$lpiid' DESC, ":'')." ".($lager_platz_vpe?" lpi.lager_platz_vpe = '$lager_platz_vpe' DESC, ":'')." $extraorder lpi.menge $sortreihenfolge 
                  LIMIT 1"
                );
              }
            }
          }
          if(!$lager_max){
            break;
          }
          if((round($maxAuslagern,8) > round($lager_max[0]['menge'],8)) && ($lager_max[0]['menge'] > 0)) {
            // es werden mehr gebraucht als im lager sind
            $menge_auslagern = $lager_max[0]['menge'];
          }
          else if( ($lager_max[0]['menge'] >= $maxAuslagern) && ($maxAuslagern > 0)  ) {
            // es sind genuegend lager
            $menge_auslagern = $maxAuslagern;
          }
          else {
            break;
          }

          $storageMovements[] = array('lager_platz' => $lager_max[0]['lager_platz'], 'artikel' => $artikel,'menge' => $menge_auslagern);


          if (!$simulieren) {
              $this->LagerAuslagernRegal($artikel,$lager_max[0]['lager_platz'],$menge_auslagern,$projekt,ucfirst($belegtyp)." $belegnr","",$belegtyp,$lieferschein, $lager_max[0]['lager_platz_vpe'], $lager_max[0]['id']);
              $storageLocations[] = $lager_max[0]['lager_platz'];
              if($anzeige_lagerplaetze_in_lieferschein){
                  $this->LagerAuslagernText($artikel, $subid, $lager_max[0]['lager_platz'], $menge_auslagern, $belegtyp);
              } else {
                  $this->LagerAuslagernObjektLagerPlatz($artikel, $subid, $lager_max[0]['lager_platz'], $menge_auslagern, $belegtyp);
              }
              $regal_name = $this->app->DB->Select("SELECT kurzbezeichnung FROM lager_platz WHERE id='".$lager_max[0]['lager_platz']."' LIMIT 1");
              $lager_string .= $regal_name."(".(float)$menge_auslagern.") ";
              if(!$nurrestmenge){
                  $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_max[0]['lager_platz'],$menge_auslagern,$projekt,ucfirst($belegtyp)." $belegnr","",$belegtyp,$lieferschein,$subid, $chargenauslagern, $mhdauslagern, $seriennummernauslagern);
              }
          }
          $restmenge = round($restmenge - $menge_auslagern, 8);
        }
      }

      if (!$simulieren) {

          $geliefert = $menge;
          if($nurrestmenge && $belegtyp=='produktion') {
            $geliefert = $menge + $artikelarr[$i]['geliefert_menge'];
          }
          $artikelhatseriennummer = $this->app->DB->Select("SELECT seriennummern FROM artikel WHERE id='".$artikel."' LIMIT 1");
          if($belegtyp == 'produktion')
          {
            $this->app->DB->Update("UPDATE ".$belegtyp."_position SET geliefert_menge='$geliefert', geliefert = 1 WHERE id='$subid' LIMIT 1");
          }else{

            if($belegtyp=="lieferschein")
            {
              $auftragposid=$this->app->DB->Select("SELECT auftrag_position_id FROM lieferschein_position WHERE id='$subid'");
              if($auftragposid>0)
              {
                $this->app->DB->Update("UPDATE auftrag_position SET geliefert_menge='$geliefert' WHERE id='$auftragposid' LIMIT 1");
              }
            }

            if($seriennummernerfassen=='1' && ($artikelhatseriennummer=='vomprodukteinlagern' || $artikelhatseriennummer=='vomprodukt' || $artikelhatseriennummer=='eigene'))
            {
              // wenn Seriennummer erfasst werden soll
              //if($anzeige_lagerplaetze_in_lieferschein)
              //{
                //$this->app->DB->Update("UPDATE ".$belegtyp."_position SET beschreibung='$beschreibung' WHERE id='$subid' LIMIT 1");
                //neue datenstruktur
              //}
              if($forceseriennummerngeliefertsetzen)$this->app->DB->Update("UPDATE ".$belegtyp."_position SET geliefert='$geliefert' WHERE id='$subid' LIMIT 1");
            } else {
              //wenn nicht
              //if($anzeige_lagerplaetze_in_lieferschein)
              //  $this->app->DB->Update("UPDATE ".$belegtyp."_position SET geliefert='$geliefert',beschreibung='$beschreibung' WHERE id='$subid' LIMIT 1");
              //else
              $this->app->DB->Update("UPDATE ".$belegtyp."_position SET geliefert='$geliefert' WHERE id='$subid' LIMIT 1");
            }
          }
       } // simulieren
    } // for loop

    if (!$simulieren) {

        if(!empty($storageLocations)) {
          $this->addStorageCountry($belegtyp, $lieferschein, $storageLocations);
        }
        $this->app->DB->Delete("DELETE FROM lager_reserviert WHERE objekt = '$belegtyp' AND parameter = '$lieferschein'");

        if($belegtyp == '' || $belegtyp === 'lieferschein')
        {
            $auftragid = $this->app->DB->Select("SELECT auftragid FROM $belegtyp WHERE id='$lieferschein'");
            if($auftragid){
              $this->app->DB->Delete("DELETE FROM lager_reserviert WHERE objekt = 'auftrag' AND parameter = '$auftragid'");
            }

          $this->RunHook('erpapi_lieferschein_auslagern', 1, $lieferschein);
          $this->SeriennummernCheckLieferscheinWarnung($lieferschein, true);
          $this->LieferscheinProtokoll($lieferschein,"Lieferschein ausgelagert");
        }
    }

    return(array('storageMovements' => $storageMovements));
  }

  /**
   * @param string $doctype
   * @param int    $doctypeId
   * @param array  $storageLocations
   */
  public function addStorageCountry($doctype, $doctypeId, $storageLocations)
  {
    if($doctype === 'lieferschein') {
      $order = $this->app->DB->SelectRow(
        sprintf(
          "SELECT o.id, o.schreibschutz
          FROM lieferschein AS dn 
          INNER JOIN auftrag AS o ON dn.auftragid = o.id AND o.belegnr <> ''
          WHERE dn.id = %d AND o.`storage_country` = '' AND o.shop = 0
          ORDER BY o.status <> 'storniert' DESC",
          $doctypeId
        )
      );
      if(!empty($order)) {
        $country = $this->app->DB->Select(
          sprintf(
            "SELECT adr.land 
            FROM lager_platz AS lp 
            INNER JOIN lager AS l ON lp.lager = l.id
            INNER JOIN adresse adr ON IF(l.adresse > 0, l.adresse, lp.adresse) = adr.id 
               AND adr.land <> '' AND adr.land <> '%s' 
            WHERE lp.id IN (%s)
            LIMIT 1",
            $this->app->DB->real_escape_string($this->app->erp->Firmendaten('land')),
            implode(',', array_unique($storageLocations))
          )
        );
        if(!empty($country)) {
          $this->app->DB->Update(
            sprintf(
              "UPDATE auftrag 
              SET storage_country = '%s', zuarchivieren = 0, schreibschutz = 0
              WHERE id = %d AND storage_country = ''",
              $this->app->DB->real_escape_string($country), $order['id']
            )
          );
          if($this->app->DB->affected_rows() > 0) {
            $this->app->erp->ANABREGSNeuberechnen($order['id'], 'auftrag');
            if($order['schreibschutz']) {
              $this->app->erp->PDFArchivieren('auftrag', $order['id'], true);
            }

            $invoice = $this->app->DB->SelectRow(
              sprintf(
                "SELECT id,storage_country, schreibschutz  
                FROM rechnung 
                WHERE auftragid = %d AND status <> 'storniert' 
                ORDER BY id DESC 
                LIMIT 1",
                $order['id']
              )
            );
            if(!empty($invoice) && empty($invoice['storage_country'])) {
              $this->app->DB->Update(
                sprintf(
                  "UPDATE rechnung 
                  SET storage_country = '%s', zuarchivieren = 0, schreibschutz = 0 
                  WHERE id = %d AND storage_country = ''",
                  $this->app->DB->real_escape_string($country), $invoice['id']
                )
              );
              $this->app->erp->ANABREGSNeuberechnen($invoice['id'], 'rechnung');
              if($invoice['schreibschutz']) {
                $this->app->erp->RechnungArchivieren($invoice['id']);
              }
            }
          }
        }
      }
    }
  }

  // @refactor in Artikel Modul
  function artikelnummerscan($artikel)
  {
    $hauptprojekt = (int)$this->app->erp->Firmendaten('projekt');
    $haupteanherstellerscanerlauben = $this->app->DB->Select("SELECT eanherstellerscanerlauben FROM projekt WHERE id = '$hauptprojekt' LIMIT 1");
    $subwhere = "";
    if($haupteanherstellerscanerlauben)$subwhere = 'or isnull(p.id)';
    $artikelnummer = $this->app->erp->FirstTillSpace($artikel);
    $artikelid = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikelnummer' AND geloescht!=1 LIMIT 1");
    if(!$artikelid)$artikelid = $this->app->DB->Select("SELECT art.id FROM artikel art 
    LEFT JOIN projekt p ON art.projekt = p.id
    WHERE (p.eanherstellerscanerlauben = 1 $subwhere) AND art.ean='$artikelnummer' AND art.ean != '' AND art.geloescht!=1 LIMIT 1");
    if(!$artikelid)$artikelid = $this->app->DB->Select("SELECT art.id FROM artikel art 
    LEFT JOIN projekt p ON art.projekt = p.id
    WHERE (p.eanherstellerscanerlauben = 1 $subwhere) AND art.herstellernummer='$artikelnummer' AND art.herstellernummer != '' AND art.geloescht!=1 LIMIT 1");
    $this->RunHook('artikelnummerscan',2, $artikel, $artikelid);
    return $artikelid;
  }

  // @refactor in TemplateMessge Komponente
  function AddTplMsg($message)
  {
    if(!isset($this->app->User))return;
    if(!method_exists($this->app->User,'GetID'))return;
    $user = (int)$this->app->User->GetID();
    $this->app->DB->Insert("INSERT INTO `templatemessage` (`message`, `user`, `zeitstempel`) VALUES ('".$this->app->DB->real_escape_string($message)."','$user',now())");
    return $this->app->DB->GetInsertID();
  }

  // @refactor in TemplateMessge Komponente
  function GetTmpMessageOut()
  {
    if(isset($this->app->Secure) && $this->app->Secure && method_exists($this->app->Secure, 'GetGET'))
    {
      $msgid = (int)$this->app->Secure->GetGET('msgid');
      if($msgid)return $this->base64_url_decode($this->GetTplMessage($msgid));
      return $this->base64_url_decode($this->app->Secure->GetGET('msg'));
    }
    return '';
  }

  // @refactor in TemplateMessge Komponente
  function GetTplMessage($id)
  {
    if(!isset($this->app->User))return;
    if(!method_exists($this->app->User,'GetID'))return;
    $user = (int)$this->app->User->GetID();
    return $this->app->DB->Select("SELECT `message` FROM `templatemessage` WHERE `user` = '$user' AND id = '$id' LIMIT 1");
  }

  // @refactor in TemplateMessge Komponente
  function base64_url_encode($input) {
    return strtr(base64_encode($input), '+/=', '-_,');
  }

  // @refactor in TemplateMessge Komponente
  function base64_url_decode($input) {
    return base64_decode(strtr($input, '-_,', '+/='));
  }

  // @refactor in Session Klasse
  function ClearCookies()
  {
    if((!empty($_COOKIE)?count($_COOKIE):0) > 0)
    {
      foreach($_COOKIE as $key=>$value)
      {
        if($key!=str_replace("SpryMedia","",$key))
          setcookie ($key, time() - 3600);
      }
    }
  }

  /** @deprecated */
  function ManuelEcho($text)
  {
    echo $this->ClearDataBeforeOutput($text);
    exit;
  }

  // @refactor Formater Komponente
  function ClearDataBeforeOutput($text, $replaceEmptyFormAction = true)
  {
    if ((bool)$replaceEmptyFormAction === true) {
      $text = str_replace('form action=""','form action="#"',$text);
    }
    $text = str_replace('NONBLOCKINGZERO','',$text);
    $text = str_replace("&apos;","'",$text);
    return $text;
  }

  function AdresseAnschriftString($id,$ansprechpartner=false)
  {
    /** @var Adresse $obj */
    $obj = $this->LoadModul('adresse');
    if(!empty($obj) && method_exists($obj, 'AdresseAnschriftString')) {
      return $obj->AdresseAnschriftString($id,$ansprechpartner);
    }
    return '';
  }


  // @refactor BelegPositionen Widget
  function EinkaufspreiseTabelle($artikel, $divid = '')
  {
    if($this->RechteVorhanden('artikel','einkauf'))
    {
      $table = new EasyTable($this->app);
      $table->Query("SELECT if(CHAR_LENGTH(adr.name) > 20, CONCAT(SUBSTRING(adr.name,1,20),'...'), adr.name) as adrname, if(CHAR_LENGTH(e.bestellnummer) > 20, CONCAT(SUBSTRING(e.bestellnummer,1,20),'...'), e.bestellnummer) as bestellnummer, trim(e.ab_menge)+0 as ab, ". $this->FormatPreis("e.preis")." as preis, e.waehrung FROM einkaufspreise e LEFT JOIN adresse adr ON e.adresse = adr.id
        WHERE e.artikel = '$artikel' AND (e.gueltig_bis = '0000-00-00' OR isnull(e.gueltig_bis) OR gueltig_bis >= now() ) ORDER BY adrname, ab_menge");
      return '
      <h3>Einkaufspreise</h3><div'.($divid!==''?' id="'.$divid.'"':'').'>'.
        $table->DisplayNew('return','W&auml;hrung','noAction').'
      </div>';
    }
    return '';
  }

  /** @deprecated */
  function DokumentAbschickenPopup()
  {
    $module = $this->app->Secure->GetGET("module");
    return "var horizontalPadding = 30;
    var verticalPadding = 30; $('<iframe id=\"externalSite\" class=\"externalSite\" src=\"index.php?module=$module&action=abschicken&id=%value%\" width=\"1000\"/>').dialog({
title: 'Abschicken',
      autoOpen: true,
      width:1100,
      height: 800,
      modal: true,
      resizable: true,
      close: function(ev, ui) {window.location.href='index.php?module=$module&action=edit&id=%value%';}
  }).width(1100 - horizontalPadding).height(800 - verticalPadding);";
  }

  public function cleanSpoolerAndFixNumbers()
  {
    $this->app->DB->Delete("DELETE FROM `drucker_spooler` WHERE DATE_SUB(CURDATE(), INTERVAL 10 DAY) >= zeitstempel");

    $this->app->DB->Update("UPDATE adresse SET kundennummer='' WHERE kundennummer='0'");
    $this->app->DB->Update("UPDATE adresse SET lieferantennummer='' WHERE lieferantennummer='0'");
    $this->app->DB->Update("UPDATE adresse SET mitarbeiternummer='' WHERE mitarbeiternummer='0'");

    $this->app->DB->Update("UPDATE auftrag SET status='freigegegen' WHERE status='bestellt'");
    $this->app->DB->Update("UPDATE auftrag SET status='freigegeben' WHERE status='freigegegen'");

    $this->app->DB->Delete("DELETE lh FROM lager_mindesthaltbarkeitsdatum lh INNER JOIN artikel a ON lh.artikel=a.id WHERE a.mindesthaltbarkeitsdatum!='1'");
    $this->app->DB->Delete("DELETE FROM lager_mindesthaltbarkeitsdatum WHERE artikel <=0");

    // status gesperrt gibt es nicht mehr
    $this->app->DB->Update("UPDATE rechnung SET status='versendet' WHERE status='gesperrt'");

    // neue bezeichnung
    $this->app->DB->Update("UPDATE verbindlichkeit SET umsatzsteuer='inland' WHERE umsatzsteuer='deutschland'");
    $this->app->DB->Update("UPDATE verbindlichkeit SET umsatzsteuer='import' WHERE umsatzsteuer='export'");
    $this->app->DB->Delete('DELETE FROM lager_platz_inhalt WHERE artikel = 0 OR lager_platz = 0');
    $this->app->DB->Delete('DELETE FROM lager_seriennummern WHERE artikel = 0 OR (lager_platz = 0 AND zwischenlagerid = 0)');
    $this->app->DB->Delete('DELETE FROM lager_charge WHERE artikel = 0 OR (lager_platz = 0 AND zwischenlagerid = 0)');
    $this->app->DB->Delete('DELETE FROM lager_mindesthaltbarkeitsdatum WHERE artikel = 0 OR (lager_platz = 0 AND zwischenlagerid = 0)');
    $this->app->DB->Update("UPDATE angebot a JOIN auftrag auf ON a.id=auf.angebotid SET a.auftragid=auf.angebotid");
    $this->app->DB->Update("UPDATE artikel SET nummer = CONCAT(nummer, '-DEL') WHERE nummer NOT LIKE '%DEL%' AND geloescht = 1");
    $this->SetKonfigurationValue('clean_spooler_and_fix_numbers', date('Y-m-d H:i:s'));
  }

  // @refactor Installer Komponente

  public function migrateIfFirstInstall()
  {
    if($this->app->DB->Select('SELECT `settings` FROM `user` WHERE `id`= 1') !== 'firstinstall') {
      return;
    }
    $this->FirmendatenVorlage();
    $this->app->DB->Update("UPDATE `user` SET `settings` = '' WHERE `id`= 1");
    /** @var Firmendaten $obj */
    $obj = $this->app->erp->LoadModul('firmendaten');
    if($obj !== null && method_exists($obj,'checkPaymentModules')){
      $obj->checkPaymentModules();
    }

    try {
      /** @var SuperSearchFullIndexTask $indexTask */
      $indexTask = $this->app->Container->get('SuperSearchFullIndexTask');
      $indexTask->execute();
      $indexTask->cleanup();
    } catch (Exception $exception) {

    }
  }

  /**
   * @param string $type
   */
  public function calledOnceAfterLogin($type)
  {
    $this->app->User->deleteParameterPrefix('tablesearch\\_');
/*    if($this->app->DB->Select('SELECT `settings` FROM `user` WHERE `id`= 1')==='firstinstall') {
      $this->UpgradeDatabase();
    }*/

    $this->app->User->SetParameter('zeiterfassung_create_datumzeiterfassung','');

    //TODO Inhalt auf pos.php aus Logout
    $this->app->User->SetParameter('pos_list_projekt',      '0');
    $this->app->User->SetParameter('pos_list_kassierer',    '0');
    $this->app->User->SetParameter('pos_list_kassierername','0');
    $this->app->User->SetParameter('pos_list_lkadresse',    '0');

    $this->app->User->SetParameter('lohnabrechnung_von','');
    $this->app->User->SetParameter('lohnabrechnung_bis','');
    $this->app->erp->RunHook('calledonceafterlogin');
    $this->CheckGPSStechuhr();
    $this->app->User->SetParameter('updatekey',1);

    // Alte Realtime-Benachrichtigungen löschen
    // Das sind Benachrichtigungen die nur zur Laufzeit relevant sind; z.b. Callcenter-Benachrichtigungen
    $notification = $this->app->Container->get('NotificationService');
    $notification->deleteByTags(['realtime'], $this->app->User->GetID());
    if(
      !$this->app->DB->Select(
        "SELECT `id` FROM `prozessstarter` WHERE `parameter` = 'cleaner' AND `aktiv` = 1 LIMIT 1"
      )
    ) {
      // Drucker spooler loeschen
      $cleanSpooler = $this->GetKonfiguration('clean_spooler_and_fix_numbers');
      if(empty($cleanSpooler) || ((strtotime($cleanSpooler) + 86400 + 14400) < time())) {
        $this->cleanSpoolerAndFixNumbers();
      }
      $this->app->DB->Delete("DELETE FROM `templatemessage` WHERE `zeitstempel` < DATE_SUB(now(), INTERVAL 1 DAY)");
    }

    if($this->Firmendaten('zeiterfassung_pflicht')=='1' && $this->RechteVorhanden('zeiterfassung','create')) {

      if(date('w')==1) // brauche heute - 2 Tage
      {
        $checkzeit2=$this->app->DB->Select("SELECT DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 3 DAY),'%Y-%m-%d')");
      }
      else {
        $checkzeit2 = $this->app->DB->Select("SELECT DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 1 DAY),'%Y-%m-%d')");
      }
      $checkzeit = $this->app->DB->Select(
        sprintf(
          "SELECT DATE_FORMAT(MAX(`bis`),'%%Y-%%m-%%d') 
          FROM `zeiterfassung` 
          WHERE `adresse` = %d 
          AND DATE_FORMAT(`bis`,'%%Y-%%m-%%d')='%s'",
          $this->app->User->GetAdresse(), $checkzeit2
        )
      );

      if($checkzeit!=$checkzeit2) {
        $msg = $this->base64_url_encode(
            "<div class=\"error\">Es wurde keine Zeiterfassung am letzten Werktag gefunden. Bitte diese jetzt nachtragen.</div>  ");
        header("Location: index.php?module=zeiterfassung&action=create&top=TWVpbiBCZXJlaWNo&msg=$msg");
        exit;
      }
      // am montag auf freitag schauen
      // sonst schauen ob es gestern war
    }
  }

  // @refactor in Gpsstechuhr Modul
  function CheckGPSStechuhr()
  {
    $module=$this->app->Secure->GetGET('module');
    if($module === 'gpsstechuhr') {
      return;
    }
    if(
      $this->app->DB->Select(
        sprintf(
          'SELECT `gpsstechuhr` FROM `user` WHERE `id` = %d',
          $this->app->User->GetID()
        )
      ) <= 0) {
      return;
    }
    if(!$this->ModulVorhanden('gpsstechuhr')) {
      return;
    }

    $check = $this->app->DB->Select(
      sprintf(
        "SELECT `id` 
        FROM `gpsstechuhr`
        WHERE `user` = %d AND `adresse`= %d
        AND DATE_FORMAT(`zeit`,'%%Y-%%m-%%d')= DATE_FORMAT( NOW( ) , '%%Y-%%m-%%d' ) 
        LIMIT 1",
        $this->app->User->GetID(), $this->app->User->GetAdresse()
      )
    );
    if($check > 0) {
      return;
    }

    $this->app->Location->execute('index.php?module=gpsstechuhr&action=create');
  }

  // @refactor DocumentPdf Komponente
  function ParseFormVars($fields)
  {
    foreach($fields as $key)
    {
      $this->app->Tpl->Set(strtoupper($key),$this->app->Secure->GetPOST($key));
    }
  }

  // @refactor Document Komponente
  function Zahlungsweisetext($doctype,$doctypeid)
  {
    //if($doctype!="rechnung") return;//AUSKOMMENTIEREN?
    $doctypeRow = $this->app->DB->SelectRow(sprintf("SELECT * FROM `%s` WHERE id=%d LIMIT 1", $doctype, (int)$doctypeid));
    if(empty($doctypeRow['zahlungsweise'])) {
      $zahlungsweise = '';
    }
    $zahlungsweise = !empty($doctypeRow['zahlungsweise'])?$doctypeRow['zahlungsweise']:'';
    $zahlungsstatus = !empty($doctypeRow['zahlungsstatus'])?$doctypeRow['zahlungsstatus']:'';
    $zahlungszieltage = !empty($doctypeRow['zahlungszieltage'])?$doctypeRow['zahlungszieltage']:'';
    $zahlungszieltageskonto = !empty($doctypeRow['zahlungszieltageskonto'])?$doctypeRow['zahlungszieltageskonto']:'';
    $zahlungszielskonto = !empty($doctypeRow['zahlungszielskonto'])?$doctypeRow['zahlungszielskonto']:'';

    $zahlungszielskontototal=$zahlungszielskonto;

    if($doctype === 'auftrag' || $doctype === 'rechnung' || $doctype === 'gutschrift' || $doctype === 'angebot' || $doctype === 'bestellung')
    {
      if(empty($doctypeRow['skontoberechnet'])) {
        $skontobetrag = null;
      } else {
        $skontobetrag = isset($doctypeRow['skontobetrag'])?$doctypeRow['skontobetrag']:null;
      }
      if($skontobetrag !== null)
      {
        if($doctype === 'auftrag' || $doctype === 'angebot' || $doctype === 'bestellung')
        {
          $soll = !empty($doctypeRow['gesamtsumme'])?$doctypeRow['gesamtsumme']:0;
        }else{
          $soll = !empty($doctypeRow['soll'])?$doctypeRow['soll']:0;
        }
        //$zahlungszielskonto = round((100 * $skontobetrag / $soll),2); // den wert lassen sonst sieht es komisch am briefpapier aus Ticket 757670
      }
    }

    $zahlungszieltage = (int) $zahlungszieltage;

    $zahlungdatum = $this->app->DB->Select("SELECT DATE_FORMAT(DATE_ADD(datum, INTERVAL $zahlungszieltage DAY),'%d.%m.%Y') FROM $doctype WHERE id='$doctypeid' LIMIT 1");

    $anzeigen = false;
    $zahlungsweisetext = "";

    $projekt = !empty($doctypeRow['projekt'])?$doctypeRow['projekt']:0;
    $zahlungsweiseid = $this->app->DB->SelectRow("SELECT id, modul,freitext FROM zahlungsweisen WHERE type = '$zahlungsweise' AND aktiv = 1 AND geloescht = 0 AND (projekt = 0 OR projekt = '$projekt') ORDER BY projekt = '$projekt' DESC LIMIT 1");

    if(!empty($zahlungsweiseid))
    {
      // if there is an translation then use this
      $zahlungsweisetext2 = $this->app->erp->Beschriftung("zahlungsweise_freitext_".$zahlungsweiseid['id']);
      $zahlungsweisetext = ($zahlungsweisetext2!=""?$zahlungsweisetext2:$zahlungsweiseid['freitext']);

      if($zahlungsweiseid['modul'] != '')
      {
        $zahlungsweiseid['modul'] = preg_replace('/[^a-zA-Z0-9\_]/','',$zahlungsweiseid['modul']);
        $pfad = dirname(__DIR__).'/lib/zahlungsweisen/'.$zahlungsweiseid['modul'].'.php';
        if($zahlungsweiseid['modul'] && @is_file($pfad))
        {
          $classname = 'Zahlungsweise_'.$zahlungsweiseid['modul'];
          if(!class_exists($classname)){
            include_once($pfad);
          }
          if(class_exists($classname))
          {
            $obj = new $classname($this->app, $zahlungsweiseid['id']);
            if($obj && method_exists($obj, 'GetZahlungsweiseText'))
            {
              $zahlungsweisetexttmp = $obj->GetZahlungsweiseText($doctype, $doctypeid);
              if($zahlungsweisetexttmp!='') {
                if($zahlungsweiseid['modul'] == 'tagxmonat'){
                  $zahlungsweisetext = $zahlungsweisetexttmp."\r\n";
                }
                else{
                  $zahlungsweisetext .= "\r\n".$zahlungsweisetexttmp."\r\n";
                }
              }
            }
          }
        }
      }
    }

    //$this->RunHook('ZahlungsweisetextZahlungsdatum',4, $doctype, $doctypeid, $zahlungdatum, $zahlungsweisetext);

    $zahlungszieltageskonto = (int) $zahlungszieltageskonto;

    $zahlungszielskontodatum = $this->app->DB->Select("SELECT DATE_FORMAT(DATE_ADD(datum, INTERVAL $zahlungszieltageskonto DAY),'%d.%m.%Y') FROM $doctype WHERE id='$doctypeid' LIMIT 1");

    $adresse = !empty($doctypeRow['adresse'])?$doctypeRow['adresse']:0;

    $skontofaehig = $this->Skontofaehig($doctypeid, $doctype);
    $skontofaehig = number_format((float)$skontofaehig,2,',','.');

    $skontofaehignetto = $this->Skontofaehig($doctypeid, $doctype,false);
    $skontofaehignetto = number_format((float)$skontofaehignetto,2,',','.');

    if($zahlungszieltageskonto<=0)
      $zahlungszielskontodatum = $zahlungdatum;

    $sprache = !empty($doctypeRow['sprache'])?$doctypeRow['sprache']:$this->app->DB->Select("SELECT sprache FROM adresse WHERE id='$adresse' LIMIT 1");

    $this->app->erp->BeschriftungSprache($sprache);

    $zahlungsweise = strtolower($zahlungsweise);

    //if($zahlungsweise=="rechnung"&&$zahlungsstatus!="bezahlt")
    if($zahlungsweisetext == '')
    {
      if($doctype==='rechnung'){
        if($zahlungsweise==='rechnung' || $zahlungsweise==='einzugsermaechtigung' || $zahlungsweise==='lastschrift')
        {

          if($zahlungsweise==='rechnung')
          {
            if($zahlungszieltage==0){
              $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_rechnung_sofort_de");
              //if($zahlungsweisetext=='') {
              //  $zahlungsweisetext = 'Rechnung zahlbar sofort. ';
              //}
            }else{
              $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_rechnung_de");
              //if($zahlungsweisetext=="") $zahlungsweisetext ="Rechnung zahlbar innerhalb von {ZAHLUNGSZIELTAGE} Tagen bis zum {ZAHLUNGBISDATUM}. ";
              $zahlungsweisetext = str_replace("{ZAHLUNGSZIELTAGE}",$zahlungszieltage,$zahlungsweisetext);
              $zahlungsweisetext = str_replace("{ZAHLUNGBISDATUM}",$zahlungdatum,$zahlungsweisetext);
            }


          if($this->app->erp->Firmendaten("eigener_skontotext")=="1" && ($zahlungszielskonto>0 || $skontobetrag > 0))
          {
            $skontotext = $this->app->erp->Beschriftung("eigener_skontotext_re");
            $skontotext = str_replace('{ZAHLUNGSZIELSKONTO}',number_format($zahlungszielskonto,2,',','.'),$skontotext);
            $skontotext = str_replace('{ZAHLUNGSZIELSKONTOTOTAL}',number_format($zahlungszielskontototal,2,',','.'),$skontotext);
            $skontotext = str_replace('{ZAHLUNGSZIELTAGESKONTO}',$zahlungszieltageskonto,$skontotext);
            $skontotext = str_replace('{ZAHLUNGSZIELSKONTODATUM}',$zahlungszielskontodatum,$skontotext);

            $zahlungsweisetext .= "\n".$skontotext;
          }else{
            if($zahlungszielskonto!=0)
            {
              $zahlungsweisetext .="\n".$this->app->erp->Beschriftung("dokument_skonto")." ".number_format($zahlungszielskonto,2,',','.')." % ".$this->app->erp->Beschriftung("dokument_innerhalb")." $zahlungszieltageskonto ".$this->app->erp->Beschriftung("dokument_tagebiszum")." ".$zahlungszielskontodatum;
            }
          }
        }else{
          //lastschrift
          $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_".$zahlungsweise."_de");
          if($zahlungsweisetext=="") $zahlungsweisetext ="Der Betrag wird von Ihrem Konto abgebucht.";
          if($zahlungszielskonto!=0)
            $zahlungsweisetext .="\r\n".$this->app->erp->Beschriftung("dokument_skontoanderezahlungsweisen");
            //$zahlungsweisetext .="\r\n".$this->app->erp->Beschriftung("dokument_skonto")." $zahlungszielskonto % aus Zahlungskonditionen";

            $zahlungsweisetext = str_replace('{ZAHLUNGSZIELSKONTO}',number_format($zahlungszielskonto,2,',','.'),$zahlungsweisetext);
            $zahlungsweisetext = str_replace('{ZAHLUNGSZIELSKONTOTOTAL}',number_format($zahlungszielskontototal,2,',','.'),$zahlungsweisetext);
          }

        }else{
          // schauen ob es zahlungsweise gibt
          $zahlungsweisetext = $this->Beschriftung("zahlungsweise_freitext_".$this->app->DB->Select("SELECT id FROM zahlungsweisen WHERE type='".$zahlungsweise."' AND aktiv='1' AND type!='' LIMIT 1"));
          if($zahlungsweisetext=="")
          {
            $zahlungsweisetext = $this->app->DB->Select("SELECT freitext FROM zahlungsweisen WHERE type='".$zahlungsweise."' AND aktiv='1' AND type!='' LIMIT 1");
          }

          if($zahlungsweisetext=="")
            $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_".$zahlungsweise."_de");

        if($zahlungsweisetext=="")// || $zahlungsweise=="vorkasse")
        {
          $zahlweisetmp = ucfirst($zahlungsweise);
          if($zahlweisetmp == "Eckarte") $zahlweisetmp = "EC-Karte";
          $zahlungsweisetext = $this->app->erp->Beschriftung("dokument_zahlung_per")." ".$zahlweisetmp;
        }
      }
    }

    if($doctype=="auftrag"){
      //$zahlungstext = "\nZahlungsweise: $zahlungsweise ";

        if($zahlungsweise=="lastschrift" || $zahlungsweise=="einzugsermaechtigung")
          $zahlungsweise="lastschrift";

        if($zahlungsweise=="rechnung")
        {
          // das ist immer ein Vorschlag und keine Rechnung! Daher hier anderen Text!
          if($zahlungszieltage >0) {
            $zahlung_auftrag_de = $this->app->erp->Beschriftung("zahlung_auftrag_de");
            if(empty($zahlung_auftrag_de)){
              $zahlungsweisetext = $this->app->erp->Beschriftung("dokument_zahlung_rechnung_anab");
            }
            else{
              $zahlungsweisetext = $zahlung_auftrag_de;
            }
          }
          else {
            $zahlung_auftrag_sofort_de =$this->app->erp->Beschriftung("zahlung_auftrag_sofort_de");
            if(empty($zahlung_auftrag_sofort_de))
            {
              $zahlungsweisetext = $this->app->erp->Beschriftung("dokument_zahlung_rechnung_anab");
            }else{
              $zahlungsweisetext =$zahlung_auftrag_sofort_de;
            }
          }
          if($this->app->erp->Firmendaten("eigener_skontotext")=="1" && $zahlungszielskonto>0)
          {
            $skontotext = $this->app->erp->Beschriftung("eigener_skontotext_anab");
            $skontotext = str_replace('{ZAHLUNGSZIELSKONTO}',number_format($zahlungszielskonto,2,',','.'),$skontotext);
            $skontotext = str_replace('{ZAHLUNGSZIELSKONTOTOTAL}',number_format($zahlungszielskontototal,2,',','.'),$skontotext);
            $skontotext = str_replace('{ZAHLUNGSZIELTAGESKONTO}',$zahlungszieltageskonto,$skontotext);
            $zahlungsweisetext .= "\n".$skontotext;
          } else {
            if($zahlungszielskonto>0) $zahlungsweisetext .= "\n".$this->app->erp->Beschriftung("dokument_skonto")." ".number_format($zahlungszielskonto,2,',','.')."% ".$this->app->erp->Beschriftung("dokument_innerhalb")." $zahlungszieltageskonto ".$this->app->erp->Beschriftung("dokument_tagen");
          }
        }
        else {
          // schauen ob es zahlungsweise gibt

          if($zahlungsweisetext=="")
            $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_".$zahlungsweise."_de");
          if($zahlungsweisetext=="")
            $zahlungsweisetext = $this->app->erp->Beschriftung("dokument_zahlung_per")." ".ucfirst($zahlungsweise);

          // alt
          //if($zahlungszielskonto>0) $zahlungsweisetext .= "\n".$this->app->erp->Beschriftung("dokument_skonto")." ".number_format($zahlungszielskonto,2,',','.')."% ";
          if($zahlungszielskonto!=0)
              $zahlungsweisetext .="\r\n".$this->app->erp->Beschriftung("dokument_skontoanderezahlungsweisen");

          if($zahlungsweisetext =='') {
            $zahlungsweisetext = "\n".ucfirst($zahlungsweise);
          }
        }
      }

      if($doctype==='angebot')
      {
        if($zahlungsweise==='rechnung')
        {
          if($zahlungszieltage >0) {
            $zahlung_rechnung_de = $this->app->erp->Beschriftung('zahlung_auftrag_de');
            if(empty($zahlung_rechnung_de)) {
              $zahlungsweisetext = $this->app->erp->Beschriftung('dokument_zahlung_rechnung_anab');
            }
            else {
              $zahlungsweisetext = $zahlung_rechnung_de;
            }
          }
          else {
            $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_auftrag_sofort_de");
          }

          if($zahlungszielskonto>0 && $this->app->erp->Firmendaten('eigener_skontotext')=='1') {
            $skontotext = $this->app->erp->Beschriftung("eigener_skontotext_anab");
            $skontotext = str_replace('{ZAHLUNGSZIELSKONTO}',number_format($zahlungszielskonto,2,',','.'),$skontotext);
            $skontotext = str_replace('{ZAHLUNGSZIELTAGESKONTO}',$zahlungszieltageskonto,$skontotext);
            $zahlungsweisetext .= "\n".$skontotext;
          } else {
            if($zahlungszielskonto>0) {
              $zahlungsweisetext .= "\n".$this->app->erp->Beschriftung("dokument_skonto")." ".number_format($zahlungszielskonto,2,',','.')."% ".$this->app->erp->Beschriftung("dokument_innerhalb")." $zahlungszieltageskonto ".$this->app->erp->Beschriftung("dokument_tagen");
            }
          }

        } else {
          $zahlungsweisetext = $this->app->DB->Select("SELECT freitext FROM zahlungsweisen WHERE type='".$zahlungsweise."' AND aktiv='1' AND type!='' LIMIT 1");
          if($zahlungsweisetext=="")
            $zahlungsweisetext = $this->app->erp->Beschriftung("zahlung_".$zahlungsweise."_de");
          if($zahlungsweisetext=="")
            $zahlungsweisetext = $this->app->erp->Beschriftung("dokument_zahlung_per")." ".ucfirst($zahlungsweise);
        }
      }


      if($doctype=="rechnung"){
        if(1)//$zahlungszielskonto!=0)
        {
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELSKONTO}",number_format($zahlungszielskonto,2,',','.'),$zahlungsweisetext);
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELSKONTOTOTAL}",number_format($zahlungszielskontototal,2,',','.'),$zahlungsweisetext);
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELTAGESKONTO}",$zahlungszieltageskonto,$zahlungsweisetext);
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELSKONTODATUM}",$zahlungszielskontodatum,$zahlungsweisetext);
        } /*else {
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELSKONTO}","0",$zahlungsweisetext);
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELTAGESKONTO}","0",$zahlungsweisetext);
          $zahlungsweisetext = str_replace("{ZAHLUNGSZIELSKONTODATUM}",$zahlungdatum,$zahlungsweisetext);
        }*/
      }
    }
    $zahlungsweisetext = str_replace('{SKONTOFAEHIG}',$skontofaehig, $zahlungsweisetext);
    $zahlungsweisetext = str_replace('{SKONTOFAEHIGNETTO}',$skontofaehignetto, $zahlungsweisetext);
    $zahlungsweisetext = $this->ParseUserVars($doctype,$doctypeid, $zahlungsweisetext);

    return $zahlungsweisetext;
  }

  public function getDeliverythresholdvatid($projektid = null)
  {
    $vatid = '';
    if($projektid > 0){
      $vatid = $this->Projektdaten($projektid, 'steuernummer');
      if(!empty($vatid)){
        return $vatid;
      }
    }
    return $this->Firmendaten('steuernummer');
  }

  // @refactor DocumentPdf Komponente
  public function ParseUserVars($type,$id,$text, $removeuneused = true)
  {
    if(strpos($text, '}') === false) {
      return $text;
    }
    $liefertext = '';
    $liefertextlang = '';
    $this->RunHook('parseuservars', 3, $type, $id,$text);

    $result = $this->app->DB->SelectArr("SELECT * FROM $type WHERE id='$id' LIMIT 1");
    $waehrung = $result[0]['waehrung'];
    $text = str_replace('{BELEGART}',ucfirst($type),$text);

    $text = str_replace('{FIRMA}',$this->Firmendaten("name"),$text);
    if($type === 'rechnung' && !empty($result[0]['belegnr'])) {
      $text = str_replace('{RECHNUNG}',$result[0]['belegnr'], $text);
    }
    if($result[0]['projekt'] > 0){
      $projektArr = $this->app->DB->SelectRow("SELECT abkuerzung, name FROM projekt WHERE id='" . $result[0]['projekt'] . "' LIMIT 1");
    }else{
      $projektArr = null;
    }
    if(!empty($projektArr)){
      $projektabkuerzung = $projektArr['abkuerzung'];
      $projektname = $projektArr['name'];
    }else{
      $projektabkuerzung = '';
      $projektname = '';
    }
    $text = str_replace('{DELIVERYTHRESHOLDVATID}',!empty($result[0]['deliverythresholdvatid'])?$result[0]['deliverythresholdvatid']:'',$text);
    $text = str_replace('{PROJEKT}',$projektabkuerzung,$text);
    $text = str_replace('{PROJEKTNUMMER}',$projektabkuerzung,$text);


    $text = str_replace('{PROJEKTNAME}',$projektname,$text);

    $projekt = $result[0]['projekt'];

    $versandartbezeichnung = '';
    if($result[0]['versandart']!='')
    {
      $versandartbezeichnung = $this->Beschriftung("versandart_bezeichnung_".$this->app->DB->Select("SELECT id FROM versandarten WHERE type='".$result[0]['versandart']."' LIMIT 1"));
      if($versandartbezeichnung=="")
      {
        $versandartbezeichnung = $this->app->DB->Select("SELECT bezeichnung FROM versandarten WHERE type='".$result[0]['versandart']."' LIMIT 1");
      }
    }
    $text = str_replace('{VERSANDARTBEZEICHNUNG}',$versandartbezeichnung,$text);

    if($type==='produktion')
    {
      $result[0]['kundenname'] = $this->app->DB->Select("SELECT a.name as kundenname FROM produktion p LEFT JOIN adresse a ON a.id=p.adresse WHERE p.id='$id' LIMIT 1");
    }


    if($type==='gutschrift')
    {
      $rechnungid = $result[0]['rechnungid'];
      $result[0]['auftragid'] = $this->app->DB->Select("SELECT auftragid FROM rechnung WHERE id='".$rechnungid."' LIMIT 1");
      $result[0]['rechnung'] = $this->app->DB->Select("SELECT belegnr FROM rechnung WHERE id='".$rechnungid."' LIMIT 1");
    }

    if($type!=='auftrag' && $type!=='bestellung' && $type!=='retoure')
    {
      $auftragArr = $this->app->DB->SelectRow("SELECT a.*, DATE_FORMAT(datum,'%d.%m.%Y') as datum_de FROM auftrag AS a WHERE id='".$result[0]['auftragid']."' LIMIT 1");

      if (!empty($auftragArr)) {

          $result[0]['internet'] = $auftragArr['internet'];
          $result[0]['abweichendelieferadresse']=$auftragArr['abweichendelieferadresse'];
          $result[0]['liefername']=$auftragArr['liefername'];
          $result[0]['lieferabteilung']=$auftragArr['lieferabteilung'];
          $result[0]['lieferunterabteilung']=$auftragArr['lieferunterabteilung'];
          $result[0]['lieferadresszusatz']=$auftragArr['lieferadresszusatz'];
          $result[0]['liefertitel']=$auftragArr['liefertitel'];
          $result[0]['lieferansprechpartner']=$auftragArr['lieferansprechpartner'];
          $result[0]['lieferstrasse']=$auftragArr['lieferstrasse'];
          $result[0]['lieferplz']=$auftragArr['lieferplz'];
          $result[0]['lieferland']=$auftragArr['lieferland'];
          $result[0]['lieferort'] = $auftragArr['lieferort'];
          $result[0]['liefergln'] = $auftragArr['liefergln'];
          $result[0]['lieferemail'] = $auftragArr['lieferemail'];
        }
    }

    if($type=="angebot" || $type=="auftrag")
    {
      $soll = $result[0]['gesamtsumme'];
      $skonto = $this->app->DB->Select("SELECT (gesamtsumme/100)*zahlungszielskonto FROM $type WHERE id='".$id."' LIMIT 1");
      $skontobetrag = $result[0]['skontobetrag'];
      if(!is_null($skontobetrag))$skonto = $skontobetrag;
      $text = str_replace('{SOLL}',$this->formatMoney($soll,$waehrung),$text);
      $text = str_replace('{SOLLMITSKONTO}',$this->formatMoney($soll-$skonto,$waehrung),$text);
      $text = str_replace('{SKONTOBETRAG}',$this->formatMoney((float)$skonto,$waehrung),$text);
    }

    if($type=="angebot" || $type=="auftrag" || $type=="lieferschein" )
    { 
      if($result[0]['lieferid'] > 0)
      {
        $lieferhinweis = $this->app->DB->Select("SELECT hinweis FROM lieferadressen WHERE id='".$result[0]['lieferid']."' LIMIT 1");
        $text = str_replace('{LIEFERADRESSE_HINWEIS}',$lieferhinweis,$text);
      }
    }

    if($type=="rechnung" || $type=="gutschrift" || $type=="auftrag" || $type=="angebot")
    {
      $docarr = $result[0];
      $soll = null;
      $normal = null;
      $ermaessigt = null;
      $skonto = null;
      $skontobetrag = null;
      if(!empty($docarr)){
        $soll = $docarr['soll'];
        $normal = $docarr['steuersatz_normal'];
        $ermaessigt = $docarr['steuersatz_ermaessigt'];
        $skonto = $docarr['soll']/100*$docarr['zahlungszielskonto'];
        $skontobetrag = $docarr['skontobetrag'];
      }
      if($skontobetrag !== null) {
        $skonto = $skontobetrag;
      }
      $text = str_replace('{SOLL}',$this->formatMoney($soll,$waehrung),$text);
      $text = str_replace('{SOLLMITSKONTO}',$this->formatMoney($soll-$skonto,$waehrung),$text);
      $text = str_replace('{SKONTOBETRAG}',$this->formatMoney((float)$skonto,$waehrung),$text);

      $summe_normal = $this->BelegZwischensummeSteuersaetzeBrutto2($id,$type,"normal");
      $summe_ermaessigt = $this->BelegZwischensummeSteuersaetzeBrutto2($id,$type,"ermaessigt");

      $text = str_replace('{STEUERNORMAL}',$this->formatMoney($normal,$waehrung),$text);
      $text = str_replace('{GESAMTNETTO}',$this->formatMoney(($summe_normal/((100+$normal)/100))+($summe_ermaessigt/((100+$ermaessigt)/100)),$waehrung),$text);
      $text = str_replace('{GESAMTNETTONORMAL}',$this->formatMoney($summe_normal/((100+$normal)/100),$waehrung),$text);
      $text = str_replace('{STEUERERMAESSIGT}',$this->formatMoney($ermaessigt,$waehrung),$text);
      $text = str_replace('{GESAMTNETTOERMAESSIGT}',$this->formatMoney($summe_ermaessigt/((100+$ermaessigt)/100),$waehrung),$text);
    } else {
      $text = str_replace('{SOLL}',"",$text);
      $text = str_replace('{SOLLMITSKONTO}',"",$text);
      $text = str_replace('{SKONTOBETRAG}',"",$text);
    }

    //internet
    //transaktionsnummer
    if($type==="auftrag")
    {
      $text = str_replace('{INTERNET}',$result[0]['internet'],$text);
      $text = str_replace('{TRANSAKTIONSNUMMER}',$result[0]['transaktionsnummer'],$text);
      $text= str_replace('{AUFTRAG}',$result[0]['belegnr'],$text);
      $text= str_replace('{GESAMT}',$result[0]['gesamtsumme'],$text);
      $text= str_replace('{DATUM}',$this->app->DB->Select("SELECT DATE_FORMAT(datum,'%d.%m.%Y') FROM auftrag WHERE id='$id' LIMIT 1"),$text);
      if(strpos($text, '{RECHNUNG}') !== false) {
        $rechnungBelegnr = $this->app->DB->Select(
          sprintf(
            "SELECT belegnr FROM rechnung WHERE auftragid = %d AND auftragid > 0 AND belegnr <> '' LIMIT 1",
            $id
          )
        );
        $text = str_replace('{RECHNUNG}', $rechnungBelegnr, $text);
      }
    }

    if($type === 'retoure') {
      $orderId = $result[0]['auftragid'] > 0?$result[0]['auftragid']:$result[0]['replacementorder_id'];
      if($orderId > 0) {
        $order = $this->app->DB->SelectRow(
          sprintf(
            'SELECT `belegnr`, `internet`, `transaktionsnummer`, `gesamtsumme` 
            FROM `auftrag` WHERE `id` = %d LIMIT 1',
            $orderId
          )
        );
        if(!empty($order['belegnr'])) {
          $text= str_replace('{AUFTRAG}', $order['belegnr'], $text);
        }
        if(!empty($order['internet'])) {
          $text = str_replace('{INTERNET}',$order['internet'],$text);
        }
        if(!empty($order['gesamtsumme'])) {
          $text = str_replace('{GESAMT}',$order['gesamtsumme'],$text);
        }
        if(!empty($order['transaktionsnummer'])) {
          $text = str_replace('{TRANSAKTIONSNUMMER}',$order['transaktionsnummer'],$text);
        }
        if(!empty($order) && strpos($text, '{RECHNUNG}') !== false) {
          $rechnungBelegnr = $this->app->DB->Select(
            sprintf(
              "SELECT `belegnr` FROM `rechnung` WHERE `auftragid` = %d AND `auftragid` > 0 AND `belegnr` <> '' LIMIT 1",
              $orderId
            )
          );
          $text = str_replace('{RECHNUNG}', $rechnungBelegnr, $text);
        }
      }
    }

    if($type==="rechnung")
    {
      $zahlungsstatus = $result[0]['zahlungsstatus'];
      $bezahlt = $this->Beschriftung("rechnung_footer_bezahlt");
      $offen = $this->Beschriftung("rechnung_footer_offen");
      if($zahlungsstatus=="offen" || $zahlungsstatus=="")
        $text = str_replace('{ZAHLUNGSSTATUS}',$offen,$text);
      else if ($zahlungsstatus=="bezahlt")
        $text = str_replace('{ZAHLUNGSSTATUS}',$bezahlt,$text);
    }

    if($type==='rechnung' || $type==='lieferschein' || $type==='retoure' || $type==='gutschrift')
    {
      $auftragid = $result[0]['auftragid'];
      if($auftragid > 0) {
        $orderRow = $this->app->DB->SelectRow(
          sprintf(
            'SELECT internet,transaktionsnummer,DATE_FORMAT(datum,\'%%d.%%m.%%Y\') as datum_de 
          FROM auftrag WHERE id=%d LIMIT 1',
            (int)$auftragid
          )
        );
        if(!empty($orderRow)) {
          $text = str_replace(
            ['{INTERNET}','{TRANSAKTIONSNUMMER}','{AUFTRAGSDATUM}'],
            [$orderRow['internet'], $orderRow['transaktionsnummer'], $orderRow['datum_de']],
            $text
          );
        }
      }
    }

    if($type=="rechnung" || $type=="auftrag" || $type=="angebot" || $type=="bestellung")
    {
      $zahlungszieltage = $result[0]['zahlungszieltage'];
      $zahlungszieltageskonto = $result[0]['zahlungszieltageskonto'];
      $zahlungszielskonto = $result[0]['zahlungszielskonto'];
      $zahlungdatum = $this->app->DB->Select("SELECT DATE_FORMAT(DATE_ADD(datum, INTERVAL $zahlungszieltage DAY),'%d.%m.%Y') FROM $type WHERE id='$id' LIMIT 1");
      $zahlungszielskontodatum = $this->app->DB->Select("SELECT DATE_FORMAT(DATE_ADD(datum, INTERVAL $zahlungszieltageskonto DAY),'%d.%m.%Y') FROM $type WHERE id='$id' LIMIT 1");
      $text = str_replace("{ZAHLUNGSZIELTAGE}",$zahlungszieltage,$text);
      $text = str_replace("{ZAHLUNGBISDATUM}",$zahlungdatum,$text);
      $text = str_replace("{ZAHLUNGSZIELSKONTODATUM}",$zahlungszielskontodatum,$text);
    } else {
      $text = str_replace("{ZAHLUNGSZIELTAGE}","",$text);
      $text = str_replace("{ZAHLUNGBISDATUM}","",$text);
    }
    if(strpos($text, '}') === false) {
      return $text;
    }

    if ($type=="lieferschein")
    {
      $rechnungsadresse = '';
      $rechnungsid = $this->app->DB->Select("SELECT id FROM rechnung WHERE lieferschein='$id' LIMIT 1");
      if($rechnungsid > 0)
      {
        $resultrechnung = $this->app->DB->SelectArr("SELECT * FROM rechnung WHERE id='$rechnungsid' LIMIT 1");
        if($resultrechnung[0]['name']!="")
          $rechnungsadresse .= $resultrechnung[0]['name']."\r\n";
        if($resultrechnung[0]['abteilung']!="")
          $rechnungsadresse .= $resultrechnung[0]['abteilung']."\r\n";
        if($resultrechnung[0]['unterabteilung']!="")
          $rechnungsadresse .= $resultrechnung[0]['unterabteilung']."\r\n";
        if($resultrechnung[0]['strasse']!="")
          $rechnungsadresse .= $resultrechnung[0]['strasse']."\r\n";
        if($resultrechnung[0]['adresszusatz']!="")
          $rechnungsadresse .= $resultrechnung[0]['adresszusatz']."\r\n";
        if($resultrechnung[0]['ansprechpartner']!="")
          $rechnungsadresse .= $resultrechnung[0]['ansprechpartner']."\r\n";
        if($resultrechnung[0]['plz']!="")
          $rechnungsadresse .= $resultrechnung[0]['land']."-".$resultrechnung[0]['plz']." ".$resultrechnung[0]['ort']."\r\n";
        else
          $rechnungsadresse .= $resultrechnung[0]['land']." ".$resultrechnung[0]['ort']."\r\n";
      }

      if($rechnungsid <=0){
        $text = str_replace('{RECHNUNGSADRESSE}', "", $text);
      }
      else{
        $text = str_replace('{RECHNUNGSADRESSE}', "Rechnungsadresse: \r\n" . $rechnungsadresse, $text);
        if(!empty( $resultrechnung[0]['belegnr'])) {
          $text = str_replace('{RECHNUNG}', $resultrechnung[0]['belegnr'], $text);
        }
      }
    }

    // Netto gewicht
    if($type=="auftrag" || $type=="angebot" || $type=="lieferschein" || $type=="retoure" || $type=="rechnung" || $type=="gutschrift" || $type=="bestellung" | $type=="proformarechnung" || $type=="preisanfrage")
    {

      $anzahlteile = $this->app->DB->Select("SELECT TRIM(SUM(ap.menge))+0
          FROM ".$type."_position ap LEFT JOIN artikel a ON ap.artikel=a.id WHERE ap.$type='$id' AND a.porto!=1 AND a.rabatt!=1 ");

      $text = str_replace("{ANZAHLTEILEALLE}",$anzahlteile,$text);

      if($type==='bestellung' || $type==='preisanfrage' ) {
        $anzahlteilesichtbar = $anzahlteile;
      }
      else if($type=="auftrag" || $type=="angebot" || $type=="rechnung" || $type=="gutschrift")
      {
        $anzahlteilesichtbar = $this->app->DB->Select("SELECT TRIM(SUM(ap.menge))+0
          FROM " . $type . "_position ap LEFT JOIN artikel a ON ap.artikel=a.id WHERE ap.$type='$id' AND a.porto!=1 AND a.rabatt!=1 AND ap.ausblenden_im_pdf!=1");
      } else {
        $anzahlteilesichtbar = $this->app->DB->Select("SELECT TRIM(SUM(ap.menge))+0
          FROM ".$type."_position ap LEFT JOIN artikel a ON ap.artikel=a.id WHERE ap.$type='$id' AND a.porto!=1 AND a.rabatt!=1");
      }

      $text = str_replace("{ANZAHLTEILE}",$anzahlteilesichtbar,$text);



      $nettogewicht = $this->app->DB->Select(
        "SELECT 
            SUM(
                REPLACE(
                    IF(a.nettogewicht='' OR a.nettogewicht IS NULL OR a.nettogewicht = 0,
                       a.gewicht,
                       a.nettogewicht
                    ),',','.') * ap.menge
            )
          FROM ".$type."_position ap LEFT JOIN artikel a ON ap.artikel=a.id WHERE ap.$type='$id'"
      );
      $text = str_replace('{NETTOGEWICHT}',number_format((float)$nettogewicht,2,",",""),$text);
      $zahlungsweise = '';
      if($type !== 'lieferschein'){
        $zahlungsweise = $result[0]['zahlungsweise'];
      }
      $text = str_replace("{ZAHLUNGSWEISE}",$zahlungsweise,$text);
    } else {
      $text = str_replace('{NETTOGEWICHT}',"-",$text);
      $text = str_replace("{ZAHLUNGSWEISE}","-",$text);
    }

    if(isset($result[0]) && $result[0])
    {
      foreach($result[0] as $key=>$value)
        $result[0][$key]=str_replace('NONBLOCKINGZERO','',$result[0][$key]);
    }

    if($type === 'adresse') {
      $tmpAddr = $result[0];
    }
    else{
      $tmpAddr = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='" . $result[0]['adresse'] . "' LIMIT 1");
    }
    if(!empty($tmpAddr)) {
      $text = str_replace(
        ['{FREIFELD1}','{FREIFELD2}','{FREIFELD3}'],
        [$tmpAddr['freifeld1'],$tmpAddr['freifeld2'],$tmpAddr['freifeld3']],
        $text);
      $result[0]['kundennummer'] = $tmpAddr['kundennummer'];
      $result[0]['verbandsnummer'] = $tmpAddr['verbandsnummer'];
      //if($result[0]['anschreiben']==''){ // heute wieder raus 509913
      //  $result[0]['anschreiben'] = $tmpAddr['anschreiben'];
      //}
    } else {
      $result[0]['kundennummer'] = '';
      $result[0]['verbandsnummer'] = '';
    }

    $result[0]['verband'] = $this->GetVerbandName($this->GetVerband($result[0]['adresse']));

    if($result[0]['anschreiben']!="")
      $text = str_replace('{ANSCHREIBEN}',$result[0]['anschreiben'],$text);
    else
      $text = str_replace('{ANSCHREIBEN}',$this->app->erp->Beschriftung("dokument_anschreiben"),$text);

    if($result[0]['ansprechpartner']!="")
      $text = str_replace('{ANSPRECHPARTNER}',$result[0]['ansprechpartner'],$text);
    else
      $text = str_replace('{ANSPRECHPARTNER}',"",$text);

    if($result[0]['belegnr']!="")
      $text = str_replace('{BELEGNR}',$result[0]['belegnr'],$text);
    else
      $text = str_replace('{BELEGNR}',"",$text);

    if($result[0]['belegnr']!="")
      $text = str_replace('{BELEGNUMMER}',$result[0]['belegnr'],$text);
    else
      $text = str_replace('{BELEGNUMMER}',"",$text);

    if($result[0]['kundennummer']!="")
      $text = str_replace('{KUNDENNUMMER}',$result[0]['kundennummer'],$text);
    else
      $text = str_replace('{KUNDENNUMMER}',"",$text);

    if($result[0]['verbandsnummer']!="")
      $text = str_replace('{VERBANDSNUMMER}',$result[0]['verbandsnummer'],$text);
    else
      $text = str_replace('{VERBANDSNUMMER}',"Keine Nummer",$text);

    if($result[0]['verband']!="")
      $text = str_replace('{VERBAND}',$result[0]['verband'],$text);
    else
      $text = str_replace('{VERBAND}',"Kein Verband",$text);


    if($type=="rechnung" || $type=="lieferschein")
    {
      $tmpauftragid =$result[0]['auftragid'];
      $result[0]['lieferdatum'] = $this->app->DB->Select("SELECT lieferdatum FROM auftrag WHERE id='$tmpauftragid' LIMIT 1");
      $result[0]['tatsaechlicheslieferdatum'] = $this->app->DB->Select("SELECT tatsaechlicheslieferdatum FROM auftrag WHERE id='$tmpauftragid' LIMIT 1");
    }
    if($type==='bestellung'){
      $result[0]['lieferdatum'] = $result[0]['gewuenschteslieferdatum'];

      $check = $this->app->DB->SelectArr("SELECT a.belegnr, a.id, a.name
        FROM bestellung_position bp
        INNER JOIN auftrag_position ap ON ap.id = bp.auftrag_position_id
        INNER JOIN auftrag a ON ap.auftrag = a.id
        WHERE bp.bestellung='$id' GROUP BY a.belegnr, a.id ORDER BY a.belegnr, a.id");
      if($check)
      {
        $tmpauftragbelegnr = array();
        foreach($check as $row)
        {
          $tmpauftragbelegnr[] = ($row['belegnr']?$row['belegnr']:'Entwurf')." ".$row['name'].'';
        }
        $text = str_replace('{AUFTRAG}',implode('\r\n',$tmpauftragbelegnr),$text);
      }
    }

    $result[0]['tatsaechlicheslieferdatum'] = $this->app->String->Convert($result[0]['tatsaechlicheslieferdatum'],"%1-%2-%3","%3.%2.%1");

    if(isset($result[0]['gewuenschteslieferdatum']) && $this->CheckDateValidate($result[0]['gewuenschteslieferdatum'])){
      $result[0]['gewuenschteslieferdatum'] = $this->app->String->Convert($result[0]['gewuenschteslieferdatum'],"%1-%2-%3","%3.%2.%1");
    } else {
      $result[0]['gewuenschteslieferdatum'] = $this->app->erp->Beschriftung("dokument_lieferdatum_sofort");
    }

    if($result[0]['lieferdatum']!="0000-00-00" && $result[0]['lieferdatum']!="")
    {
      if($type==="angebot" || $type==="auftrag")
      {
        $lieferdatumkw = $result[0]['lieferdatumkw'];
      }

      $ddate = $result[0]['lieferdatum'];
      $result[0]['lieferdatum'] = $this->app->String->Convert($result[0]['lieferdatum'],"%1-%2-%3","%3.%2.%1");
      $duedt = explode("-", $ddate);
      $date  = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
      $week  = date('W/Y', $date);

      if($lieferdatumkw==1)
      {
        $text = str_replace('{LIEFERTERMIN}',$week,$text);
        $result[0]['lieferdatum'] = $week;
      }
      else {
        $text = str_replace('{LIEFERTERMIN}',$result[0]['lieferdatum'],$text);
      }

      $text = str_replace('{LIEFERWOCHE}',$week,$text);
    }
    else
    {
      $text = str_replace('{LIEFERTERMIN}',$this->app->erp->Beschriftung("dokument_lieferdatum_sofort"),$text);
      $text = str_replace('{LIEFERWOCHE}',$this->app->erp->Beschriftung("dokument_lieferdatum_sofort"),$text);
    }

    if(isset($result[0]) && isset($result[0]['gueltigbis']) && $result[0]['gueltigbis']!="0000-00-00" && $result[0]['gueltigbis']!="")
    {
      $ddate = $result[0]['gueltigbis'];
      $result[0]['gueltigbis'] = $this->app->String->Convert($result[0]['gueltigbis'],"%1-%2-%3","%3.%2.%1");
      $duedt = explode("-", $ddate);
      $date  = mktime(0, 0, 0, $duedt[1], $duedt[2], $duedt[0]);
      $week  = date('W/Y', $date);
      $text = str_replace('{GUELTIGBIS}',$result[0]['gueltigbis'],$text);
      $text = str_replace('{GUELTIGBISWOCHE}',$week,$text);
    }
    else
    {
      $text = str_replace('{GUELTIGBIS}',"",$text);
      $text = str_replace('{GUELTIGBISWOCHE}',"",$text);
    }

    if(isset($result[0]) && isset($result[0]['gueltigbis']) && $result[0]['gueltigbis']!="0000-00-00" && $result[0]['gueltigbis']!="")
    {
      $ddate = $result[0]['gueltigbis'];
      $result[0]['gueltigbis'] = $this->app->String->Convert($result[0]['gueltigbis'],"%1-%2-%3","%3.%2.%1");
      $duedt = explode("-", $ddate);
      $date  = mktime(0, 0, 0, (int) $duedt[1], (int) $duedt[2], (int) $duedt[0]);
      $week  = date('W/Y', $date);
      $text = str_replace('{GUELTIGBIS}',$result[0]['gueltigbis'],$text);
      $text = str_replace('{GUELTIGBISWOCHE}',$week,$text);
    }
    else
    {
      $text = str_replace('{GUELTIGBIS}',"",$text);
      $text = str_replace('{GUELTIGBISWOCHE}',"",$text);
    }
    if(strpos($text, '}') === false) {
      return $text;
    }
    //TRackingnummer
    if($type=="rechnung" || $type=="lieferschein")
    {
      if($type=="rechnung") {
        $lieferscheine = $this->app->DB->SelectArr("SELECT id FROM lieferschein WHERE rechnungid='$id'");
        if(empty($lieferscheine))
        {
          $lieferscheine[0]['id'] = $this->app->DB->Select("SELECT lieferschein FROM rechnung WHERE id='$id' AND id > 0 LIMIT 1");
        }
      }
      else
      {
        $lieferscheine[0]['id']=$id;
      }

      $clieferscheine = !empty($lieferscheine)?count($lieferscheine):0;
      for($li=0;$li<$clieferscheine;$li++)
      {
    /*    $tracking = $this->app->DB->SelectArr("SELECT tracking FROM versand WHERE lieferschein='".$lieferscheine[$li]['id']."' AND lieferschein > 0 AND tracking!=''");
        $ctracking = !empty($tracking)?count($tracking):0;
        for($i=0;$i<$ctracking;$i++) {
          $tmptracking[] = $tracking[$i]['tracking'];
        }
*/

        $sql = "SELECT SQL_CALC_FOUND_ROWS
                v.id,                   
                v.tracking as tracking,
                v.tracking_link
            FROM 
                versandpakete v
            LEFT JOIN
                versandpaket_lieferschein_position vlp ON v.id = vlp.versandpaket
            LEFT JOIN
                lieferschein_position lp ON lp.id = vlp.lieferschein_position
            LEFT JOIN
                lieferschein l ON lp.lieferschein = l.id
            WHERE l.id = ".$lieferscheine[$li]['id']." OR v.lieferschein_ohne_pos = ".$lieferscheine[$li]['id']."
            GROUP BY 
               v.id
            ";
        $tracking = $this->app->DB->SelectArr($sql);
        $tracking_list = array();
        foreach ($tracking as $single_tracking) {
            $tmptracking[] = $single_tracking['tracking'];
            $tracking_list[] =  '<a href="'.$single_tracking['tracking_link'].'">'.$single_tracking['tracking'].'</a>';
        }

/*
        $nve = $this->app->DB->SelectArr("SELECT nve FROM spedition_packstuecke WHERE lieferschein='".$lieferscheine[$li]['id']."' AND nve!='' AND status!='storniert'");
        $cnve = !empty($nve)?count($nve):0;
        for($i=0;$i<$cnve;$i++) {
          $tmpnve[] = $nve[$i]['nve'];
        }*/
      }

    

      $text = str_replace('{TRACKINGNUMMER}',!empty($tmptracking)?implode(", ",$tmptracking):'',$text);
      $text = str_replace('{TRACKINGLINK}',!empty($tracking_list)?implode(", ",$tracking_list):'',$text);
      $text = str_replace('{NVE}',!empty($tmpnve)?implode(", ",$tmpnve):'',$text);
    }

    if(isset($result[0]['verzollungadresse']) && $result[0]['verzollungadresse']==1)
    {
      $text = str_replace('{VERZOLLUNGADRESSE}',$result[0]['verzollungadresse'],$text);
      $text = str_replace('{VERZOLLUNGNAME}',$result[0]['verzollungname'],$text);
      $text = str_replace('{VERZOLLUNGABTEILUNG}',$result[0]['verzollungabteilung'],$text);
      $text = str_replace('{VERZOLLUNGUNTERABTEILUNG}',$result[0]['verzollungunterabteilung'],$text);
      $text = str_replace('{VERZOLLUNGLAND}',$result[0]['verzollungland'],$text);
      $text = str_replace('{VERZOLLUNGSTRASSE}',$result[0]['verzollungstrasse'],$text);
      $text = str_replace('{VERZOLLUNGORT}',$result[0]['verzollungort'],$text);
      $text = str_replace('{VERZOLLUNGPLZ}',$result[0]['verzollungplz'],$text);
      $text = str_replace('{VERZOLLUNGADRESSZUSATZ}',$result[0]['verzollungadresszusatz'],$text);
      $text = str_replace('{VERZOLLUNGANSPRECHPARTNER}',$result[0]['verzollungansprechpartner'],$text);
      $text = str_replace('{VERZOLLUNGINFORMATIONEN}',$result[0]['verzollunginformationen'],$text);
    }
    if(strpos($text, '}') === false) {
      return $text;
    }
    $abweichende_rechnungsadresse = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='".$result[0]['adresse']."' AND id >0 LIMIT 1");

    if($abweichende_rechnungsadresse)
    {
      if($abweichende_rechnungsadresse['abweichende_rechnungsadresse']=="1")
      {
        $abweichende_rechnungsadressetext ="";
        $abweichende_rechnungsadressetextlang ="";

        $fieldabw = array('rechnung_name','rechnung_ansprechpartner','rechnung_abteilung','rechnung_unterabteilung','rechnung_adresszusatz','rechnung_strasse');
        foreach($fieldabw as $keyabw)
        {
          if($abweichende_rechnungsadresse[$keyabw]!="")
          {
            $abweichende_rechnungsadressetext .= $abweichende_rechnungsadresse[$keyabw]."\r\n";
            $abweichende_rechnungsadressetextlang .= $abweichende_rechnungsadresse[$keyabw].", ";
          }
        }

        if(!empty($abweichende_rechnungsadresse['rechnung_plz']))
        {
          $abweichende_rechnungsadressetext .= $abweichende_rechnungsadresse['rechnung_land']."-".$abweichende_rechnungsadresse['rechnung_plz']." ".$abweichende_rechnungsadresse['rechnung_ort']."\r\n";
          $abweichende_rechnungsadressetextlang .= $abweichende_rechnungsadresse['rechnung_land']."-".$abweichende_rechnungsadresse['rechnung_plz']." ".$abweichende_rechnungsadresse['rechnung_ort']." ";
        } else {
          $abweichende_rechnungsadressetext .= $abweichende_rechnungsadresse['rechnung_land']." ".$abweichende_rechnungsadresse['rechnung_ort']."\r\n";
          $abweichende_rechnungsadressetextlang .= $abweichende_rechnungsadresse['rechnung_land']." ".$abweichende_rechnungsadresse['rechnung_ort']." ";
        }
        $text = str_replace('{ABWEICHENDE_RECHNUNGSADRESSE}',$abweichende_rechnungsadressetext,$text);
        $text = str_replace('{ABWEICHENDE_RECHNUNGSADRESSELANG}',$abweichende_rechnungsadressetextlang,$text);
      }
    }

    if($type=="rechnung" || $type=="lieferschein")
    {
      $tmpauftragid = $resul[0]['auftragid'];
      $auftragsadresse = $this->app->DB->SelectRow("SELECT * FROM auftrag WHERE id='$tmpauftragid' LIMIT 1");
      if(!empty($auftragsadresse)){
        $auftragsadressetext = '';
        $auftragsadressetextlang = '';

        $fieldabw = array('name', 'ansprechpartner', 'abteilung', 'unterabteilung', 'adresszusatz', 'strasse');
        foreach ($fieldabw as $keyabw) {
          if(!empty($auftragsadresse[$keyabw])){
            $auftragsadressetext .= $auftragsadresse[$keyabw] . "\r\n";
            $auftragsadressetextlang .= $auftragsadresse[$keyabw] . ", ";
          }
        }

        if(!empty($auftragsadresse['plz'])){
          $auftragsadressetext .= $auftragsadresse['land'] . "-" . $auftragsadresse['plz'] . " " . $auftragsadresse['ort'] . "\r\n";
          $auftragsadressetextlang .= $auftragsadresse['land'] . "-" . $auftragsadresse['plz'] . " " . $auftragsadresse['ort'] . " ";
        }else{
          $auftragsadressetext .= $auftragsadresse['land'] . " " . $auftragsadresse['ort'] . "\r\n";
          $auftragsadressetextlang .= $auftragsadresse['land'] . " " . $auftragsadresse['ort'] . " ";
        }
      }
    }
    if($result[0]['abweichendelieferadresse']=="1")
    {
      $liefertext ="";

      if(!empty($result[0]['liefertitel']))
      {
        $liefertext .= $result[0]['liefertitel']." ";
        $liefertextlang .= $result[0]['liefertitel']." ";
      }

      if(!empty($result[0]['liefername']))
      {
        $liefertext .= $result[0]['liefername']."\r\n";
        $liefertextlang .= $result[0]['liefername'].", ";
      }

      if(trim($result[0]['lieferansprechpartner']) !="")
      {
        $liefertext .= $result[0]['lieferansprechpartner']."\r\n";
        $liefertextlang .= $result[0]['lieferansprechpartner'].", ";
      }

      if($result[0]['lieferabteilung']!="")
      {
        $liefertext .= $result[0]['lieferabteilung']."\r\n";
        $liefertextlang .= $result[0]['lieferabteilung'].", ";
      }

      if($result[0]['lieferunterabteilung']!="")
      {
        $liefertext .= $result[0]['lieferunterabteilung']."\r\n";
        $liefertextlang .= $result[0]['lieferunterabteilung'].", ";
      }

      if(trim($result[0]['lieferadresszusatz'])!="")
      {
        $liefertext .= $result[0]['lieferadresszusatz']."\r\n";
        $liefertextlang .= $result[0]['lieferadresszusatz'].", ";
      }

      if($result[0]['lieferstrasse']!="")
      {
        $liefertext .= $result[0]['lieferstrasse']."\r\n";
        $liefertextlang .= $result[0]['lieferstrasse'].", ";
      }

      if($result[0]['lieferplz']!="")
      {
        $liefertext .= $result[0]['lieferland']."-".$result[0]['lieferplz']." ".$result[0]['lieferort']."\r\n";
        $liefertextlang .= $result[0]['lieferland']."-".$result[0]['lieferplz']." ".$result[0]['lieferort']." ";
      } else {
        $liefertext .= $result[0]['lieferland']." ".$result[0]['lieferort']."\r\n";
        $liefertextlang .= $result[0]['lieferland']." ".$result[0]['lieferort']." ";
      }

      if($liefertext=="")
      {
        $abweichende_rechnungsadresse = $this->app->DB->Select("SELECT abweichende_rechnungsadresse FROM adresse WHERE id='".$result[0]['adresse']."' LIMIT 1");
        if($abweichende_rechnungsadresse)
        {
          $text = str_replace('{LIEFERADRESSE}',($auftragsadressetext!=""?$auftragsadressetext:$this->Beschriftung("entspricht_hauptadresse")),$text);
          $text = str_replace('{LIEFERADRESSELANG}',($auftragsadressetextlang!=""?$auftragsadressetextlang:$this->Beschriftung("entspricht_hauptadresse")),$text);
        } else {
          $text = str_replace('{LIEFERADRESSE}',$this->Beschriftung("entspricht_rechnungsadresse"),$text);
          $text = str_replace('{LIEFERADRESSELANG}',$this->Beschriftung("entspricht_rechnungsadresse"),$text);
        }
      }
      else
      {
        $text = str_replace('{LIEFERADRESSE}',$liefertext,$text);
        $text = str_replace('{LIEFERADRESSELANG}',$liefertextlang,$text);
      }

      $text = str_replace('{LIEFERNAME}',$result[0]['liefername'],$text);
      $text = str_replace('{LIEFERABTEILUNG}',$result[0]['lieferabteilung'],$text);
      $text = str_replace('{LIEFERUNTERABTEILUNG}',$result[0]['lieferunterabteilung'],$text);
      $text = str_replace('{LIEFERLAND}',$result[0]['lieferland'],$text);
      $text = str_replace('{LIEFERSTRASSE}',$result[0]['lieferstrasse'],$text);
      $text = str_replace('{LIEFERORT}',$result[0]['lieferort'],$text);
      $text = str_replace('{LIEFERPLZ}',$result[0]['lieferplz'],$text);
      $text = str_replace('{LIEFERADRESSZUSATZ}',$result[0]['lieferadresszusatz'],$text);
      $text = str_replace('{LIEFERANSPRECHPARTNER}',$result[0]['lieferansprechpartner'],$text);
    } else {
      if($result[0]['name']!="")
      {
        $liefertext .= $result[0]['name']."\r\n";
        $liefertextlang .= $result[0]['name'].", ";
      }
      if($result[0]['ansprechpartner']!="")
      {
        $liefertext .= $result[0]['ansprechpartner']."\r\n";
        $liefertextlang .= $result[0]['ansprechpartner'].", ";
      }
      if($result[0]['abteilung']!="")
      {
        $liefertext .= $result[0]['abteilung']."\r\n";
        $liefertextlang .= $result[0]['abteilung'].", ";
      }
      if($result[0]['unterabteilung']!="")
      {
        $liefertext .= $result[0]['unterabteilung']."\r\n";
        $liefertextlang .= $result[0]['unterabteilung'].", ";
      }
      if($result[0]['strasse']!="")
      {
        $liefertext .= $result[0]['strasse']."\r\n";
        $liefertextlang .= $result[0]['strasse'].", ";
      }
      if($result[0]['adresszusatz']!="")
      {
        $liefertext .= $result[0]['adresszusatz']."\r\n";
        $liefertextlang .= $result[0]['adresszusatz'].", ";
      }

      if($result[0]['plz']!="")
      {
        $liefertext .= $result[0]['land']."-".$result[0]['plz']." ".$result[0]['ort']."\r\n";
        $liefertextlang .= $result[0]['land']."-".$result[0]['plz']." ".$result[0]['ort'];
      } else {
        $liefertext .= $result[0]['land']." ".$result[0]['ort']."\r\n";
        $liefertextlang .= $result[0]['land']." ".$result[0]['ort'];
      }

      if(1)//$type=="bestellung")
      {

        $abweichende_rechnungsadresse = $this->app->DB->Select("SELECT abweichende_rechnungsadresse FROM adresse WHERE id='".$result[0]['adresse']."' LIMIT 1");
        if($abweichende_rechnungsadresse)
        {
          //$text = str_replace('{LIEFERADRESSE}',$this->Beschriftung("entspricht_hauptadresse"),$text);
          //$text = str_replace('{LIEFERADRESSELANG}',$this->Beschriftung("entspricht_hauptadresse"),$text);
         $text = str_replace('{LIEFERADRESSE}',($auftragsadressetext!=""?$auftragsadressetext:$this->Beschriftung("entspricht_hauptadresse")),$text);
         $text = str_replace('{LIEFERADRESSELANG}',($auftragsadressetextlang!=""?$auftragsadressetextlang:$this->Beschriftung("entspricht_hauptadresse")),$text);
        } else {
          $text = str_replace('{LIEFERADRESSE}',$this->Beschriftung("entspricht_rechnungsadresse"),$text);
          $text = str_replace('{LIEFERADRESSELANG}',$this->Beschriftung("entspricht_rechnungsadresse"),$text);
        }
      }
      else
      {
        $text = str_replace('{LIEFERADRESSE}',$liefertext,$text);
        $text = str_replace('{LIEFERADRESSELANG}',$liefertextlang,$text);
      }


      $text = str_replace('{LIEFERNAME}',$result[0]['name'],$text);
      $text = str_replace('{LIEFERABTEILUNG}',$result[0]['abteilung'],$text);
      $text = str_replace('{LIEFERUNTERABTEILUNG}',$result[0]['unterabteilung'],$text);
      $text = str_replace('{LIEFERLAND}',$result[0]['land'],$text);
      $text = str_replace('{LIEFERSTRASSE}',$result[0]['strasse'],$text);
      $text = str_replace('{LIEFERORT}',$result[0]['ort'],$text);
      $text = str_replace('{LIEFERPLZ}',$result[0]['plz'],$text);
      $text = str_replace('{LIEFERADRESSZUSATZ}',$result[0]['adresszusatz'],$text);
      $text = str_replace('{LIEFERANSPRECHPARTNER}',$result[0]['ansprechpartner'],$text);
    }

    $result[0]['datum'] = $this->app->String->Convert($result[0]['datum'],"%1-%2-%3","%3.%2.%1");

    if($result[0]['lieferland']=="") $result[0]['lieferland'] = $result[0]['land'];

    foreach($result[0] as $key_i=>$value_i)
    {
      if($type=="rechnung" && $key_i=="lieferschein") $result[0][$key_i] = $this->app->DB->Select("SELECT belegnr FROM lieferschein WHERE id='".$result[0][$key_i]."' AND id >0 LIMIT 1");
      $text = str_replace('{'.strtoupper($key_i).'}',$result[0][$key_i],$text);
    }
    if(strpos($text, '}') === false) {
      return $text;
    }
    $belege_check = array();

    switch($type)
    {
      case "rechnung":
        $belege_check['rechnung']=$id;
        $belege_check['lieferschein']=$this->app->DB->Select("SELECT lieferschein FROM rechnung WHERE id='$id' LIMIT 1");
        $belege_check['auftrag']=$this->app->DB->Select("SELECT auftragid FROM rechnung WHERE id='$id' LIMIT 1");
      break;
      case "lieferschein":
        $belege_check['lieferschein']=$id;
        $belege_check['auftrag']=$this->app->DB->Select("SELECT auftragid FROM lieferschein WHERE id='$id' LIMIT 1");
        $belege_check['rechnung']=$this->app->DB->Select("SELECT id FROM rechnung  WHERE lieferschein='$id' LIMIT 1");
      break;
      case "retoure":
        $belege_check['retoure']=$id;
        $belege_check['lieferschein']=$this->app->DB->Select("SELECT lieferscheinid FROM retoure WHERE id='$id' LIMIT 1");
        $belege_check['auftrag']=$this->app->DB->Select("SELECT auftragid FROM retoure WHERE id='$id' LIMIT 1");
      break;
      case "gutschrift":
        $belege_check['gutschrift']=$id;
        $belege_check['rechnung']=$this->app->DB->Select("SELECT rechnungid FROM gutschrift WHERE id='$id' LIMIT 1");
      break;
    }

    if((!empty($belege_check)?count($belege_check):0)>0)
    {
      foreach($belege_check as $table=>$tableid) {
        $belege_arr = $this->app->DB->SelectRow("SELECT * FROM $table WHERE id='".$tableid."'");
        if($belege_arr) {
          foreach($belege_arr as $key_i=>$value_i)
          {
            if (strpos($key_i, 'datum') !== false) {
              $belege_arr[$key_i] = $this->app->String->Convert($belege_arr[$key_i],"%1-%2-%3","%3.%2.%1");
            } 
            $text = str_replace('{'.strtoupper($table).'_'.strtoupper($key_i).'}',$belege_arr[$key_i],$text);
          }
        }
      }
    }

    $adresse_arr = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='".$result[0]['adresse']."'");
    if($adresse_arr) {
      foreach($adresse_arr as $key_i=>$value_i)
      {
        $text = str_replace('{ADRESSE_'.strtoupper($key_i).'}',$adresse_arr[$key_i],$text);
      }
    }

    $projekt_arr = $this->app->DB->SelectRow("SELECT * FROM projekt WHERE id='".$projekt."' AND id > 0");
    if($projekt_arr)
    {
      foreach($projekt_arr as $key_i=>$value_i) {
        $text = str_replace('{PROJEKT_'.strtoupper($key_i).'}',$projekt_arr[$key_i],$text);
      }
    }

    $anzahlfreifelder = 20;
    for($i=1;$i<=0;$i++)
    {
      if($adresse_arr["freifeld".$i]!="")
        $text = str_replace('{BESCHRIFTUNG_FREIFELD'.$i.'}',$this->app->erp->Firmendaten("adressefreifeld".$i).": ",$text);
      else
        $text = str_replace('{BESCHRIFTUNG_FREIFELD'.$i.'}',"",$text);
    }

    if(strpos($text, '{GRUPPE_') !== false) {
      $text = $this->parseGroupSum($type,$id,$text);
    }

    if(!$removeuneused) {
      return $this->ParseIfVars($text);
    }
    //return $text;
    return $this->RemoveUnusedParsevars($this->ParseIfVars($text));
  }

  /**
   * @param string $doctype
   * @param int    $id
   * @param string $text
   *
   * @return string
   */
  public function parseGroupSum($doctype,$id,$text)
  {
    if($id <= 0 || !in_array($doctype, ['angebot','auftrag','rechnung','gutschrift']) ||
      strpos($text, '{GRUPPE_') === false) {
      return $text;
    }

    $zwischenPositionen = $this->app->DB->SelectArr(
      sprintf(
        "SELECT * 
        FROM `beleg_zwischenpositionen` 
        WHERE doctype = '%s' AND doctypeid = %d 
          AND (postype = 'gruppensumme' OR postype = 'gruppensummemitoptionalenpreisen' OR postype = 'gruppe')
        ORDER BY pos, sort",
        $doctype, $id
      )
    );
    if(empty($zwischenPositionen)) {
      return $text;
    }
    $method =  $doctype.'MitUmsatzeuer';
    $withTax = !method_exists($this, $method)?true:$this->$method($id);
    $normal = !$withTax?1:$this->GetSteuersatzNormal(true, $id, $doctype);
    $reduced = !$withTax?1:$this->GetSteuersatzErmaessigt(true, $id, $doctype);

    $positions = $this->app->DB->SelectArr(
      sprintf(
        'SELECT * FROM `%s` WHERE `%s` = %d ORDER BY sort, id',
        $doctype.'_position',
        $doctype, $id
      )
    );
    if(empty($positions)) {
      return $text;
    }
    $sortToKey = [];
    foreach($positions as $posKey =>  $position) {
      $sortToKey[$position['sort']] = $posKey;
    }
    $index = 0;
    $sums = [];

    foreach($zwischenPositionen as $zwischenPosition) {
      if($zwischenPosition['postype'] === 'gruppe') {
        $index++;
        $sums[$index] = ['startpos' => $zwischenPosition['pos'] + 1,'endpos' => $zwischenPosition['pos']];
      }
      if($zwischenPosition['postype'] === 'gruppensumme' && $index > 0) {
        $sums[$index]['endpos'] = $zwischenPosition['pos'];
        $sums[$index]['type'] = 'gruppensumme';
      }
      elseif($zwischenPosition['postype'] === 'gruppensummemitoptionalenpreisen' && $index > 0) {
        $sums[$index]['endpos'] = $zwischenPosition['pos'];
        $sums[$index]['type'] = 'gruppensummemitoptionalenpreisen';
      }
    }

    if(empty($sums)) {
      return $text;
    }

    foreach($sums as $index => $sum) {
      $val = 0;
      for($i = $sum['startpos']; $i <= $sum['endpos']; $i++) {
        if(!isset($sortToKey[$i])) {
          continue;
        }
        $position = $positions[$sortToKey[$i]];
        if($sum['type'] !== 'gruppensummemitoptionalenpreisen'
          && $doctype === 'angebot' && !empty($position['optional'])) {
          continue;
        }
        $price = $position['preis'] * $position['menge'] * (1 - $position['rabatt'] / 100);
        if($withTax) {
          if($position['steuersatz'] !== null && $position['steuersatz'] >= 0) {
            $price *= 1+ $position['steuersatz'] / 100;
          }
          elseif($position['umsatzsteuer'] === 'ermaessigt') {
            $price *= $reduced;
          }
          elseif($position['umsatzsteuer'] === 'befreit') {
            $price *= $normal;
          }
        }
        $val += (float)$price;
      }
      $text = str_replace('{GRUPPE_'.$index.'}', $val, $text);
    }

    return $text;
  }

  // @refactor DocumentPdf Komponente
  function RemoveUnusedParsevars($text)
  {
    return preg_replace('/([^\{]|^)\{([A-Z\_0-9]+)\}([^\}]|$)/','$1$3', $text); // Ersetze {AB_12} aber nicht {{ABC}}, da für Formel reserviert
  }

  // @refactor DocumentPdf Komponente
  function ParseIfVars($text, $removevars = false)
  {
    if((String)$text === '')
    {
      return $text;
    }
    $if = strpos($text, '{IF}');
    if($if === false)
    {
      return $text;
    }
    $then = strpos($text, '{THEN}', $if);
    if($then === false)
    {
      return $text;
    }
    $endif = strpos($text, '{ENDIF}', $then);
    if($endif === false)
    {
      return $text;
    }
    $else = strpos($text, '{ELSE}', $then);
    if($else !== false)
    {
      $elses[] = $else;
      while(false !== ($dummy = strpos($text, '{ELSE}', $elses[(!empty($elses)?count($elses):0)-1]+1)))
      {
        $elses[] = $dummy;
      }
    }
    $ifs[] = $if;
    $thens[] = $then;
    $endifs[] = $endif;
    while(false !== ($dummy = strpos($text, '{IF}', $ifs[(!empty($ifs)?count($ifs):0)-1]+1)))
    {
      $ifs[] = $dummy;
    }
    while(false !== ($dummy = strpos($text, '{THEN}', $thens[(!empty($thens)?count($thens):0)-1]+1)))
    {
      $thens[] = $dummy;
    }
    while(false !== ($dummy = strpos($text, '{ENDIF}', $endifs[(!empty($endifs)?count($endifs):0)-1]+1)))
    {
      $endifs[] = $dummy;
    }
    foreach($ifs as $v)
    {
      $element[$v] = array('if', $v);
    }
    foreach($thens as $v)
    {
      $element[$v] = array('then', $v);
    }
    foreach($endifs as $v)
    {
      $element[$v] = array('endif', $v);
    }
    if(!empty($elses))
    {
      foreach($elses as $v)
      {
        $element[$v] = array('else', $v);
      }
    }
    if((!empty($ifs)?(!empty($ifs)?count($ifs):0):0) != (!empty($thens)?count($thens):0) || count($ifs) != (!empty($endifs)?count($endifs):0))
    {
      return $text;
    } //Fehlende Elemente
    $stufe = 0;
    $maxstufe = 0;
    $akt[0] = 0;
    $elements = null;
    if(!empty($element)){
      ksort($element);
      foreach ($element as $k => $v) {
        if($v[0] == 'if'){
          $stufe++;
          $akt[$stufe] = 1;
          $lastif[$stufe] = $elements ? count($elements) : 0;
        }elseif($v[0] == 'then'){
          $akt[$stufe] = 2;
        }elseif($v[0] == 'else'){
          $akt[$stufe] = 3;
        }elseif($v[0] == 'endif'){

        }
        $elements[] = array('pos' => $v[1], 'type' => $v[0], 'stufe' => $stufe, 'akt' => $akt[$stufe]);
        if($v[0] == 'endif'){
          if(isset($lastif[$stufe])){
            $elements[(!empty($elements)?count($elements):0) - 1]['if'] = $lastif[$stufe];
            $elements[$lastif[$stufe]]['endif'] = (!empty($elements)?count($elements):0) - 1;
            unset($lastif[$stufe]);
            $stufe--;
          }
        }elseif($v[0] == 'then'){
          if(isset($lastif[$stufe])){
            $elements[(!empty($elements)?count($elements):0) - 1]['if'] = $lastif[$stufe];
            $elements[$lastif[$stufe]]['then'] = (!empty($elements)?count($elements):0) - 1;
          }
        }elseif($v[0] == 'else'){
          if(isset($lastif[$stufe])){
            $elements[(!empty($elements)?count($elements):0) - 1]['if'] = $lastif[$stufe];
            $elements[$lastif[$stufe]]['else'] = (!empty($elements)?count($elements):0) - 1;
          }
        }
      }
    }

    $ret = '';
    $pos = 0;
    if(!empty($elements)){
      foreach ($elements as $k => $v) {
        if(($v['type'] == 'if') && ($v['stufe'] == 1)){
          if($v['pos'] > $pos)
          {
            if($pos >= 0)
            {
              $ret .= substr($text, $pos, $v['pos'] - $pos);
            }

            if(is_numeric($matches[1][0]) && is_numeric($matches[2][0]))
            {
              if($matches[1][0] != $matches[2][0])
              {
                $check = '';
              }
            }elseif($matches[1][0] !== $matches[2][0])
            {
              $check = '';
            }
          }
          if(!isset($v['then']))
          {
            return $text;
          }
          $thenpos = $v['then'];
          if($thenpos == $k + 1){
            $check = strip_tags(substr($text, $v['pos'] + 4, $elements[$thenpos]['pos'] - ($v['pos'] + 4)));
          }else{
            $check = strip_tags($this->ParseIfVars(substr($text, $v['pos'] + 4, $elements[$thenpos]['pos'] - ($v['pos'] + 4))));
          }
          $check = $this->RemoveUnusedParsevars($check);
          if(trim((String)$check) === '0' || trim((String)$check) === '')
          {
            $check = '';
          }
          if($removevars) $check = preg_replace('/\{([^{}]*+|(?R))*\}\s*/', '', $check);
          if((String)$check !== ''){
            if(preg_match_all('/^(.*)\=\"(.*)\"/', $check, $matches)){
              if($matches[1][0] !== $matches[2][0]) $check = '';
            }elseif(preg_match_all('/^(.*)\=&quot;(.*)&quot;/', str_replace('&quot,','&quot;', $check), $matches)){
              if($matches[1][0] !== $matches[2][0]) $check = '';
            }
          }
          if((String)$check !== ''){
            if(isset($v['else'])){
              $ret .= $this->ParseIfVars(substr($text, $elements[$v['then']]['pos'] + 6, $elements[$v['else']]['pos'] - ($elements[$v['then']]['pos'] + 6)));
            }elseif(isset($v['endif'])){
              $ret .= $this->ParseIfVars(substr($text, $elements[$v['then']]['pos'] + 6, $elements[$v['endif']]['pos'] - ($elements[$v['then']]['pos'] + 6)));
            }else
            {
              return $text;
            }
            $pos = $elements[$v['endif']]['pos'] + 7;
          }else{
            if(isset($v['else'])){
              $ret .= $this->ParseIfVars(substr($text, $elements[$v['else']]['pos'] + 6, $elements[$v['endif']]['pos'] - ($elements[$v['else']]['pos'] + 6)));
            }elseif(isset($v['endif'])){

            }else
            {
              return $text;
            }
            $pos = $elements[$v['endif']]['pos'] + 7;
          }
        }elseif(($v['type'] == 'endif') && ($v['stufe'] == 1)){
          $pos = $v['pos'] + 7;
        }
      }
    }

    $toAdd = substr($text, $pos);

    $brpatternStart = '/(^<\s*br\s*\/*>)/i';
    $brpatternEnd = '/(<\s*br\s*\/*>$)/i';

    //Zeilenumbrüche am Anfang
    if(preg_match($brpatternStart, $ret)){
        while(preg_match($brpatternStart, $ret)){
        $ret = preg_replace($brpatternStart, '', $ret);
      }
    }

    //Zeilenumbrüche dazwischen
    if( preg_match($brpatternEnd, $ret) && preg_match($brpatternStart, $toAdd)){
      while(preg_match($brpatternStart, $toAdd)){
        $toAdd = preg_replace($brpatternStart, '', $toAdd);
      }
    }

    $ret .=$toAdd;

    return $ret;
  }

    /*
    * Replace {VARS} with texts given in array
    * Input array(key => value)
    */
    function ParseVars(array $mapping, $text) { 
        foreach ($mapping as $key => $value) {
            $text = str_replace('{'.strtoupper($key).'}',$value,$text);
        }
        return $text;
    }


  // @refactor Document Komponente
  function CheckBearbeiter($id,$module)
  {
    if(empty($id) || empty($module)) {
      return;
    }
    if($this->Firmendaten('vertriebbearbeiterfuellen')=='1') {
      $this->app->DB->Update("UPDATE $module SET bearbeiter='' WHERE id='$id' AND bearbeiter REGEXP '^[0-9]+$' LIMIT 1");
      return;
    }

    $docArr = $this->app->DB->SelectRow(
      sprintf(
        'SELECT bearbeiter, adresse FROM `%s` WHERE id = %d',
        $module, $id
      )
    );
    if(!empty($docArr)) {
      $bearbeiter = $docArr['bearbeiter'];
    }
    else{
      $bearbeiter = $this->app->DB->Select("SELECT bearbeiter FROM $module WHERE id='$id' LIMIT 1");
    }
    if($bearbeiter=='' || $bearbeiter=='0') {
      // pruefe ob es innendienst verantwortlichen gib
      $adresse = !empty($docArr)?$docArr['adresse']: $this->app->DB->Select(
        "SELECT adresse FROM $module WHERE id='$id' LIMIT 1"
      );
      $innendienst = empty($adresse)?null:$this->app->DB->Select("SELECT innendienst FROM adresse WHERE id='$adresse' LIMIT 1");
      $innendienst_name = empty($innendienst)?null:$this->app->DB->Select("SELECT name FROM adresse WHERE id='$innendienst' LIMIT 1");
      if($innendienst_name!='' && $innendienst_name!='0') {

        $this->app->DB->Update(
          sprintf(
            "UPDATE `%s` 
            SET bearbeiter='%s',bearbeiterid=%d 
            WHERE id=%d
            LIMIT 1",
            $module, $this->app->DB->real_escape_string($innendienst_name), $innendienst,$id
          )
        );
      }
      else {
        $this->app->DB->Update(
          sprintf(
            "UPDATE `%s` 
            SET bearbeiter='%s',bearbeiterid=%d 
            WHERE id=%d 
            LIMIT 1",
            $module, $this->app->DB->real_escape_string($this->app->User->GetName()),
            $this->app->User->GetAdresse(), $id
          )
        );
      }
    }
    else if (is_numeric($bearbeiter)) {
      $bearbeiter = $this->app->DB->Select("SELECT name FROM adresse WHERE id='".$bearbeiter."' LIMIT 1");
      if(empty($bearbeiter)) {
        return;
      }
      $this->app->DB->Update(
        sprintf(
        "UPDATE `%s` SET bearbeiter='%s' WHERE id=%d LIMIT 1",
          $module, $this->app->DB->real_escape_string($bearbeiter), $id
        )
      );
    }
  }

  function LoadModul($class)
  {
    return $this->app->loadModule($class);
  }

  // @refactor ApplicationCore Klasse
  function InstallModul($module)
  {
    if(!$this->ModulVorhanden($module)) {
      return false;
    }
    if(strpos($module,'cronjob_') === 0) {
      $module = substr($module, 8);
      if(!$this->ModulVorhanden($module)) {
        return false;
      }
    }

    try {
      $obj = $this->LoadModul($module);
    }
    catch(Exception $e) {
      return false;
    }
    if(empty($obj)) {
      return false;
    }
    if(!method_exists($obj, 'Install')) {
      return false;
    }
    try {
      return $obj->Install();
    }
    catch(Exception $e) {
      return false;
    }
  }

  // @refactor Document Komponente
  function VertriebAendern($table,$id,$cmd="",$sid="")
  {
    $saction = $this->app->Secure->GetGET("saction");
    if ($cmd=="change")
    {
      if($sid > 0 && $id > 0)
      {
        $name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$sid' LIMIT 1");
        $this->app->DB->Update("UPDATE $table SET vertriebid = $sid, vertrieb='$name' WHERE id='$id' LIMIT 1");
        header("Location: index.php?module=$table&action=edit&id=$id&cmd=");
        exit;
      }
    }
    else if($cmd!="change" && $cmd!="" && $saction=="" && $cmd!="changeinnendienst")
    {
      $this->app->erp->MenuEintrag("index.php?module=$table&action=edit&id=$id","Zur&uuml;ck zur &Uuml;bersicht");
      $this->app->Tpl->Set('TAB1',"<div class=\"info\">Bitte den neuen Verteter bzw. Verk&auml;ufer f&uuml;r die Abrechnung der Provision ausw&auml;hlen.</div>");

      $this->app->YUI->TableSearch('TAB1',"adressevertrieb");

      $this->app->Tpl->Parse('PAGE',"tabview.tpl");
      return 1;
    }
    else {
      $schreibschutz= $this->app->DB->Select("SELECT schreibschutz FROM $table WHERE id='$id' LIMIT 1");
      if($schreibschutz!="1")
      {
        $this->app->Tpl->Set('VERTRIEBBUTTON',"<a href=\"index.php?module=$table&action=edit&id=$id&cmd=$table\"><img src=\"./themes/new/images/edit.svg\"></a>");
      }
      return 0;
    }
  }

  // @refactor Document Komponente
  function InnendienstAendern($table,$id,$cmd="",$sid="")
  {
    $saction = $this->app->Secure->GetGET("saction");
    if ($cmd=="changeinnendienst")
    {
      if($sid > 0 && $id > 0)
      {
        $name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$sid' LIMIT 1");
        $this->app->DB->Update("UPDATE $table SET bearbeiterid = $sid, bearbeiter='$name' WHERE id='$id' LIMIT 1");
        header("Location: index.php?module=$table&action=edit&id=$id&cmd=");
        exit;
      }
    }
    else if($cmd!="change" && $cmd!="" && $saction=="innendienst")
    {
      $this->app->erp->MenuEintrag("index.php?module=$table&action=edit&id=$id","Zur&uuml;ck zur &Uuml;bersicht");
      $this->app->Tpl->Set('TAB1',"<div class=\"info\">Bitte den neuen Innendienst bzw. Bearbeiter ausw&auml;hlen.</div>");

      $this->app->YUI->TableSearch('TAB1',"adresseinnendienst");

      $this->app->Tpl->Parse('PAGE',"tabview.tpl");
      return 1;
    }
    else {
      $schreibschutz= $this->app->DB->Select("SELECT schreibschutz FROM $table WHERE id='$id' LIMIT 1");
      if($schreibschutz!="1")
      {
        $this->app->Tpl->Set('INNENDIENSTBUTTON',"<a href=\"index.php?module=$table&action=edit&id=$id&cmd=$table&saction=innendienst\"><img src=\"./themes/new/images/edit.svg\"></a>");
      }
      return 0;
    }
  }

  /** @deprecated @refactor in scripts.js */
  function EnableTab($tab)
  {
    $this->app->Tpl->Add('ADDITIONALJAVASCRIPT',"<script type=\"text/javascript\">
        $(document).ready(function() {
          $('a[href=\"#$tab\"]').click();
          });</script>");
  }

  // @refactor Document Komponente
  function CheckVertrieb($id,$module)
  {
    if(empty($id) || empty($module)) {
      return;
    }
    if($this->Firmendaten('vertriebbearbeiterfuellen')=='1') {
      $this->app->DB->Update("UPDATE $module SET vertrieb='' WHERE id='$id' AND vertrieb REGEXP '^[0-9]+$' LIMIT 1");
      return;
    }
    if($module === 'auftrag'){
      $docArr = $this->app->DB->SelectRow(
        sprintf(
          'SELECT shop,adresse, vertriebid, vertrieb FROM auftrag WHERE id = %d',
          $id
        )
      );
    }
    else {
      $docArr = $this->app->DB->SelectRow(
        sprintf(
          'SELECT adresse, vertriebid, vertrieb FROM `%s` WHERE id = %d',
          $module,
          $id
        )
      );
    }
    $vertrieb = !empty($docArr)?$docArr['vertriebid']: $this->app->DB->Select("SELECT vertriebid FROM $module WHERE id='$id' LIMIT 1");

    // bei shops nicht
    if($module==='auftrag') {
      $shop = !empty($docArr)?$docArr['shop']:$this->app->DB->Select("SELECT shop FROM auftrag WHERE id='$id' LIMIT 1");
      if($shop > 0) {
        return;
      }
    }

    if($vertrieb<=0 || $vertrieb=='' || $vertrieb=='0') {
      // pruefe ob es innendienst verantwortlichen gib
      $adresse = !empty($docArr)?$docArr['adresse']:$this->app->DB->Select("SELECT adresse FROM $module WHERE id='$id' LIMIT 1");

      $vertrieb = empty($adresse)?null:$this->app->DB->Select("SELECT vertrieb FROM adresse WHERE id='$adresse' LIMIT 1");
      $vertrieb_name = empty($vertrieb)?null: $this->app->DB->Select("SELECT name FROM adresse WHERE id='$vertrieb' LIMIT 1");

      if($vertrieb_name!='' && $vertrieb_name!='0') {
        $this->app->DB->Update(
          sprintf(
            "UPDATE `%s` 
            SET vertriebid=%d,vertrieb='%s' 
            WHERE id=%d 
            LIMIT 1",
            $module, $vertrieb, $this->app->DB->real_escape_string($vertrieb_name), $id
          )
        );
      }
      else {
        $checktmp = !empty($docArr)?$docArr['vertrieb']: $this->app->DB->Select("SELECT vertrieb FROM $module WHERE id='$id' LIMIT 1");
        if($checktmp=='' || $checktmp=='0') {
          if($vertrieb<=0) {
            $vertrieb = $this->app->User->GetAdresse(); // falls kein vertrieb in der adresse definiert ist kriegt es der der angelegt war
          }
          $this->app->DB->Update(
            sprintf(
              "UPDATE `%s` 
              SET vertriebid=%d, vertrieb='%s' 
              WHERE id=%d
              LIMIT 1",
              $module, $vertrieb, $this->app->DB->real_escape_string($this->app->User->GetName()), $id
            )
          );
        }
      }
    }
    else if (is_numeric($vertrieb)) {
      $vertrieb_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='".$vertrieb."' LIMIT 1");
      $this->app->DB->Update(
        sprintf(
          "UPDATE `%s` SET vertrieb='%s',vertriebid=%d WHERE id=%d LIMIT 1",
          $module, $this->app->DB->real_escape_string($vertrieb_name), $vertrieb, $id
        )
      );
    }
  }

  // @refactor Document Komponente
  function CheckBuchhaltung($id,$module)
  {
    $buchhaltung = $this->app->DB->Select("SELECT buchhaltung FROM $module WHERE id='$id' LIMIT 1");
    if($buchhaltung=="")
      $this->app->DB->Update("UPDATE $module SET buchhaltung='".$this->app->User->GetName()."' WHERE id='$id' LIMIT 1");
    else if (is_numeric($buchhaltung))
    {
      $buchhaltung = $this->app->DB->Select("SELECT name FROM adresse WHERE id='".$buchhaltung."' LIMIT 1");
      $this->app->DB->Update("UPDATE $module SET bearbeiter='".$buchhaltung."' WHERE id='$id' LIMIT 1");
    }
  }

  // @refactor in Lager Modul
  function GetArtikelStandardlager($artikel,$send_id=false)
  {
    if($send_id)
    {
      $standardlager = $this->app->DB->Select("SELECT a.lager_platz FROM artikel a INNER JOIN lager_platz lp ON lp.id=a.lager_platz
        WHERE lp.id > 0 AND lp.kurzbezeichnung!='' AND a.id='".$artikel."' LIMIT 1");
      if($standardlager <=0)
      {
        //lagerplatz wo am meisten drinnen ist
        $lagerbezeichnung = $this->app->DB->Select("SELECT lp.id FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz
          WHERE lpi.artikel='".$artikel."' AND lp.autolagersperre!=1 AND lp.sperrlager!='1' ORDER by lpi.menge DESC LIMIT 1");
      } else {
        $lagerbezeichnung = $this->app->DB->Select("SELECT id FROM lager_platz WHERE id='".$standardlager."' LIMIT 1");
      }
      return $lagerbezeichnung;

    } else {
      $standardlager = $this->app->DB->Select("SELECT a.lager_platz FROM artikel a INNER JOIN lager_platz lp ON lp.id=a.lager_platz
        WHERE lp.id > 0 AND lp.kurzbezeichnung!='' AND a.id='".$artikel."' LIMIT 1");
      if($standardlager <=0)
      {
        //lagerplatz wo am meisten drinnen ist
        $lagerbezeichnung = $this->app->DB->Select("SELECT lp.kurzbezeichnung FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz
          WHERE lpi.artikel='".$artikel."' AND lp.autolagersperre!=1 AND lp.sperrlager!='1' ORDER by lpi.menge DESC LIMIT 1");
      } else {
        $lagerbezeichnung = $this->app->DB->Select("SELECT kurzbezeichnung FROM lager_platz WHERE id='".$standardlager."' LIMIT 1");
      }
      return $lagerbezeichnung;
    }
  }

  // @refactor in Etiketten Modul
  function LieferscheinPositionenDrucken($lieferschein,$etiketten_drucker,$etiketten_art,$etiketten_sort=0)
  {
    /** @var Etiketten $obj */
    $obj = $this->LoadModul('etiketten');
    if(!empty($obj) && method_exists($obj, 'LieferscheinPositionenDrucken')) {
      $obj->LieferscheinPositionenDrucken($lieferschein,$etiketten_drucker,$etiketten_art,$etiketten_sort);
    }
  }


  // @refactor Document Komponente
  function MessageHandlerStandardForm()
  {
    $module = $this->app->Secure->GetGET("module");
    $id = $this->app->Secure->GetGET("id");

    if($this->app->Secure->GetPOST("speichern")!="")
    {
      if($this->app->Secure->GetGET("msg")=="")
      {
        $msg = $this->app->Secure->GetGET("msg");
        $msg = $msg.$this->app->Tpl->Get('MESSAGE');
        $msg = base64_encode($msg);
      } else {
        $msg = $this->app->Secure->GetGET("msg");
      }
      $msgid = (int)$this->app->Secure->GetGET("msgid");
      header("Location: index.php?module=$module&action=edit&id=$id&msg=$msg".($msgid>0?"&msgid=$msgid":''));
      exit;
    }


  }

  // @refactor in Secure oder StringCleaner Klasse
  function superentities( $str ){
    // get rid of existing entities else double-escape

    $str = html_entity_decode(stripslashes($str),ENT_QUOTES| ENT_HTML5,'UTF-8');
    //              $str = str_replace("'","&apos;",$str);
    //                              return $str;
    $ar = preg_split('/(?<!^)(?!$)/u', $str );  // return array of every multi-byte character
    foreach ($ar as $c){
      $o = ord($c);
      if ( (strlen($c) > 1) || /* multi-byte [unicode] */
          ($o <32 || $o > 126) || /* <- control / latin weirdos -> */
          ($o >33 && $o < 35) ||/* quotes + ambersand */
          ($o >35 && $o < 40) ||/* quotes + ambersand */
          ($o >59 && $o < 63) /* html */
         ) {
        // convert to numeric entity
        //$c = @mb_encode_numericentity($c,array (0x0, 0xffff, 0, 0xffff), 'UTF-8');
        $c = $this->convertToHtml($c);
      }
      if(!isset($str2))$str2 = '';
      $str2 .= $c;
    }
    return $str2;
  }

  // @refactor in Secure oder StringCleaner Klasse
  function convertToHtml($str) {
    //                  $str = utf8_decode($str);
    //              $trans_tbl = get_html_translation_table (HTML_ENTITIES,ENT_HTML5);
    if (version_compare(PHP_VERSION, '5.3.4') >= 0) {
      $trans_tbl = array_flip(get_html_translation_table(HTML_ENTITIES, ENT_COMPAT, 'UTF-8'));
    } else {
      $trans_tbl = array_flip(get_html_translation_table(HTML_ENTITIES, ENT_COMPAT));
      if (!empty($trans_tbl)) {
        foreach ($trans_tbl as $key => $entry) {
          $trans_tbl[$key] = utf8_encode($entry);
        }
      }
    }

    // MS Word strangeness..
    // smart single/ double quotes:
    $trans_tbl[chr(39)] = '&apos;';
    $trans_tbl[chr(145)] = '\'';
    $trans_tbl[chr(146)] = '\'';
    //$trans_tbl[chr(147)] = '&quot;';
    $trans_tbl[chr(148)] = '&quot;';
    $trans_tbl[chr(142)] = '&eacute;';
    //&#65279;
    //$trans_tbl[$this->unicode_chr(65279)] = "BENE";
    //$str = str_replace("\xFF\xFE", "BENE", $str);


    return strtr ($str, $trans_tbl);
  }

  // @refactor Installer Komponente
  function InitialSetup()
  {
    //pruefe ob es bereits daten gibt
    //$this->app->DB->Select("LOCK TABLES adresse WRITE;");
    if($this->app->DB->Select("SELECT COUNT(id) FROM adresse WHERE geloescht!=1")<=0)
    {
      $mitarbeiternummer = $this->GetNextMitarbeiternummer();

      $sql = 'INSERT INTO `adresse` (`id`, `typ`, `marketingsperre`, `trackingsperre`, `rechnungsadresse`, `sprache`, `name`, `abteilung`, `unterabteilung`, `ansprechpartner`, `land`, `strasse`, `ort`, `plz`, `telefon`, `telefax`, `mobil`, `email`, `ustid`, `ust_befreit`, `passwort_gesendet`, `sonstiges`, `adresszusatz`, `kundenfreigabe`, `steuer`, `logdatei`, `kundennummer`, `lieferantennummer`, `mitarbeiternummer`, `konto`, `blz`, `bank`, `inhaber`, `swift`, `iban`, `waehrung`, `paypal`, `paypalinhaber`, `paypalwaehrung`, `projekt`, `partner`, `geloescht`, `firma`) VALUES (NULL, \'\', \'\', \'\', \'\', \'\', \'Administrator\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', NOW(), \'\', \'\', \''.$mitarbeiternummer.'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'1\', \'\', \'\', \'1\');';
      $this->app->DB->InsertWithoutLog($sql);
      $adresse = $this->app->DB->GetInsertID();

      $sql = "INSERT INTO `adresse_rolle` (`id`, `adresse`, `projekt`, `subjekt`, `praedikat`, `objekt`, `parameter`, `von`, `bis`) VALUES
        ('', '$adresse', 0, 'Mitarbeiter', '', '', '', NOW(), '0000-00-00');";
      $this->app->DB->InsertWithoutLog($sql);

      $sql = 'INSERT INTO `firma` (`id`, `name`, `standardprojekt`) VALUES (NULL, \'Musterfirma\', \'1\');';
      $this->app->DB->InsertWithoutLog($sql);

      $salt = hash('sha512', microtime(true));
      $sha512 = hash('sha512', 'admin' . $salt);
      $sql = 'INSERT INTO `user` (`id`, `username`, `password`, `repassword`, `salt`, `passwordsha512`, `description`, `settings`, `parentuser`, `activ`, `type`, `adresse`, `standarddrucker`, `firma`, `logdatei`,`externlogin`) VALUES (NULL, \'admin\', \'\', \'\', \'' . $salt . '\', \'' . $sha512 . '\', NULL, \'\', NULL, \'1\', \'admin\', \''.$adresse.'\', \'\', \'1\', NOW(),\'1\');';
      $this->app->DB->InsertWithoutLog($sql);

      $sql = 'INSERT INTO `projekt` (`id`, `name`, `abkuerzung`, `verantwortlicher`, `beschreibung`, `sonstiges`, `aktiv`, `farbe`, `autoversand`, `checkok`, `checkname`, `zahlungserinnerung`, `zahlungsmailbedinungen`, `folgebestaetigung`, `kundenfreigabe_loeschen`, `autobestellung`, `firma`, `logdatei`) VALUES (NULL, \'Hauptprojekt\', \'HAUPTPROJEKT\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'\', \'1\', \'\');';
      $this->app->DB->InsertWithoutLog($sql);
    }
    //$this->app->DB->Select("UNLOCK TABLES;");
  }

  // @refactor in Lager Modul
  function ValidLager($lager)
  {
    $result = $this->app->DB->Select("SELECT id FROM lager_platz WHERE id='$lager' LIMIT 1");
    return $result > 0?1:0;
  }

  // @refactor in Artikel Modul
  function ValidArtikelID($artikel)
  {
    if($artikel<=0 || $artikel=="" || !is_numeric($artikel)){
      return 0;
    }

    $result = $this->app->DB->Select("SELECT id FROM artikel WHERE id='$artikel' LIMIT 1");
    return $result > 0?1:0;
  }

  // @refactor in Artikel Modul
  function ValidArtikelnummer($artikel)
  {
    if($artikel<=0 || $artikel=="")
      return 0;

    $result = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikel' LIMIT 1");
    if($result > 0)
      return 1;

    $result = $this->app->DB->Select("SELECT id FROM artikel WHERE id='$artikel' LIMIT 1");
    if($result > 0)
      return 1;

    $result = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='$artikel' LIMIT 1");
    if($result > 0)
      return 1;

    return 0;
  }


  // @refactor in UserPermission Komponente

  /**
   * @return string
   */
  public function ProjektleiterRechte()
  {

    // alle projekte Wo Mitarbeiter ist
    $result = $this->app->DB->SelectArr(
      sprintf(
        "SELECT DISTINCT parameter 
        FROM adresse_rolle 
        WHERE subjekt='Projektleiter' AND (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis < NOW()) 
          AND adresse=%d",
        $this->app->User->GetAdresse()
      )
    );
    //if($sql!="" && (!empty($result)?count($result):0)>0) $sql .= " OR ";
    if(empty($result)) {
      return '';
    }
    $cResult = (!empty($result)?count($result):0);
    $sql = '';
    for($i=0;$i<$cResult;$i++) {
      $sql .= "p.id='".$result[$i]['parameter']."'";
      if($i < $cResult - 1){
        $sql .= ' OR ';
      }
    }

    return " AND ($sql) ";
  }

  // @refactor in UserPermission Komponente

  /**
   * @param int $projekt
   *
   * @return bool
   */
  public function UserProjektRecht($projekt)
  {
    if($projekt <= 0) {
      return true;
    }
    if($this->app->User->GetType()==='admin') {
      return true;
    }
    if($this->Projektdaten($projekt, 'oeffentlich')) {
      return true;
    }
    if($this->Firmendaten('onlyemployeeprojects')) {
      return  $this->app->DB->Select(
        sprintf(
          "SELECT id 
          FROM adresse_rolle 
          WHERE (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis <= CURDATE()) AND adresse = %d 
                AND (parameter = '' OR parameter = '0' OR parameter = '%d')
                AND objekt LIKE 'projekt' AND subjekt = 'Mitarbeiter'
           LIMIT 1",
          $this->app->User->GetAdresse(), $projekt
        )
      ) > 0;
    }

    return $this->app->DB->Select(
        sprintf(
          "SELECT id 
          FROM adresse_rolle 
          WHERE (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis <= CURDATE()) AND adresse = %d 
                AND (parameter = '' OR parameter = '0' OR parameter = '%d')
                AND objekt LIKE 'projekt'
           LIMIT 1",
          $this->app->User->GetAdresse(), $projekt
        )
      ) > 0;
  }

  // @refactor in UserPermission Komponente

  /**
   * @param string $prefix
   * @param bool   $cache
   * @param string $prefixvertreter
   * @param bool   $auchprojekte
   * @param string $subsql
   *
   * @return string
   */
  public function ProjektRechte($prefix='p.id', $cache = true, $prefixvertreter = '', $auchprojekte = false, $subsql='')
  {
    $db = $this->app->Conf->WFdbname;
    if($this->app->User->GetType()==='admin') {
      return '';
    }

    $addressId = (int)$this->app->User->GetAdresse();

    if($cache && !empty($this->cache[$db]) && !empty($this->cache[$db]['projectall_by_user'])
      && isset($this->cache[$db]['projectall_by_user'][$addressId])
    ) {
      $resultalle = $this->cache[$db]['projectall_by_user'][$addressId];
    }
    else{
      // wenn mitarbeiter projektleiter für alles     dann darf man alles sehen
      if($this->Firmendaten('onlyemployeeprojects')){
        $resultalle = $this->app->DB->Select(
          sprintf(
            "SELECT id 
            FROM adresse_rolle 
            WHERE (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis > NOW()) AND adresse= %d 
            AND (parameter='' OR parameter='0') AND objekt LIKE 'projekt' AND subjekt = 'Mitarbeiter'
            LIMIT 1",
            $addressId
          )
        );
      }else{
        $resultalle = $this->app->DB->Select(
          sprintf(
            "SELECT id 
            FROM adresse_rolle 
            WHERE (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis > NOW()) AND adresse= %d 
            AND (parameter='' OR parameter='0') AND objekt LIKE 'projekt'
            LIMIT 1",
            $addressId
          )
        );
      }
      if($cache){
        $this->cache[$db]['projectall_by_user'][$addressId] = (int)$resultalle;
      }
    }
    if($resultalle > 0) {
      return '';
    }

    if($cache && !empty($this->cache) && isset($this->cache[$db]['projektoeffentlich'])) {
      $result = $this->cache[$db]['projektoeffentlich'];
    }
    else{
    // alle oeffentlichen projekte
      $result = $this->app->DB->SelectArr('SELECT id FROM projekt WHERE oeffentlich=1');
      if($cache) {
        $this->cache[$db]['projektoeffentlich'] = $result;
      }
    }
    $cresult = !empty($result)?count($result):0;
    for($i=0;$i<$cresult;$i++) {
      if(!isset($sql)) {
        $sql = '';
      }
      $sql .= $prefix."='".$result[$i]['id']."'";
      if($i < $cresult - 1){
        $sql .= ' OR ';
      }
    }

    if($cache && !empty($this->cache[$db]) && !empty($this->cache[$db]['projects_employee'])
      && isset($this->cache[$db]['projects_employee'][$addressId])
    ) {
      $result = $this->cache[$db]['projects_employee'][$addressId];
    }
    else{
      // alle projekte Wo Mitarbeiter ist
      if($this->Firmendaten('onlyemployeeprojects')){
        $result = $this->app->DB->SelectArr(
          sprintf(
            "SELECT DISTINCT parameter 
            FROM adresse_rolle 
            WHERE (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis < NOW()) AND adresse=%d 
            AND objekt LIKE 'projekt' AND subjekt = 'Mitarbeiter'",
            $addressId
          )
        );
      }else{
        $result = $this->app->DB->SelectArr(
          sprintf(
            "SELECT DISTINCT parameter 
            FROM adresse_rolle 
            WHERE (IFNULL(bis,'0000-00-00')='0000-00-00' OR bis < NOW()) AND adresse=%d AND objekt LIKE 'projekt'",
            $addressId
          )
        );
      }
      if($cache) {
        if($result === null) {
          $result = [];
        }
        $this->cache[$db]['projects_employee'][$addressId] = $result;
      }
    }

    $cresult = !empty($result)?count($result):0;
    if(isset($sql) && $sql!='' && $cresult > 0) {
      $sql .= ' OR ';
    }

    for($i=0;$i<$cresult;$i++) {
      if(!isset($sql)) {
        $sql = '';
      }
      $sql .= $prefix."='".$result[$i]['parameter']."'";
      if($i < (!empty($result)?count($result):0) - 1){
        $sql .= ' OR ';
      }
    }
    if(!isset($sql)) {
      $sql = '0';
    }
    if($auchprojekte && is_array($auchprojekte)) {
      foreach($auchprojekte as $v) {
        $sql .= " OR $prefix = '$v' ";
      }
    }
    if($prefixvertreter && !$this->ModulVorhanden('vertriebscockpit')) {
      $prefixvertreter = '';
    }
    if($prefixvertreter != '') {
      return " AND ($sql OR $prefixvertreter = '".$addressId."' $subsql) ";
    }

    return " AND ($sql $subsql) ";
  }

  // @refactor DocumentContext Komponente
  function StandardVersandart($projekt="")
  {
    if($projekt > 0)
    {
      $tmp = $this->app->DB->Select("SELECT versandart FROM projekt WHERE id='$projekt' LIMIT 1");
      if($tmp != '') {
        return $tmp;
      }
    }

    return $this->Firmendaten('versandart');
  }

  // @refactor DocumentContext Komponente
  function StandardZahlungsweiseLieferant($projekt="")
  {
    if($projekt > 0) {
      $tmp = $this->app->DB->Select("SELECT zahlungsweiselieferant FROM projekt WHERE id='$projekt' LIMIT 1");
      if($tmp != '') {
        return $tmp;
      }
    }

    $tmp = $this->Firmendaten('zahlungsweiselieferant');
    if($tmp != '') {
      return $tmp;
    }

    return 'rechnung';
  }

  // @refactor DocumentContext Komponente
  function StandardZahlungsweise($projekt="")
  {
    if($projekt > 0) {
      $tmp = $this->app->DB->Select("SELECT zahlungsweise FROM projekt WHERE id='$projekt' LIMIT 1");
      if($tmp != '') {
        return $tmp;
      }
    }

    $tmp = $this->Firmendaten('zahlungsweise');

    return empty($tmp)?'rechnung':$tmp;
  }

  // @refactor DocumentContext Komponente
  function ZahlungsZielSkonto($projekt="")
  {
    $tmp = $this->Firmendaten("zahlungszielskonto");

    return $tmp <= 0?0:$tmp;
  }

  // @refactor DocumentContext Komponente
  function ZahlungsZielTageSkonto($projekt="")
  {
    $tmp = $this->Firmendaten("zahlungszieltageskonto");

    return $tmp <= 0?0:$tmp;
  }

  // @refactor DocumentContext Komponente
  function ZahlungsZielTage($projekt="")
  {
    $tmp = $this->Firmendaten("zahlungszieltage");

    return $tmp <= 0?0:$tmp;
  }

  // @refactor ApplicationCore Klasse

  /**
   * @param string $module
   * @param bool   $showdeactivated
   *
   * @return bool
   */
  public function ModulVorhanden($module, $showdeactivated = false)
  {
    if(in_array($module, ['welcome', 'ajax', 'appstore'])) {
      return true;
    }
    if(!$showdeactivated) {
      /** @var Appstore $appstore */
      $appstore = $this->app->loadModule('appstore', false);
      if(!empty($appstore) && method_exists($appstore, 'isModuleDeactivated')
        && $appstore->isModuleDeactivated($module)
      ) {
        return false;
      }
    }

    if(isset($this->modulvorhandenlist) && $this->modulvorhandenlist && isset($this->modulvorhandenlist[$module])) {
      return (bool)$this->modulvorhandenlist[$module];
    }
    if($module==='verband') {
      if($this->Firmendaten('modul_verband')!='1') {
        $this->modulvorhandenlist[$module] = false;
        return false;
      }
    }
    else if($module==='multilevel') {
      if($this->Firmendaten('modul_mlm')!='1') {
        $this->modulvorhandenlist[$module] = false;
        return false;
      }
    }
    else if($module==='verein') {
      if($this->Firmendaten('modul_verein')!='1') {
        $this->modulvorhandenlist[$module] = false;
        return false;
      }
    }

    $subdir = '/../pages/';
    $modulefile = $module;
    $isModulePage = false;
    $isModuleCronjob = false;
    if(strpos($module, 'zahlungsweise_') === 0){
      $subdir = '/zahlungsweisen/';
      $modulefile = substr($module, 14);
    }
    elseif(strpos($module, 'versandarten_') === 0){
      $subdir = '/versandarten/';
      $modulefile = substr($module, 13);
    }
    elseif(strpos($module, 'cronjob_') === 0) {
      $subdir = '/../../cronjobs/';
      $modulefile = substr($module, 8);
      $isModuleCronjob = true;
    }
    elseif(strpos($module, 'konto_') === 0) {
      $subdir = '/../plugins/liveimport/'.substr($module, 6).'/';
      $modulefile = substr($module, 6);
    }
    elseif(strpos($module, 'Transfer') === 0) {
      $subdir = '/Transfer/'.$module.'/';
    }
    elseif(strpos($module, 'Printer') === 0) {
      $subdir = '/Printer/'.$module.'/';
    }
    else {
      $isModulePage = true;
    }

    if(!@is_file(__DIR__.$subdir.$modulefile.'.php')) {
      $this->modulvorhandenlist[$module] = false;
      return false;
    }

    $this->modulvorhandenlist[$module] = true;
    return true;
  }

  // @refactor in UserPermission Komponente

  /**
   * @param string $cmd
   *
   * @return bool
   */
  public function TableSearchAllowed($cmd)
  {
    $tmp = $this->app->YUI->TableSearch('',$cmd,'allowed');
    if(empty($tmp)) {
      return true; // dient nur vorruebergeben bis alle faelle in yui class umgestellt sind
    }

    foreach($tmp as $module=>$value) {
      if(empty($value)) {
        continue;
      }
      foreach($tmp[$module] as $action) {
        if($this->RechteVorhanden($module,$action)) {
          return true;
        }
      }
    }

    return false;
  }

  // @refactor in UserPermission Komponente

  /**
   * @return array
   */
  public function getUserModules()
  {
    if($this->app->User->GetType() === 'admin') {
      return [];
    }
    $modules = $this->app->DB->SelectFirstCols(
      sprintf(
        "SELECT `module` FROM `userrights` WHERE `user` = %d AND `module` <> '' AND `permission` = 1 GROUP BY `module`",
        $this->app->User->GetID()
      )
    );

    $deactivated = $this->app->DB->SelectFirstCols(
      "SELECT DISTINCT `module` FROM `module_status` WHERE `active` = 0 AND `module` <> ''"
    );
    if(!empty($deactivated)) {
      return array_diff($modules, $deactivated);
    }

    return $modules;
  }

  /**
   * @param string $module
   * @param string $action
   *
   * @return bool
   */
  public function RechteVorhanden($module,$action)
  {
    if(empty($module) || empty($action)) {
      return false;
    }
    if(!@is_file('pages/'.$module.'.php') || !$this->ModulVorhanden($module)) {
      return false;
    }

    if($this->isActionExistsInModule($module,$action) === false) {
      return false;
    }

    if($this->app->User->GetType() === 'admin') {
      return true;
    }

    return (int)$this->app->DB->Select(
      sprintf(
        "SELECT ur.id 
        FROM `userrights` AS `ur`
        WHERE ur.module='%s' AND ur.action='%s' AND ur.permission=1 AND ur.user = %d 
        LIMIT 1",
        $this->app->DB->real_escape_string($module),
        $this->app->DB->real_escape_string($action),
        $this->app->User->GetID()
      )
    ) > 0;
  }

  /**
   * @param string $module
   * @param array  $actionList
   */
  public function addActionHandler($module, $actionList)
  {
    if(empty($module) || empty($actionList) || !is_array($actionList)) {
      return;
    }
    $actions = array_unique(array_keys($actionList));
    $actionsInDb = $this->getActionsByModule($module);
    $toDelete = array_diff($actionsInDb, $actions);
    if(!empty($toDelete)) {
      $this->deleteActionEntry($module, $toDelete);
    }
    $toAdd = array_diff($actions, $actionsInDb);
    if(empty($toAdd)) {
      return;
    }
    $this->addActionsToModule($module, $actions);
  }

  /**
   * @param string $module
   * @param array  $actions
   */
  public function addActionsToModule($module, $actions)
  {
    if(empty($module) || empty($actions)) {
      return;
    }
    foreach($actions as $action) {

	$sql = 
        sprintf(
          "INSERT INTO `module_action` (`module`,`action`) VALUES ('%s','%s') ON DUPLICATE KEY UPDATE `module`='%s', `action`='%s'",
          $this->app->DB->real_escape_string($module), $this->app->DB->real_escape_string($action),
          $this->app->DB->real_escape_string($module), $this->app->DB->real_escape_string($action)        
      );

      $this->app->DB->Insert(
	$sql
      );
      $this->moduleActions[$module][] = $action;
    }
  }

  /**
   * @param string $module
   * @param array  $actions
   */
  public function deleteActionEntry($module, $actions)
  {
    if(empty($module) || empty($actions)) {
      return;
    }
    foreach($actions as $action) {
      $this->app->DB->Delete(
        sprintf(
          "DELETE FROM `module_action` WHERE `module` = '%s' AND `action` = '%s'",
          $this->app->DB->real_escape_string($module), $this->app->DB->real_escape_string($action)
        )
      );
    }
    $this->moduleActions[$module] = array_diff($this->moduleActions[$module], $actions);
  }

  /**
   * @param string $module
   *
   * @return array
   */
  public function getActionsByModule($module)
  {
    if(empty($module)) {
      return [];
    }
    if(!isset($this->moduleActions[$module])) {
      $this->moduleActions[$module] = $this->app->DB->SelectFirstCols(
        sprintf(
          "SELECT DISTINCT `action` FROM `module_action` WHERE `module` = '%s' AND `action` <> ''",
          $this->app->DB->real_escape_string($module)
        )
      );
    }

    return $this->moduleActions[$module];
  }

  /**
   * @param string $module
   * @param string $action
   *
   * @return null|bool
   */
  public function isActionExistsInModule($module, $action)
  {
    $actions = $this->getActionsByModule($module);
    if(empty($actions)) {
      return null;
    }

    return in_array($action, $actions);
  }

  function fixeUmlaute($text) {
    return $this->app->String->fixeUmlaute($text);
  }

  function getUmlauteArray() {
    return $this->app->String->getUmlauteArray();
  }

  /**
   * @deprecated use directly htmlentities() instead
   */
  function ConvertForDBUTF8($string, $htmlentities = true, $isHtmlTransformation = false)
  {
    if(!$htmlentities || !$isHtmlTransformation) {
      return $string;
    }
    return htmlentities($string,ENT_QUOTES);
  }

  /**
   * @deprecated use directly htmlentities() and utf8_decode() instead
   */
  function ConvertForDB($string, $htmlentities = true, $isHtmlTransformation = false)
  {
    if(!$isHtmlTransformation) {
      return $string;
    }
    if(!$htmlentities) {
      return utf8_decode($string);
    }
    return htmlentities(utf8_decode($string),ENT_QUOTES);
  }

  function ConvertForTableSearch($string)
  {
    $string = $this->unicode_decode($string);
    $cmd = $this->app->Secure->GetGET('cmd');
    if($cmd==='kontoauszuege'){
      return trim(html_entity_decode($string, ENT_QUOTES, 'UTF-8')); //uahlungseingang
    }

    return $string;
  }

  // @refactor in HtmlTransformer Komponente
  function make_clickable($text)
  {
    return preg_replace('@(?<![.*">])\b(?:(?:https?|ftp|file)://|[a-z]\.)[-A-Z0-9+&#/%=~_|$?!:,.]*[A-Z0-9+&#/%=~_|$]@i', '<a href="\0">\0</a>', $text);
  }

  // @refactor in WawiString oder HtmlTransformer Klasse
  function unicode_decode($content) {
    $ISO10646XHTMLTrans = array(
        "&"."#34;" => "&quot;",
        "&"."#38;" => "&amp;",
        "&"."#39;" => "&apos;",
        "&"."#60;" => "&lt;",
        "&"."#62;" => "&gt;",
        "&"."#128;" => "&euro;",
        "&"."#160;" => "",
        "&"."#161;" => "&iexcl;",
        "&"."#162;" => "&cent;",
        "&"."#163;" => "&pound;",
        "&"."#164;" => "&curren;",
        "&"."#165;" => "&yen;",
        "&"."#166;" => "&brvbar;",
        "&"."#167;" => "&sect;",
        "&"."#168;" => "&uml;",
        "&"."#169;" => "&copy;",
        "&"."#170;" => "&ordf;",
        "&"."#171;" => "&laquo;",
        "&"."#172;" => "&not;",
        "&"."#173;" => "­",
        "&"."#174;" => "&reg;",
        "&"."#175;" => "&macr;",
        "&"."#176;" => "&deg;",
        "&"."#177;" => "&plusmn;",
        "&"."#178;" => "&sup2;",
        "&"."#179;" => "&sup3;",
        "&"."#180;" => "&acute;",
        "&"."#181;" => "&micro;",
        "&"."#182;" => "&para;",
        "&"."#183;" => "&middot;",
        "&"."#184;" => "&cedil;",
        "&"."#185;" => "&sup1;",
        "&"."#186;" => "&ordm;",
        "&"."#187;" => "&raquo;",
        "&"."#188;" => "&frac14;",
        "&"."#189;" => "&frac12;",
        "&"."#190;" => "&frac34;",
        "&"."#191;" => "&iquest;",
        "&"."#192;" => "&Agrave;",
        "&"."#193;" => "&Aacute;",
        "&"."#194;" => "&Acirc;",
        "&"."#195;" => "&Atilde;",
        "&"."#196;" => "&Auml;",
        "&"."#197;" => "&Aring;",
        "&"."#198;" => "&AElig;",
        "&"."#199;" => "&Ccedil;",
        "&"."#200;" => "&Egrave;",
        "&"."#201;" => "&Eacute;",
        "&"."#202;" => "&Ecirc;",
        "&"."#203;" => "&Euml;",
        "&"."#204;" => "&Igrave;",
        "&"."#205;" => "&Iacute;",
        "&"."#206;" => "&Icirc;",
        "&"."#207;" => "&Iuml;",
        "&"."#208;" => "&ETH;",
        "&"."#209;" => "&Ntilde;",
        "&"."#210;" => "&Ograve;",
        "&"."#211;" => "&Oacute;",
        "&"."#212;" => "&Ocirc;",
        "&"."#213;" => "&Otilde;",
        "&"."#214;" => "&Ouml;",
        "&"."#215;" => "&times;",
        "&"."#216;" => "&Oslash;",
        "&"."#217;" => "&Ugrave;",
        "&"."#218;" => "&Uacute;",
        "&"."#219;" => "&Ucirc;",
        "&"."#220;" => "&Uuml;",
        "&"."#221;" => "&Yacute;",
        "&"."#222;" => "&THORN;",
        "&"."#223;" => "&szlig;",
        "&"."#224;" => "&agrave;",
        "&"."#225;" => "&aacute;",
        "&"."#226;" => "&acirc;",
        "&"."#227;" => "&atilde;",
        "&"."#228;" => "&auml;",
        "&"."#229;" => "&aring;",
        "&"."#230;" => "&aelig;",
        "&"."#231;" => "&ccedil;",
        "&"."#232;" => "&egrave;",
        "&"."#233;" => "&eacute;",
        "&"."#234;" => "&ecirc;",
        "&"."#235;" => "&euml;",
        "&"."#236;" => "&igrave;",
        "&"."#237;" => "&iacute;",
        "&"."#238;" => "&icirc;",
        "&"."#239;" => "&iuml;",
        "&"."#240;" => "&eth;",
        "&"."#241;" => "&ntilde;",
        "&"."#242;" => "&ograve;",
        "&"."#243;" => "&oacute;",
        "&"."#244;" => "&ocirc;",
        "&"."#245;" => "&otilde;",
        "&"."#246;" => "&ouml;",
        "&"."#247;" => "&divide;",
        "&"."#248;" => "&oslash;",
        "&"."#249;" => "&ugrave;",
        "&"."#250;" => "&uacute;",
        "&"."#251;" => "&ucirc;",
        "&"."#252;" => "&uuml;",
        "&"."#253;" => "&yacute;",
        "&"."#254;" => "&thorn;",
        "&"."#255;" => "&yuml;",
        "&"."#338;" => "&OElig;",
        "&"."#339;" => "&oelig;",
        "&"."#352;" => "&Scaron;",
        "&"."#353;" => "&scaron;",
        "&"."#376;" => "&Yuml;",
        "&"."#402;" => "&fnof;",
        "&"."#710;" => "&circ;",
        "&"."#732;" => "&tilde;",
        "&"."#913;" => "&Alpha;",
        "&"."#914;" => "&Beta;",
        "&"."#915;" => "&Gamma;",
        "&"."#916;" => "&Delta;",
        "&"."#917;" => "&Epsilon;",
        "&"."#918;" => "&Zeta;",
        "&"."#919;" => "&Eta;",
        "&"."#920;" => "&Theta;",
        "&"."#921;" => "&Iota;",
        "&"."#922;" => "&Kappa;",
        "&"."#923;" => "&Lambda;",
        "&"."#924;" => "&Mu;",
        "&"."#925;" => "&Nu;",
        "&"."#926;" => "&Xi;",
        "&"."#927;" => "&Omicron;",
        "&"."#928;" => "&Pi;",
        "&"."#929;" => "&Rho;",
        "&"."#931;" => "&Sigma;",
        "&"."#932;" => "&Tau;",
        "&"."#933;" => "&Upsilon;",
        "&"."#934;" => "&Phi;",
        "&"."#935;" => "&Chi;",
        "&"."#936;" => "&Psi;",
        "&"."#937;" => "&Omega;",
        "&"."#945;" => "&alpha;",
        "&"."#946;" => "&beta;",
        "&"."#947;" => "&gamma;",
        "&"."#948;" => "&delta;",
        "&"."#949;" => "&epsilon;",
        "&"."#950;" => "&zeta;",
        "&"."#951;" => "&eta;",
        "&"."#952;" => "&theta;",
        "&"."#953;" => "&iota;",
        "&"."#954;" => "&kappa;",
        "&"."#955;" => "&lambda;",
        "&"."#956;" => "&mu;",
        "&"."#957;" => "&nu;",
        "&"."#958;" => "&xi;",
        "&"."#959;" => "&omicron;",
        "&"."#960;" => "&pi;",
        "&"."#961;" => "&rho;",
        "&"."#962;" => "&sigmaf;",
        "&"."#963;" => "&sigma;",
        "&"."#964;" => "&tau;",
        "&"."#965;" => "&upsilon;",
        "&"."#966;" => "&phi;",
        "&"."#967;" => "&chi;",
        "&"."#968;" => "&psi;",
        "&"."#969;" => "&omega;",
        "&"."#977;" => "&thetasym;",
        "&"."#978;" => "&upsih;",
        "&"."#982;" => "&piv;",
        "&"."#8194;" => "&ensp;",
        "&"."#8195;" => "&emsp;",
        "&"."#8201;" => "&thinsp;",
        "&"."#8204;" => "&zwnj;",
        "&"."#8205;" => "&zwj;",
        "&"."#8206;" => "&lrm;",
        "&"."#8207;" => "&rlm;",
        "&"."#8211;" => "&ndash;",
        "&"."#8212;" => "&mdash;",
        "&"."#8216;" => "&lsquo;",
        "&"."#8217;" => "&rsquo;",
        "&"."#8218;" => "&sbquo;",
        "&"."#8220;" => "&ldquo;",
        "&"."#8221;" => "&rdquo;",
        "&"."#8222;" => "&bdquo;",
        "&"."#8224;" => "&dagger;",
        "&"."#8225;" => "&Dagger;",
        "&"."#8226;" => "&bull;",
        "&"."#8230;" => "&hellip;",
        "&"."#8240;" => "&permil;",
        "&"."#8242;" => "&prime;",
        "&"."#8243;" => "&Prime;",
        "&"."#8249;" => "&lsaquo;",
        "&"."#8250;" => "&rsaquo;",
        "&"."#8254;" => "&oline;",
        "&"."#8260;" => "&frasl;",
        "&"."#8364;" => "&euro;",
        "&"."#8465;" => "&image;",
        "&"."#8472;" => "&weierp;",
        "&"."#8476;" => "&real;",
        "&"."#8482;" => "&trade;",
        "&"."#8501;" => "&alefsym;",
        "&"."#8592;" => "&larr;",
        "&"."#8593;" => "&uarr;",
        "&"."#8594;" => "&rarr;",
        "&"."#8595;" => "&darr;",
        "&"."#8596;" => "&harr;",
        "&"."#8629;" => "&crarr;",
        "&"."#8656;" => "&lArr;",
        "&"."#8657;" => "&uArr;",
        "&"."#8658;" => "&rArr;",
        "&"."#8659;" => "&dArr;",
        "&"."#8660;" => "&hArr;",
        "&"."#8704;" => "&forall;",
        "&"."#8706;" => "&part;",
        "&"."#8707;" => "&exist;",
        "&"."#8709;" => "&empty;",
        "&"."#8711;" => "&nabla;",
        "&"."#8712;" => "&isin;",
        "&"."#8713;" => "&notin;",
        "&"."#8715;" => "&ni;",
        "&"."#8719;" => "&prod;",
        "&"."#8721;" => "&sum;",
        "&"."#8722;" => "&minus;",
        "&"."#8727;" => "&lowast;",
        "&"."#8730;" => "&radic;",
        "&"."#8733;" => "&prop;",
        "&"."#8734;" => "&infin;",
        "&"."#8736;" => "&ang;",
        "&"."#8743;" => "&and;",
        "&"."#8744;" => "&or;",
        "&"."#8745;" => "&cap;",
        "&"."#8746;" => "&cup;",
        "&"."#8747;" => "&int;",
        "&"."#8756;" => "&there4;",
        "&"."#8764;" => "&sim;",
        "&"."#8773;" => "&cong;",
        "&"."#8776;" => "&asymp;",
        "&"."#8800;" => "&ne;",
        "&"."#8801;" => "&equiv;",
        "&"."#8804;" => "&le;",
        "&"."#8805;" => "&ge;",
        "&"."#8834;" => "&sub;",
        "&"."#8835;" => "&sup;",
        "&"."#8836;" => "&nsub;",
        "&"."#8838;" => "&sube;",
        "&"."#8839;" => "&supe;",
        "&"."#8853;" => "&oplus;",
        "&"."#8855;" => "&otimes;",
        "&"."#8869;" => "&perp;",
        "&"."#8901;" => "&sdot;",
        "&"."#8968;" => "&lceil;",
        "&"."#8969;" => "&rceil;",
        "&"."#8970;" => "&lfloor;",
        "&"."#8971;" => "&rfloor;",
        "&"."#9001;" => "&lang;",
        "&"."#9002;" => "&rang;",
        "&"."#9674;" => "&loz;",
        "&"."#9824;" => "&spades;",
        "&"."#9827;" => "&clubs;",
        "&"."#9829;" => "&hearts;",
        "&"."#9830;" => "&diams;"
          );


    reset($ISO10646XHTMLTrans);
//    while(list($UnicodeChar, $XHTMLEquiv) = each($ISO10646XHTMLTrans)) {
    foreach($ISO10646XHTMLTrans as $UniccideChar => $XHTMLEquiv) 
    {
      $content = str_replace($UnicodeChar, $XHTMLEquiv, $content);
    }

    //      $content = html_entity_decode($content, ENT_COMPAT, 'UTF-8');

    // return translated
    return($content);
  }

  /** @deprecated */
  function html_entity_decode_utf8($string)
  {
    static $trans_tbl;
    $string = preg_replace('~&#x([0-9a-f]+);~ei','code2utf(hexdec(“\\1″))', $string);
    $string = preg_replace('~&#([0-9]+);~e', 'code2utf(\\1)',$string);

    if (!isset($trans_tbl))
    {
      $trans_tbl = array();
      foreach (get_html_translation_table(HTML_ENTITIES) as
          $val=>$key)
        $trans_tbl[$key] = utf8_encode($val);
    }
    return strtr($string, $trans_tbl);
  }

  function GetPlainText($string)
  {
    /** @var $api $obj */
    $obj = $this->LoadModul('api');
    if(!empty($obj) && method_exists($obj, 'GetPlainText'))
    {
      return $obj->GetPlainText($string);
    }
  }

  // @refactor PdfHelper Komponente
  function MergePDF($files,$pdftk=0)
  {

    if($pdftk==1)
    {
      //PDF Dateien erstellen
      $pdffiles = implode(" ",$files);

      $tmpname = tempnam($this->GetTMP(),"");

      //echo("pdftk $pdffiles cat output ".$dir."/".$abrechnung.".pdf");

      system("pdftk $pdffiles cat output ".$tmpname);

      $raw_content = file_get_contents($tmpname);
      unlink($tmpname);
    } else {

      $Brief = new SuperFPDF('P','mm','A4');
      //$Brief->filename="merge.pdf";
      $cfiles = !empty($files)?count($files):0;
      for($i=0;$i<$cfiles;$i++)
      {
        $Brief->AddPDF(file_get_contents($files[$i]));
      }
      $raw_content = $Brief->displayAnhaenge('S');
    }
    return $raw_content;
  }

  // @refactor in WawiString oder HtmlTransformer Klasse
  function isHTML($string){
    return $string != strip_tags($string);
  }

  /**
   * @deprecated
   */
  function RemoveNewlineAfterBreaks($string)
  {
    return $string;
  }

  function ReadyForPDF($string="")
  {
    return $this->app->String->ReadyForPDF($string);
  }

  /**
   * @deprecated
   */
  function ColorPicker() {
    $colors = array('#004704','#C40046','#832BA8','#FF8128','#7592A0');

    $out = "<option value=\"\" style=\"background-color: #FFFFFF;color:red\">Keine</option>";
    for($i=0;$i<(!empty($colors)?count($colors):0);$i++)
      $out .= "<option value=\"{$colors[$i]}\" style=\"background-color: {$colors[$i]}\">".$colors[$i]."</option>";

    return $out;
  }

  // @refactor in DevTools
  function hex_dump($data, $newline="\n")
  {
    static $from = '';
    static $to = '';

    static $width = 16; # number of bytes per line

      static $pad = '.'; # padding for non-visible characters

      if ($from==='')
      {
        for ($i=0; $i<=0xFF; $i++)
        {
          $from .= chr($i);
          $to .= ($i >= 0x20 && $i <= 0x7E) ? chr($i) : $pad;
        }
      }

    $hex = str_split(bin2hex($data), $width*2);
    $chars = str_split(strtr($data, $from, $to), $width);

    $offset = 0;
    foreach ($hex as $i => $line)
    {
      echo sprintf('%6X',$offset).' : '.implode(' ', str_split($line,2)) . ' [' . $chars[$i] . ']' . $newline;
      $offset += $width;
    }
  }

  /**
   * @param string $parsetarget
   */
  public function KalenderList($parsetarget)
  {
    /** @var Kalender $obj */
    $obj = $this->LoadModul('kalender');
    if(!empty($obj) && method_exists($obj,'showKalenderList')) {
      $obj->showKalenderList($parsetarget);
    }
  }

  // @refactor UserPermission Komponente oder Navigation Widget
  function CalculateNavigation($navarray)
  {

    $type = $this->app->User->GetType();
    //if($type=="admin") return $navarray['menu']['admin'];

    $permissions_module = $this->app->DB->SelectArr("SELECT module,action FROM userrights WHERE user='".$this->app->User->GetID()."' AND permission='1'");
    $navigation_alternative = $this->app->DB->SelectArr("SELECT * FROM navigation_alternative WHERE aktiv = 1 AND first != '' AND module != '' AND action != '' AND sec != '' ORDER BY first, sec, prio");
    if($navigation_alternative)
    {
      foreach($navigation_alternative as $v)
      {
        $alt[$v['first']][$v['sec']][] = $v;
      }
    }
    $permission_module_new=null;
    if($permissions_module)
    {
      for($i=0;$i<(!empty($permissions_module)?count($permissions_module):0);$i++)
      {
        if(@is_file("./pages/".$permissions_module[$i]["module"].".php") && $this->ModulVorhanden($permissions_module[$i]["module"]))
          $permission_module_new[] = $permissions_module[$i]["module"]."_".$permissions_module[$i]["action"];
      }
    }

    // logout ist immer erlaubt
    $permission_module_new[] = "welcome_logout";

    $menu = 0;
    $menu_no=1;
    foreach($navarray['menu']['admin'] as $key=>$value){
      //echo "haupt:".$value['first'][0]."<br>";
      $menu++;
      if(count($value['sec'])>0){
        foreach($value['sec'] as $secnav){
          //echo $secnav[0]." ".$secnav[1]." ".$secnav[2]."<br>";
          $und_pos = stripos ( $secnav[2] , '&');
          if($und_pos>0)
            $secnav_check =  substr ( $secnav[2] , 0,stripos ( $secnav[2] , '&') );
          else
            $secnav_check = $secnav[2];

        // pruefe ob recht vorhanden
        if(@in_array($secnav[1]."_".$secnav_check,$permission_module_new) || ($type=="admin" && @is_file("./pages/".$secnav[1].".php") && $this->ModulVorhanden($secnav[1])))
        {
          $navarray['menu']['tmp'][$menu]['sec'][]  = array($secnav[0],$secnav[1],$secnav[2]);
          $menu_no=0;
        }elseif(isset($alt) && isset($alt[$value['first'][0]]) && isset($alt[$value['first'][0]][$secnav[0]])){
          foreach($alt[$value['first'][0]][$secnav[0]] as $v)
          {
            $und_pos = stripos ( $v['action'] , '&');
            if($und_pos>0)
              $secnav_check =  substr ( $v['action'] , 0,stripos ( $v['action'] , '&') );
            else
              $secnav_check = $v['action'];

            if(@in_array($v['module']."_".$secnav_check,$permission_module_new) || ($type=="admin" && @is_file("./pages/".$v['module'].".php")))
            {
              $navarray['menu']['tmp'][$menu]['sec'][]  = array($secnav[0],$v['module'],$v['action']);
              $menu_no = 0;
              break;
            }
          }
        }else{

        }
      }
    }
    if($menu_no==0)
      $navarray['menu']['tmp'][$menu]['first'] = array($value['first'][0],$value['first'][1],'main');
    $menu_no=1;

    }

    return $navarray['menu']['tmp'];
  }

  // @refactor Navigation Widget
  function NavigationENT()
  {
    return $this->Navigation();
  }

  // @refactor Navigation Widget
  function Navigation()
  {
    // admin menu
    $menu = 0;

    // ------ Stammdaten
    $navarray['menu']['admin'][++$menu]['first']  = array('Stammdaten','adresse','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Adressen','adresse','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Artikel','artikel','list');
    $navarray['menu']['admin'][$menu]['sec'][] = array('Projekte','projekt','list');

    // ------ Verkauf
    $navarray['menu']['admin'][++$menu]['first']  = array('Verkauf','auftrag','list');
    if($this->ModulVorhanden("anfrage")){
      $navarray['menu']['admin'][$menu]['sec'][] = array('Anfrage', 'anfrage', 'list');
    }
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Angebot'.($this->Firmendaten("bezeichnungangebotersatz") && $this->Firmendaten("bezeichnungangebotersatz") != 'Angebot'? ' / '.$this->Firmendaten("bezeichnungangebotersatz"):''),'angebot','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Auftrag','auftrag','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('POS','pos','list');

    // ------ Beschaffung
    $navarray['menu']['admin'][++$menu]['first']  = array('Beschaffung','auftrag','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Bestellung','bestellung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Bestellvorschlag','bestellvorschlag','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Preisanfrage','preisanfrage','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Produktion','produktion','list');

    // ------ Logistik
    $navarray['menu']['admin'][++$menu]['first'] = array('Logistik','lager','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Artikelkontingente','artikelkontingente','list');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Ein- und auslagern','lager','letztebewegungen');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Inventur','inventur','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Kommissionieraufkleber','kommissionieraufkleber','list');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Kommissionierung','kommissionierung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Lagermindestmengen','lagermindestmengen','list');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Lagerverwaltung','lager','list');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Lieferschein','lieferschein','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Mindesthaltbarkeit','mhdwarning','list');
    if($this->ModulVorhanden('lagermobil')) {
      $navarray['menu']['admin'][$menu]['sec'][]   = array('Mobile Lagerverwaltung','lagermobil','list');
    }
    if($this->ModulVorhanden('multiorderpicking')) {
      $navarray['menu']['admin'][$menu]['sec'][]  = array('Multiorder-Picking','multiorderpicking','list');
    }
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Produktionszentrum','produktionszentrum','list');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Reservierung','lager','reservierungen');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Versand','versandpakete','lieferungen');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Versandzentrum','versanderzeugen','offene');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Wareneingang','wareneingang','list');
    $navarray['menu']['admin'][$menu]['sec'][]   = array('Zwischenlager','lager','buchenzwischenlager');

    // ------ Buchhaltung
    $navarray['menu']['admin'][++$menu]['first']  = array('Buchhaltung','rechnung','list');

    $navarray['menu']['admin'][$menu]['sec'][]  = array('Abolauf','rechnungslauf','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Arbeitsnachweis','arbeitsnachweis','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Buchungen','fibu_buchungen','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Dokumenten Scanner','docscan','list');

    $navarray['menu']['admin'][$menu]['sec'][]  = array('Gutschriften / '.$this->Firmendaten("bezeichnungstornorechnung"),'gutschrift','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Kontoausz&uuml;ge','kontoauszuege','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Lieferantengutschriften','lieferantengutschrift','list');

    $navarray['menu']['admin'][$menu]['sec'][]  = array('Mahnwesen','mahnwesen','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Proformarechnung','proformarechnung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Rechnungen','rechnung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Reisekosten','reisekosten','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Finanzbuchhaltung Export','buchhaltungexport','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Verbandsabrechnungen','verband','offene');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Vertreterabrechnungen','vertreter','list');
    if ($this->ModulVorhanden('provisionenartikelvertreter'))
    {
      $navarray['menu']['admin'][$menu]['sec'][]  = array('Provisionen','provisionenartikelvertreter','list');
    } else {
      $navarray['menu']['admin'][$menu]['sec'][]  = array('Provisionen','provisionenartikel','list');
    }
    if($this->Firmendaten("modul_mlm")=="1"){
      $navarray['menu']['admin'][$menu]['sec'][] = array('Multilevel', 'multilevel', 'list');
    }
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Lohnabrechnung','lohnabrechnung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Verbindlichkeiten','verbindlichkeit','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Kassenbuch','kasse','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Zahlungseingang','zahlungseingang','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Zahlungsverkehr','zahlungsverkehr','ueberweisung');

    // ------ Controlling
    $navarray['menu']['admin'][++$menu]['first']  = array('Controlling','marketing','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Aktionscodes','aktionscodes','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Berichte','report','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Management Board','managementboard','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Statistiken','statistiken','dashboard');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Umsatzstatistik','umsatzstatistik','allgemein');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Verkaufszahlen','verkaufszahlen','list');

    // ------ Verwaltung
    $navarray['menu']['admin'][++$menu]['first']  = array('Verwaltung','rechnung','list');
    if(!$this->RechteVorhanden('mitarbeiterzeiterfassung','dashboard')){
      $navarray['menu']['admin'][$menu]['sec'][]  = array('Antrag einreichen','mitarbeiterzeiterfassung','timemanagementrequest');
    }
    else{
      $navarray['menu']['admin'][$menu]['sec'][]  = array('Mitarbeiterzeiterfassung','mitarbeiterzeiterfassung','dashboard');
    }
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Import/Export Zentrale','importvorlage','uebersicht');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Seriennummern','seriennummern','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Chargen','chargen','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('RMA Lieferungen','rma','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Service & Support','service','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Etikettendrucker','etikettendrucker','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('W&auml;hrungen','waehrungumrechnung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Ticketregeln','ticketregeln','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Zeitkonten','zeiterfassung','list');

    // ------ System
    $navarray['menu']['admin'][++$menu]['first']  = array('System','rechnung','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Einstellungen','einstellungen','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Online-Shops / Marktplätze','onlineshops','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Upgrade','upgrade','list','recover','delete','reset');

    // ------ Mein Bereich
    $navarray['menu']['admin'][++$menu]['first']  = array('Mein Bereich','welcome','main');
    $startseite = $this->app->DB->Select("SELECT startseite FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
    if($startseite!="") {
        $navarray['menu']['admin'][$menu]['sec'][]  = array('Meine Startseite','welcome','startseite');
    }
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Aufgaben','aufgaben','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Chat','chat','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Einstellungen','welcome','settings');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('E-Mail','webmail','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Kalender','kalender','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Interner Support', 'internalsupport', 'list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Pinnwand','welcome','pinwand');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Startseite','welcome','start');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Tickets','ticket','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Wiedervorlage','wiedervorlage','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Wiki','wiki','list');
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Zeiterfassung','zeiterfassung','create');

    foreach ($navarray['menu']['admin'] as $key => $menuitem) {
        usort($menuitem['sec'], function ($a, $b) {
          $a_val = $a[0];
          $b_val = $b[0];

          if($a_val > $b_val) return 1;
          if($a_val < $b_val) return -1;
          return 0;
        });
        $navarray['menu']['admin'][$key] = $menuitem;
    }

    // Always the last entry
    $navarray['menu']['admin'][$menu]['sec'][]  = array('Abmelden','welcome','logout');

    return $this->CalculateNavigation($navarray);
  }


// @refactor LicenceManager Komponente

  /**
   * @return string
   */
  public function Branch()
  {
    $version = 'OSS';
    include dirname(dirname(__DIR__)).'/version.php';
    switch($version) {
      case 'ENT':
        return 'Home';
      case 'OSS':
        return 'Open-Source';
      default:
        return 'Unknown';
    }
  }

// @refactor LicenceManager Komponente

  /**
   * @return string
   */
  public function Version()
  {
    $version = '';
    include dirname(dirname(__DIR__)).'/version.php';

    return $version;
  }


// @refactor LicenceManager Komponente
function RevisionPlain()
{
  include(dirname(dirname(__DIR__))."/version.php");
  return $version_revision;
}


// @refactor LicenceManager Komponente
function Revision()
{
  include(dirname(dirname(__DIR__))."/version.php");
  return $version_revision;
}


// @refactor In Wiki Modul
function WikiPage($page)
{
  $content = $this->app->DB->Select("SELECT content FROM wiki WHERE name='$page' LIMIT 1");
  $str = $this->ReadyForPDF($content);
  $wikiparser = new WikiParser();
  if (preg_match('/(<[^>].*?>)/e', $str))
  {
    $str=preg_replace('#(href)="([^:"]*)(?:")#','$1="index.php?module=wiki&action=list&name=$2"',$str);
    $content = $str;
  } else {
    $content = $wikiparser->parse($content);
    //$index = $wikiparser->BuildIndex();
  }
  return $content;
}

  /**
   * @param string $config
   *
   * @return array
   */
public function Config2Array($config)
{
  /** @var Konten $obj */
  $obj = $this->app->loadModule('konten', false);
  if($obj === null || !method_exists($obj, 'Config2Array')) {
    return [];
  }

  return $obj->Config2Array($config);
}


// @refactor Payment Komponente

  /**
   * @param int $konto
   *
   * @return string
   */
public function LiveImport($konto)
{
  $kontoRow = $this->app->DB->SelectRow(
    sprintf(
      'SELECT liveimport,liveimport_passwort,type 
      FROM konten 
      WHERE id=%d 
      LIMIT 1',
      $konto
    )
  );
  if(empty($kontoRow) || empty($kontoRow['type'])) {
    return '';
  }
  $zugangsdaten = $kontoRow['liveimport'];
  $zugangsdaten = html_entity_decode($zugangsdaten,ENT_QUOTES,'UTF-8');

  $liveimport_passwort = $kontoRow['liveimport_passwort'];
  if($liveimport_passwort!='') {
    $zugangsdaten = str_replace('{PASSWORT}',$liveimport_passwort,$zugangsdaten);
  }

  $zugangsdaten = $this->Config2Array($zugangsdaten);

  $kontotyp = $kontoRow['type'];
  if(!@is_file(dirname(__DIR__)."/plugins/liveimport/$kontotyp/$kontotyp.php")) {
    return '';
  }

  if(!class_exists($kontotyp)){
    include_once dirname(__DIR__) . "/plugins/liveimport/$kontotyp/$kontotyp.php";
  }
  if(!class_exists($kontotyp)) {
    return '';
  }

  $tmp = new $kontotyp();
  if(!method_exists($tmp,'Import')) {
    return '';
  }
  if($kontotyp === 'kasse'){
    return $tmp->Import($konto, $this->app);
  }
  if($kontotyp === 'hbci4phpapi'){
    return $tmp->Import($zugangsdaten, $konto, $this->app);
  }
  try {
    $r = new ReflectionMethod($tmp, 'Import');
    $params = $r->getParameters();
    $anzargs = (!empty($params)?count($params):0);
  }
  catch(Exception $e) {
    $anzargs = 1;
  }
  if($anzargs <= 1){
    return $tmp->Import($zugangsdaten);
  }
  if($anzargs == 2) {
    return $tmp->Import($zugangsdaten, $this->app);
  }

  return $tmp->Import($zugangsdaten, $konto, $this->app);
}


// @refactor PopupTable Widget
function AdresseAlsVerzollungsadresseButton($adresse, $postfix = "")
{
  $this->app->Tpl->Set('POPUPWIDTH',"1200");
  $this->app->Tpl->Set('ADRESSEVERZOLLUNGADRESSEPOPUP'.$postfix,'
      <script>
      $(function() {
        $("#mehr5'.$postfix.'").button();
        });
      function closeIframe()
      {
      $(\'.externalSite\').dialog(\'close\');
      return false;
      }
      </script>
      <a id="mehr5'.$postfix.'" style="font-size: 8pt; " href="index.php?module=adresse&action=adressestammdatenpopup&cmd=alsverzollungadresse&id='.$adresse.'&iframe=true'.($postfix?'&postfix='.$postfix:'').'" class="popup" title="Adresse aus Stammdaten einf&uuml;gen">aus Stammdaten</a>');
}

// @refactor PopupTable Widget
function AdresseAlsAnsprechpartner($adresse, $postfix = "")
{
  $this->app->Tpl->Set('POPUPWIDTH',"1200");
  $this->app->Tpl->Set('ADRESSEANSPRECHPARTNERPOPUP'.$postfix,'
      <script>
      $(function() {
        $("#mehr4'.$postfix.'").button();
        });
      function closeIframe()
      {
      $(\'.externalSite\').dialog(\'close\');
      return false;
      }
      </script>
      <a id="mehr4'.$postfix.'" style="font-size: 8pt; " href="index.php?module=adresse&action=adressestammdatenpopup&cmd=alsansprechpartner&id='.$adresse.'&iframe=true'.($postfix?'&postfix='.$postfix:'').'" class="popup" title="Adresse aus Stammdaten einf&uuml;gen">aus Stammdaten</a>');
}


// @refactor PopupTable Widget
function AdresseAlsLieferadresseButton($adresse, $postfix = "")
{
  $this->app->Tpl->Set('POPUPWIDTH',"1200");
  $this->app->Tpl->Set('ADRESSELIEFERADRESSEPOPUP'.$postfix,'
      <script>
      $(function() {
        $("#mehr4'.$postfix.'").button();
        });
      function closeIframe()
      {
      $(\'.externalSite\').dialog(\'close\');
      return false;
      }
      </script>
      <a id="mehr4'.$postfix.'" style="font-size: 8pt; " href="index.php?module=adresse&action=adressestammdatenpopup&cmd=alslieferadresse&id='.$adresse.'&iframe=true'.($postfix?'&postfix='.$postfix:'').'" class="popup" title="Adresse aus Stammdaten einf&uuml;gen">aus Stammdaten</a>');
}

// @refactor PopupTable Widget
function AnsprechpartnerAlsLieferadresseButton($adresse, $postfix = "")
{
  $this->app->Tpl->Set('POPUPWIDTH',"1200");
  $this->app->Tpl->Set('ANSPRECHPARTNERLIEFERADRESSEPOPUP'.$postfix,'
      <script>
      $(function() {
        $("#mehr3'.$postfix.'").button();
        });
      function closeIframe()
      {
      $(\'.externalSite\').dialog(\'close\');
      return false;
      }
      </script>
      <a id="mehr3'.$postfix.'" style="font-size: 8pt; " href="index.php?module=adresse&action=ansprechpartnerpopup&cmd=alslieferadresse&id='.$adresse.'&iframe=true'.($postfix?'&postfix='.$postfix:'').'" class="popup" title="Ansprechpartner als Lieferadresse einf&uuml;gen">Ansprechpartner</a>');
}



// @refactor PopupTable Widget
function LieferadresseButton($adresse, $postfix = "")
{
  $this->app->Tpl->Set('POPUPWIDTH',"1200");
  $this->app->Tpl->Set('LIEFERADRESSEPOPUP'.$postfix,'
      <script>
      $(function() {
        $("#mehr2'.$postfix.'").button();
        });

      function closeIframe()
      {
      $(\'.externalSite\').dialog(\'close\');
      return false;
      }

      </script>

      <a id="mehr2'.$postfix.'" style="font-size: 8pt; " href="index.php?module=adresse&action=lieferadressepopup&id='.$adresse.'&iframe=true'.($postfix?'&postfix='.$postfix:'').'" class="popup" title="Lieferadresse einf&uuml;gen">Lieferadresse</a>');

}

// @refactor Cache Komponente
function ClearSqlCache($shortcode, $seconds = 0)
{
  if($shortcode == '') {
    if($seconds > 0) {
      $this->app->DB->Delete(
        sprintf(
          "DELETE FROM sqlcache WHERE TIMESTAMPDIFF(SECOND,zeitstempel, NOW()) > %d",
          $seconds
        )
      );
      return;
    }
    $this->app->DB->Delete('DELETE FROM sqlcache');
    return;
  }
  if($seconds > 0) {
    $this->app->DB->Delete(
      sprintf(
        "DELETE FROM sqlcache WHERE shortcode = '%s' AND  TIMESTAMPDIFF(SECOND,zeitstempel, NOW()) > %d",
        $this->app->DB->real_escape_string($shortcode), $seconds
      )
    );
    return;
  }
  $this->app->DB->Delete(
    sprintf(
      "DELETE FROM sqlcache WHERE shortcode = '%s'",
      $this->app->DB->real_escape_string($shortcode)
    )
  );
}

// @refactor In Inhalt Modul
function GetNavigationSelect($shop)
{


  $oberpunkte = $this->app->DB->SelectArr("SELECT id, bezeichnung, bezeichnung_en, plugin,pluginparameter FROM shopnavigation WHERE parent=0  AND shop='$shop' ORDER BY position");

  $tmp = array();
  foreach($oberpunkte as $punkt)
  {
    $tmp["{$punkt["id"]}"]=$punkt["bezeichnung"];
    $unterpunkte = $this->app->DB->SelectArr("SELECT id, bezeichnung, bezeichnung_en, plugin,pluginparameter FROM shopnavigation WHERE parent='".$punkt["id"]."' AND shop='$shop' ORDER BY position");

    foreach($unterpunkte as $upunkt)
      $tmp["{$upunkt["id"]}"]="&nbsp;&nbsp;&nbsp;".$upunkt["bezeichnung"];
  }

  return $tmp;
}



// @refactor PopupTable Widget
function AnsprechpartnerButton($adresse)
{
  $this->app->Tpl->Set('POPUPWIDTH',"1200");
  $this->app->Tpl->Set('ANSPRECHPARTNERPOPUP','
      <script>
      $(function() {
        $("#mehr").button();
        });

      function closeIframe()
      {
      $(\'.externalSite\').dialog(\'close\');
      return false;
      }

      </script>

      <a id="mehr" style="font-size: 8pt; " href="index.php?module=adresse&action=ansprechpartnerpopup&id='.$adresse.'&iframe=true" class="popup" title="Ansprechpartner einf&uuml;gen">Ansprechpartner</a>');
  //"<input type=\"button\" value=\"Ansprechpartner einf&uuml;gen\">");
}

// @refactor in Lager Modul
function ArtikelAnzahlLagerPlatz($artikel,$lager_platz, $isProduction = false, $ignoreSperrLager = false)
{
  if($isProduction) {
    $result =  $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi
      LEFT JOIN lager_platz lp ON lp.id=lpi.lager_platz
      WHERE lpi.artikel='$artikel' AND lpi.lager_platz='$lager_platz' AND (lp.sperrlager!=1 OR lp.allowproduction = 1)");
  }
  else{
    $sperrlagerSQL = $ignoreSperrLager ? '' : "AND lp.sperrlager!='1'";

    $result = $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi
      LEFT JOIN lager_platz lp ON lp.id=lpi.lager_platz
      WHERE lpi.artikel='$artikel' AND lpi.lager_platz='$lager_platz' {$sperrlagerSQL}");
  }
  if($result <=0) {
    return 0;
  }

  return $result;
}

// @refactor in Lager Modul
function ArtikelAnzahlLagerOhneNachschublager($artikel)
{
  return $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi LEFT JOIN lager_platz lp ON lp.id=lpi.lager_platz
      WHERE lpi.artikel='$artikel' AND lp.autolagersperre!='1' AND lp.sperrlager!='1'");
}


// @refactor in Lager Modul
function ArtikelAnzahlLagerNurNachschublager($artikel)
{
  return $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz
      WHERE lpi.artikel='$artikel' AND lp.autolagersperre='1'");
}

// @refactor in Lager Modul
function ArtikelAnzahlLagerPOS($artikel,$lager)
{
  return $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz
        WHERE lpi.artikel='$artikel' AND lp.lager='$lager' AND lp.poslager='1'");
}

// @refactor in Lager Modul
function ArtikelAnzahlLager($artikel,$lager=0, $projektlager = 0)
{
  if($lager<=0)
  {
    if($projektlager)
    {
      return $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz INNER JOIN lager lag ON lp.lager = lag.id AND lag.geloescht <> 1
          WHERE lpi.artikel='$artikel' AND lp.sperrlager!='1' AND lag.projekt = '$projektlager'");
    }
    return $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi LEFT JOIN lager_platz lp ON lp.id=lpi.lager_platz
        WHERE lpi.artikel='$artikel' AND lp.sperrlager!='1'");
  }
  else
  {
    return $this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz
        WHERE lpi.artikel='$artikel' AND lp.lager='$lager' AND lp.sperrlager!='1'");
  }
}


// @refactor in Lager Modul
function ArtikelAnzahlOffene($artikel, $projekt = 0)
{
  return $this->app->DB->Select("SELECT SUM(ap.menge) FROM auftrag_position ap INNER JOIN auftrag a ON a.id=ap.auftrag WHERE ap.artikel='$artikel' AND a.status='freigegeben'".($projekt?" AND a.projekt = '$projekt' ":''));
  //              return $this->app->DB->Select("SELECT SUM(menge) FROM lager_reserviert WHERE artikel='$artikel'");
}



// @refactor in Lager Modul
function ArtikelAnzahlBestellung($artikel)
{
  return $this->app->DB->Select("SELECT SUM(bp.menge-bp.geliefert) FROM bestellung_position bp INNER JOIN bestellung b ON b.id=bp.bestellung 
   WHERE bp.artikel='$artikel' AND (b.status='freigegeben' OR b.status='versendet')");
  //              return $this->app->DB->Select("SELECT SUM(menge) FROM lager_reserviert WHERE artikel='$artikel'");
}


// @refactor in Lager Modul
function ArtikelAnzahlReserviert($artikel, $auftragprojekt = 0)
{
  if($auftragprojekt)
  {
    return $this->app->DB->Select("SELECT SUM(r.menge) FROM lager_reserviert r INNER JOIN auftrag a ON r.objekt = 'auftrag' AND r.parameter = a.id AND a.status = 'freigegeben' WHERE r.artikel='$artikel'");
  }
  return $this->app->DB->Select("SELECT SUM(menge) FROM lager_reserviert WHERE artikel='$artikel'");
}

  /**
   * @deprecated
   */
function MaxArtikelbezeichnung($delta=0)
{
  return 100000; // die funktion kann man mal komplett entfernen TODO

  return 50+$delta;
}

  // @refactor in Secure oder StringCleaner Klasse
function CleanStringUTF8($value, $withhtmlentities = true)
{
  $value=trim($value);
  $value = $this->app->Secure->stripallslashes($value);
  $value = $this->app->Secure->smartstripslashes($value);
  //$value = htmlspecialchars($value,ENT_QUOTES);
  // $value = str_replace('"','&Prime;',$value);
  // $value = str_replace("'",'&prime;',$value);
  //$value = $this->ConvertForDB($value);
  if($withhtmlentities)$value = $this->ConvertForDBUTF8($value);
  return $value;
}


// @refactor in Secure oder StringCleaner Klasse
function CleanString($value, $withhtmlentities = true)
{
  $value=trim($value);
  $value = $this->app->Secure->stripallslashes($value);
  $value = $this->app->Secure->smartstripslashes($value);
  //$value = htmlspecialchars($value,ENT_QUOTES);
  // $value = str_replace('"','&Prime;',$value);
  // $value = str_replace("'",'&prime;',$value);
  //$value = $this->ConvertForDB($value);
  $value = $this->ConvertForDB($value, $htmlentities);
  return $value;
}


// @refactor in Secure oder StringCleaner Klasse
function CleanDataBeforImportUTF8($data, $withhtmlentities = true)
{
  if(is_array($data))
  {
    foreach($data as $key=>$value)
    {
      if(!is_array($data[$key]) && is_string($value))
        $data[$key] = $this->CleanStringUTF8($value, $withhtmlentities);
    }

    return $data;

  }
  if(is_string($data)) {
    $data = $this->CleanStringUTF8($data, $withhtmlentities);
  }
  return $data;
}

  // @refactor in Secure oder StringCleaner Klasse
  function CleanDataBeforImport($data, $htmlentities = true)
  {
    if(is_array($data))
    {
      foreach($data as $key=>$value)
      {
        if(!is_array($data[$key]) && is_string($value))
          $data[$key] = $this->CleanString($value, $htmlentities);
      }

      return $data;
    }
    if(is_string($data)) {
      $data = $this->CleanString($data, $htmlentities);
    }
    return $data;
  }

/**
 * @deprecated
 */
function GetStandardProjekt()
{
  return $this->app->DB->Select("SELECT standardprojekt FROM firma WHERE id='".$this->app->User->GetFirma()."' LIMIT 1");
}

// @refactor Firmendaten Modul
function Standardprojekt($table,$id)
{
  if(!$id)return;
  $projekt = $this->app->DB->Select("SELECT projekt FROM `$table` WHERE id='$id' LIMIT 1");
  if($projekt<1)
  {
    $standardprojekt = $this->app->DB->Select("SELECT standardprojekt FROM firma WHERE id='".$this->app->User->GetFirma()."' LIMIT 1");
    $this->app->DB->Update("UPDATE `$table` SET projekt='".$standardprojekt."' WHERE id='".$id."' LIMIT 1");
  }
}

function GetLagerNachkommastellen()
{
  return 4;
}

  // @refactor ProcessManager
function SetCheckCronjob($value)
{
  if(!$value)
  {
    $this->app->erp->SetKonfigurationValue('checkcronjob_deaktiviert', 1);
  }else{
    $this->app->erp->SetKonfigurationValue('checkcronjob_deaktiviert', '');
    $this->app->erp->SetKonfigurationValue('checkcronjob_db', $this->app->Conf->WFdbname);
    $this->app->erp->SetKonfigurationValue('checkcronjob_host', $this->app->Conf->WFdbhost);
    $datei = $this->app->Conf->WFuserdata.'/cronjobkey.txt';
    if(file_exists($datei))
    {
      $key = trim(file_get_contents($datei));
      if($key != '')
      {
        $this->app->erp->SetKonfigurationValue('checkcronjob_key', $key);
      }else{
        $dbkey = $this->app->erp->GetKonfiguration('checkcronjob_key');
        if($dbkey != '')
        {
          if(!file_put_contents($datei, $dbkey))
          {
            $this->app->erp->SetKonfigurationValue('checkcronjob_key', '');
          }
        }else{
          $dbkey = sha1(microtime(true));
          if(file_put_contents($datei, $dbkey))
          {
            $this->app->erp->SetKonfigurationValue('checkcronjob_key', $dbkey);
          }
        }
      }
    }else{
      $dbkey = $this->app->erp->GetKonfiguration('checkcronjob_key');
      if($dbkey != '')
      {
        if(!file_put_contents($datei, $dbkey))
        {
          $this->app->erp->SetKonfigurationValue('checkcronjob_key', '');
        }
      }else{
        $dbkey = sha1(microtime(true));
        if(file_put_contents($datei, $dbkey))
        {
          $this->app->erp->SetKonfigurationValue('checkcronjob_key', $dbkey);
        }
      }
    }
  }
}

  /**
   * @return bool
   */
  public function isMarkedAsBlockedByBackup()
  {
    return $this->app->erp->GetKonfiguration('update_maintenance') == '1'
      && $this->app->erp->GetKonfiguration('update_maintenance_mode') === 'backup';
  }

  /**
   * @return bool
   */
  public function canRunCronjob($parameterToReset = [])
  {
    if(!$this->isMarkedAsBlockedByBackup()) {
      return true;
    }
    if(empty($parameterToReset)) {
      return false;
    }
    $this->app->DB->Update(
      sprintf(
        "UPDATE `prozessstarter` 
        SET `letzteausfuerhung` = NOW(), `mutex` = 0, `mutexcounter` = 0 
        WHERE `parameter` IN ('%s')",
        implode("', '", $parameterToReset)
      )
    );

    return false;
  }

  /**
   * @return bool
   */
  public function isSystemBlockedByBackup()
  {
    if(!$this->isMarkedAsBlockedByBackup()) {
      return false;
    }
    $maintenanceMode = $this->app->erp->GetKonfiguration('update_maintenance_mode');
    if($maintenanceMode !== 'backup') {
      return false;
    }

    $backUpCrons = $this->app->DB->SelectFirstCols(
      "SELECT `id` FROM `prozessstarter` WHERE `aktiv` = 1 AND `mutex` = 1 AND `parameter` = 'backup'"
    );

    if(empty($backUpCrons)) {
      return false;
    }
    if(empty($this->cronjobObj)) {
      /** @var Prozessstarter cronjobObj */
      $this->loadCronjobObj();
    }
    if(empty($this->cronjobObj)) {
      $this->app->erp->SetKonfigurationValue('update_maintenance', 0);
      $this->app->erp->SetKonfigurationValue('update_maintenance_mode','');
      return true;
    }
    if(!method_exists($this->cronjobObj,'removeKilledCronjobs')) {
      $this->app->erp->SetKonfigurationValue('update_maintenance', 0);
      $this->app->erp->SetKonfigurationValue('update_maintenance_mode','');
      return true;
    }
    $this->cronjobObj->removeKilledCronjobs();

    $runningCronjobs = $this->cronjobObj->getAllRunningCronjobs();
    if(empty($runningCronjobs)) {
      $this->app->erp->SetKonfigurationValue('update_maintenance', 0);
      $this->app->erp->SetKonfigurationValue('update_maintenance_mode','');
      return true;
    }
    foreach($runningCronjobs as $runningCronjob){
      if(in_array($runningCronjob['task_id'], $backUpCrons)) {
        return false;
      }
    }

    $this->app->erp->SetKonfigurationValue('update_maintenance', 0);
    $this->app->erp->SetKonfigurationValue('update_maintenance_mode','');
    return true;
  }

  // @refactor ProcessManager

  /**
   * @param bool $checkMaintenance
   *
   * @return bool
   */
public function CheckCronjob($checkMaintenance = true)
{
  if (!empty($this->app->erp->GetKonfiguration('last_isdevelopmentversion'))) {
    $this->app->erp->SetKonfigurationValue('last_isdevelopmentversion', '');
    $this->app->erp->SetKonfigurationValue('checkcronjob_deaktiviert', '1');
    return false;
  }
  if($this->app->erp->GetKonfiguration('checkcronjob_deaktiviert') == '1') {
    return false;
  }
  $maintenanceMode = $this->app->erp->GetKonfiguration('update_maintenance_mode');
  if($checkMaintenance && $maintenanceMode !== 'backup') {
    $checkMaintenance = false;//@todo not backupmode check
  }
  if($checkMaintenance && $this->app->erp->GetKonfiguration('update_maintenance') == '1') {
    $timeMaintenance = (int)$this->app->erp->GetKonfiguration('update_maintenance_time');
    if(empty($timeMaintenance)) {
      $this->app->erp->SetKonfigurationValue('update_maintenance_time', time());
      return false;
    }
    if(time() - $timeMaintenance < 600) {
      return false;
    }
    if($this->isSystemBlockedByBackup()) {
      return false;
    }

    $this->app->erp->SetKonfigurationValue('update_maintenance', 0);
    $this->app->erp->SetKonfigurationValue('update_maintenance_mode','');
  }
  $datei = $this->app->Conf->WFuserdata.'/cronjobkey.txt';
  $confdb = $this->app->Conf->WFdbname;
  if($confdb == '') {
    return true;
  }
  $confhost = $this->app->Conf->WFdbhost;
  $dbdb = $this->app->erp->GetKonfiguration('checkcronjob_db');
  $dbhost = $this->app->erp->GetKonfiguration('checkcronjob_host');
  $dbkey = $this->app->erp->GetKonfiguration('checkcronjob_key');
  if($dbdb == '')
  {
    $this->app->erp->SetKonfigurationValue('checkcronjob_db', $confdb);
    $dbdb = $confdb;
  }
  if($dbhost == '')
  {
    $this->app->erp->SetKonfigurationValue('checkcronjob_host', $confhost);
    $dbhost = $confhost;
  }

  $dbs = ConfigLoader::loadAllWithActiveCronjobs();
  if(!empty($dbs) && (!empty($dbs)?count($dbs):0) > 1){
    foreach($dbs as $v) {
      if($v->WFdbhost === $confhost && $v->WFdbname === $confdb) {
        return true;
      }
    }
  }

  if($dbdb != $confdb)return false;
  if($dbhost != $confhost)return false;
  if(file_exists($datei))
  {
    $key = trim(file_get_contents($datei));
    if($key != '' && $dbkey == '')
    {
      $this->app->erp->SetKonfigurationValue('checkcronjob_key', $key);
    }
    if($key != $dbkey)return false;
  }else{
    if($dbkey == '')
    {
      $dbkey = sha1(microtime(true));
    }
    if(file_put_contents($datei, $dbkey))
    {
      $this->app->erp->SetKonfigurationValue('checkcronjob_key', $dbkey);
    }
  }
  return true;
}

// @refactor FileManager
function RemoveFile($file){
  if($file == '')return;
  if(strpos($file,'cronjobs') !== false)
  {
    $filea = pathinfo($file);
    $parameter = $filea['filename'];
    if($this->app->DB->Select("SELECT id FROM prozessstarter WHERE parameter = '".$this->app->DB->real_escape_string($parameter)."' LIMIT 1"))return;
  }
  if(file_exists(__DIR__ . '/../../'.$file))@unlink(__DIR__ . '/../../'.$file);
}

// @refactor FileManager
function RemoveFolder($folder)
{
  if($folder == '')return;
  if(strpos($folder,'..') !== false)return;
  $folder = rtrim($folder, '/');
  $folderabs = __DIR__.'/../../'.$folder;
  if(!is_dir($folderabs))return;
  if($handle = opendir($folderabs))
  {
    while (false !== ($entry = readdir($handle))) {
      if($entry != '.' && $entry != '..')
      {
        if(is_dir($folderabs.'/'.$entry))
        {
          $this->RemoveFolder($folder.'/'.$entry);
        }else
        {
          $this->RemoveFile($folder.'/'.$entry);
        }
      }
    }
    closedir($handle);
  }
  if(is_dir($folder)){
    @rmdir($folder);
  }
}

// @refactor Installer Komponente
function fixDatabaseNullIDs($table)
{
  $query = $this->CheckAlterTable("SELECT * FROM `$table` WHERE id = '0'");
  if(!$query)return;
  while($val = $this->app->DB->Fetch_Assoc($query))
  {
    $maxid = 1+(int)$this->app->DB->Select("SELECT max(id) FROM `$table`");
    $this->app->DB->Update("UPDATE `$table` set id = '$maxid' WHERE id = '0' LIMIT 1");
  }
  $this->app->DB->free($query);

  $doppelteids = $this->app->DB->SelectArr("SELECT id, count(*) as co FROM `$table` GROUP BY id HAVING COUNT(*) > 1");
  if($doppelteids)
  {
    foreach($doppelteids as $val)
    {
      $maxid = 1+(int)$this->app->DB->Select("SELECT max(id) FROM `$table`");
      $doppelte = $this->app->DB->SelectArr("SELECT * FROM `$table` WHERE id = '".$val['id']."'");
      for($i = 1; $i < $val['co']; $i++)
      {
        $this->app->DB->Update("UPDATE `$table` SET id = '$maxid' WHERE id = '".$val['id']."' LIMIT 1");
        $maxid++;
      }
    }
  }
  $this->CheckAlterTable("ALTER TABLE `$table` ADD PRIMARY KEY(`id`);");
  $maxid = 1+(int)$this->app->DB->Select("SELECT max(id) FROM `$table`");
  $this->CheckAlterTable("ALTER TABLE `$table` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=".$maxid);
}

// @refactor Changelog Komponente/Modul
function StartChangeLog($table, $tableid = 0, $module = '', $action = '', $bearbeiter = ''){
  $this->Changelog = null;
  if($module == '' && isset($this->app->Secure) && $this->app->Secure && method_exists($this->app->Secure, 'GetGET'))$module = $this->app->Secure->GetGET('module');
  if($action == '' && isset($this->app->Secure) && $this->app->Secure && method_exists($this->app->Secure, 'GetGET'))$action = $this->app->Secure->GetGET('action');
  if($table == '')$table = $module;
  if($table == '')return;
  if($tableid <= 0 && isset($this->app->Secure) && $this->app->Secure && method_exists($this->app->Secure, 'GetGET'))$tableid = (int)$this->app->Secure->GetGET('id');
  if($tableid <= 0)return;
  if($bearbeiter == '' && isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))$bearbeiter = $this->app->User->GetName();
  $arr = $this->app->DB->SelectRow("SELECT * FROM $table WHERE id = '$tableid' LIMIT 1");
  if(!$arr)return;
  $this->Changelog = array('data'=>$arr,'module'=>$module,'action'=>$action,'bearbeiter'=>$bearbeiter,'table'=>$table,'tableid'=>$tableid);
}

// @refactor Changelog Komponente/Modul
function WriteChangeLog()
{
  if(!isset($this->Changelog) || !$this->Changelog)return;
  $arr = $this->app->DB->SelectRow("SELECT * FROM ".$this->Changelog['table']." WHERE id = '".$this->Changelog['tableid']."' LIMIT 1");
  if(!$arr)
  {
    $this->Changelog = null;
    return;
  }
  $changes = null;
  foreach($arr as $k => $v)
  {
    if($k != 'zeitstempel' && $k != 'useredittimestamp' && $k != 'usereditid')
    {
      if((String)$v != (String)$this->Changelog['data'][$k])
      {
        $changes[$k] = array('oldvalue'=>(String)$this->Changelog['data'][$k], 'newvalue'=>(String)$v);
      }
    }
  }
  $change_log = null;
  if($changes)
  {
    $this->app->DB->Insert("INSERT INTO change_log (`bearbeiter`, `module`, `action`, `tabelle`, `tableid`, `zeitstempel`) VALUES (
    '".$this->app->DB->real_escape_string($this->Changelog['bearbeiter'])."',
    '".$this->app->DB->real_escape_string($this->Changelog['module'])."',
    '".$this->app->DB->real_escape_string($this->Changelog['action'])."',
    '".$this->app->DB->real_escape_string($this->Changelog['table'])."',
    '".(int)$this->Changelog['tableid']."',now())");
    $change_log = $this->app->DB->GetInsertID();
    $this->Changelog = null;
    if(!$change_log)return;
    foreach($changes as $k => $v)
    {
      $this->app->DB->Insert("INSERT INTO change_log_field (change_log, fieldname, oldvalue, newvalue) VALUES ('$change_log',
      '".$this->app->DB->real_escape_string($k)."',
      '".$this->app->DB->real_escape_string($v['oldvalue'])."',
      '".$this->app->DB->real_escape_string($v['newvalue'])."')");
    }
  }
  $this->Changelog = null;
  return $change_log;
}

// @refactor Installer Komponente
function CheckFirmendaten()
{
  $check = $this->app->DB->Select("SELECT count(id) FROM firmendaten_werte");
  if(!$check)
  {
    $altefirmendatenspalten = $this->app->DB->SelectArr("show columns from firmendaten");
    if($altefirmendatenspalten){
      foreach($altefirmendatenspalten as $zeile)
      {
        if($zeile['Field'] != 'id')
        {
          $type = strtolower($zeile['Type']);
          $name = $zeile['Field'];
          $typ = '';
          $typ1 = '';
          $typ2 = '';
          $default_value = '';
          $default_null = false;
          $darf_null = false;
          if(is_null($zeile['Default']))
          {
            $default_null = true;
          }else{
            $default_value = $zeile['Default'];
          }
          if(strtoupper($zeile['Null']) == 'YES')$darf_null = true;
          if(substr($type ,0,3) == 'int')
          {
            $typ = 'int';
            $typ1 = (int)str_replace(array('int(',')'),array('',''),$type);
          }elseif(substr($type ,0,7) == 'tinyint')
          {
            $typ = 'tinyint';
            $typ1 = (int)str_replace(array('tinyint(',')'),array('',''),$type);
          }elseif(substr($type ,0,7) == 'varchar')
          {
            $typ = 'varchar';
            $typ1 = (int)str_replace(array('varchar(',')'),array('',''),$type);
          }elseif(substr($type ,0,8) == 'datetime')
          {
            $typ = 'datetime';
          }elseif(substr($type ,0,4) == 'date')
          {
            $typ = 'date';
          }elseif(substr($type ,0,7) == 'decimal')
          {
            $typ = 'decimal';
            $decimala = explode(',',str_replace(array('decimal(',')'),array('',''),$type));
            $typ1 = (int)$decimala[0];
            $typ2 = (int)$decimala[1];
          }
          if($typ)
          {
            $wert = $this->app->DB->Select("SELECT $name FROM firmendaten LIMIT 1");
            $this->AddNeuenFirmendatenWert($name, $typ, $typ1, $typ2, $wert, $default_value, $default_null, $darf_null);
          }
        }
      }
    }
  }
}

public function activateCleanerOnce()
{
  $activatedCleanerOnce = (string)$this->GetKonfiguration('cleaner_activated_one');
  if($activatedCleanerOnce === '1') {
    return;
  }
  $tables = [
    'logfile'        => 60,
    'shopexportlog'  => 30,
    'versandzentrum' => 90,
    'uebertragungen' => 90,
    'adapterbox'     => 20,
    'protokoll'      => 90
  ];
  foreach($tables as $col => $days) {
    if(!$this->Firmendaten('cleaner_'.$col)) {
      $this->FirmendatenSet('cleaner_'.$col, '1');
    }
    if(!$this->Firmendaten('cleaner_'.$col.'_tage')) {
      $this->FirmendatenSet('cleaner_'.$col.'_tage', $days);
    }
  }

  $cleanerCronjob = $this->app->DB->SelectRow(
    "SELECT `id`, `aktiv` FROM `prozessstarter` WHERE `parameter` = 'cleaner' ORDER BY `aktiv` DESC LIMIT 1"
  );
  if(!empty($cleanerCronjob) && empty($cleanerCronjob['aktiv'])) {
    $this->app->DB->Update(
      sprintf(
        "UPDATE `prozessstarter` SET `aktiv` = 1 WHERE `id` = %d AND `parameter` = 'cleaner' LIMIT 1",
        $cleanerCronjob['id']
      )
    );
  }

  $this->SetKonfigurationValue('cleaner_activated_one', '1');
}

// @refactor Installer Komponente
function StandardFirmendatenWerte()
{
  $this->NeueFirmendatenWerteSammeln(true);
  $this->AddNeuenFirmendatenWert( 'absender', 'varchar', '1024', '', 'Musterfirma GmbH | Musterweg 5 | 12345 Musterstadt', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'sichtbar', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'barcode', 'int', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schriftgroesse', 'int', '1', '', '9', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schriftgroesse_gesamt', 'int', '1', '', '9', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schriftgroesse_gesamt_steuer', 'int', '1', '', '8', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zeilenuntertext', 'int', '1', '', '7', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'infobox', 'int', '1', '', '8', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'spaltenbreite', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_0_0', 'varchar', '512', '', 'Sitz der Gesellschaft / Lieferanschrift', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_0_1', 'varchar', '512', '', 'Musterfirma GmbH', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_0_2', 'varchar', '512', '', 'Musterweg 5', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_0_3', 'varchar', '512', '', 'D-12345 Musterstadt', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_0_4', 'varchar', '512', '', 'Telefon +49 123 12 34 56 7', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_0_5', 'varchar', '512', '', 'Telefax +49 123 12 34 56 78', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_1_0', 'varchar', '64', '', 'Bankverbindung', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_1_1', 'varchar', '64', '', 'Musterbank', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_1_2', 'varchar', '64', '', 'Konto 123456789', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_1_3', 'varchar', '64', '', 'BLZ 72012345', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_1_4', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_1_5', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_2_0', 'varchar', '64', '', 'IBAN DE1234567891234567891', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_2_1', 'varchar', '64', '', 'BIC/SWIFT DETSGDBWEMN', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_2_2', 'varchar', '64', '', 'Ust-IDNr. DE123456789', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_2_3', 'varchar', '64', '', 'E-Mail: info@musterfirma-gmbh.de', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_2_4', 'varchar', '64', '', 'Internet: http://www.musterfirma.de', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_2_5', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_3_0', 'varchar', '64', '', 'Geschäftsführer', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_3_1', 'varchar', '64', '', 'Max Musterman', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_3_2', 'varchar', '64', '', 'Handelsregister: HRB 12345', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_3_3', 'varchar', '64', '', 'Amtsgericht: Musterstadt', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_3_4', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'footer_3_5', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'hintergrund', 'varchar', '64', '', 'kein', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'bcc3', 'varchar', '255', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'logo_type', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'briefpapier_type', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'email', 'varchar', '64', '', 'mail@ihr_mail_server.de', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'absendername', 'varchar', '64', '', 'Meine Firma', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'strasse', 'varchar', '64', '', 'Musterweg 5', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'plz', 'varchar', '64', '', '12345', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'ort', 'varchar', '64', '', 'Musterstadt', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'steuernummer', 'varchar', '64', '', 'DE123456789', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'startseite_wiki', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'projekt', 'int', '11', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_preisanfrage', 'varchar', '64', '', '100000', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_angebot', 'varchar', '64', '', '100003', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_auftrag', 'varchar', '64', '', '200005', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_gutschrift', 'varchar', '64', '', '900000', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_lieferschein', 'varchar', '64', '', '300001', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_retoure', 'varchar', '64', '', '500001', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_bestellung', 'varchar', '64', '', '100002', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_rechnung', 'varchar', '64', '', '400001', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_kundennummer', 'varchar', '64', '', '10003', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_lieferantennummer', 'varchar', '64', '', '70002', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_mitarbeiternummer', 'varchar', '64', '', '90001', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_waren', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_sonstiges', 'varchar', '64', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'next_produktion', 'varchar', '64', '', '400000', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'breite_position', 'int', '11', '', '10', '10', 0, 0);
  $this->AddNeuenFirmendatenWert( 'breite_menge', 'int', '11', '', '10', '10', 0, 0);
  $this->AddNeuenFirmendatenWert( 'breite_nummer', 'int', '11', '', '20', '20', 0, 0);
  $this->AddNeuenFirmendatenWert( 'breite_einheit', 'int', '11', '', '15', '15', 0, 0);
  $this->AddNeuenFirmendatenWert( 'skonto_ueberweisung_ueberziehen', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'kleinunternehmer', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuerfrei_inland_ausblenden', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuerspalteausblenden', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mahnwesenmitkontoabgleich', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'porto_berechnen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'auftrag_eantab', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'immernettorechnungen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'erweiterte_positionsansicht', 'int', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schnellanlegen', 'int', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schnellanlegen_ohnefreigabe', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellvorschlaggroessernull', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'versand_gelesen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'versandart', 'varchar', '64', '', 'versandunternehmen', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlungsweise', 'varchar', '64', '', 'rechnung', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlungsweiselieferant', 'varchar', '64', '', 'rechnung', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_lastschrift_konditionen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'breite_artikelbeschreibung', 'tinyint', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'langeartikelnummern', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'deviceenable', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'etikettendrucker_wareneingang', 'int', '11', '', '2', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'aufgaben_bondrucker', 'int', '11', '', '2', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'waehrung', 'varchar', '64', '', 'EUR', 'EUR', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_breite1', 'int', '11', '', '50', '50', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_breite4', 'int', '11', '', '40', '40', 0, 0);
  $this->AddNeuenFirmendatenWert( 'boxausrichtung', 'varchar', '64', '', 'L', 'R', 0, 0);
  $this->AddNeuenFirmendatenWert( 'branch', 'varchar', '64', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'version', 'varchar', '64', '', '15.4.f7412d4', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'standard_datensaetze_datatables', 'int', '11', '', '0', '10', 0, 0);
  $this->AddNeuenFirmendatenWert( 'auftrag_bezeichnung_vertrieb', 'varchar', '64', '', 'Vertrieb', 'Vertrieb', 0, 0);
  $this->AddNeuenFirmendatenWert( 'auftrag_bezeichnung_bearbeiter', 'varchar', '64', '', 'Bearbeiter', 'Bearbeiter', 0, 0);
  $this->AddNeuenFirmendatenWert( 'auftrag_bezeichnung_bestellnummer', 'varchar', '64', '', 'Ihre Bestellnummer', 'Ihre Bestellnummer', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungkundennummer', 'varchar', '64', '', 'Kundennummer', 'Kundennummer', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungstornorechnung', 'varchar', '64', '', 'Stornorechnung', 'Stornorechnung', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellungohnepreis', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellungmitartikeltext', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellungeigeneartikelnummer', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellunglangeartikelnummern', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'rechnung_gutschrift_ansprechpartner', 'int', '1', '', '0', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'angebot_auftrag_bestellung_ansprechpartner', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_initkey', 'varchar', '1024', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_remotedomain', 'varchar', '1024', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_eventurl', 'varchar', '1024', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_enable', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_cleanutf8', 'tinyint', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_importwarteschlange', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'api_importwarteschlange_name', 'varchar', '64', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wareneingang_zwischenlager', 'int', '1', '', '0', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'modul_mlm', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'modul_verband', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'modul_mhd', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mhd_warnung_tage', 'int', '11', '', '3', '3', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_anzahlmonate', 'int', '11', '', '11', '11', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_01_punkte', 'int', '11', '', '2999', '2999', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_02_punkte', 'int', '11', '', '3000', '3000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_03_punkte', 'int', '11', '', '5000', '5000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_04_punkte', 'int', '11', '', '10000', '10000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_05_punkte', 'int', '11', '', '15000', '15000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_06_punkte', 'int', '11', '', '25000', '25000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_07_punkte', 'int', '11', '', '50000', '50000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_08_punkte', 'int', '11', '', '100000', '100000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_09_punkte', 'int', '11', '', '150000', '150000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_10_punkte', 'int', '11', '', '200000', '200000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_11_punkte', 'int', '11', '', '250000', '250000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_12_punkte', 'int', '11', '', '300000', '300000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_13_punkte', 'int', '11', '', '350000', '350000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_14_punkte', 'int', '11', '', '400000', '400000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_15_punkte', 'int', '11', '', '450000', '450000', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_01_mindestumsatz', 'int', '11', '', '50', '50', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_02_mindestumsatz', 'int', '11', '', '50', '50', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_03_mindestumsatz', 'int', '11', '', '50', '50', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_04_mindestumsatz', 'int', '11', '', '50', '50', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_05_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_06_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_07_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_08_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_09_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_10_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_11_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_12_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_13_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_14_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mlm_15_mindestumsatz', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'standardaufloesung', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'standardversanddrucker', 'int', '11', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'standardetikettendrucker', 'int', '11', '', '2', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wareneingangdmsdrucker', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'externereinkauf', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'schriftart', 'varchar', '64', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'knickfalz', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'artikeleinheit', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'artikeleinheit_standard', 'varchar', '64', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'abstand_boxrechtsoben_lr', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlungszieltage', 'int', '11', '', '14', '14', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlungszielskonto', 'int', '11', '', '2', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'zahlungszieltageskonto', 'int', '11', '', '10', '', 1, 0);

  $this->AddNeuenFirmendatenWert( 'lieferdatumkw', 'int', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'eigener_skontotext', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'eigener_skontotext_re', 'varchar', '512', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'eigener_skontotext_anab', 'varchar', '512', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'zahlung_rechnung', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_vorkasse', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_nachnahme', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_kreditkarte', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_paypal', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_bar', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_lastschrift', 'int', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_amazon', 'int', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_ratenzahlung', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'briefpapier2vorhanden', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'briefpapier_ohnedoppelstrich', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'artikel_suche_kurztext', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'artikel_suche_variante_von', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'adresse_freitext1_suche', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'iconset_dunkel', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'warnung_doppelte_nummern', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'warnung_doppelte_seriennummern', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'next_arbeitsnachweis', 'varchar', '64', '', '300000', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_reisekosten', 'varchar', '64', '', '31000', '', 1, 1);
  $receiptDocumentNumber = $this->app->erp->GetKonfiguration('receiptdocument_number');
  if(empty($receiptDocumentNumber)) {
    $receiptDocumentNumber= '300000';
  }
  $this->AddNeuenFirmendatenWert( 'next_receiptdocument', 'varchar', '64', '', $receiptDocumentNumber, '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_anfrage', 'varchar', '64', '', '50000', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_artikelnummer', 'varchar', '64', '', '1000000', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'seite_von_ausrichtung', 'varchar', '64', '', 'R', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'seite_von_sichtbar', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'seite_belegnr', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'parameterundfreifelder', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'firmenlogotype', 'varchar', '64', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'firmenlogoaktiv', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'projektnummerimdokument', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'bearbeiteremailimdokument', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'typimdokument', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'staffelpreiseanzeigen', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'auftragabschliessen', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'dateienweiterfuehren', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'systemmailsabschalten', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'lagerbestand_in_auftragspositionen_anzeigen', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'systemmailsempfaenger', 'varchar', '255', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bearbeitertelefonimdokument', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'herstellernummerimdokument', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'abmessungimdokument', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'standardmarge', 'int', '11', '', '30', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'steuer_standardkonto_aufwendungen', 'int', '1', '', '1', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_standardkonto', 'varchar', '10', '', '1370', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_normal', 'varchar', '10', '', '4400', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_normal', 'varchar', '10', '', '5400', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_ermaessigt', 'varchar', '10', '', '4300', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_steuerfrei', 'varchar', '10', '', '4110', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_innergemeinschaftlich', 'varchar', '10', '', '4125', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_innergemeinschaftlich', 'varchar', '10', '', '5425', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_eunormal', 'varchar', '10', '', '4315', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_eunormal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_export', 'varchar', '10', '', '4120', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_import', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_anpassung_kundennummer', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_1', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_1_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_1_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_1_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_2', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_2_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_2_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_2_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_3', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_3_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_3_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_3_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_4', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_4_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_4_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_4_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_5', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_5_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_5_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_5_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_6', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_6_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_6_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_6_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_7', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_7_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_7_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_7_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_8', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_8_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_8_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_8_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_9', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_9_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_9_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_9_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_10', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_10_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_10_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_10_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_11', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_11_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_11_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_11_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_12', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_12_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_12_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_12_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_13', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_13_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_13_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_13_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_14', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_14_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_14_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_14_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_15', 'varchar', '30', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_15_normal', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_15_ermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_art_15_steuerfrei', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'rechnung_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'reisekosten_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'lieferschein_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'angebot_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'auftrag_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'gutschrift_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'bestellung_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'arbeitsnachweis_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'proformarechnung_ohnebriefpapier', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'abstand_adresszeileoben', 'int', '11', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'abstand_boxrechtsoben', 'int', '11', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'wareneingang_kamera_waage', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'briefhtml', 'tinyint', '1', '', '1', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'seite_von_ausrichtung_relativ', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'absenderunterstrichen', 'tinyint', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schriftgroesseabsender', 'int', '11', '', '7', '7', 0, 0);
  $this->AddNeuenFirmendatenWert( 'datatables_export_button_flash', 'tinyint', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'land', 'varchar', '2', '', 'DE', 'DE', 0, 0);
  $this->AddNeuenFirmendatenWert( 'modul_finanzbuchhaltung', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'testmailempfaenger', 'varchar', '128', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'immerbruttorechnungen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'sepaglaeubigerid', 'varchar', '64', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'viernachkommastellen_belege', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungangebotersatz', 'varchar', '64', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'stornorechnung_standard', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'angebotersatz_standard', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'angebot_anzahltage', 'int', '1', '', '28', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'angebot_anzahlwiedervorlage', 'int', '1', '', '14', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'angebot_pipewiedervorlage', 'varchar', '250', '', '', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'modul_verein', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_gesamtsumme_lr', 'int', '11', '', '100', '100', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_amazon_bestellung', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_billsafe', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_sofortueberweisung', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_secupay', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'artikel_bilder_uebersicht', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'artikel_baum_uebersicht', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_nichtsteuerbar', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_erloese_inland_euermaessigt', 'varchar', '10', '', '4310', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_nichtsteuerbar', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'steuer_aufwendung_inland_euermaessigt', 'varchar', '10', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_seitenrandlinks', 'int', '11', '', '15', '15', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_umbruchunten', 'int', '11', '', '37', '37', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_adresszeilelinks', 'int', '11', '', '15', '15', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wareneingang_gross', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wareneingangbildtypvorauswahl', 'varchar', '255', '', 'Shopbild', 'Shopbild', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wareneingangscanverhalten', 'varchar', '255', '', 'Shopbild', 'Shopbild', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wareneingang_lagerartikel', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'barcode_x_header', 'int', '11', '', '12', '12', 0, 0);
  $this->AddNeuenFirmendatenWert( 'barcode_x', 'int', '11', '', '12', '12', 0, 0);
  $this->AddNeuenFirmendatenWert( 'barcode_y_header', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_seiten_unten', 'int', '11', '', '34', '34', 0, 0);
  $this->AddNeuenFirmendatenWert( 'mailgrussformel', 'varchar', '1024', '', '\r\n\r\n\r\nF&uuml;r R&uuml;ckfragen stehe ich Ihnen gerne zur Verf&uuml;gung.\r\n\r\nMit freundlichen Gr&uuml;ßen\r\n{MITARBEITER}', '\r\n\r\n\r\nF&uuml;r R&uuml;ckfragen stehe ich Ihnen gerne zur Verf&uuml;gung.\r\n\r\nMit freundlichen Gr&uuml;ßen\r\n{MITARBEITER}', 0, 0);
  $this->AddNeuenFirmendatenWert( 'geburtstagekalender', 'tinyint', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungproformarechnungersatz', 'varchar', '64', '', 'Lieferschein mit Preis', 'Lieferschein mit Preis', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungauftragersatz', 'varchar', '64', '', 'Proformarechnung', 'Proformarechnung', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungrechnungersatz', 'varchar', '64', '', 'Quittung', 'Quittung', 0, 0);
  $this->AddNeuenFirmendatenWert( 'rechnungersatz_standard', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnunglieferscheinersatz', 'varchar', '64', '', 'Alternative Beschriftung', 'Alternative Beschriftung', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungbestellungersatz', 'varchar', '64', '', 'Alternative Beschriftung', 'Alternative Beschriftung', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_zentriert', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_farbe', 'int', '11', '', '30', '30', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_einzugsermaechtigung', 'int', '1', '', '0', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'zahlung_eckarte', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abseite2y', 'int', '11', '', '50', '50', 0, 0);
  $this->AddNeuenFirmendatenWert( 'artikel_freitext1_suche', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'artikel_artikelnummer_suche', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'next_kalkulation', 'varchar', '128', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_preisanfrage', 'varchar', '128', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_proformarechnung', 'varchar', '128', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_serviceauftrag', 'varchar', '128', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_verbindlichkeit', 'varchar', '128', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_lieferantengutschrift', 'varchar', '128', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'zahlung_auftrag_sofort_de', 'text', '', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'zahlung_auftrag_de', 'text', '', '', '', '', 1, 1);

  for($i = 1; $i <= 20; $i++)
  {
    $this->AddNeuenFirmendatenWert( 'adressefreifeld'.$i.'typ', 'varchar', '16', '', 'einzeilig', 'einzeilig', 0, 0);
    $this->AddNeuenFirmendatenWert( 'adressefreifeld'.$i.'spalte', 'int', '11', '', '0', '0', 0, 0);
    $this->AddNeuenFirmendatenWert( 'adressefreifeld'.$i.'sort', 'int', '11', '', '0', '0', 0, 0);
  }

  for($i = 1; $i <= 40; $i++)
  {
    $this->AddNeuenFirmendatenWert( 'freifeld'.$i.'typ', 'varchar', '16', '', 'einzeilig', 'einzeilig', 0, 0);
    $this->AddNeuenFirmendatenWert( 'freifeld'.$i.'spalte', 'int', '11', '', '0', '0', 0, 0);
    $this->AddNeuenFirmendatenWert( 'freifeld'.$i.'sort', 'int', '11', '', '0', '0', 0, 0);
  }
  for($i = 1; $i <= 20; $i++)
  {
    $this->AddNeuenFirmendatenWert( 'projektfreifeld'.$i, 'varchar', '256', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'projektfreifeld'.$i.'typ', 'varchar', '16', '', 'einzeilig', 'einzeilig', 0, 0);
    $this->AddNeuenFirmendatenWert( 'projektfreifeld'.$i.'spalte', 'int', '11', '', '0', '0', 0, 0);
    $this->AddNeuenFirmendatenWert( 'projektfreifeld'.$i.'sort', 'int', '11', '', '0', '0', 0, 0);
    $this->AddNeuenFirmendatenWert( 'projektfreifeld'.$i.'tabelle', 'int', '11', '', '0', '0', 0, 0);
    $this->AddNeuenFirmendatenWert( 'projektfreifeld'.$i.'breite', 'int', '11', '', '10', '10', 0, 0);
  }

  $this->AddNeuenFirmendatenWert( 'beleg_artikelbild', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'lieferschein_artikelbild', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'rechnung_artikelbild', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellung_artikelbild', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'gutschrift_artikelbild', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'angebot_artikelbild', 'int', '1', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'wareneingangauftragzubestellung', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'freifelderimdokument', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'internetnummerimbeleg', 'int', '1', '', '', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'vertriebbearbeiterfuellen', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'beschriftunginternetnummer', 'varchar', '64', '', 'Internetnummer', 'Internetnummer', 0, 0);
  $this->AddNeuenFirmendatenWert( 'briefpapier_bearbeiter_ausblenden', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'briefpapier_vertrieb_ausblenden', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'wiedervorlage_mitarbeiter', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'auftragmarkierenegsaldo', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'breite_artikel', 'int', '11', '', '76', '76', 1, 1);
  $this->AddNeuenFirmendatenWert( 'breite_steuer', 'int', '11', '', '15', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'next_projektnummer', 'varchar', '255', '', '1000', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_anderemitarbeiter', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'auftragexplodieren_unterstuecklisten', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'dienstleistungsartikel_nicht_zu_lieferschein', 'int', '1', '', '1', '1', 0, 0);

  $this->AddNeuenFirmendatenWert( 'zeiterfassung_beschreibungssperre', 'int', '1', '', '0', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_kommentar', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_erweitert', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_ort', 'int', '1', '', '1', '', 1, 1);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_abrechnenvorausgewaehlt', 'int', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_angebot', 'varchar', '2048', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_auftrag', 'varchar', '2048', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_rechnung', 'varchar', '2048', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_gutschrift', 'varchar', '2048', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_lieferschein', 'varchar', '2048', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_bestellung', 'varchar', '2048', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_proformarechnung', 'varchar', '2048', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_angebot_aktivieren', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_auftrag_aktivieren', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_rechnung_aktivieren', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_gutschrift_aktivieren', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_lieferschein_aktivieren', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_bestellung_aktivieren', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_reihenfolge_proformarechnung_aktivieren', 'int', '1', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'beleg_pos_ean', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'beleg_pos_charge', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'beleg_pos_mhd', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'beleg_pos_sn', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'beleg_pos_zolltarifnummer', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'beleg_pos_herkunftsland', 'int', '1', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'noauth', 'tinyint', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'reihenfolge_zwischenspeicher', 'varchar', '2048', '', "{ADRESSE_NAME}\r\n{ADRESSE_ANSPRECHPARTNER}\r\n{ADRESSE_ABTEILUNG}\r\n{ADRESSE_UNTERABTEILUNG}\r\n{ADRESSE_ADRESSZUSATZ}\r\n{ADRESSE_STRASSE}\r\n{ADRESSE_LAND}-{ADRESSE_PLZ} {ADRESSE_ORT}",'', 0, 0);

  $this->AddNeuenFirmendatenWert( 'adresse_vorlage', 'varchar', '64', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'belege_subpositionen', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'belege_stuecklisteneinrueckenmm', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'belege_subpositionenstuecklisten', 'tinyint', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'guenstigste_vk', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'festetrackingnummer', 'tinyint', '1', '', '1', '1', 0, 0);

  $this->AddNeuenFirmendatenWert( 'oneclickrelease', 'tinyint', '1', '', '1', '1', 0, 0);

  $this->AddNeuenFirmendatenWert( 'loadcurrencyrate', 'tinyint', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'cleaner_logfile', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_logfile_tage', 'int', '11', '', '60', '60', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_shopexportlog', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_shopexportlog_tage', 'int', '11', '', '30', '30', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_versandzentrum', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_versandzentrum_tage', 'int', '11', '', '90', '90', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_uebertragungen', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_uebertragungen_tage', 'int', '11', '', '90', '90', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_adapterbox', 'tinyint', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_adapterbox_tage', 'int', '11', '', '20', '20', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_protokoll', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_protokoll_tage', 'int', '11', '', '90', '90', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_shopimport', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'tabsnavigationfarbe', 'varchar', '32', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'tabsnavigationfarbeschrift', 'varchar', '32', '', '#000', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'cleaner_shopimport_tage', 'int', '11', '', '90', '90', 0, 0);
  $this->AddNeuenFirmendatenWert( 'paketmarke_mit_waage', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'artikel_beschleunigte_suche', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'internebemerkungminidetails', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'navigationfarbeschrift2', 'varchar', '32', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'gewichtzukgfaktor', 'varchar', '32', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'gewichtbezeichnung', 'varchar', '32', '', '', '', 0, 0);


  $this->AddNeuenFirmendatenWert( 'begrenzen_artikeltabelle', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'begrenzen_adressetabelle', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'begrenzen_belege', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'versandmail_zwischenspeichern', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'begrenzenanzahl_artikeltabelle', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'begrenzenanzahl_adressetabelle', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'begrenzenanzahl_belege', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'versandmails_max', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'autoversand_maxauftraege', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'autoversand_locked_orders', 'int', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'schnellsuche', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'schnellsuchecount', 'int', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'zeiterfassung_schliessen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_schliessentage', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'zeiterfassung_pflicht', 'int', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'ampellager', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelporto', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelust', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelzahlung', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelnachnahme', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelautoversand', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelkunde', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelliefertermin', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelkreditlimit', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelliefersperre', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'ampelproduktion', 'int', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'keinhauptmenurahmen', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bordertabnav', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'navigationfarbe2', 'varchar', '32', '', '', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'freitext1x', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext1y', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext1schriftgroesse', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext1breite', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext1aktiv', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'freitext1inhalt', 'varchar', '2048', '', '', '', 1, 0);

  $this->AddNeuenFirmendatenWert( 'freitext2x', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext2y', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext2schriftgroesse', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext2breite', 'varchar', '32', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'freitext2aktiv', 'int', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'freitext2inhalt', 'varchar', '2048', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'kommissionskonsignationslager', 'varchar', '255', '', 'Kommissions-/Konsignationslager', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'bezeichnungaktionscodes', 'varchar', '255', '', 'Aktionscode', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'produktionsverhalten','varchar','64','','explodieren','',0,0);
  $this->AddNeuenFirmendatenWert( 'projektoeffentlich', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'verkaufspreisevpe', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'einkaufspreisevpe', 'tinyint', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'barcode', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'tabellenbeschriftung', 'int', '1', '', '8', '8', 0, 0);
  $this->AddNeuenFirmendatenWert( 'tabelleninhalt', 'int', '1', '', '8', '8', 0, 0);
  $this->AddNeuenFirmendatenWert( 'freitext', 'int', '1', '', '8', '8', 0, 0);
  $this->AddNeuenFirmendatenWert( 'brieftext', 'varchar', '64', '', '9', '9', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_betreffzeileoben', 'int', '11', '', '15', '15', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_name_beschreibung', 'int', '11', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_seitenrandrechts', 'int', '11', '', '15', '15', 0, 0);
  $this->AddNeuenFirmendatenWert( 'abstand_artikeltabelleoben', 'int', '11', '', '10', '10', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footersichtbar', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_breite2', 'int', '11', '', '40', '40', 0, 0);
  $this->AddNeuenFirmendatenWert( 'footer_breite3', 'int', '11', '', '55', '55', 0, 0);

  $this->AddNeuenFirmendatenWert( 'ldap_host', 'varchar', '2048', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'ldap_bindname', 'varchar', '2048', '', 'uid=%user%,cn=users,cn=accounts,dc=eigenerdcname,dc=de', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'ldap_searchbase', 'varchar', '2048', '', 'cn=accounts,dc=eigenerdcname,dc=de', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'ldap_filter', 'varchar', '2048', '', '', '', 1, 0);

  $this->AddNeuenFirmendatenWert( 'firmenhoherformularkontrast', 'int', '1', '', '', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'positionenkaufmaenischrunden', 'int', '1', '', '', '', 0, 0);


  $this->AddNeuenFirmendatenWert( 'stuecklistegewichtnurartikel', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'bestellungabschliessen', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'gutschriftkursvonrechnung', 'tinyint', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'position_quantity_change_price_update', 'int', '1', '', '1', '1', 0, 0);

  $belege = array('an','ab','re','gs','ls','be','pr','pa','pd');
  foreach($belege as $value)
  {
    for($i=1;$i<=40;$i++)
      $this->AddNeuenFirmendatenWert( 'freifeld'.$i.$value, 'tinyint', '1', '', '0', '0', 0, 0);
  }

  $this->AddNeuenFirmendatenWert( 'apiohnehtmlumwandlung', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'externeurlsblockieren', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'additionalcspheader', 'varchar', '255', '', '', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'dsgvoversandunternehmen', 'tinyint', '1', '', '0', '0', 0, 0);

  $this->AddNeuenFirmendatenWert( 'belegnummersortierungint', 'tinyint', '1', '', '0', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'belegeinanhang', 'tinyint', '1', '', '0', '0', 0, 0);

  for($i = 1; $i <= 5; $i++)
  {
    $this->AddNeuenFirmendatenWert( 'artikeltabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'adressetabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'auftragtabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'lieferscheintabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'rechnungtabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'produktiontabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'bestellungtabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
    $this->AddNeuenFirmendatenWert( 'erwbestellvorschlagtabellezusatz'.$i, 'varchar', '255', '', '', '', 0, 0);
  }
  $this->AddNeuenFirmendatenWert( 'produktionskorrektur_nichtverwenden', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'disableproductionautostart', 'int', '1', '', '0', '', 0, 0);
  $this->AddNeuenFirmendatenWert( 'closesubproductions', 'int', '1', '', '1', '1', 0, 0);
  $this->AddNeuenFirmendatenWert( 'disablecreateproductiononextern', 'int', '1', '', '0', '', 0, 0);

  $this->AddNeuenFirmendatenWert( 'server_url', 'varchar', '255', '', '', '', 1, 0);
  $this->AddNeuenFirmendatenWert( 'server_port', 'varchar', '5', '', '', '', 1, 0);

  $this->AddNeuenFirmendatenWert( 'cronjob_limit', 'int', '11', '', '3', '3', 1, 0);
  $this->AddNeuenFirmendatenWert( 'poll_repeattime', 'int', '11', '', '5', '5', 1, 0);

  $this->AddNeuenFirmendatenWert( 'versandzentrum_bild', 'tinyint', '1', '', '0', '0', 1, 0);
  $this->AddNeuenFirmendatenWert( 'proformainvoice_juststorgearticles', 'tinyint', '1', '', '1', '1', 1, 0);
  $this->AddNeuenFirmendatenWert( 'onlyemployeeprojects', 'tinyint', '1', '', '0', '0', 1, 0);
  $this->AddNeuenFirmendatenWert( 'taxfromdoctypesettings', 'tinyint', '1', '', '0', '0', 1, 0);

  $this->AddNeuenFirmendatenWert( 'group_sales', 'varchar', '255', '', '', '0', 0, 0);
  $this->AddNeuenFirmendatenWert( 'group_employee', 'varchar', '255', '', '', '0', 0, 0);

  $this->NeueFirmendatenWerteSammeln(false);
}

// @refactor Artikel Modul
public function getArtikelCachedfelder()
{
  return array(
    'lager_verfuegbar'=>'Menge',
    'ek_netto'=>'Preis',
    'ek_brutto'=>'Preis',
    'vk_netto'=>'Preis',
    'vk_brutto'=>'Preis',
    'inzulauf'=>'Menge',
    'imsperrlager'=>'Menge',
    'eigenschaften'=>'Eigenschaften',
    'inproduktion'=>'Menge',
  );
}

// @refactor Artikel Modul
public function getZusatzfelderArtikel()
{
  $artikelzusatzfelder = array(''=>'','vk_netto'=>'VK netto','vk_brutto'=>'VK brutto','ek_netto'=>'EK netto','ek_brutto'=>'EK brutto',
    'pseudopreis'=>'Pseudo Preis / UVP','lager_verfuegbar'=>'Lager verf&uuml;gbar','inzulauf'=>'in Zulauf','imsperrlager'=>'im Sperrlager', 'inproduktion'=>'in Produktion',
    'eigenschaften'=>'Eigenschaften','ean'=>'EAN','hersteller'=>'Hersteller','herstellernummer'=>'Hersteller Nr.','zolltarifnummer'=>'Zolltarifnummer');
  for($i = 1; $i <= 40; $i++) {
    $freifeldname = $this->app->erp->Firmendaten('freifeld' . $i);
    if($freifeldname != '') {
      if($this->app->erp->Firmendaten('freifeld'.$i.'typ') === 'select') {
        $freifeldname = explode('|', $freifeldname);
        $freifeldname = trim(reset($freifeldname));
      }
    } else {
      $freifeldname ='Freifeld ' . $i;
    }
    $artikelzusatzfelder['freifeld' . $i] = $freifeldname;
  }
  return $artikelzusatzfelder;
}

  /**
   * @param string $typ
   *
   * @return array
   */
  public function getFreifeldNameArr($typ)
  {
    if($typ === 'adresse') {
      $prefix = 'adresse';
    }
    elseif($typ === 'artikel') {
      $prefix = '';
    }
    else {
      return [];
    }
    $freifelder = [];
    for($i = 1; $i <= 40; $i++) {
      $freifeldname = $this->app->erp->Firmendaten($prefix.'freifeld' . $i);
      if($freifeldname != '') {
        if($this->app->erp->Firmendaten($prefix.'freifeld'.$i.'typ') === 'select') {
          $freifeldname = explode('|', $freifeldname);
          $freifeldname = trim(reset($freifeldname));
        }
      } else {
        $freifeldname ='Freifeld ' . $i;
      }
      $freifelder['freifeld' . $i] = $freifeldname;
    }
    return $freifelder;
  }

// @refactor Auftrag Modul
public function getZusatzfelderAuftrag()
{
  return array(''=>'','internet'=>'Internet','lieferdatum'=>'Wunsch Liefertermin','tatsaechlicheslieferdatum'=>'Auslieferung Lager','versandart'=>'Versandart','vertrieb'=>'Vertrieb','bearbeiter'=>'Bearbeiter','umsatz_netto'=>'Betrag (netto)');
}
// @refactor Rechnung Modul
public function getZusatzfelderRechnung()
{
  return array(''=>'','internet'=>'Internet','versandart'=>'Versandart','umsatz_netto'=>'Betrag (netto)');
}
// @refactor Auftrag Modul
public function getZusatzfelderLieferschein()
{
  return array(''=>'','internet'=>'Internet','versandart'=>'Versandart');
}

public function getZusatzfelderProduktion()
{
  return array(''=>'','datumauslieferung'=>'Auslieferung Lager','datumbereitstellung'=>'Bereitstellung Start','datumproduktion'=>'Produktion Start',
               'datumproduktionende'=>'Produktion Ende','charge'=>'Charge','mhd'=>'MHD','artikelkategorie'=>'Artikelkategorie');
}

public function getZusatzfelderBestellung()
{
  return array(''=>'','bestaetigteslieferdatum'=>'Best&auml;tigtes Lieferdatum','gewuenschteslieferdatum'=>'Wunsch Liefertermin');
}

public function getZusatzfelderErwBestellvorschlag()
{
  $erwBestellvorschlagZusatzfelder = array(''=>'');
  for($i = 1; $i <= 40; $i++) {
    $freifeldname = $this->app->erp->Firmendaten('freifeld' . $i);
    if($freifeldname != '') {
      if($this->app->erp->Firmendaten('freifeld'.$i.'typ') === 'select') {
        $freifeldname = explode('|', $freifeldname);
        $freifeldname = trim(reset($freifeldname));
      }
    } else {
      $freifeldname ='Freifeld ' . $i;
    }
    $erwBestellvorschlagZusatzfelder['freifeld' . $i] = $freifeldname;
  }
  return $erwBestellvorschlagZusatzfelder;
}




// @refactor In Adresse Modul
public function getZusatzfelderAdresse()
{
  $adressezusatzfelder = array(''=>'','telefon'=>'Telefon','telefax'=>'Fax','mobil'=>'Mobil','ansprechpartner'=>'Ansprechpartner','abteilung'=>'Abteilung','unterabteilung'=>'Unterabteilung','ustid'=>'Ust-ID','steuernummer'=>'Steuernummer','gln'=>'GLN','mitarbeiternummer'=>'Mitarbeiternummer');
  for($i = 1; $i <= 20; $i++)
  {
    $freifeldname = $this->app->erp->Firmendaten('adressefreifeld' . $i);
    if($freifeldname != '') {
      if($this->app->erp->Firmendaten('adressefreifeld'.$i.'typ') === 'select') {
        $freifeldname = explode('|', $freifeldname);
        $freifeldname = trim(reset($freifeldname));
      }
    } else {
      $freifeldname ='Freifeld ' . $i;
    }
    $adressezusatzfelder['freifeld'.$i] = $freifeldname;
  }
  return $adressezusatzfelder;
}

function BelegeimportAusfuehren($idliste = null, $uebertragungen = false)
{
  /** @var Api $api */
  $api = $this->LoadModul('api');
  if(!empty($api) && method_exists($api, 'BelegeimportAusfuehren')) {
    return $api->BelegeimportAusfuehren($idliste, $uebertragungen);
  }
}

function BelegeimportDatei($_datei = null, $uebertragungen = false)
{
  /** @var Api $api */
  $api = $this->LoadModul('api');
  if(!empty($api) && method_exists($api, 'BelegeimportDatei')) {
    return $api->BelegeimportDatei($_datei, $uebertragungen);
  }
}


  /**
   * @return int
   */
  public function GetVersandmailsMax()
  {
    /** @var Firmendaten $obj */
    $obj = $this->app->erp->LoadModul('firmendaten');
    if(empty($obj) || !method_exists($obj, 'getMaxTrackingMailToSend')) {
      return 0;
    }

    return $obj->getMaxTrackingMailToSend();
  }

  /**
   * @return int
   */
  public function GetAutoversandMaxAuftraege()
  {
    /** @var Firmendaten $obj */
    $obj = $this->app->erp->LoadModul('firmendaten');
    if(empty($obj) || !method_exists($obj, 'getMaxAutoOrderSend')) {
      return 0;
    }

    return $obj->getMaxAutoOrderSend();
  }

// @refactor In Firmendaten Modul
public function CheckSchnellsuche($cmd, $anz, $time)
{
  if(!($anz > 10000 || ($anz > 5000 && $time > 1)) ||
    !in_array($cmd, array('artikeltabelle','ticket_offene','webmail_listall','emailtabelle')) ||
    $this->Firmendaten('schnellsuche') || $this->GetKonfiguration('firmendaten_schnellsuche_gesetzt')) {
    return;
  }
  if($this->Firmendaten('schnellsuche') && !$this->GetKonfiguration('firmendaten_schnellsuche_gesetzt')) {
    $this->SetKonfigurationValue('firmendaten_schnellsuche_gesetzt',1);
    return;
  }
  $this->SetKonfigurationValue('firmendaten_schnellsuche_gesetzt',1);
  $this->FirmendatenSet('schnellsuche',1);
}

// @refactor In Firmendaten Modul
public function CheckBegrenzungLiveTabelle($cmd, $anz, $time)
{
  if(!($anz > 10000 || ($anz > 5000 && $time > 1))) {
    return;
  }
  $spalte = $this->GetBegrenzungLivetabelleColumn($cmd);
  if(empty($spalte) || $this->Firmendaten($spalte[0]) || $this->GetKonfiguration('firmendaten_'.$spalte[0].'_gesetzt')) {
    return;
  }
  $this->SetKonfigurationValue('firmendaten_'.$spalte[0].'_gesetzt',1);
  $this->FirmendatenSet($spalte[0],1);
}

// @refactor In Firmendaten Modul
public function GetBegrenzungLivetabelleColumn($cmd)
{
  switch($cmd)
  {
    case 'adressetabelle':
      return array('begrenzen_adressetabelle','begrenzenanzahl_adressetabelle');
      break;
    case 'artikeltabelle':
    case 'artikeltabellebilder':
    case 'kundeartikelpreise':
      return array('begrenzen_artikeltabelle','begrenzenanzahl_artikeltabelle');
    break;
    case 'rechnungen':
    case 'rechnungenoffene':
    case 'rechnungeninbearbeitung':
    case 'auftraege':
    case 'auftraegeinbearbeitung':
    case 'lieferscheine':
    case 'lieferscheineoffene':
    case 'gutschriften':
    case 'gutschrifteninbearbeitung':
    case 'gutschriftenoffene':
      return array('begrenzen_belege','begrenzenanzahl_belege');
      break;
  }
}

// @refactor In Firmendaten Modul
public function BegrenzungLivetabelle($cmd, $limit)
{
  $spalte = $this->GetBegrenzungLivetabelleColumn($cmd);
  if(empty($spalte) || !$this->Firmendaten($spalte[0])) {
    return false;
  }
  $limit2 = (int)$this->Firmendaten($spalte[1]);
  return $limit > $limit2?$limit:$limit2;
}

// @refactor Installer Komponente
function NeueFirmendatenWerteSammeln($aktiv)
{
  $this->firmendatenwertesammeln = $aktiv;
  if($aktiv) {
    return;
  }
  if(empty($this->firmendatenwertelist) || !is_array($this->firmendatenwertelist)) {
    return;
  }

  $firmendaten_werte = $this->app->DB->SelectArr("SELECT name FROM firmendaten_werte ORDER by name");
  $firmendaten = $this->app->DB->SelectArr("SELECT * FROM firmendaten ORDER by id DESC LIMIT 1");
  if($firmendaten_werte) {
    foreach($firmendaten_werte as $value) {
      $firmendatenexistieren[] = $value['name'];
    }
  }
  foreach($this->firmendatenwertelist as $key => $value) {
    if(!isset($firmendatenexistieren) || !in_array($value['name'], $firmendatenexistieren)) {
      $name = $value['name'];
      $typ = $value['typ'];
      $typ1 = $value['typ1'];
      $typ2 = $value['typ2'];
      $wert = $value['wert'];
      $default_value = $value['default_value'];
      $default_null = $value['default_null'];
      $darf_null = $value['darf_null'];
      if(isset($firmendaten) && isset($firmendaten[0][$name]))$wert = $firmendaten[0][$name];
      $this->app->DB->Insert("INSERT INTO firmendaten_werte (name, typ, typ1, typ2, wert, default_value, default_null, darf_null)
      values ('".$this->app->DB->real_escape_string($name)."','".$this->app->DB->real_escape_string($typ)."','".$this->app->DB->real_escape_string($typ1)."','".$this->app->DB->real_escape_string($typ2)."','".$this->app->DB->real_escape_string($wert)."','".$this->app->DB->real_escape_string($default_value)."','".(int)($default_null)."','".(int)($darf_null)."')
      ");
    }
    unset($this->firmendatenwertelist[$key]);
  }
}


// @refactor Installer Komponente
function FirmendatenVorlage()
{
    $this->FirmendatenSet("angebot_header","{ANSCHREIBEN},<br /><br />hiermit bieten wir Ihnen an:");
    $this->FirmendatenSet("angebot_footer","{IF}{GUELTIGBIS}{THEN}Das Angebot ist g&uuml;ltig bis zum: {GUELTIGBIS}{ELSE}{ENDIF}<br /><br />{IF}{LIEFERADRESSELANG}{THEN}Ihre Lieferadresse: {LIEFERADRESSELANG}{ELSE}{ENDIF}<br /><br />Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift g&uuml;ltig.");
    $this->FirmendatenSet(
        'rechnung_header',
        '{ANSCHREIBEN},<br /><br />anbei Ihre Rechnung.<br /><br />{IF}{INTERNET}{THEN}Bestellnummer: {INTERNET}<br />{ELSE}{ENDIF}{IF}{TRANSAKTIONSNUMMER}{THEN}Transaktionsnummer: {TRANSAKTIONSNUMMER}<br />{ELSE}{ENDIF}{IF}{USTID}{THEN}Ihre USt-ID: {USTID}<br />{ELSE}{ENDIF}{IF}{LIEFERBEDINGUNG}{THEN}Lieferbedingung: {LIEFERBEDINGUNG}<br />{ELSE}{ENDIF}'
    );
    $this->FirmendatenSet(
        'rechnung_footer',
        '{IF}{LIEFERADRESSE}{THEN}<strong>Lieferadresse:</strong><br />{LIEFERADRESSE}{ELSE}{ENDIF}<br />Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift g&uuml;ltig.'
    );
    $this->FirmendatenSet("lieferschein_header","{ANSCHREIBEN},<br /><br />wir liefern Ihnen:<br /><br />{IF}{TRACKINGNUMMER}{THEN}Trackingnummer/n:{TRACKINGNUMMER}{ELSE}{ENDIF}<br />&nbsp;");
    $this->FirmendatenSet("auftrag_header","{ANSCHREIBEN},<br /><br />vielen Dank f&uuml;r Ihren Auftrag.<br /><br />{IF}{LIEFERTERMIN}{THEN}Ihr Wunschliefertermin: {LIEFERTERMIN}{ELSE}{ENDIF} / {IF}{LIEFERWOCHE}{THEN}Lieferwoche: {LIEFERWOCHE}{ELSE}{ENDIF}<br /><br />{IF}{LIEFERBEDINGUNG}{THEN}Lieferbedingung: {LIEFERBEDINGUNG}{ELSE}{ENDIF}");
    $this->FirmendatenSet("gutschrift_header","{ANSCHREIBEN},<br /><br />anbei Ihre {ART}:");
    $this->FirmendatenSet("bestellung_header","{ANSCHREIBEN},<br /><br />wir bestellen hiermit:<br /><br />Unsere Auftragsnummer: {BESTELLUNGBESTAETIGTABNUMMER}<br /><strong>Lieferadresse: </strong>{LIEFERADRESSELANG}<br /><br /><strong>Bitte liefern Sie bis zum: </strong>{GEWUENSCHTESLIEFERDATUM}<br />&nbsp;");

    $this->FirmendatenSet("proformarechnung_header","{IF}{USTID}{THEN}Ihre USt-ID:{USTID}{ELSE}{ENDIF}<br />&nbsp;");
    $this->FirmendatenSet("proformarechnung_footer","Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift gültig.");
    $this->FirmendatenSet("arbeitsnachweis_header","{ANSCHREIBEN},<br /><br />wir liefern Ihnen:");
    $this->FirmendatenSet("provisionsgutschrift_header","{ANSCHREIBEN},<br /><br />,");
    $this->FirmendatenSet("lieferschein_footer","Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift gültig.");
    $this->FirmendatenSet("auftrag_footer","{IF}{LIEFERADRESSE}{THEN}<strong>Lieferadresse:</strong><br />{LIEFERADRESSE}{ELSE}{ENDIF}<br /><br />{IF}{ABWEICHENDE_RECHNUNGSADRESSE}{THEN}<strong>Abweichende Rechnungsadresse:</strong><br />{ABWEICHENDE_RECHNUNGSADRESSE}{ELSE}{ENDIF}<br /><br />Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift g&uuml;ltig.");
    $this->FirmendatenSet("gutschrift_footer","Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift gültig.");
    $this->FirmendatenSet("arbeitsnachweis_footer","Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift gültig.");
    $this->FirmendatenSet("provisionsgutschrift_footer","Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift gültig.");
    $this->FirmendatenSet("eu_lieferung_vermerk","Steuerfrei nach § 4 Nr. 1b i.V.m. § 6 a UStG. Ihre USt-IdNr. {USTID} Land: {LAND}");
    $this->FirmendatenSet("export_lieferung_vermerk","Steuerfrei (Drittland) gem. §4 Nr. 1a UStG");
    $this->FirmendatenSet("bestellung_footer","Dieses Formular wurde maschinell erstellt und ist ohne Unterschrift gültig.");
}

// @refactor Installer Komponente
function AddNeuenFirmendatenWert($name, $typ, $typ1, $typ2, $wert, $default_value, $default_null, $darf_null)
{
  if($name == '' || $typ == '')return false;
  if(isset($this->firmendatenwertesammeln) && $this->firmendatenwertesammeln)
  {
    $this->firmendatenwertelist[] = array('name'=>$name, 'typ'=>$typ,'typ1'=>$typ1,'typ2'=>$typ2,'wert'=>$wert,'default_value'=>$default_value,'default_null'=>$default_null,'darf_null'=>$darf_null);
    return;
  }
  $check = $this->app->DB->Select("SELECT id FROM firmendaten_werte WHERE name = '".$this->app->DB->real_escape_string($name)."' LIMIT 1");
  if($check)return false;
  $wert_alt = $this->app->DB->Select("SELECT $name FROM firmendaten LIMIT 1");
  if(!$this->app->DB->error())
  {
    $wert = $wert_alt;
  }
  $this->app->DB->Insert("INSERT INTO firmendaten_werte (name, typ, typ1, typ2, wert, default_value, default_null, darf_null)
  values ('".$this->app->DB->real_escape_string($name)."','".$this->app->DB->real_escape_string($typ)."','".$this->app->DB->real_escape_string($typ1)."','".$this->app->DB->real_escape_string($typ2)."','".$this->app->DB->real_escape_string($wert)."','".$this->app->DB->real_escape_string($default_value)."','".(int)($default_null)."','".(int)($darf_null)."')
  ");
  return $this->app->DB->GetInsertID();
}

// @refactor Installer Komponente
function CheckGeschaeftsbriefvorlagen($subjekt,$sprache,$betreff,$text)
{
  if($sprache=="") $sprache="deutsch";

  if($sprache=="deutsch" || $sprache=="")
    $check = $this->app->DB->Select("SELECT id FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND subjekt!='' LIMIT 1");
  else if($sprache!="")
    $check = $this->app->DB->Select("SELECT id FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND subjekt!='' AND sprache='$sprache' LIMIT 1");

  if($check <=0)
  {
    $this->app->DB->Insert("INSERT INTO geschaeftsbrief_vorlagen (sprache, betreff, text, subjekt, projekt, firma) VALUES ('$sprache', '$betreff', '$text', '$subjekt', '0', 1)");
  }
}

// START deprecated database upgrade functions

  public function ensureDatabaseUpgradeProperty()
  {
/*    if ($this->app->DatabaseUpgrade === null) {
      $this->app->DatabaseUpgrade = new DatabaseUpgrade($this->app);
    }*/
  }

  function CheckTable($table, $pk = 'id')
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->CheckTable($table, $pk);*/
  }

  function UpdateColumn($column,$type,$table,$default="NOT NULL")
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->UpdateColumn($column,$type,$table,$default);*/
  }

  public function emptyTableCache()
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->emptyTableCache();*/
  }

  public function DeleteColumn($column,$table)
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->DeleteColumn($column,$table);*/
  }

  public function CheckColumn($column,$type,$table,$default="")
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->CheckColumn($column,$type,$table,$default);*/
  }

  /**
   * @param string $table
   * @param array  $columns
   */
  public function dropIndex($table, $columns)
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->dropIndex($table, $columns);*/
  }

  protected function ChangeFirmendatenToMyIsam()
  {
/*    $this->ensureDatabaseUpgradeProperty();
    $this->app->DatabaseUpgrade->ChangeFirmendatenToMyIsam();*/
  }


  public function CheckDoubleIndex($table, $indexe)
  {
/*    $this->ensureDatabaseUpgradeProperty();
    return $this->app->DatabaseUpgrade->CheckDoubleIndex($table,$indexe);*/
  }

  public function CheckFulltextIndex($table, $column)
  {
/*    $this->ensureDatabaseUpgradeProperty();
    return $this->app->DatabaseUpgrade->CheckFulltextIndex($table,$column);*/
  }

  public function CheckIndex($table, $column, $unique = false)
  {
/*    $this->ensureDatabaseUpgradeProperty();
    return $this->app->DatabaseUpgrade->CheckIndex($table,$column,$unique);*/
  }

  public function CheckAlterTable($sql, $force = false)
  {
/*    $this->ensureDatabaseUpgradeProperty();
    return $this->app->DatabaseUpgrade->CheckAlterTable($sql,$force);*/
  }

// END deprecated database upgrade functions
    
  // @refactor Welcome Modul
  function CheckFav($bezeichnung, $url)
  {
    if($this->app->erp->GetKonfiguration('checkFav'. md5($url))) {
      return;
    }
    $this->app->erp->SetKonfigurationValue('checkFav'. md5($url),1);
    $user = $this->app->DB->SelectArr(
      "SELECT u.id 
      FROM `user` u 
      LEFT JOIN `userrights` ur ON u.id = ur.`user` AND ur.module = 'amazon' AND ur.action = 'list' 
      WHERE NOT isnull(ur.id) OR u.type = 'admin'"
    );
    if(empty($user)) {
      return;
    }
    foreach($user as $vu) {
      $u = $vu['id'];
      $eigenlinks = $this->app->DB->Select("SELECT uk.`value` FROM `userkonfiguration` uk WHERE `name` = 'welcome_links_eigen' AND `user` = '$u'  LIMIT 1");
      $index = 1;
      $check2 = null;
      $check3 = null;
      if($eigenlinks)
      {
        for($i = 1; $i <= 8; $i++)
        {
          $link = $this->app->DB->SelectRow("SELECT uk.`value`, uk.id FROM `userkonfiguration` uk WHERE `name` = 'welcome_linklink".$i."' AND `user` = '$u'  LIMIT 1");
          if(!$link)
          {
            $link = array('id'=>0, 'link'=>'');
          }
          if(stripos($link['value'], $url) !== false)
          {
            $index = 9;
            break;
          }
          if($link['value'] != '')
          {
            if($index == $i)$index++;
          }else{
            $check2 = $link['id'];
            $check3 = $this->app->DB->Select("SELECT uk.id FROM `userkonfiguration` uk WHERE `name` = 'welcome_linkname".$i."' AND `user` = '$u'  LIMIT 1");
            break;
          }
        }
      }else{
        $check = $this->app->DB->Select("SELECT id FROM `userkonfiguration` uk WHERE `name` = 'welcome_links_eigen' AND `user` = '$u'  LIMIT 1");
        if($check)
        {
          $this->app->DB->Update("UPDATE `userkonfiguration` SET `value` = '1' WHERE id = '$check' LIMIT 1");
        }else{
          $this->app->DB->Insert("INSERT INTO `userkonfiguration` (`user`, `value`, `name`) VALUES ('$u', '1', 'welcome_links_eigen')");
        }
        if(!$this->app->DB->Select("SELECT id FROM `userkonfiguration` WHERE `user` = '$u' AND `name` LIKE 'welcome\_linklink_%'"))
        {
          $index = 2;
          $this->app->DB->Insert("INSERT INTO `userkonfiguration` (`user`, `value`, `name`) VALUES ('$u', 'index.php?module=welcome&action=settings', 'welcome_linklink1')");
          $this->app->DB->Insert("INSERT INTO `userkonfiguration` (`user`, `value`, `name`) VALUES ('$u', 'Eigene Einstellungen', 'welcome_linkname1')");
        }
      }
      if($index <= 8)
      {
        if($check2)
        {
          $this->app->DB->Update("UPDATE `userkonfiguration` SET `value` = '".$this->app->DB->real_escape_string($url)."' WHERE id = '$check2' LIMIT 1");
        }else
        {
          $this->app->DB->Insert("INSERT INTO `userkonfiguration` (`user`, `value`, `name`) VALUES ('$u', '".$this->app->DB->real_escape_string($url)."', 'welcome_linklink".$index."')");
        }
        if($check3)
        {
          $this->app->DB->Update("UPDATE `userkonfiguration` SET `value` = '".$this->app->DB->real_escape_string($bezeichnung)."' WHERE id = '$check3' LIMIT 1");
        }else{
          $this->app->DB->Insert("INSERT INTO `userkonfiguration` (`user`, `value`, `name`) VALUES ('$u', '".$this->app->DB->real_escape_string($bezeichnung)."', 'welcome_linkname".$index."')");
        }
      }
    }
  }

  /**
   * @param string $parameter
   * @param string $target
   * @param bool   $withForm
   */
  public function checkActiveCronjob($parameter, $target = 'MESSAGE', $withForm = true)
  {
    /** @var Prozessstarter $obj */
    $obj = $this->app->erp->LoadModul('prozessstarter');
    if($obj && method_exists($obj,'checkActiveCronjob')) {
      $obj->checkActiveCronjob($parameter, $target, $withForm);
    }
  }

  // @refactor Installer Komponente

  /**
   * @param string $bezeichnung
   * @param string $art
   * @param string $periode
   * @param string $startzeit
   * @param string $typ
   * @param string $parameter
   * @param int    $aktiv
   *
   * @return bool|int|string|null
   */
  public function CheckProzessstarter($bezeichnung,$art='periodisch',$periode='1440',$startzeit='',$typ='cronjob',$parameter='',$aktiv=0)
  {
    if($parameter === '') {
      return false;
    }
    $check = $this->app->DB->SelectRow(
      sprintf(
        "SELECT `id`, `recommended_period` FROM `prozessstarter` WHERE `parameter` LIKE '%s' LIMIT 1",
        $this->app->DB->real_escape_string($parameter)
      )
    );
    if(!empty($check)) {
      if((int)$check['recommended_period'] !== (int)$periode) {
        $this->app->DB->Update(
          sprintf(
            'UPDATE `prozessstarter` SET `recommended_period` = %d WHERE `id` = %d',
            $periode, $check['id']
          )
        );
      }
      return false;
    }

    $sql = sprintf(
      "INSERT INTO `prozessstarter` (`bezeichnung`,`art`,`periode`,`recommended_period`,
                              `startzeit`,`typ`,`parameter`,`aktiv`) 
       VALUES ('%s','%s','%d','%d','%s','%s','%s','%d')",
      $this->app->DB->real_escape_string($bezeichnung),
      $this->app->DB->real_escape_string($art),
      $periode,
      $periode,
      $this->app->DB->real_escape_string($startzeit),
      $this->app->DB->real_escape_string($typ),
      $this->app->DB->real_escape_string($parameter),
      (int)(bool)$aktiv
    );
    $this->app->DB->Insert($sql);
    return $this->app->DB->GetInsertID();
  }

  // @refactor Firmendaten Modul
  function ArtikelFreifeldBezeichnungen()
  {
    for($i = 1; $i <= 40; $i++) {
      $freifeldbezeichnung = $this->app->erp->Firmendaten('freifeld'.$i);
      if($freifeldbezeichnung == '') {
        $this->app->Tpl->Set('FREIFELD' . $i . 'BEZEICHNUNG', 'Freifeld '.$i);
        continue;
      }
      $freifeldtyp = $this->app->erp->Firmendaten('freifeld'.$i.'typ');
      if($freifeldtyp === 'select') {
        $freifeldbezeichnung = explode('|', $freifeldbezeichnung);
        $freifeldbezeichnung = trim(reset($freifeldbezeichnung));
      }
      $this->app->Tpl->Set('FREIFELD' . $i . 'BEZEICHNUNG', $freifeldbezeichnung);
    }
  }


  // @refactor Firmendaten Modul
  function ProjektFreifeldBezeichnungen()
  {
    for($i = 1; $i <= 20; $i++) {
      if($this->app->erp->Firmendaten('projektfreifeld'.$i)!='') {
        $this->app->Tpl->Set('PROJEKTFREIFELD' . $i . 'BEZEICHNUNG', $this->app->erp->Firmendaten('projektfreifeld' . $i));
      }
      else {
        $this->app->Tpl->Set('PROJEKTFREIFELD' . $i . 'BEZEICHNUNG', "Freifeld $i");
      }
    }
  }

// @refactor DateHelper Komponente
function IstWerktag($datum)
{
  if($this->IstFreierTag($datum)) return false;
  else return true;
}

// @refactor Arbeitsfreietage Modul
function IstFreierTag($datum) {

  $tmp = explode('-',$datum);
  $jahr = $tmp[0];
  $monat = $tmp[1];
  $tag = $tmp[2];

  // Parameter in richtiges Format bringen
  if(strlen($tag) == 1) {
    $tag = "0$tag";
  }
  if(strlen($monat) == 1) {
    $monat = "0$monat";
  }

  // Wochentag berechnen
  $datum = getdate(mktime(0, 0, 0, $monat, $tag, $jahr));
  $wochentag = $datum['wday'];

  // Prüfen, ob Wochenende
  if($wochentag == 0 || $wochentag == 6) {
    return true;
  }

  // Feste Feiertage werden nach dem Schema ddmm eingetragen
  $feiertage[] = "0101"; // Neujahrstag
  $feiertage[] = "0105"; // Tag der Arbeit
  $feiertage[] = "0310"; // Tag der Deutschen Einheit
  $feiertage[] = "2512"; // Erster Weihnachtstag
  $feiertage[] = "2612"; // Zweiter Weihnachtstag

  // Bewegliche Feiertage berechnen
  $tage = 60 * 60 * 24;
  $ostersonntag = easter_date($jahr);
  $feiertage[] = date("dm", $ostersonntag - 2 * $tage);  // Karfreitag
  $feiertage[] = date("dm", $ostersonntag + 1 * $tage);  // Ostermontag
  $feiertage[] = date("dm", $ostersonntag + 39 * $tage); // Himmelfahrt
  $feiertage[] = date("dm", $ostersonntag + 50 * $tage); // Pfingstmontag
  $feiertage[] = date("dm", $ostersonntag + 60 * $tage); // Frohnleichnahm

  // Prüfen, ob Feiertag
  $code = $tag.$monat;
  return in_array($code, $feiertage);
}

// @refactor Firmendaten Modul
function NeueArtikelNummer($artikelart="",$firma="",$projekt="")
{
  return $this->GetNextArtikelnummer($artikelart,$firma,$projekt);
}



    // @refactor Adapterbox Modul
    function GetAdapterboxAPIDisplay($deviceiddest,$ausgabe)
    {
      // hole baudrate aus einstellungen
      $art = "display";
      if(!isset($ausgabe[0])) $ausgabe[0] = "";
      if(!isset($ausgabe[1])) $ausgabe[1] = "";

      // alte zeilen loeschen
      $anzahlzeichen = 19;
      $ausgabe[0] = str_pad(substr(trim($ausgabe[0]),0,$anzahlzeichen+1), $anzahlzeichen+1, " ", STR_PAD_RIGHT);
      $ausgabe[1] = str_pad(substr(trim($ausgabe[1]),0,$anzahlzeichen), $anzahlzeichen, " ", STR_PAD_RIGHT);
      $text = implode($ausgabe);

      //$ausgabe[0] = "012345678901234567890";

      //$job = '<display>'.$disbase64.'</display>';
      $job = '<display><text>'.$text.'</text></display>';
      $result = $this->AdapterboxAPI($deviceiddest,$art,$job,false);

      return unserialize(base64_decode($result));
    }

    // @refactor Adapterbox Modul
    function GetAdapterboxAPIBondrucker($deviceiddest,$bonbase64)
    {
      // hole baudrate aus einstellungen
      $art = "bondrucker";

      $job = '<label>'.$bonbase64.'</label>';
      $result = $this->AdapterboxAPI($deviceiddest,$art,$job,false);

      return unserialize(base64_decode($result));
    }

    // @refactor Adapterbox Modul
    function GetAdapterboxAPIImage($deviceiddest,$width=0,$height=0)
    {
      //480x360
      //800x600
      //960x720
      // hole baudrate aus einstellungen
      $art = "kamera";

      $job = '<image><settings width="'.$width.'" height="'.$height.'"></settings></image>';
      $result = $this->AdapterboxAPI($deviceiddest,$art,$job,true);

      return unserialize(base64_decode($result));
    }
    // @refactor Adapterbox Modul
    function GetAdapterboxAPIRFID($deviceiddest)
    {
      $art = "metratecrfid";

      $job="";
      $result = $this->AdapterboxAPI($deviceiddest,$art,$job,true, 3);
      if(rand(0,100) == 0)$this->app->DB->Delete("DELETE FROM device_jobs WHERE art = 'metratecrfid' AND zeitstempel < DATE_SUB(now(), INTERVAL 5 MINUTE)");//Hin und wieder alte Einträge entfernen
      return $result;
    }
    // @refactor Adapterbox Modul
    function GetAdapterboxAPIRKSVlight($deviceiddest,$parameters)
    {
      $art = "rksvlight";
      $job = '<rksvlight>'.$parameters.'</rksvlight>';
      $result = $this->AdapterboxAPI($deviceiddest,$art,$job,true);
      return $result;
    }
    // @refactor Adapterbox Modul
    function GetAdapterboxAPIWaage($deviceiddest)
    {
      $baud = $this->app->DB->Select("SELECT baudrate FROM adapterbox WHERE seriennummer='$deviceiddest' LIMIT 1");
      if($baud=="") $baud=1;

      $model = $this->app->DB->Select("SELECT model FROM adapterbox WHERE seriennummer='$deviceiddest' LIMIT 1");
      if($model=="") $model="marel";

      switch($model)
      {
        case "marel":
          $timeout = 2;
          $chars = 100;
        break;
        case "pce":
          $timeout = 10;
          $chars = 15;
        break;
        case "sartorius":
          $timeout = 20;
          $chars = 150;
        break;

      }

      // hole baudrate aus einstellungen
      //$baud = 2; // 1 = 4800, 2 = 9600
      //$model = "marel";
      $art = "waage";
      if($model=="sartorius")
        $job = '<waage><settings baud="'.$baud.'" chars="'.$chars.'" timeout="'.$timeout.'" parity="1"></settings></waage>';
      else
        $job = '<waage><settings baud="'.$baud.'" chars="'.$chars.'" timeout="'.$timeout.'"></settings></waage>';

      $result = $this->AdapterboxAPI($deviceiddest,$art,$job,true);

      // gewicht string entpacken
      //$result =  base64_decode(urldecode($result));

      if($model=="marel")
      {
        $result = explode("kg",$result);
        $last_string =  $result[(!empty($result)?count($result):0)-2];
        $result = explode(" ",$last_string);
        return $result[(!empty($result)?count($result):0)-2];
      }
      if($model=="sartorius")
      {
        $matches = array();
        $regex = "/N*+([\. 0-9_]*)g/";
        preg_match_all($regex, $result, $matches);
        return trim($matches[1][0]);
      }
      if($model=="pce")
      {
        if (strpos($result, 'kg') !== false) {
          // neue PCE-PB N Serie
          $result = explode("kg",$result);
          $result[0] = str_replace('+','',$result[0]);
          $result[0] = str_replace('-','',$result[0]);
          return trim($result[0]);
        }
        //altes modell
        $result = explode("Kg",$result);

        $last_string =  $result[(!empty($result)?count($result):0)-2];
        $result = explode(" ",$last_string);
        $tmp =  $result[(!empty($result)?count($result):0)-2];

        preg_match_all("/\d+/",$tmp,$result);
        return (int)$result[0][count($result[0])-1]/1000;
      }

      return $result;
    }
// @refactor Payment Komponente
function SendPaypalFromAuftrag($auftrag, $test = false)
{
  $konten = $this->app->DB->SelectArr("SELECT * FROM konten WHERE type = 'paypal' AND aktiv = 1");
  if(empty($konten) || (!empty($konten)?count($konten):0) != 1) {
    return false;
  }

  $konto = $konten[0]['id'];
  $zugangsdaten = $this->app->DB->Select("SELECT liveimport FROM konten WHERE id='$konto' LIMIT 1");
  $zugangsdaten = html_entity_decode($zugangsdaten,ENT_QUOTES,"UTF-8");
  $zugangsdaten = $this->Config2Array($zugangsdaten);
  if(empty($zugangsdaten)) {
    return false;
  }

  if(!isset($zugangsdaten['SECRET']) || !isset($zugangsdaten['CLIENT_ID']) || !isset($zugangsdaten['API_EMAIL'])){
    return false;
  }
  $arr = $this->app->DB->SelectRow("SELECT * FROM auftrag WHERE id = '$auftrag' LIMIT 1");
  if(empty($arr)) {
    return false;
  }
  if($arr['zahlungsweise'] !== 'paypal' || !empty($arr['transaktionsnummer']) || empty($arr['email'])) {
    return false;
  }

  if($test) {
    return true;
  }
  $positionen = $this->app->DB->SelectArr(
    "SELECT * FROM auftrag_position WHERE auftrag = '$auftrag' ORDER BY sort"
  );
  if(empty($positionen)) {
    return false;
  }

  if(isset( $zugangsdaten['SANDBOX']) && $zugangsdaten['SANDBOX'])
  {
    $urltoken = "https://api.sandbox.paypal.com/v1/oauth2/token";
    $urlcreateinvoice = 'https://api.sandbox.paypal.com/v1/invoicing/invoices';
  } else {
    $urltoken = "https://api.paypal.com/v1/oauth2/token";
    $urlcreateinvoice = 'https://api.paypal.com/v1/invoicing/invoices';
  }

  $headers = array(
    "Accept: application/json",
    "Accept-Language: de_DE",
  );
  $ch = curl_init();
  $clientId = $zugangsdaten['CLIENT_ID'];
  $secret = $zugangsdaten['SECRET'];
  $email = $zugangsdaten['API_EMAIL'];
  if(!$ch) {
    return array('error'=>'Falsche Zugangsdaten');
  }
  curl_setopt($ch, CURLOPT_URL,$urltoken);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_TIMEOUT, 60);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($ch, CURLOPT_USERPWD, $clientId.":".$secret);
  curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
  $content=curl_exec($ch);
  if(empty($content)) {
    return array('error'=>'Falsche Zugangsdaten');
  }
  $json= json_decode($content);
  if(!isset($json->access_token)) {
    return array('error'=>'Falsche Zugangsdaten');
  }
  $access_token = $json->access_token;

  $data = new stdClass();
  $data->number = $arr['belegnr'];
  $data->invoice_date = $arr['datum'].' PST';
  $data->merchant_info = new stdClass();

  $data->merchant_info->email = $email;
  $data->merchant_info->business_name = $this->Firmendaten('name');
  //$data->merchant_info->phone = new stdClass();
  //$data->merchant_info->phone->country_code = "49";
  //$data->merchant_info->phone->national_number = "821";
  $data->merchant_info->address = new stdClass();
  $data->merchant_info->address->line1 = $this->Firmendaten('strasse');
  $data->merchant_info->address->city = $this->Firmendaten('ort');
  $data->merchant_info->address->state = '-';
  $data->merchant_info->address->postal_code = $this->Firmendaten('plz');
  $data->merchant_info->address->country_code = $this->Firmendaten('land');
  $billing_info = new stdClass();
  $billing_info->email = $arr['email'];
  $data->billing_info[] = $billing_info;

  $data->custom = new stdClass();
  $data->custom->label = 'Gesamtsumme';
  $data->custom->amount = new stdClass();
  $data->custom->amount->value = $arr['gesamtsumme'];
  $data->custom->amount->currency = $arr['waehrung']?$arr['waehrung']:'EUR';

  $data->note = 'Detailierte Informationen zu einelnen Positionen finden Sie in der Auftragsbestätigung AB'.$arr['belegnr'];

  $data->shipping_info = new stdClass();

  if(empty($arr['ansprechpartner']))
  {
    $name = explode(' ',$arr['name'],2);
    if((!empty($name)?count($name):0) == 2)
    {
      $data->shipping_info->first_name = $name[0];
      $data->shipping_info->last_name = $name[1];
    }else{
      $data->shipping_info->last_name = $name[0];
    }
  }else{
    $data->shipping_info->business_name = $arr['name'];
  }

  $data->shipping_info->address = new stdClass();
  $data->shipping_info->address->line1 = $arr['strasse'];
  $data->shipping_info->address->city = $arr['ort'];
  $data->shipping_info->address->postal_code = $arr['plz'];
  $data->shipping_info->address->state = '-';
  $data->shipping_info->address->country_code = $arr['land'];
  $ch = curl_init();
  $headers2 = array(
      "Content-Type: application/json",
   "Authorization: Bearer ".$access_token
  );
  curl_setopt($ch, CURLOPT_URL,$urlcreateinvoice);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_TIMEOUT, 60);
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers2);
  curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  $content=curl_exec($ch);
  $erg= json_decode($content);
  if(isset($erg->id)) {
    $this->app->DB->Update("UPDATE auftrag set transaktionsnummer = '".($erg->id)."' WHERE id = '$auftrag' LIMIT 1");
    curl_close($ch);
    $headers3 = array(
        "Content-Type: application/json",
     "Authorization: Bearer ".$access_token
    );
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$urlcreateinvoice.'/'.$erg->id.'/send');
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_TIMEOUT, 60);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers3);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
    $content=curl_exec($ch);
    $getinfo = curl_getinfo($ch);
    if($getinfo['http_code'] != '202')
    {
      return array('error'=>'Email konnte nicht an Absender Versendet werden HTTP-Code: '.$getinfo['http_code'],'ID'=>$erg->id);
    }
    curl_close($ch);
    return array('status'=>'ok','ID'=>$erg->id);
  }
  if(isset($erg->details))
  {
    foreach($erg->details as $fehler )
    {
      $res[] = $fehler->field.' '.$fehler->issue;
    }
    return array('error'=>'Es sind Fehler aufgetreten: '.implode('<br>',$res));
  }
  return array('error'=>'Es sind Fehler aufgetreten: '.json_encode($erg));
}

    // @refactor Adapterbox Modul
    function AdapterboxAPI($deviceiddest,$art,$job,$with_answer = false, $maxseconds = 10)
    {

      $status = $this->app->DB->Select("SELECT if(TIME_TO_SEC(TIMEDIFF(NOW(),letzteverbindung)) > 10 OR letzteverbindung IS NULL,'disconnected','connected') FROM adapterbox
        WHERE seriennummer='$deviceiddest' AND seriennummer!='' LIMIT 1");

      // pruefe ob es ein drucker ist
      $check_printer = $this->app->DB->Select("SELECT id FROM drucker WHERE adapterboxseriennummer!='' AND adapterboxseriennummer='$deviceiddest' LIMIT 1");

      if($check_printer > 0)
      {
        // drucker auftraege koennen immer angenommen werden
      } else {
        if($status !='connected') {
          return -1;
        }
      }

      $this->app->DB->Insert("INSERT INTO device_jobs (id,zeitstempel,deviceidsource,deviceiddest,job,art) VALUES ('',NOW(),'000000000','$deviceiddest','$job','$art')");
      $request_id = $this->app->DB->GetInsertID();

      if($with_answer!=true) return;

      $nottimeout=0;
      while(1)
      {
        $nottimeout++;
        usleep(200000); // millisekunden

        // 10 sekunden
        if($nottimeout > $maxseconds*5)
        {
          if($art == 'metratecrfid')
          {
            $this->app->DB->Delete("DELETE FROM device_jobs WHERE id = '$request_id' LIMIT 1");
          }
          return "no answer from device (not timeout)";
          break;
        }

        $check_result = $this->app->DB->Select("SELECT id FROM device_jobs WHERE request_id='$request_id' AND request_id>0 LIMIT 1");

        if($check_result > 0)
        {
          $job = $this->app->DB->Select("SELECT job FROM device_jobs WHERE id='$check_result' LIMIT 1");
          $this->app->DB->Delete("DELETE FROM device_jobs WHERE id='$check_result' LIMIT 1");
          //$job =  base64_decode($job); // device_job layer
          $job =  base64_decode($job); // device_job layer
          $job =  base64_decode(urldecode($job));
          if($art == 'metratecrfid')$this->app->DB->Delete("DELETE FROM device_jobs WHERE id = '$request_id' LIMIT 1");
          return $job;
        }
      }
    }

    // @refactor Etiketten Modul
    function PNG2Etikett($pfad)
    {
      $image_string = file_get_contents($pfad);

      if(mime_content_type($pfad)!="image/png") return array('result'=>0,'message'=>"Falsches Dateiformat! Es wird nur monochrom .png unterstuetzt");

      $image = imagecreatefromstring($image_string);
      $width = imagesx($image);
      $height = imagesy($image);
      $colors = array();

      for ($y = 0; $y < $height; $y++)
      {
        for ($x = 0; $x < $width; $x++)
        {
          $rgb = imagecolorat($image, $x, $y);
          $r = ($rgb >> 16) & 0xFF;
          $g = ($rgb >> 8) & 0xFF;
          $b = $rgb & 0xFF;

          $black = ($r == 0 && $g == 0 && $b == 0);
          $colors[$x][$y] = $black;

          if($counter <=7)
          {
            if($black)
              $binary .="0";
            else
              $binary .="1";
          }
          $counter++;


          if($counter >7)
          {
            $gesamt[] = bindec($binary);
            $binary="";
            $counter=0;
          }
        }
      }
      $image = $gesamt;
      //echo "height: $height \r\n";
      //echo "width: $width \r\n";

      $stream = "";
      for($i=0;$i<$width*$height;$i = $i + 32)
      {
        //if(!isset($image[$i]))$image[$i]=0xFF;
        $stream .= pack("C*",$image[$i],$image[$i+1],$image[$i+2],$image[$i+3],$image[$i+4],$image[$i+5],$image[$i+6],$image[$i+7],
            $image[$i+8],$image[$i+9],$image[$i+10],$image[$i+11],$image[$i+12],$image[$i+13],$image[$i+14],$image[$i+15],
            $image[$i+16],$image[$i+17],$image[$i+18],$image[$i+19],$image[$i+20],$image[$i+21],$image[$i+22],$image[$i+23],
            $image[$i+24],$image[$i+25],$image[$i+26],$image[$i+27],$image[$i+28],$image[$i+29],$image[$i+30],$image[$i+31]
            );
      }


      $stream = serialize($stream);
      $stream = gzcompress($stream, 9);
      $stream = base64_encode($stream);
      return array('width'=>$width,'height'=>$height,'stream'=>$stream,'result'=>1);
    }

    // @refactor Etiketten Modul
    function ArtikelStuecklisteDrucken($artikel)
    {
      $artikel = $this->app->DB->SelectArr("SELECT * FROM stueckliste WHERE stuecklistevonartikel='$artikel'");
      if(empty($artikel))
      {
        return;
      }
      for($i=0;$i<(!empty($artikel)?count($artikel):0);$i++)
      {
        $artikelid = $artikel[$i]['artikel'];
        $variablen = reset($artikel);
        $this->EtikettenDrucker("artikel_klein",1,"artikel",$artikelid,$variablen);
      }
    }

    // @refactor Bondrucker Komponente
    function AufgabeBonDrucker($id,$seriennummer)
    {
      $data = $this->app->DB->SelectRow("SELECT * FROM aufgabe WHERE id='$id' LIMIT 1");

      if($data['kunde'] > 0)
      {
        $kunde = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='".$data['kunde']."' LIMIT 1");
      }
      if($data['adresse'] > 0)
      {
        $adresse = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='".$data['adresse']."' LIMIT 1");
      }

      if($data['projekt'] > 0)
      {
        $projekt = $this->app->DB->SelectRow("SELECT * FROM projekt WHERE id='".$data['projekt']."' LIMIT 1");
      }

      $printer = new phpprint();
      //$printer->pulse();
      $printer->newline();


      $printer->set_justification(phpprint::JUSTIFY_CENTER);
      $printer->qrCode("AUFGABE:$id",phpprint::QR_ECLEVEL_L,6);
      $printer->feed(2);

      $printer->set_font(phpprint::FONT_A);
      $printer->enlargePrint(true);

      $printer->set_justification(phpprint::JUSTIFY_LEFT);

      if($data['kunde'] > 0)
        $printer->text("Kunde: ".$kunde['name']."\n");
      else
        $printer->text("Allgemeine Aufgabe"."\n");

      $printer->newline();
      $printer->enlargePrint();
      $printer->set_font(phpprint::FONT_C);

      $printer->text($data['aufgabe']."\n");
      $printer->feed(1);


      if($data['beschreibung']!=$data['aufgabe'] && $data['aufgabe']!="")
      {
        $printer->text("Beschreibung: ".$projekt['abkuerzung']."\n");
        $printer->text("------------------------------------------\n");
        $printer->text($data['beschreibung']."\n");
        $printer->feed(1);
      }

      $zeitstempel = date('d.m.y H:i:s');

      if($data['adresse'] > 0)
        $printer->text("Mitarbeiter: ".substr($adresse['name'],0,25)."\n");

      if($data['projekt'] > 0)
        $printer->text("Projekt: ".$projekt['abkuerzung']."\n");
      $printer->text("Gedruckt am: ".$zeitstempel."\n");

      $printer->cut();

      $bon = base64_encode($printer->str);

      $this->app->erp->GetAdapterboxAPIBondrucker($seriennummer,$bon);
    }

    // @refactor POS Modul
    function RKSVSignatur($projekt,$rechnungid=0,$normaltax,$discount1,$discount2,$special,$zero,$type="normal")
    {
      $obj = $this->app->erp->LoadModul('pos');
      if(!empty($obj) && method_exists($obj,'RKSVSignatur')){
        return $obj->RKSVSignatur($projekt,$rechnungid,$normaltax,$discount1,$discount2,$special,$zero,$type);
      }
    }

    // @refactor POS Modul
    function KommandoRKSV($deviceiddest,$art,$type,$cashbox,$reader,$cardpin,$receipt,$datetime,$normal,$discount1,$discount2,$special,$zero,$salescounter,$siglastreceipt,$aesbase64,&$signature,&$error)
    {
      $obj = $this->app->erp->LoadModul('pos');
      if(!empty($obj) && method_exists($obj,'KommandoRKSV')){
        return $obj->KommandoRKSV($deviceiddest,$art,$type,$cashbox,$reader,$cardpin,$receipt,$datetime,$normal,$discount1,$discount2,$special,$zero,$salescounter,$siglastreceipt,$aesbase64,$signature,$error);
      }
    }




  // @refactor EtikettenDrucker Komponente
  function EtikettenDrucker($kennung,$anzahl,$tabelle,$id,$variables="",$xml="",$druckercode="",$filenameprefix="",$xmlaspdf=false,$adresse=0,$verwendenals="")
  {
    if($anzahl<=0){
      $anzahl=1;
    }

    $this->RunHook('erpapi_etikettendrucker', 11, $kennung,$anzahl,$tabelle,$id,$variables,$xml,$druckercode,$filenameprefix,$xmlaspdf,$adresse,$verwendenals);

    if($anzahl <= 0){
      return;
    }

      if($druckercode <=0)
      {
          $druckercode = $this->Firmendaten("standardetikettendrucker");
          if($druckercode <=0)
          {
            $druckercode = $this->app->DB->Select("SELECT id FROM drucker WHERE art=2 LIMIT 1");
          }
      }

          //format
        $tmpdata = $this->app->DB->SelectRow("SELECT format,art,anbindung FROM drucker WHERE id='$druckercode' LIMIT 1");

        $format = $tmpdata['format'];

        if($tmpdata['art']==2 && $tmpdata['anbindung']!="adapterbox")
          $checkpdf=1;
        else
          $checkpdf=0;

        if($tmpdata['anbindung']=="spooler") $checkpdf=1;

        //$this->LogFile("Drucker $druckercode format $format");

        switch($kennung)
        {
          case "artikel_klein":
            switch($format)
            {
              case "30x15x3":
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="4" type="1">{NUMMER}</barcode>
                  <line x="3" y="7" size="2">NR {NUMMER}</line>
                  <line x="3" y="10" size="2">{NAME_DE}</line>
                  </label>
                  ';
                break;
              default: //50x18x3
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="8" type="2">{NUMMER}</barcode>
                  <line x="3" y="10" size="4">NR {NUMMER}</line>
                  <line x="3" y="13" size="4">{NAME_DE}</line>
                  </label>
                  ';
            }
            break;

          case "lieferschein_position":
            switch($format)
            {
              case "30x15x3":
                $xml ='
                  <label>
                    <barcode y="1" x="3" size="6" type="2">{NUMMER}</barcode>
                    <line x="3" y="8" size="3">Artikel-Nr. {NUMMER}</line>
                    <line x="3" y="11" size="3">{NAME_DE} </line>
                    <line x="3" y="14" size="3">LS: {BELEGNR} Menge: {MENGE} {LAGER_PLATZ_NAME}</line>

                  </label>
                  ';
                break;
              default: //50x18x3
                $xml ='
                  <label>
                    <barcode y="1" x="3" size="6" type="2">{NUMMER}</barcode>
                    <line x="3" y="8" size="3">Artikel-Nr. {NUMMER}</line>
                    <line x="3" y="11" size="3">{NAME_DE}</line>
                    <line x="3" y="14" size="3">LS: {BELEGNR} Menge: {MENGE} {LAGER_PLATZ_NAME}</line>
                  </label>
                  ';
            }
            break;



          case "seriennummer":
            switch($format)
            {
              case "30x15x3":
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="6" type="1">{SERIENNUMMER}</barcode>
                  <line x="3" y="8" size="3">SRN:{SERIENNUMMER}</line>
                  </label>
                  ';
                break;
              default: //50x18x3
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="8" type="2">{SERIENNUMMER}</barcode>
                  <line x="3" y="10" size="3">SRN: {SERIENNUMMER}</line>
                  </label>
                  ';
            }
            break;


          case "dms":
            switch($format)
            {
              case "30x15x3":
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="6" type="1">{ID}</barcode>
                  <line x="3" y="8" size="3">DMS: {LABEL} {ID}</line>
                  </label>
                  ';
                break;
              default: //50x18x3
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="8" type="2">{ID}</barcode>
                  <line x="3" y="10" size="3">DMS: {LABEL} {ID}</line>
                  </label>
                  ';
            }
            break;


          case "lagerplatz_klein":
            switch($format)
            {
              case "30x15x3":
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="6" type="1">{ID}</barcode>
                  <line x="3" y="8" size="3">Lager:{KURZBEZEICHNUNG}</line>
                  </label>
                  ';
                break;
              default: //50x18x3
                $xml ='
                  <label>
                  <barcode y="1" x="3" size="8" type="2">{ID}</barcode>
                  <line x="3" y="10" size="4">Lager: {KURZBEZEICHNUNG}</line>
                  </label>
                  ';
            }
            break;

          case "etikettendrucker_einfach":
            switch($format)
            {
              case "30x15x3":
                $xml ='
                  <label>
                  <line x="3" y="1" size="3">{BEZEICHNUNG1}</line>
                  <line x="3" y="3" size="3">{BEZEICHNUNG2}</line>
                  </label>
                  ';
                break;
              default: //50x18x3
                $xml ='
                  <label>
                  <line x="3" y="2" size="4">{BEZEICHNUNG1}</line>
                  <line x="3" y="10" size="4">{BEZEICHNUNG2}</line>
                  </label>
                  ';
            }
            break;

          case "kommissionieraufkleber":
            switch($format)
            {
              case "30x15x3":
                break;
              default: //50x18x3
                $xml = '<label>
                  <barcode x="2" y="0" size="8" type="2">{LIEFERSCHEIN}</barcode>
                  <line x="2" y="8" size="3">---------------------------</line>
                  <line x="2" y="10" size="4">{IHREBESTELLNUMMER}</line>
                  <line x="2" y="15" size="1">{FIRMA}</line>
                  </label>';
            }

            break;
        }


        // pruefe ob es ein ueberladendes etikett gibt
        $tmpxml = $this->ReadyForPDF($this->app->DB->Select("SELECT xml FROM etiketten WHERE verwendenals='".$kennung."' LIMIT 1"));



        if($this->app->Secure->GetGET("module") == 'schneller_wareneingang'){
          //Wenn über schnellen Wareneingang gedruckt wird

          //Um welchen Artikel handelt es sich?
          if($this->app->Secure->GetGET("action") == 'printetikett'){
            $etikett_artikelid = $this->app->Secure->GetPOST("lp");
            $etikett_tmp = $this->app->DB->Select("SELECT autodrucketikett FROM artikel WHERE id='$etikett_artikelid' LIMIT 1");
          }elseif($this->app->Secure->GetGET("action") == 'distriinhaltschnell'){
            $etikett_tmp = $this->app->DB->Select("SELECT autodrucketikett FROM artikel WHERE id='$id' LIMIT 1");
          }

          //Prüfen ob es ein Prioritätsetikett (Eingestellt auf Artikelebene) für Artikel für schnellen Wareneingang gibt
          if($etikett_tmp != '0' && $etikett_tmp != ''){
            $xml = $this->app->DB->Select("SELECT xml FROM etiketten WHERE id='$etikett_tmp' LIMIT 1");
            $tmpxml = '';
          }else{
            //Prüfen ob es ein Standardetikett für den schnellen Wareneinang gibt
            $etikett_tmp = $this->app->erp->GetKonfiguration("schneller_wareneingang_einstellungen_etiketten");
            if($etikett_tmp != '0' && $etikett_tmp != ''){
              $xml = $this->app->DB->Select("SELECT xml FROM etiketten WHERE id='$etikett_tmp' LIMIT 1");
              $tmpxml = '';
            }
          }
        }


        if(is_numeric($kennung))
          $tmpxml = $this->ReadyForPDF($this->app->DB->Select("SELECT xml FROM etiketten WHERE id='".$kennung."' LIMIT 1"));
        else
          $kennung = $this->app->DB->Select("SELECT id FROM etiketten WHERE verwendenals='".$kennung."' LIMIT 1");

        $manuell = $this->app->DB->Select("SELECT manuell FROM etiketten WHERE id='".$kennung."' LIMIT 1");

        // wenn es ein ueberladenes etikett gibt
        if($tmpxml!="" && $manuell=="1") {
          // standard etiketten werte laden
          $xml = $tmpxml;

          // wenn manuell dann diese werte
          $labelbreite = $this->app->DB->Select("SELECT labelbreite FROM etiketten WHERE id='".$kennung."' LIMIT 1");
          $labelhoehe = $this->app->DB->Select("SELECT labelhoehe FROM etiketten WHERE id='".$kennung."' LIMIT 1");
          $labelabstand = $this->app->DB->Select("SELECT labelabstand FROM etiketten WHERE id='".$kennung."' LIMIT 1");
          $labeloffsetx = $this->app->DB->Select("SELECT labeloffsetx FROM etiketten WHERE id='".$kennung."' LIMIT 1");
          $labeloffsety = $this->app->DB->Select("SELECT labeloffsety FROM etiketten WHERE id='".$kennung."' LIMIT 1");

        } else {
          if($tmpxml!="")
            $xml = $tmpxml;
          switch($format)
          {
            case "30x15x3":
              $labelbreite = 30;
              $labelhoehe = 15;
              $labelabstand = 3;
              $labeloffsetx=0;
              $labeloffsety=0;
              break;
            case "100x50x5":
              $labelbreite = 100;
              $labelhoehe = 50;
              $labelabstand = 5;
              $labeloffsetx=0;
              $labeloffsety=0;
              break;
            default:
              // standard etiketten werte laden
              $labelbreite = 50;
              $labelhoehe = 18;
              $labelabstand = 3;
              $labeloffsetx=0;
              $labeloffsety=16;
          }
        }

        //$labelbreite = 100;
        //$labelhoehe = 152;

        $xmlconfig = "<settings width=\"$labelbreite\" height=\"$labelhoehe\" distance=\"$labelabstand\" offsetx=\"$labeloffsetx\" offsety=\"$labeloffsety\" />";
        $xml = str_replace("<label>","<label>".$xmlconfig,$xml);


        switch($tabelle)
        {
          case "produktion":
            $tmp = $this->app->DB->SelectArr("SELECT a.name as kundenname FROM produktion p LEFT JOIN adresse a ON a.id=p.adresse WHERE p.id='$id' LIMIT 1");
          break;
          case "artikel":
            $tmp = $this->app->DB->SelectArr("SELECT *,nummer as artikelnummer, name_de as artikel_name_de FROM artikel WHERE id='$id' LIMIT 1");

            $projekt = $tmp[0]['projekt'];
            if($tmp[0]['umsatzsteuer']=="ermaessigt")
              $steuer = ($this->GetStandardSteuersatzErmaessigt($projekt) + 100)/100.0;
            elseif($tmp[0]['umsatzsteuer']=="befreit")
              $steuer = 1;
            else
              $steuer = ($this->GetStandardSteuersatzNormal($projekt) + 100)/100.0;

            $tmp[0]['projektname'] = $this->app->DB->Select("SELECT name FROM projekt WHERE id='".$projekt."' LIMIT 1");
            $tmp[0]['projekt'] = $this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='".$projekt."' LIMIT 1");
            if($tmp[0]['variante_von'] > 0)
            {
              $tmp[0]['variante_von'] = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id='".$tmp[0]['variante_von']."' LIMIT 1");
            } else {
              $tmp[0]['variante_von'] = "";
            }

            $tmp[0]['verkaufspreisbrutto']=number_format($this->GetVerkaufspreis($id,1)*$steuer,2,',','.');
            $tmp[0]['verkaufspreisnetto']=number_format($this->GetVerkaufspreis($id,1),2,',','.');

            //standardlagerplatz
            $tmp[0]['lager_platz_standard'] = $this->GetArtikelStandardlager($id);
            $tmp[0]['lager_platz_name'] = $this->GetArtikelStandardlager($id);
            $tmp[0]['lager_platz_id'] = $this->GetArtikelStandardlager($id,true);

            $tmp[0]['datum'] = date('d.m.Y');
            $tmp[0]['datum_version1'] = date('d.m.y');
            $tmp[0]['datum_version2'] = date('d-m-Y');
            $tmp[0]['datum_version3'] = date('d-m-y');
            $tmp[0]['datum_version4'] = date('d/m/Y');
            $tmp[0]['datum_version5'] = date('d/m/y');
            $tmp[0]['datum_version6'] = date('y-m-d');
            $tmp[0]['datum_version7'] = date('Y-m-d');

            $eigenschaften = $this->app->DB->SelectArr("
              SELECT 
                ae.name, 
                aw.wert 
              FROM artikeleigenschaften ae LEFT JOIN artikeleigenschaftenwerte aw ON aw.artikeleigenschaften=ae.id WHERE aw.artikel='$id'");

            foreach($eigenschaften as $name=>$row)
            {
              $tmp[0]['eigenschaft:'.$row['name']]=$row['wert'];
              $tmp[0]['eigenschaft:'.$row['name'].'_DE'] = $row['wert'];
            }

            $sprachen = $this->GetSelectSprachenListe(true);

            preg_match_all('/{[\w\s_!äöüÄÖÜß:!?]*_(\w\w)}/', $xml, $alleSprachenImEtikett);

            $beschriftungSprache = $this->beschriftung_sprache;

            if($beschriftungSprache === 'franzoesisch'){
              $beschriftungSprache = 'französisch';
            }

            if($beschriftungSprache === 'hollaendisch'){
              $beschriftungSprache = 'holländisch';
            }

            $sprachen = array_change_key_case($sprachen, CASE_LOWER);
            if(array_key_exists($beschriftungSprache, $sprachen)){
              $sprache = $sprachen[$beschriftungSprache];
            }else{
              $sprache = strtoupper($beschriftungSprache);
            }
            $tmp[0]['sprache'] = $sprache;
            $alleSprachenImEtikett[1][] = $sprache;


            $etikettEigSprachen = '';
            $etikettFSprachen = '';
            if(!empty($alleSprachenImEtikett)){
              $alleSprachenImEtikett = array_flip(array_flip($alleSprachenImEtikett[1]));
              $etikettEigSprachen = implode("' OR language_to = '", $alleSprachenImEtikett);
              $etikettEigSprachen = " AND (language_to = '".$etikettEigSprachen."')";

              $etikettFSprachen = implode("' OR sprache = '", $alleSprachenImEtikett);
              $etikettFSprachen = " AND (sprache = '".$etikettFSprachen."')";
            }

            $eigenschaftenUebersetzungen = $this->app->DB->SelectArr("SELECT language_to, property_from, property_value_from, property_to, property_value_to 
                                                                      FROM article_property_translation 
                                                                      WHERE article_id = '$id' $etikettEigSprachen 
                                                                      ORDER BY shop_id DESC");

            foreach($eigenschaftenUebersetzungen as $name=>$row){
              if($sprache == $row['language_to']){
                $tmp[0]['eigenschaft:'.$row['property_from']] = $row['property_value_to'];
              }
              $tmp[0]['eigenschaft:'.$row['property_from'].'_'.$row['language_to']] = $row['property_value_to'];
            }


            $freifelderUebersetzungen = $this->app->DB->SelectArr("SELECT sprache, nummer, wert 
                                                                   FROM artikel_freifelder 
                                                                   WHERE artikel = '$id' $etikettFSprachen");


            for($i=1;$i<=40;$i++){
              $tmp[0]['freifeld'.$i.'_DE'] = $tmp[0]['freifeld'.$i];
            }

            foreach($freifelderUebersetzungen as $name=>$row){
              if($sprache == $row['sprache']){
                $tmp[0]['freifeld'.$row['nummer']] = $row['wert'];
              }
              $tmp[0]['freifeld'.$row['nummer'].'_'.$row['sprache']] = $row['wert'];
            }


            $artikelNameUebersetzungen = $this->app->DB->SelectArr("SELECT sprache, name FROM artikel_texte WHERE artikel = '$id' $etikettFSprachen");
            foreach($artikelNameUebersetzungen as $name=>$row){
              if($sprache == $row['sprache']){
                $tmp[0]['artikel_name'] = $row['name'];
              }
              $tmp[0]['artikel_name'.'_'.$row['sprache']] = $row['name'];
            }

            $artikelbild = $this->GetEtikettenbild($id,true);
            if($artikelbild > 0)
            {
              $tmp[0]['etikettenbild'] = $this->GetDateiPfad($artikelbild);
            }

            break;
          case "lager_platz":
            $tmp = $this->app->DB->SelectArr("SELECT *,id as lager_platz_id, kurzbezeichnung as lager_platz_name FROM lager_platz WHERE id='$id' LIMIT 1");
            $tmp[0]['id'] = str_pad($tmp[0]['id'], 7, '0', STR_PAD_LEFT);
            break;
        }

        if(!empty($tmp))
        {
          foreach($tmp[0] as $key=>$value)
          {
            $value = $this->UmlauteEntfernen($value);
            $xml = str_replace("{".strtoupper($key)."}",$value,$xml);
          }
        }

        if (is_array($variables)) {        
            if($variables['datum']=="") {
                 $variables['datum']=date('d.m.Y');
            }

            if(!empty($variables))
            {
              foreach($variables as $key=>$value)
              {
                $value = $this->UmlauteEntfernen($value);
                $xml = str_replace("{".strtoupper($key)."}",$value,$xml);
              }
            }
        }

        // y to z wenn Kein PDF -> also nur bei EPL Drucker - 09.06.2019 BS heute auf 0 gestellt bei deutschen adapterboxen eventuell
        if(0)//$checkpdf!="1")
        {
          $from = array('\-','[y]','[z]','[Y]','[Z]','SIGNCET','SIGNEPSI','SIGNGCET','SIGNGEPSI');
          $to = array('/','SIGNCET','SIGNEPSI','SIGNGCET','SIGNGEPSI','z','y','Z','Y');
          for($i_from=0;$i_from<(!empty($from)?count($from):0);$i_from++)
          {
            $do = true;
            $i = 0;

            $sign_from = $from[$i_from];
            $sign_to = $to[$i_from];
            while($do && preg_match_all("/(.*)<barcode(.*)>(.*)$sign_from(.*)<\/barcode>(.*)/",$xml,$erg))
            {
              $i++;
              if($i > 10)$do = false;//Endlosschleife bei Fehler verhindern
              $xml = preg_replace("/(.*)<barcode(.*)>(.*)$sign_from(.*)<\/barcode>(.*)/", "$1<barcode$2>$3".$sign_to."$4</barcode>$5", $xml);
            }
          }
        }

        if (strpos($xml, 'multiline') !== false) {
          $xml = "<label>".$this->ExtractMultiLine($xml)."</label>";
        }

      //Remove Text Between Parentheses PHP
      if(!empty($tabelle) && !empty($id) && strpos($xml,'{') !== false) {
        $xml = $this->ParseUserVars($tabelle, $id, $xml, false);
      }
      $xml = $this->ParseIfVars($xml, true);

      $xml = preg_replace('/\{([^{}]*+|(?R))*\}\s*/', '', $xml);

        // check ob drucker pdf oder epl spricht
        if($checkpdf==1 || $xmlaspdf)
        {
          if(empty($xml)) {
            return;
          }
          if(class_exists('EtikettenPDFCustom'))
          {
            $pdf = new EtikettenPDFCustom($this->app,$projekt);
          }else{
            $pdf = new EtikettenPDF($this->app,$projekt);
          }
          for($i=0;$i<$anzahl;$i++)
          {
            $pdf->SetXML($xml);
          }
          if($befehl=="")$befehl=sys_get_temp_dir();
          if($filenameprefix!="")$filenameprefix=$filenameprefix."_"; else $filenameprefix="";
          $tmp = tempnam($befehl,$filenameprefix."pdfetikett");
          $pdf->Output($tmp,'F');
          $newfilename=$tmp.$i.".pdf";
          rename($tmp,$newfilename);
          if($xmlaspdf && $xmlaspdf != 'D') return $newfilename;
          else $this->app->printer->Drucken($druckercode,$newfilename,"",1);


        } else {
          $this->app->printer->Drucken($druckercode,$xml,"",$anzahl);
    }
  }

  // @refactor EtikettenDrucker Komponente
  function ExtractMultiLine($xml)
  {
    $xml = @simplexml_load_string($xml);

    $newxml = '';
    if(empty($xml) || !method_exists($xml,'children')) {
      return '<line x="1" y="1" size="3">XML-Fehler</line>';
    }
    foreach($xml->children() as $tag=>$tagcontent)
    {
      switch($tag)
      {
        case "multiline":

          $wrap = (int)$tagcontent->attributes()->wrap;

          if($wrap <=0) return $line;

          $wrapheight = (int)$tagcontent->attributes()->wrapheight;

          $x = (int)$tagcontent->attributes()->x;
          $y = (int)$tagcontent->attributes()->y;
          $size = (int)$tagcontent->attributes()->size;
          $content = (String)$tagcontent[0];

          $tmp = explode("\n",wordwrap($content,$wrap));
          $ctmp = (!empty($tmp)?count($tmp):0);
          for($i=0;$i<$ctmp;$i++)
          {
            $newxml .= '<line x="'.$x.'" y="'.$y.'" size="'.$size.'">'.$tmp[$i].'</line>';
            $y = $y + $wrapheight;
          }
          break;
        default:
          $newxml .= $tagcontent->asXML();
      }
    }

    return $newxml;
  }

  // @refactor Lager Modul
  function ArtikelLagerInfo($artikel)
  {
    $obj = $this->LoadModul('artikel');
    if(!empty($obj) && method_exists($obj, 'ArtikelLagerInfo'))
    {
      return $obj->ArtikelLagerInfo($artikel);
    }
  }


  function ArtikelInventursperre($datum_be,$datum_ab,$simulate=false)
  {
    /** @var Inventur $obj */
    $obj = $this->LoadModul('inventur');
    if(!empty($obj) && method_exists($obj, 'ArtikelInventursperre'))
    {
      $obj->ArtikelInventursperre($datum_be,$datum_ab,$simulate);
    }
  }



  // @refactor Formater Komponente
  //Formatiert eine Dezimal Zahl fuer CSV Ausgabe automatisch
  function ParseDecimalForCSV($value)
  {
    // alle zahlen werte mit punkt zu komma
    $checkvalue = str_replace('.','',$value);
    if(is_numeric($checkvalue) && count(explode('.',$value))<=2)
    {
      $value = str_replace('.',',',$value);
    }
    return $value;
  }

  // @refactor Formater Komponente
  function MengeFormat($menge)
  {
    if($menge<=0) return "";
    else if($menge == round($menge)) return round($menge);
    else return number_format($menge,2, '.', '');
  }

  // @refactor Formater Komponente
  function LimitChar($string,$length,$minword=3)
  {
    if(strlen($string) > $length) {
      $string = substr($string,0,$length)."...";
      $string_ende = strrchr($string, " ");
      $string = str_replace($string_ende," ...", $string);
    }
    return $string;
  }

  // @refactor Formater Komponente
  function LimitWord($word,$count,$sign="...")
  {
    $length = strlen($word);

    $parts= explode("\n", wordwrap($word, $count, "\n"));
    $word = $parts[0];

    if(strlen($word) < $length)
      $word.=$sign;

    return $word;
  }

  // @refactor Hook Komponente

  /**
   * @param string   $name
   * @param int      $parametercount
   * @param bool|int $aktiv
   * @param bool     $new
   *
   * @return array
   */
  public function GenerateHook($name, $parametercount, $aktiv, $new = false)
  {
    if(empty($name)) {
      return [];
    }
    $checkarr = $this->app->DB->SelectRow(
      "SELECT h.id, h.parametercount, h.aktiv FROM `hook` AS `h` WHERE h.name = '$name' LIMIT 1"
    );
    $aktiv = (int)$aktiv;
    if($checkarr && $new) {
      if($parametercount === null) {
        return $checkarr;
      }
      $parametercount = (int)$parametercount;
      if($parametercount != $checkarr['parametercount']) {
        $this->app->DB->Update(
          "UPDATE `hook` 
          SET `parametercount` = '$parametercount' 
          WHERE `id` = '".$checkarr['id']."' LIMIT 1"
        );
        if($this->app->DB->affected_rows() > 0) {
          $checkarr['parametercount'] = $parametercount;
        }
      }

      return $checkarr;
    }
    if($checkarr) {
      $check = (int)$checkarr['id'];
      if($checkarr['aktiv'] != $aktiv) {
        $this->app->DB->Update(
          "UPDATE `hook` SET `aktiv` = '$aktiv' WHERE `id` = '$check'"
        );
        if($this->app->DB->affected_rows() > 0){
          $checkarr['aktiv'] = $aktiv;
        }
      }

      if($checkarr['parametercount'] != $parametercount) {
        $this->app->DB->Update(
          "UPDATE `hook` SET `parametercount` = '$parametercount' WHERE `id` = '$check'"
        );
        if($this->app->DB->affected_rows() > 0) {
          $checkarr['parametercount'] = $parametercount;
        }
      }

      return $checkarr;
    }
    $this->app->DB->Insert(
      "INSERT INTO `hook` (`name`, `aktiv`, `parametercount`) VALUES ('$name','$aktiv','$parametercount')"
    );
    $id = (int)$this->app->DB->GetInsertID();
    if($id > 0) {
      return ['id'=>$id, 'parametercount'=>$parametercount, 'name' => $name,'aktiv' => $aktiv];
    }

    $max = 1+(int)$this->app->DB->Select("SELECT MAX(h.id) FROM `hook` AS `h`");

    $this->app->DB->Update(
      "UPDATE `hook` SET `id` = '$max' WHERE `id` = 0 AND `name` = '$name' AND `aktiv` = '$aktiv' AND `parametercount` = '$parametercount' LIMIT 1");
    if($this->app->DB->affected_rows() > 0) {
      return ['id'=>$max, 'parametercount'=>$parametercount, 'name' => $name,'aktiv' => $aktiv];
    }
    return [];
  }

  // @refactor Hook Komponente

  /**
   * @param string $module
   * @param int    $aktiv
   * @param bool   $new
   *
   * @return array
   */
  public function GenerateMenuHook($module, $aktiv = 1, $new = false)
  {
    if(empty($module)) {
      return [];
    }
    $checkarr = $this->app->DB->SelectRow(
      "SELECT hm.id, hm.aktiv, hm.module FROM `hook_menu` AS `hm` WHERE hm.module = '$module' LIMIT 1"
    );
    if($checkarr && $new) {
      return $checkarr;
    }
    if($checkarr) {
      $check = $checkarr['id'];
      if($checkarr['aktiv'] != $aktiv) {
        $this->app->DB->Update("UPDATE `hook_menu` SET `aktiv` = '$aktiv' WHERE `id` = '$check'");
        if($this->app->DB->affected_rows() > 0) {
          $checkArr['aktiv'] = $aktiv;
        }
      }

      return $checkarr;
    }
    $this->app->DB->Insert("INSERT INTO `hook_menu` (`module`, `aktiv`) VALUES ('$module','$aktiv')");
    $id = (int)$this->app->DB->GetInsertID();
    if($id > 0) {
      return ['id' => $id, 'aktiv' => $aktiv, 'module' => $module];
    }

    $max = 1+(int)$this->app->DB->Select("SELECT MAX(hm.id) FROM `hook_menu` AS `hm`");
    $this->app->DB->Update("UPDATE `hook_menu` SET `id` = '$max' WHERE `id` = 0 AND `module` = '$module' LIMIT 1");
    if($this->app->DB->affected_rows() > 0) {
      return ['id' => $max, 'aktiv' => $aktiv, 'module' => $module];
    }

    return [];
  }

  // @refactor Hook Komponente
  public function RegisterHook($name, $callmodule, $funktion, $aktiv = 1, $new = false, $position = null, $moduleParameter = 0)
  {
    $alias = $this->getHookByAlias($name);
    if(!empty($alias)) {
      $name = $alias['name'];
    }
    $hookArr = $this->GenerateHook($name, null ,1, true);
    if(empty($hookArr)) {
      $hook = $this->app->DB->Select(
        sprintf("SELECT h.id FROM `hook` AS `h` WHERE h.name = '%s' LIMIT 1", $name)
      );
    }
    else {
      $hook = $hookArr['id'];
    }
    if(empty($hook)) {
      return false;
    }
    $check = $this->app->DB->Select(
      sprintf(
        "SELECT hr.id FROM `hook_register` AS `hr` WHERE hr.hook = %d AND hr.module = '%s' AND hr.module_parameter = %d LIMIT 1",
        (int)$hook, $callmodule, (int)$moduleParameter
      )
    );
    if($check && $new) {
      return false;
    }
    if($check) {
      $this->app->DB->Update(
        sprintf(
          "UPDATE `hook_register` SET `aktiv` = %d, `function` = '%s' WHERE `id` = %d LIMIT 1",
          $aktiv, $funktion, $check
        )
      );
      if($position !== null) {
        $this->app->DB->Update(
          sprintf(
            'UPDATE `hook_register` SET `position` = %d WHERE `id` = %d LIMIT 1',
            (int)$position, $check
          )
        );
      }
      return true;
    }
    if($position === null) {
      $position = 1+(int)$this->app->DB->Select(
        sprintf('SELECT MAX(hr.position) FROM `hook_register` AS `hr` WHERE hr.hook = %d', $hook)
      );
    }
    $this->app->DB->Insert(
      sprintf("INSERT INTO `hook_register` (`hook`, `module`, `function`, `aktiv`, `position`, `module_parameter`) 
        VALUES (%d,'%s','%s',%d,%d,%d)",
      $hook, $callmodule, $funktion, (int)$aktiv, (int)$position, (int)$moduleParameter
      )
    );

    return $this->app->DB->GetInsertID() > 0;
  }

  // @refactor Hook Komponente
  public function RegisterNavigationAlternative($first, $sec, $module, $action, $aktiv = 1,$prio = 0, $force = false)
  {
    $check = $this->app->DB->Select("SELECT id FROM navigation_alternative WHERE module = '$module' AND action = '$action' AND first = '$first' AND sec = '$sec' LIMIT 1");
    if($check && !$force) {
      return;
    }
    if($check) {
      $this->app->DB->Update("UPDATE navigation_alternative SET aktiv = '$aktiv', prio = '$prio' WHERE id = '$check' LIMIT 1");
      return;
    }
    $this->app->DB->Insert("INSERT INTO navigation_alternative (module, action,first, sec, aktiv, prio) values ('$module', '$action', '$first', '$sec','$aktiv', '$prio')");
  }

  // @refactor Hook Komponente

  /**
   * @param string $hookname
   * @param mixed  $callmodule
   */
  public function RemoveMenuHook($hookname, $callmodule)
  {
    if(empty($callmodule) || empty($hookname)) {
      return;
    }
    if(is_string($callmodule)) {
      $callerclass = 'String';
    }
    else {
      $callerclass = get_class($callmodule);
    }
    if($callerclass && $callerclass !== 'String') {
      $callmodule = strtolower(str_replace('Custom','',$callerclass));
    }
    if(empty($callmodule)) {
      return;
    }

    $hook_menuarr = $this->app->DB->SelectRow("SELECT hm.id FROM `hook_menu` WHERE hm.module = '$hookname' LIMIT 1");
    if(empty($hook_menuarr)) {
      return;
    }
    $hook_menu = $hook_menuarr['id'];
    $this->app->DB->Update(
      "UPDATE `hook_menu_register` SET `aktiv` = 0 WHERE `hook_menu` = '$hook_menu' AND `module` = '$callmodule'"
    );
  }

  // @refactor Hook Komponente
  /**
   * @param string   $hookname
   * @param string   $funktion
   * @param string   $callmodule
   * @param null|int $aktiv
   * @param null|int $position
   *
   * @return int
   */
  public function RegisterMenuHook($hookname, $funktion, $callmodule, $aktiv = null, $position = null )
  {
    $callerclass = get_class($callmodule);

    if($callerclass && $callerclass !== 'String') {
      $callmodule = strtolower(str_replace('Custom','',$callerclass));
    }
    if(!$callmodule) {
      return 0;
    }
    if(empty($hookname)) {
      return 0;
    }
    $hook_menuarr = $this->app->DB->SelectRow("SELECT hm.id FROM `hook_menu` AS `hm` WHERE hm.module = '$hookname' LIMIT 1");
    if(empty($hook_menuarr)) {
      $hook_menuarr = $this->GenerateMenuHook($hookname, 1, true);
    }
    if(empty($hook_menuarr)) {
      return false;
    }
    $hook_menu = $hook_menuarr['id'];
    $checkarr = $this->app->DB->SelectRow(
      "SELECT hmr.* FROM `hook_menu_register` AS `hmr` WHERE hmr.hook_menu = '$hook_menu' AND hmr.module = '$callmodule' LIMIT 1"
    );
    if($checkarr) {
      $check = (int)$checkarr['id'];
      if($aktiv === null) {
        return 0;
      }
      if($checkarr['aktiv'] != $aktiv || $checkarr['funktion'] != $funktion) {
        $this->app->DB->Update(
          "UPDATE `hook_menu_register` SET `aktiv` = '$aktiv', `funktion` = '$funktion' WHERE `id` = '$check' LIMIT 1"
        );
      }
      if($position !== null && $checkarr['position'] != $position) {
        $this->app->DB->Update("UPDATE `hook_menu_register` SET `position` = '$position' WHERE `id` = '$check' LIMIT 1");
      }

      return $check;
    }

    if($aktiv === null) {
      $aktiv = 1;
    }
    $position = 1+(int)$this->app->DB->Select(
      "SELECT MAX(hmr.position) FROM `hook_menu_register` AS `hmr` WHERE hmr.hook_menu = '$hook_menu'"
      );
    $this->app->DB->Insert(
      "INSERT INTO `hook_menu_register` (`hook_menu`, `module`, `funktion`, `aktiv`, `position`) 
      values ('$hook_menu','$callmodule','$funktion','$aktiv','$position')"
    );

    return (int)$this->app->DB->GetInsertID();
  }

  // @refactor Hook Komponente

  /**
   * @param string $name
   */
  public function RemoveHook($name)
  {
    $this->app->DB->Delete(
      sprintf(
        "DELETE `h`, `hr` 
        FROM `hook` AS `h` 
        LEFT JOIN `hook_register` AS `hr` ON h.id = hr.hook 
        WHERE h.name = '%s'",
        $this->app->DB->real_escape_string($name)
      )
    );
  }

  /**
   * @param string $hookName
   * @param string $module
   * @param string $callback
   */
  public function removeHookRegister($hookName, $module, $callback)
  {
    if(empty($hookName) || empty($module) || empty($callback)) {
      return;
    }
    $hook = $this->app->DB->Select(
      sprintf(
        "SELECT h.id FROM `hook` AS `h` WHERE h.name = '%s' OR h.alias = '%s' LIMIT 1",
        $this->app->DB->real_escape_string($hookName),
        $this->app->DB->real_escape_string($hookName)
      )
    );
    if(empty($hook)) {
      return;
    }
    $this->app->DB->Delete(
      sprintf(
        "DELETE FROM `hook_register` WHERE `hook` = %d AND `module` = '%s' AND `function` = '%s'",
        $hook,
        $this->app->DB->real_escape_string($module),
        $this->app->DB->real_escape_string($callback)
      )
    );
  }

  /**
   * @param string $alias
   *
   * @return array|null
   */
  public function getHookByAlias($alias)
  {
    if(empty($alias)) {
      return null;
    }
    return $this->app->DB->SelectRow(
      sprintf(
        "SELECT h.* FROM `hook` AS `h` WHERE h.alias = '%s' AND h.name <> ''",
        $this->app->DB->real_escape_string($alias)
      )
    );
  }

  /**
   * @param string $name
   * @param string $alias
   */
  public function addAliasToHook($name, $alias)
  {
    if(empty($name) || empty($alias) || $name === $alias) {
      return;
    }
    $hook = $this->app->DB->SelectRow(
      sprintf(
        "SELECT h.id, h.name, h.alias
        FROM `hook` AS `h` 
        WHERE h.name = '%s' OR (h.name = '%s' AND h.alias = '%s') ",
        $this->app->DB->real_escape_string($alias),
        $this->app->DB->real_escape_string($name),
        $this->app->DB->real_escape_string($alias)
      )
    );
    if(!empty($hook)) {
      if($hook['name'] === $name && $hook['alias'] === $alias) {
        return;
      }
      if($hook['name'] === $alias && $hook['alias'] === $name) {
        $this->app->DB->Update(
          sprintf(
            "UPDATE `hook` SET `name` = '%s' AND `alias` = '%s' WHERE `id` = %d",
            $this->app->DB->real_escape_string($alias),
            $this->app->DB->real_escape_string($name),
            $hook['id']
          )
        );
        return;
      }
      if(empty($hook['alias']) && $hook['name'] === $alias) {
        if(
          !$this->app->DB->Select(
            sprintf(
              "SELECT COUNT(h.*) FROM `hook` AS `h` WHERE h.id <> %d AND (h.name = '%s' OR h.alias = %s)",
              $this->app->DB->real_escape_string($name),
              $this->app->DB->real_escape_string($name),
              $hook['id']
            )
          )
        ) {
          $this->app->DB->Update(
            sprintf(
              "UPDATE `hook` 
              SET `alias` = '%s', `name` = '%s' 
              WHERE `id` = %d 
              LIMIT 1",
              $this->app->DB->real_escape_string($alias),
              $this->app->DB->real_escape_string($name),
              $hook['id']
            )
          );
        }
      }
      return;
    }
    $hooks = $this->app->DB->SelectArr(
      sprintf(
        "SELECT h.* 
        FROM `hook` AS `h` 
        WHERE (h.name = '%s' OR h.name = '%s' OR h.name = '%s' OR h.name = '%s') 
        ORDER BY h.name = '%s' DESC",
        $this->app->DB->real_escape_string($name),
        $this->app->DB->real_escape_string($alias),
        $this->app->DB->real_escape_string($name),
        $this->app->DB->real_escape_string($alias),
        $this->app->DB->real_escape_string($name)
      )
    );
    if(empty($hooks)){
      $this->app->DB->Insert(
        sprintf(
          "INSERT INTO `hook` (`name`, `alias`, `aktiv`, `parametercount`) 
            values ('%s','%s',1, 0)",
          $this->app->DB->real_escape_string($name),
          $this->app->DB->real_escape_string($alias)
        )
      );
      return;
    }
    if($hooks[0]['alias'] === $alias && $hooks[0]['name'] === $name) {
      return;
    }
    if($hooks[0]['name'] === $name) {
      $this->app->DB->Update(
        sprintf(
          "UPDATE `hook` SET `alias` = '%s' WHERE `id` = %d LIMIT 1",
          $this->app->DB->real_escape_string($alias), $hooks[0]['id']
        )
      );
      return;
    }
    if(((!empty($hooks)?count($hooks):0) === 1 || $hooks[0]['name'] === $alias) && $hooks[0]['alias'] === $name) {
      $this->app->DB->Update(
        sprintf(
          "UPDATE `hook` 
          SET `alias` = '%s', `name` = '%s' 
          WHERE `id` = %d 
          LIMIT 1",
          $this->app->DB->real_escape_string($alias),
          $this->app->DB->real_escape_string($name),
          $hooks[0]['id']
        )
      );
    }
  }

  // @refactor Hook Komponente
  public function RunHook($name, $parametercount = 0, &$parameter1 = null, &$parameter2 = null,&$parameter3 = null,&$parameter4 = null,&$parameter5 = null,&$parameter6 = null,&$parameter7 = null,&$parameter8 = null,&$parameter9 = null,&$parameter10 = null,&$parameter11 = null,&$parameter12 = null,&$parameter13 = null)
  {
    $checkAlias = $this->getHookByAlias($name);
    if(!empty($checkAlias)) {
      $name = $checkAlias['name'];
    }
    $check = $this->GenerateHook($name, $parametercount, 1, true);
    if(empty($check) || !isset($check['id']) || !isset($check['aktiv']) || !isset($check['parametercount'])) {
      $check = $this->app->DB->SelectRow("SELECT id, aktiv, parametercount FROM hook WHERE name = '$name' LIMIT 1");
    }
    if(!$check || !$check['aktiv']) {
      return;
    }
    $hook = $check['id'];
    $hooks = $this->app->DB->SelectArr(
      sprintf(
        "SELECT hr.module, hr.function, hr.module_parameter
        FROM `hook_register` AS `hr` 
        WHERE hr.hook = %d AND hr.aktiv = 1 AND hr.module <> '' AND hr.function <> '' 
        GROUP BY hr.module, hr.function, hr.module_parameter
        ORDER BY MIN(hr.position)",
        $hook
      )
    );
    if(empty($hooks)) {
      return;
    }

      /** @var Appstore $appstore */
      $appstore = $this->app->loadModule('appstore');
      foreach($hooks as $hook) {
        if(!empty($appstore) && method_exists($appstore, 'isModuleDeactivated') && $appstore->isModuleDeactivated($hook['module'])) {
          continue;
        }
        $obj = null;
        $modulelower = strtolower($hook['module']);

        $classname = ucfirst($hook['module']);

        $funktion = $hook['function'];
        $ok = false;

        if(file_exists(dirname(__DIR__).'/pages/'.$hook['module'].'.php') &&
          !empty($hook['module']) && !$this->ModulVorhanden($hook['module'])
        ) {
          continue;
        }

        if(!class_exists($classname) && !class_exists($classname.'_custom'))
        {
          if(file_exists(dirname(__DIR__).'/pages/'.$hook['module'].'_custom.php'))
          {
            include dirname(__DIR__).'/pages/'.$hook['module'].'_custom.php';
            $ok = true;
          }elseif(file_exists(dirname(__DIR__).'/pages/'.$modulelower.'_custom.php'))
          {
            include dirname(__DIR__).'/pages/'.$modulelower.'_custom.php';
            $ok = true;
          }elseif(file_exists(dirname(__DIR__).'/pages/'.$hook['module'].'.php')){
            include dirname(__DIR__).'/pages/'.$hook['module'].'.php';
            $ok = true;
          }elseif(file_exists(dirname(__DIR__).'/pages/'.$modulelower.'.php')){
            include dirname(__DIR__).'/pages/'.$modulelower.'.php';
            $ok = true;
          }
        }else {
          $ok = true;
        }
        $isTransfer = strpos($hook['module'],'Transfer') === 0;
        $checkUebertragungen = $isTransfer && $this->app->erp->ModulVorhanden('uebertragungen');
        if($isTransfer && !$checkUebertragungen) {
          $ok = false;
          continue;
        }
        if($isTransfer && empty($hook['module_parameter'])) {
          $ok = false;
          continue;
        }
        if($isTransfer && !empty($hook['module_parameter'])) {
          if(!$this->ModulVorhanden($hook['module'])) {
            continue;
          }
          /** @var Uebertragungen $subObj */
          $subObj = $this->app->erp->LoadModul('uebertragungen');
          if(!empty($subObj)) {
            $obj = $subObj->LoadTransferModul($hook['module'], $hook['module_parameter']);
            if(!empty($obj)) {
              $ok = true;
              $className = $hook['module'];
            } else {
              unset($subObj);
              continue;
            }
          }
        }
        elseif(strpos($hook['module'],'Printer') === 0 && !empty($hook['module_parameter'])) {
          if(!$this->ModulVorhanden($hook['module'])) {
            continue;
          }
          /** @var Drucker $subObj */
          $subObj = $this->app->erp->LoadModul('drucker');
          if(!empty($subObj)) {
            $obj = $subObj->loadPrinterModul($hook['module'], $hook['module_parameter']);
            if(!empty($obj)) {
              $ok = true;
              $className = $hook['module'];
            } else {
              unset($subObj);
              continue;
            }
          }
        }
        if(!$ok) {
          continue;
        }

        $classname2 = explode('_', $classname);
        foreach($classname2 as $k => $v) {
          $classname2[$k] = ucfirst($v);
        }
        $classname2 = implode('_', $classname2);
        if(!class_exists($classname.'Custom') && class_exists($classname2.'Custom')) {
          $classname = $classname2;
        }
        if(!class_exists($classname) && class_exists($classname2)) {
          $classname = $classname2;
        }
        if(!empty($obj) || class_exists($classname.'Custom'))
        {
          $classname = $classname.'Custom';
          if(empty($obj)) {
            $obj = new $classname($this->app, true);
          }
          if(method_exists($obj, $funktion))
          {
            switch($parametercount)
            {
              case '0':
                $obj->$funktion();
              break;
              case '1':
                $obj->$funktion($parameter1);
              break;
              case '2':
                $obj->$funktion($parameter1,$parameter2);
              break;
              case '3':
                $obj->$funktion($parameter1,$parameter2,$parameter3);
              break;
              case '4':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4);
              break;
              case '5':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5);
              break;
              case '6':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6);
              break;
              case '7':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7);
              break;
              case '8':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8);
              break;
              case '9':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9);
              break;
              case '10':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10);
              break;
              case '11':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10,$parameter11);
              break;
              case '12':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10,$parameter11,$parameter12);
              break;
              case '13':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10,$parameter11,$parameter12,$parameter13);
              break;
            }
          }
        }elseif(class_exists($classname))
        {
          if(empty($obj)){
            $obj = new $classname($this->app, true);
          }
          if(method_exists($obj, $funktion))
          {
            switch($parametercount)
            {
              case '0':
                $obj->$funktion();
              break;
              case '1':
                $obj->$funktion($parameter1);
              break;
              case '2':
                $obj->$funktion($parameter1,$parameter2);
              break;
              case '3':
                $obj->$funktion($parameter1,$parameter2,$parameter3);
              break;
              case '4':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4);
              break;
              case '5':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5);
              break;
              case '6':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6);
              break;
              case '7':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7);
              break;
              case '8':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8);
              break;
              case '9':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9);
                break;
              case '10':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10);
                break;
              case '11':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10,$parameter11);
                break;
              case '12':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10,$parameter11,$parameter12);
                break;
              case '13':
                $obj->$funktion($parameter1,$parameter2,$parameter3,$parameter4,$parameter5,$parameter6,$parameter7,$parameter8,$parameter9,$parameter10,$parameter11,$parameter12,$parameter13);
                break;

            }
          }
        }

      }
      if(isset($obj)) {
        unset($obj);
      }

  }

  // @refactor Hook Komponente

  /**
   * @param string $module
   */
  public function RunMenuHook($module)
  {
    if(empty($module)) {
      return;
    }
    $check = $this->GenerateMenuHook($module, 1, true);
    if(empty($check) || !isset($check['id']) || !isset($check['aktiv'])) {
      $check = $this->app->DB->SelectRow("SELECT hm.id, hm.aktiv FROM `hook_menu` AS `hm` WHERE hm.module = '$module' LIMIT 1");
    }
    if(empty($check) || !$check['aktiv']) {
      return;
    }
    $hook_menu = $check['id'];
    $hooks = $this->app->DB->SelectArr(
      "SELECT hmr.module, hmr.funktion 
      FROM `hook_menu_register` AS `hmr` 
      WHERE hmr.hook_menu = '$hook_menu' AND hmr.aktiv = 1 AND hmr.module <> '' AND hmr.funktion <> '' 
      GROUP BY hmr.module, hmr.funktion 
      ORDER BY hmr.position"
    );
    if(empty($hooks)) {
      return;
    }

    /** @var Appstore $appstore */
    $appstore = $this->app->loadModule('appstore');

    foreach($hooks as $hook) {
      if(!empty($appstore) && method_exists($appstore, 'isModuleDeactivated')
        && $appstore->isModuleDeactivated($hook['module'])) {
        continue;
      }

      $classname = ucfirst($hook['module']);
      $funktion = $hook['funktion'];
      $ok = false;
      if(!class_exists($classname) && !class_exists($classname.'Custom')) {
        if(file_exists(dirname(__DIR__).'/pages/'.$hook['module'].'_custom.php')) {
          include_once(dirname(__DIR__).'/pages/'.$hook['module'].'.php');
          include_once(dirname(__DIR__).'/pages/'.$hook['module'].'_custom.php');
          $ok = true;
        }
        elseif(file_exists(dirname(__DIR__).'/pages/'.$hook['module'].'.php')) {
          include_once(dirname(__DIR__).'/pages/'.$hook['module'].'.php');
          $ok = true;
        }
      }
      else {
        $ok = true;
      }
      if(!$ok) {
        continue;
      }
      if(class_exists($classname.'Custom')) {
        $classname = $classname.'Custom';
        $obj = new $classname($this->app, true);
        if(method_exists($obj, $funktion)) {
          $obj->$funktion();
        }
      }
      elseif(class_exists($classname)) {
        $obj = new $classname($this->app, true);
        if(method_exists($obj, $funktion)) {
          $obj->$funktion();
        }
      }
    }
  }

  // @refactor Menu Widget
  function InsertMenuAfter($link, $beschreibung, $modulebefore, $actionbefore, $mark=false)
  {
    $action = $this->app->Secure->GetGET("action");
    $module = $this->app->Secure->GetGET("module");
    $fmodul = $this->app->Secure->GetGET("fmodul");
    $cmd = $this->app->Secure->GetGET("cmd");
    $id = $this->app->Secure->GetGET("id");
    $sid = $this->app->Secure->GetGET("sid");

    if(strpos($link,'index.php') !== false) {
      $query = parse_url($link);
      $params = [];
      if(isset($query['query'])) {
        $queryParts = explode('&', $query['query']);
        foreach ($queryParts as $param) {
          $item = explode('=', $param);
          $params[$item[0]] = !isset($item[1])?'':$item[1];
        }
        if(!empty($params['module']) && !$this->RechteVorhanden($params['module'], $params['action'])) {
          return false;
        }
      }
    }

    if("index.php?module=$module&action=$action&cmd=$cmd&id=$id&fmodul=$fmodul"==$link) $mark=1;
    else if("index.php?module=$module&action=$action&cmd=$cmd&id=$id"==$link) $mark=1;
    else if("index.php?module=$module&action=$action&cmd=$cmd"==$link) $mark=1;
    else if("index.php?module=$module&action=$action&id=$id&fmodul=$fmodul"==$link && $cmd=="") $mark=1;
    else if("index.php?module=$module&action=$action&id=$id"==$link && $cmd=="") $mark=1;
    else if("index.php?module=$module&action=$action"==$link &&$cmd=="") $mark=1;
    else if("index.php?module=$module&action=$action"==$link) $mark=1;

    $found = false;
    $_link = $link;
    $beschreibung = $this->app->Tpl->pruefeuebersetzung($beschreibung,'menu');
    $link = $this->formatmenulink($link, $beschreibung, $mark);
    if(is_array($this->menuquery) && (!empty($this->menuquery)?count($this->menuquery):0) > 0)
    {
      for($k = 0; $k < (!empty($this->menuquery)?count($this->menuquery):0);$k++)
      {
        if($_link == $this->menuquery[$k]['_link'])return;
        if((strpos($this->menuquery[$k]['link'],'module='.$modulebefore) !== false) && (empty($actionbefore) || (!empty($actionbefore) && strpos($this->menuquery[$k]['link'],'action='.$actionbefore) !== false)))
        {
          $found = $k;
          for($i = $k+1; $i < (!empty($this->menuquery)?count($this->menuquery):0); $i++)
          {
            if($this->menuquery[$i]['ind'] == $k)
            {
              $found = $i;
            }else break;
          }
          //Alle nach found um eins erhöhen
          if($found < (!empty($this->menuquery)?count($this->menuquery):0) -1)
          {
            for($j = (!empty($this->menuquery)?count($this->menuquery):0) -1 ; $j > $found; $j--)
            {
              $this->menuquery[$j+1] = $this->menuquery[$j];
            }
            $this->menuquery[$found + 1] = array('link' => $link,'_link'=>$_link,'ind' => $k);
            return;
          }
          $this->menuquery[] = array('link' => $link,'_link'=>$_link,'ind' => $k);
          return;
        }
      }
    }
    $this->menuquery[] = array('link' => $link,'_link'=>$_link,'ind' => (!empty($this->menuquery)?count($this->menuquery):0));
  }

  // @refactor Menu Widget
  function InsertMenu($link, $_link)
  {
    if(is_array($this->menuquery) && (!empty($this->menuquery)?count($this->menuquery):0) > 0)
    {
      for($k = 0; $k < (!empty($this->menuquery)?count($this->menuquery):0);$k++)
      {
        if($_link == $this->menuquery[$k]['_link'])return;
      }
    }
    $this->menuquery[] = array('link' => $link,'_link'=>$_link,'ind'=>is_array($this->menuquery)?count($this->menuquery):0);
  }

  // @refactor Menu Widget
  function ParseMenu()
  {
    $this->app->erp->RunHook('parse_menu',2, $this->menuquery, $this->backlink);
    if(is_array($this->menuquery) && (!empty($this->menuquery)?count($this->menuquery):0) > 0)
    {
      foreach($this->menuquery as $k => $v)
      {
        $this->app->Tpl->Add('TABS', $v['link']);
        unset($this->menuquery[$k]);
      }
    }
  }

  // @refactor Menu Widget
  public function formatmenulink($link, $beschreibung, $mark = false)
  {
    $params = $this->getLinkParams($link);
    $menuId = !isset($params['module']) || !isset($params['action'])
      ?null:(' id="menuEntry'.$params['module'].$params['action'].'" ');

    if($mark){
      return "<li class=\"active\"><a $menuId href=\"$link\">$beschreibung</a></li>";
    }
    return "<li ><a $menuId href=\"$link\">$beschreibung</a></li>";
  }

  /**
   * @param string $link
   *
   * @return array
   */
  public function getLinkParams($link): array
  {
    $query = parse_url($link);
    $queryParts = null;
    $params = [];
    if(isset($query['query'])) {
      $queryParts = explode('&', $query['query']);
      foreach ($queryParts as $param) {
        $item = explode('=', $param);
        $params[$item[0]] = $item[1];
      }
    }

    return $params;
  }

  // @refactor Menu Widget
  /**
   * @param string $link
   * @param string $beschreibung
   * @param bool   $mark
   *
   * @return bool|void
   */
  public function MenuEintrag($link,$beschreibung,$mark=false)
  {
    $params = $this->getLinkParams($link);

    //Alle menüs ohne rechte ausblenden
    if(!empty($params['module'])
      && strpos($link,'index.php') !== false
      && !$this->RechteVorhanden($params['module'],$params['action'])
    ) {
      return false;
    }

    $menuId = !isset($params['module']) || !isset($params['action'])
      ?null:(' id="menuEntry'.$params['module'].$params['action'].'" ');

    $this->menucounter++;
    $action = $this->app->Secure->GetGET('action');
    $module = $this->app->Secure->GetGET('module');
    $fmodul = $this->app->Secure->GetGET('fmodul');
    $cmd = $this->app->Secure->GetGET('cmd');
    $id = $this->app->Secure->GetGET('id');
    $sid = $this->app->Secure->GetGET('sid');

    if(($beschreibung==='Freigabe' || $beschreibung==='Abschlie&szlig;en') && $action!=='freigabe')
    {
        $this->app->Tpl->Add(
          'TABSFREIGABE',
          '<li class="publish"><a href="'.$link.'"'.$menuId.' class="button">'.$beschreibung.'</a></li>'
        );
        return;
    }

    if(strpos($beschreibung,'Neu')!==false){

      $this->RunHook('NewTemplateObject', 2, $module,$buttoncode);

      if($buttoncode){
        $this->app->Tpl->Set('TABSADD', $buttoncode);
      }
      else{
        // wenn link nicht index.php enthaelt
        if(strpos($link,"index.php")===false) {
          $this->app->Tpl->Set(
            'TABSADD',
            "<a class=\"neubuttonlink\" href=\"#\"><input type=\"button\" onclick=\"$link\" value=\"+ "
            .$this->app->Tpl->pruefeuebersetzung('NEU','menu')."\" class=\"neubutton\" /></a>"
          );
        }
        else {
          $this->app->Tpl->Set(
            'TABSADD',
            "<a class=\"neubuttonlink\" href=\"$link\"><input type=\"button\" value=\"+ "
            .$this->app->Tpl->pruefeuebersetzung('NEU','menu')."\" class=\"neubutton\" /></a>"
          );
        }
      }
      $this->app->Tpl->Set('TABSADDWIDTH','50');
      return;
    }
    if(strpos($beschreibung,'zur')!==false) {
      $this->backlink = $link;
      $this->app->Tpl->Set('TABSBACK',"$link");
      $this->Headlines();
      return;
    }

    if(
      $mark != 1 && (
        in_array(
          $link,
          [
            "index.php?module=$module&action=$action&cmd=$cmd&id=$id&fmodul=$fmodul",
            "index.php?module=$module&action=$action&cmd=$cmd&id=$id",
            "index.php?module=$module&action=$action&cmd=$cmd",
            "index.php?module=$module&action=$action",
          ]
        )
        || (
          $cmd == '' && in_array(
            $link,
            [
              "index.php?module=$module&action=$action&id=$id&fmodul=$fmodul",
              "index.php?module=$module&action=$action&id=$id",
              "index.php?module=$module&action=$action",
              "index.php?module=$module&action=$action&id=$id&sid=$sid",
            ]
          )
        )
      )
    ) {
      $mark = 1;
    }

    $this->InsertMenu(
      $this->formatmenulink($link,$this->app->Tpl->pruefeuebersetzung( $beschreibung,'menu'), $mark), $link
    );
  }

  /**
   * @param string $link
   */
  public function setBacklink($link)
  {
    $this->backlink = $link;
  }

  /**
   * @return string
   */
  public function getBacklink()
  {
    return (string)$this->backlink;
  }

  public function addFav()
  {
    /** @var Appstore $obj */
    $obj = $this->app->loadModule('appstore');
    if($obj !== null && method_exists($obj, 'addFav')){
      $obj->addFav();
    }
  }

  /**
   * @param int    $id
   * @param string $module
   *
   * @return string
   */
  public function getSubModule($id, $module)
  {
    /** @var Appstore $obj */
    $obj = $this->app->loadModule('appstore');
    if($obj !== null && method_exists($obj, 'getSubModule')){
      return $obj->getSubModule($id, $module);
    }

    return '';
  }

  /**
   * @return array[]
   */
  public function getInlineToolTip()
  {
    $sprachen = ['german','english'];
    if(method_exists($this->app->User,'GetSprachen')) {
      $sprachen = $this->app->User->GetSprachen();
      if(!in_array('german', $sprachen)) {
        $sprachen[] = 'german';
      }
      if(!in_array('english', $sprachen)) {
        $sprachen[] = 'english';
      }
    }
    if(!is_array($sprachen)) {
      return [[], []];
    }
    $sprachen = array_reverse($sprachen);
    $inline = [];
    $tooltip = [];
    foreach($sprachen as $sprache)  {
      if(!empty($this->inline) && !empty($this->inline[$sprache])) {
        $inline = array_merge($inline, $this->inline[$sprache]);
      }
      if(!empty($this->tooltip) && !empty($this->tooltip[$sprache])) {
        $tooltip = array_merge($tooltip, $this->tooltip[$sprache]);
      }
      if(preg_match_all('/[a-zA-Z0-9\-]/', $sprache, $erg)) {
        if(@is_file(dirname(dirname(__DIR__)).'/languages/'.$sprache.'/inline.php')) {
          include_once dirname(dirname(__DIR__)).'/languages/'.$sprache.'/inline.php';
        }
        if(@is_file(dirname(dirname(__DIR__)).'/languages/'.$sprache.'/tooltip.php')) {
          if(isset($tooltip)&& !is_array($tooltip)) {
            $tooltip = [];
          }
          include_once dirname(dirname(__DIR__)).'/languages/'.$sprache.'/tooltip.php';
        }
      }
    }

    return [
      'inline' => $inline,
      'tooltip' => $tooltip,
    ];
  }

  /**
   * @param array  $tooltip
   * @param string $module
   * @param string $action
   */
  public function addToolTipsHtml($tooltip, $module, $action)
  {
    if(empty($tooltip) || empty($tooltip[$module]) || empty($tooltip[$module][$action])) {
      return;
    }
    $i = -1;
    $tooltipjson =  [];
    foreach($tooltip[$module][$action] as $key => $v) {
      $i++;
      $tooltipjson[] = [
        'key'=>base64_encode($key),
        'wert'=>base64_encode($v)
      ];
    }
    $this->app->Tpl->Add(
      'INLINEHELP',
      '<script type="application/json" id="tooltipjson">'.json_encode($tooltipjson).'</script>'
    );
  }

  // @refactor Tooltip Widget
  public function HelpIconAndTooltip()
  {
    $toolTipInline = $this->getInlineToolTip();
    $inline = $toolTipInline['inline'];
    $tooltip  = $toolTipInline['tooltip'];
    $module = $this->app->Secure->GetGET('module');
    $action = $this->app->Secure->GetGET('action');
    $id = (int)$this->app->Secure->GetGET('id');

    $module2 = $this->getSubModule($id, $module);

    if(!$this->RechteVorhanden($module, $action)) {
      return;
    }
    $include = false;

    $this->RunHook('inline_tooltip', 7, $inline, $tooltip, $module, $action, $id, $module2);
    $this->addToolTipsHtml($toolTipInline['tooltip'], $module, $action);

    if(isset($inline) && isset($inline[$module]) && !isset($inline[$module][$action]) && isset($inline[$module]['default'])) {
      $action = 'default';
    }
    if(isset($inline) && !isset($inline[$module]) && isset($inline['default']) && isset($inline['default']['default'])) {
      $module = 'default';
      $action = 'default';
    }
    $inlinehelplink = false;
    if(isset($inline) && isset($inline[$module]) && !empty($inline[$module][$action])) {
      if(isset($inline[$module][$action]['heading'])) {
        $heading = $inline[$module][$action]['heading'];
      }
      elseif($module !== 'default') {
        $heading = ucfirst($module);
      }
      else{
        $heading = 'Hilfe';
      }

      $inlineHasMenu = false;

      if(!empty($inline[$module][$action]['faqs']) || !empty($inline[$module][$action]['extmenu'])
        || !empty($inline[$module][$action]['handbook'])) {
        $inlineHasMenu = true;
        if(!empty($inline[$module][$action]['handbook'])) {
          $this->app->Tpl->Add('INLINEHELPMENUBEFORE','<li><a class="inlinehandbooklink" href="#rhandbook">Handbuch</a></li>');
          $handbook = $inline[$module][$action]['handbook'];
          preg_match_all(
            '/<img([altheight0-9=\" ]*) src="(\.\/index|index).php\?module=wiki&amp;action=getfile&amp;workspacefolder=XentralHandbuch&amp;article=([^&]+)&amp;fileid=([0-9]+)"([^\/]*) \/>/',
            $handbook,
            $pregerg
          );
          if(!empty($pregerg) && !empty($pregerg[0])) {
            foreach($pregerg[0] as $pregKey => $pregVal) {
              $handbook = str_replace(
                $pregVal,
                '<img '.$pregerg[1][$pregKey].' class="wikigetfile" data-article="'
                .$pregerg[3][$pregKey].'" data-fileid="'
                .$pregerg[4][$pregKey].'"'.$pregerg[5][$pregKey].' />',
                $handbook
              );
            }
          }
          preg_match_all(
            '/<img([altheight0-9=\" ]*) src="(\.\/index|index).php\?module=wiki&action=getfile&workspacefolder=XentralHandbuch&article=([^&]+)&fileid=([0-9]+)"([^\/]*) \/>/',
            $handbook,
            $pregerg
          );
          if(!empty($pregerg) && !empty($pregerg[0])) {
            foreach($pregerg[0] as $pregKey => $pregVal) {
              $handbook = str_replace(
                $pregVal,
                '<img '.$pregerg[1][$pregKey].' class="wikigetfile" data-article="'
                .$pregerg[3][$pregKey].'" data-fileid="'
                .$pregerg[4][$pregKey].'"'.$pregerg[5][$pregKey].' />',
                $handbook
              );
            }
          }
          $inlinehelplink = true;
          $this->app->Tpl->Add(
            'INLINEHELP3',
            $handbook
          );
        }

        if(!empty($inline[$module][$action]['faqs'])) {
          $inlinehelplink = true;
          $this->app->Tpl->Add('INLINEHELPMENU','<li><a class="inlinefaqlink" href="#rfaq">FAQ&apos;s</a></li>');
          $this->showInlineFaq($inline[$module][$action]['faqs']);
        }
        if(!empty($inline[$module][$action]['extmenu'])) {
          $this->app->Tpl->Add('INLINEHELPMENU',$inline[$module][$action]['extmenu']);
        }
      }
      else {
        $this->app->Tpl->Set('BEFOREINLINEMENU', '<!--');
        $this->app->Tpl->Set('AFTERINLINEMENU', '-->');
      }

      $this->app->Tpl->Set('INLINEHELPHEADING',$heading.
        (!empty($inline[$module][$action]['extraheading'])?$inline[$module][$action]['extraheading']:'')
      );

      $objiframes = array();

    //$this->app->Tpl->Add('INLINEHELP','<script>var youtubeifr = Array();</script>');
    if(isset($inline[$module][$action]['youtube'])) {
      //$objiframes[] = "'".'youtubeifr'."':'".'https://www.youtube.com/embed/'.$inline[$module][$action]['youtube']."'";
      $objiframes['youtubeifr'] = 'https://www.youtube.com/embed/'.$inline[$module][$action]['youtube'];
      $this->app->Tpl->Add('INLINEHELP','
      <div class="youtubehaupt"><span class="youtubehaupttitel">'.$heading.'</span><iframe width="560" height="315" src="" id="youtubeifr" frameborder="0" allowfullscreen></iframe></div>');
      /*$this->app->Tpl->Add('INLINEHELP','
      <script>youtubeifr[\'youtubeifr\'] = \'https://www.youtube.com/embed/'.$inline[$module][$action]['youtube'].'\';</script>
      <div class="youtubehaupt"><span class="youtubehaupttitel">'.$heading.'</span><iframe width="560" height="315" src="" id="youtubeifr" frameborder="0" allowfullscreen></iframe></div>');*/
    }
    if(isset($inline[$module][$action]['weitereyoutube'])) {
      if(isset($inline[$module][$action]['weitereyoutube'][0]))
      {
        $weitereyoutube = $inline[$module][$action]['weitereyoutube'];
      }else{
        $weitereyoutube[0] = $inline[$module][$action]['weitereyoutube'];
      }
      $this->app->Tpl->Add(
          'INLINEHELP',
          '<div class="outeryoutubeweitere">'
          .((!empty($weitereyoutube)?count($weitereyoutube):0) > 2?'<div class="pfeillinks youtubepfeil" ></div>':'')
          .'<div class="youtubeweiterecontainer2"><div class="youtubeweiterecontainer"><div class="youtubeweiterecontainerinner">'
      );
      foreach($weitereyoutube as $k => $v) {
          $objiframes['youtubeifr'.$k] = 'https://www.youtube.com/embed/'.$v['youtube'].'?rel=0';
          $this->app->Tpl->Add(
              'INLINEHELP',
              '<div class="youtubeweitere">
              <span class="youtubeoverlay" ></span>
              <iframe width="190" height="105" src=""  id="youtubeifr'.$k.'" frameborder="0" allowfullscreen></iframe>
              <div class="youtubesubtitel">'.$v['titel'].'</div>
              
            </div>'
          );

      }
      $this->app->Tpl->Add(
          'INLINEHELP',
          '</div></div></div>'
          .((!empty($weitereyoutube)?count($weitereyoutube):0) > 2?'<div class="pfeilrechts youtubepfeil" ></div>':'')
          .'</div>'
      );
    }

    if(isset($inline[$module][$action]['description']))
    {
      $this->app->Tpl->Add('INLINEHELP','<div class="text-wrapper">'.$inline[$module][$action]['description'].'</div>');
    }
    if(!empty($inline[$module][$action]['extradescription'])) {
      preg_match_all(
        '/<img([altheight0-9=\" ]*) src="([^"]+)"([^\/]*) \/>/',
        $inline[$module][$action]['extradescription'],
        $pregerg
      );
      if(!empty($pregerg) && !empty($pregerg[0])) {
        foreach($pregerg[0] as $pregKey => $pregVal) {
          $inline[$module][$action]['extradescription'] = str_replace(
            $pregVal,
            '<img '.$pregerg[1][$pregKey].' src="#" data-src="'
            .$pregerg[2][$pregKey].'"
          '.$pregerg[4][$pregKey].' />',
            $inline[$module][$action]['extradescription']
          );
        }
      }
      $this->app->Tpl->Add('INLINEHELP','<div class="text-wrapper">'.$inline[$module][$action]['extradescription'].'</div>');
    }

    if(!empty($inline[$module][$action]['site2'])) {
      $this->app->Tpl->Add(
        'INLINEHEL2',$inline[$module][$action]['site2']
      );
    }

    if(isset($inline[$module][$action]['link'])
      || !empty($inline[$module][$action]['extralinks'])
      || !empty($inline[$module][$action]['extralinks3'])) {
      $inlinehelplink = true;
      $this->app->Tpl->Add(
        'INLINEHELPLINK','<div>'
      );
      if(isset($inline[$module][$action]['link'])) {
        $this->app->Tpl->Add(
          'INLINEHELPLINK',
          '<a href="'.$inline[$module][$action]['link']
          .'" target="_blank"><input type="button" value="zum Handbuch für dieses Modul" /></a>'
        );
      }
      if(!empty($inline[$module][$action]['extralinks'])) {
        foreach($inline[$module][$action]['extralinks'] as $eLink => $eValue) {
          if(is_numeric($eLink)) {
             $this->app->Tpl->Add(
              'INLINEHELPLINK',
              '<a href="'.$eValue
              .'" target="_blank"><input type="button" value="zum Handbuch für dieses Modul" /></a>'
            );
          }
          else {
            $this->app->Tpl->Add(
              'INLINEHELPLINK',
              '<a href="'.$eLink
              .'" target="_blank"><input type="button" value="'.$eValue.'" /></a>'
            );
          }
        }
      }
      if(!empty($inline[$module][$action]['extralinks3'])) {
        foreach($inline[$module][$action]['extralinks3'] as $eLink => $eValue) {
          if(is_numeric($eLink)) {
            $this->app->Tpl->Add(
              'INLINEHELP3',
              '<a href="'.$eValue
              .'" target="_blank"><input type="button" value="zum Handbuch für dieses Modul" /></a>'
            );
          }
          else {
            $this->app->Tpl->Add(
              'INLINEHELP3',
              '<a href="'.$eLink
              .'" target="_blank"><input type="button" value="'.$eValue.'" /></a>'
            );
          }
        }
      }
      $this->app->Tpl->Add(
        'INLINEHELPLINK','</div>'
      );
    }

    $this->app->Tpl->Add('INLINEHELP','<script type="application/json" id="youtubejson">');
    $this->app->Tpl->Add('INLINEHELP', json_encode($objiframes));
    $this->app->Tpl->Add('INLINEHELP','</script>');
    $include = true;

      if(is_string($inline[$module][$action])) {
        $this->app->Tpl->Set('INLINEHELP',$inline[$module][$action]);
      }
    }
    if(!$inlinehelplink) {
      //$this->app->Tpl->Add('INLINEHELPLINK','<div><a href="https://www.wawision.de/benutzer-handbuch" target="_blank"><input type="button" value="zum Handbuch" /></a></div>');
      $this->app->Tpl->Add('TABSPRINT',
        '<input type="button" value="info" id="info">
        <label for="info">
          <span class="icon">
            <a target="_blank" class="infolink" href="https://www.wawision.de/akademie-home">
              <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path fill-rule="evenodd" clip-rule="evenodd" d="M6.9987 13.4173C10.5425 13.4173 13.4154 10.5445 13.4154 7.00065C13.4154 3.45682 10.5425 0.583984 6.9987 0.583984C3.45487 0.583984 0.582031 3.45682 0.582031 7.00065C0.582031 10.5445 3.45487 13.4173 6.9987 13.4173Z" stroke="var(--text-color, #929292)" stroke-width="0.8" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M6.9974 9.91699C6.91685 9.91699 6.85156 9.98228 6.85156 10.0628C6.85156 10.1434 6.91685 10.2087 6.9974 10.2087C7.07794 10.2087 7.14323 10.1434 7.14323 10.0628C7.14323 9.98228 7.07794 9.91699 6.9974 9.91699V9.91699" stroke="var(--text-color, #929292)" stroke-width="0.8" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M5.25 5.83679C5.25013 4.96279 5.89508 4.22289 6.76088 4.10347C7.62667 3.98404 8.44784 4.52171 8.68458 5.36304C8.92132 6.20436 8.50103 7.09136 7.7 7.44096C7.27484 7.62651 7.00001 8.04632 7 8.51021V8.75054" stroke="var(--text-color, #929292)" stroke-width="0.8" stroke-linecap="round" stroke-linejoin="round"/>
              </svg>
            </a>
          </span>
        </label>'
      );
    }else {
      $this->app->Tpl->Add('TABSPRINT',
        '<input type="button" onclick="showinlinehelp()" value="info" id="info">
        <label for="info">
          <span class="icon">
            <svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path fill-rule="evenodd" clip-rule="evenodd" d="M6.9987 13.4173C10.5425 13.4173 13.4154 10.5445 13.4154 7.00065C13.4154 3.45682 10.5425 0.583984 6.9987 0.583984C3.45487 0.583984 0.582031 3.45682 0.582031 7.00065C0.582031 10.5445 3.45487 13.4173 6.9987 13.4173Z" stroke="var(--text-color, #929292)" stroke-width="0.8" stroke-linecap="round" stroke-linejoin="round"/>
              <path d="M6.9974 9.91699C6.91685 9.91699 6.85156 9.98228 6.85156 10.0628C6.85156 10.1434 6.91685 10.2087 6.9974 10.2087C7.07794 10.2087 7.14323 10.1434 7.14323 10.0628C7.14323 9.98228 7.07794 9.91699 6.9974 9.91699V9.91699" stroke="var(--text-color, #929292)" stroke-width="0.8" stroke-linecap="round" stroke-linejoin="round"/>
              <path d="M5.25 5.83679C5.25013 4.96279 5.89508 4.22289 6.76088 4.10347C7.62667 3.98404 8.44784 4.52171 8.68458 5.36304C8.92132 6.20436 8.50103 7.09136 7.7 7.44096C7.27484 7.62651 7.00001 8.04632 7 8.51021V8.75054" stroke="var(--text-color, #929292)" stroke-width="0.8" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
          </span>
        </label>'
      );
    }

    $this->app->Tpl->Add('SCRIPTJAVASCRIPT','<link rel="stylesheet" type="text/css" href="./css/tooltipinline.css?v=2">
      <script type="text/javascript" src="./js/tooltipinline.js?v=2"></script>
    ');
    if($this->app->User->GetParameter('tooltipinline_autoopen')) {
      $this->app->Tpl->Add('INLINEHELPOPEN', ' class="inlineautoopen" ');
    }
    $this->app->Tpl->Parse('PAGE','tooltipinline.tpl');
  }

  /**
   * @param array  $faqs
   * @param string $target
   */
  public function showInlineFaq($faqs, $target = 'INLINEHELP2')
  {
    $html = '<div id="faqaccordion">';
    if(!empty($faqs))  {
      foreach($faqs as $faq) {
        $html .= '<div class="group"><h2>'.$faq['question'].'</h2><div>'.$faq['answer'].'</div></div>';
      }
    }
    $html .= '</div>';
    $this->app->Tpl->Add($target, $html);
  }

  /**@deprected**/
  function HelpIcon()
  {
    $module = $this->app->Secure->GetGET("module");
    $action = $this->app->Secure->GetGET("action");
  }

  /**@deprected**/
  function PrinterIcon()
  {
 //       $this->app->Tpl->Add('TABSPRINT',"&nbsp;<a style=\"color:white;font-size:9pt\" href=\"#\" onclick=\"wawisionPrint();\"><img src=\"./themes/new/images/icons_druck.png\" height=\"18\"></a>");
  }

  // @refactor Auftrag Modul
  function SaldoAdresseAuftrag($adresse)
  {
    return $this->app->DB->Select("SELECT SUM(gesamtsumme) FROM auftrag WHERE adresse='$adresse' AND status='freigegeben' LIMIT 1");
  }

  // @refactor Adresse Modul
  function UmsatzAdresseAuftragJahr($adresse)
  {
    return $this->app->DB->Select("SELECT
        SUM(ap.preis*ap.menge*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)))
        FROM auftrag_position ap LEFT JOIN auftrag a ON ap.auftrag=a.id WHERE (a.status='freigegeben' OR a.status='abgeschlossen')
        AND DATE_FORMAT(a.datum,'%Y')=DATE_FORMAT(NOW(),'%Y') AND a.adresse='$adresse'");
    //"SELECT SUM(gesamtsumme) FROM auftrag WHERE adresse='$adresse' AND status='freigegeben'
    //                      AND DATE_FORMAT(datum,'%Y')=DATE_FORMAT(NOW(),'%Y') LIMIT 1");
  }

  // @refactor Adresse Modul
  function UmsatzAdresseRechnungJahr($adresse)
  {
    return $this->app->DB->Select("SELECT
        SUM(ap.preis*ap.menge*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)))
        FROM rechnung_position ap LEFT JOIN rechnung a ON ap.rechnung=a.id WHERE (a.status='freigegeben' OR a.status='abgeschlossen' OR a.status='versendet')
        AND DATE_FORMAT(a.datum,'%Y')=DATE_FORMAT(NOW(),'%Y') AND a.adresse='$adresse'");
  }


  // @refactor Adresse Modul
  function SaldoAdresse($adresse)
  {
    return $this->KundenSaldo($adresse);
  }

  // @refactor Adresse Modul
  public function KundenSaldo($adresse){
    if(!is_numeric($adresse) || $adresse <= 0){
      return 0;
    }

    $rechnungs = $this->app->DB->Select("SELECT IFNULL(SUM(soll-ist),0) FROM rechnung WHERE status != 'angelegt' AND zahlungsstatus != 'bezahlt' AND adresse = '$adresse'");
    $gutschrifts = $this->app->DB->Select("SELECT IFNULL(SUM(soll-ist),0) FROM gutschrift WHERE status != 'angelegt' AND (manuell_vorabbezahlt = '0000-00-00' OR manuell_vorabbezahlt IS NULL) AND zahlungsstatus != 'bezahlt' AND adresse = '$adresse'");

    $kundensaldo = $rechnungs - $gutschrifts;
    $kundensaldo = round($kundensaldo, 2);

    return $kundensaldo;
  }


  // @refactor Produktion Modul
  function genLvl($id, $typ = '')
  {
    if($typ !== 'produktion') {
      return;
    }
  }


  // @refactor Auftrag Modul
  function AuftragExplodieren($auftrag,$typ="", $listeexplodieren = null)
  {
    if($typ==='produktion') {
    }
    else {
      $auftraege = $this->app->DB->SelectRow("SELECT * FROM auftrag WHERE (status='freigegeben' OR status='angelegt') AND id='$auftrag'");
      $projektlager = 0;
    }

    $adresse = $auftraege['adresse'];
    $projekt = $auftraege['projekt'];
    $status= $auftraege['status'];

    /**
      * Die nächsten vier Zeilen zur projektabhängigen Stücklistenanpassung
      */
    if($projekt > 0) {
      if (!$listeexplodieren
        && ($this->app->DB->Select("SELECT autostuecklistenanpassung FROM projekt WHERE id='$projekt' LIMIT 1")) == 0) {
        return;
      }
      if($typ !== 'produktion') {
        $projektlager = $this->app->DB->Select("SELECT id FROM projekt WHERE id = $projekt AND projektlager = 1 LIMIT 1");
      }
    }

    if($status!=='freigegeben' && $status!=='angelegt'){
      return;
    }

    if($typ==='produktion') {
    }
    else {
      if($listeexplodieren) {
        $swhere = null;
        foreach($listeexplodieren as $v) {
          $swhere[] = " ap.id = '$v' ";
        }
        $swhere = '  ('.implode(' OR ', $swhere).') ';
        $artikelarr= $this->app->DB->SelectArr(
          "SELECT ap.* ,art.lagerartikel, art.keineeinzelartikelanzeigen,art.juststueckliste,art.stueckliste
          FROM auftrag_position AS ap
          LEFT JOIN artikel AS art ON ap.artikel = art.id
          WHERE ap.auftrag='$auftrag' AND (ap.geliefert_menge < ap.menge AND ap.geliefert=0) AND $swhere");
      }
      else {
        $artikelarr= $this->app->DB->SelectArr(
          "SELECT ap.* ,art.lagerartikel, art.keineeinzelartikelanzeigen,art.juststueckliste,art.stueckliste
          FROM auftrag_position AS ap
          LEFT JOIN artikel AS art ON ap.artikel = art.id
          WHERE ap.auftrag='$auftrag' AND (ap.geliefert_menge < ap.menge AND ap.geliefert=0)"
        );
      }
    }

    $treffer=0;
    // Lager Check
    $positionen_vorhanden = 0;
    $artikelzaehlen=0;

    $changed = false;
    if($artikelarr) {
      for($k=0;$k<(!empty($artikelarr)?count($artikelarr):0); $k++)
      {
        $menge = $artikelarr[$k]['menge'] - $artikelarr[$k]['geliefert_menge'];
        $artikel = $artikelarr[$k]['artikel'];
        $artikel_position_id = $artikelarr[$k]['id'];
        // pruefe artikel 12 menge 4
        $lagerartikel = $artikelarr[$k]['lagerartikel'];
        $keineeinzelartikelanzeigen = $artikelarr[$k]['keineeinzelartikelanzeigen'];
        //if($artikelarr[$k][nummer]!="200000" && $artikelarr[$k][nummer]!="200001"  && $artikelarr[$k][nummer]!="200002" && $lagerartikel==1)
        //if($lagerartikel==1)
        //if($artikelarr[$k][nummer]!="200000" && $artikelarr[$k][nummer]!="200001"  && $artikelarr[$k][nummer]!="200002" )
        {
          //echo "Artikel $artikel Menge $menge";
          // schaue ob es ein JUST Stuecklisten artikel ist der nicht explodiert ist
          $just_stueckliste = $artikelarr[$k]['juststueckliste'];
          if($typ==='produktion')
          {
          } else {
            $explodiert = $artikelarr[$k]['explodiert'];
            $menge = $artikelarr[$k]['menge'];
            $sort = $artikelarr[$k]['sort'];
            if($changed) {
              $positionRow = $this->app->DB->SelectRow(sprintf('SELECT explodiert,menge,sort FROM auftrag_position WHERE id=%d LIMIT 1', (int)$artikel_position_id));
              $explodiert = $positionRow['explodiert'];
              $menge = $positionRow['menge'];
              $sort = $positionRow['sort'];
            }
            if($listeexplodieren && in_array($artikel_position_id, $listeexplodieren)) {
              $just_stueckliste = 1;
            }
            $waehrung =  $this->app->DB->real_escape_string($artikelarr[$k]['waehrung']);// $this->app->DB->real_escape_string($this->app->DB->Select("SELECT waehrung FROM auftrag_position WHERE id = '$artikel_position_id' LIMIT 1"));
            if($just_stueckliste && !$explodiert && ($preproducedpartlist = $this->getPreproducedPartlistFromArticle($artikel)) &&
              (($partlistsellable = $this->ArtikelAnzahlVerkaufbar($preproducedpartlist, $projektlager)) > 0) && round($partlistsellable,7) >= round($menge,7))
            {
              $preproducednummer = $this->app->DB->real_escape_string($this->app->DB->Select("SELECT nummer FROM artikel WHERE id = $preproducedpartlist"));
              $changed = true;
              if(round($partlistsellable,7) >= round($menge,7)){
                $just_stueckliste = 0;
                $lagerartikel = 1;
                $this->app->DB->Update("UPDATE auftrag_position SET artikel = $preproducedpartlist,nummer = '$preproducednummer' WHERE id = " . $artikel_position_id);
                $this->app->DB->Update(
                  sprintf(
                    'UPDATE `artikel` SET `laststorage_changed` = NOW() WHERE `id` = %d',
                    $preproducedpartlist
                  )
                );
                $order_obj = $this->app->erp->LoadModul('auftrag');
                if(!empty($order_obj) && method_exists($order_obj,'removeExplodedArticles')){
                  $order_obj->removeExplodedArticles($auftrag, $artikel_position_id);
                }
              }else{
                $preproducedart = $artikelarr[$k];
                $preproducedart['sort'] = $sort;
                $preproducedart['menge'] = $partlistsellable;
                $preproducedart['artikel'] = $preproducedpartlist;
                $preproducedart['nummer'] = $preproducednummer;
                if(is_null($preproducedart['steuersatz']))
                {
                  $preproducedart['steuersatz'] = -1;
                }
                unset($preproducedart['id']);
                $preproducedart['id'] = $this->app->DB->InsertArr('auftrag_position','id',$preproducedart,true);
                $sort++;
                $this->app->DB->Update("UPDATE auftrag_position SET menge = menge - $partlistsellable,sort = $sort WHERE id = " . $artikel_position_id);
                $this->app->DB->Update(
                  sprintf(
                    'UPDATE `artikel` SET `laststorage_changed` = NOW() WHERE `id` = %d',
                    $preproducedpartlist
                  )
                );
              }
              $this->app->DB->Update(
                sprintf(
                  'UPDATE `artikel` SET `laststorage_changed` = NOW() WHERE `id` = %d',
                  $artikel
                )
              );
            }
          }
          //$artikel_von_stueckliste = $this->app->DB->SelectArr("SELECT * FROM stueckliste WHERE stuecklistevonartikel='$artikel' AND art!='it' AND art!='bt'");


          // mengen anpassung
/*
    // Dieses Feature stammt aus uralten Zeiten von WaWision - habs heute enternt 30.12.2018 BS da wenn man an der Stückliste was anpasst das auch dann so bleiben soll
          if($just_stueckliste=="1" && $explodiert=="1")// && $max=="9898989")
          {
            foreach($artikel_von_stueckliste as $key=>$value)
            {
              $menge_st =$value['menge']*$menge;
              if($typ=="produktion")
              {
              }
              else
              {
                $this->app->DB->Update("UPDATE auftrag_position SET menge='{$menge_st}' WHERE explodiert_parent='$artikel_position_id' AND artikel='{$value['artikel']}'");
              }
            }
          }
*/
          // darunter war ein else if
          if($just_stueckliste=="1" && $explodiert=="0")
          {
            $checklieferkette = 0;
            if($typ === 'auftrag'){
              $checklieferkette = $this->app->DB->Select("SELECT id FROM lieferkette_bestellung WHERE belegtyp='auftrag' AND belegid='$auftrag' LIMIT 1");
            }

            if($checklieferkette > 0){
              $artikel_von_stueckliste = $this->app->DB->SelectArr(
                "SELECT s.*, art.nummer AS artnummer,art.projekt AS artprojekt
              FROM stueckliste AS s
              INNER JOIN artikel AS art ON s.artikel = art.id
              WHERE s.stuecklistevonartikel='$artikel' AND s.art!='it' AND s.art!='bt'"
              );
            }
            else{
              $artikel_von_stueckliste = $this->app->DB->SelectArr(
                "SELECT s.*, art.nummer AS artnummer,art.projekt AS artprojekt
              FROM stueckliste AS s
              INNER JOIN artikel AS art ON s.artikel = art.id
              WHERE s.stuecklistevonartikel='$artikel'"
              );
            }

            $treffer++;
            $changed = true;
            //hole artikel von stueckliste

            // schiebe alle artikel nach hinten
            $erhoehe_sort = !empty($artikel_von_stueckliste)?count($artikel_von_stueckliste):0;
            if($typ==='produktion')
            {
            }
            else
            {
              $this->app->DB->Update("UPDATE auftrag_position SET sort=sort+$erhoehe_sort WHERE auftrag='$auftrag' AND sort > $sort");
            }

            if(!empty($artikel_von_stueckliste)){
              foreach ($artikel_von_stueckliste as $key => $value) {
                $sort++;
                $nummer = $value['artnummer'];
                $projekt_artikel = $value['artprojekt'];
                if($projekt_artikel > 0) $projekt = $projekt_artikel;
                if($typ === 'produktion'){
                }else{
                  $explodiert_id = $this->AddAuftragPositionNummer($auftrag, $nummer, $value['menge'] * $menge, $projekt, 1, false, "", array('forceartikelid' => $value['artikel']));
                  $this->app->DB->Update(
                    sprintf(
                      'UPDATE `artikel` SET `laststorage_changed` = NOW() WHERE `id` = %d',
                      $artikel
                    )
                  );
                  if($waehrung != '') $this->app->DB->Update("UPDATE auftrag_position SET waehrung='" . $waehrung . "' WHERE id='$explodiert_id' LIMIT 1");
                  $this->app->DB->Update("UPDATE auftrag_position SET einkaufspreis='0',einkaufspreisurspruenglich=0 WHERE id='$explodiert_id' AND preis=0");
                  $this->app->DB->Update("UPDATE auftrag_position SET ausblenden_im_pdf='" . ($keineeinzelartikelanzeigen == 1 ? 1 : 0) . "' WHERE id='$explodiert_id' ");
                  $this->app->DB->Update("UPDATE auftrag_position  SET explodiert_parent='$artikel_position_id',sort='$sort',ohnepreis=1 WHERE id='$explodiert_id' LIMIT 1");
                  if($this->app->DB->Select("SELECT id FROM artikel WHERE id = '" . $value['artikel'] . "' AND (juststueckliste = 1 " . ($listeexplodieren ? " OR stueckliste = 1 " : '') . ") LIMIT 1")) $this->app->DB->Update("UPDATE auftrag_position SET explodiert = 1 WHERE id='$explodiert_id' LIMIT 1");
                  if($this->Firmendaten('auftragexplodieren_unterstuecklisten')) $this->app->DB->Update("UPDATE auftrag_position SET explodiert = 0 WHERE id = '$explodiert_id' LIMIT 1");
                  $this->app->DB->Update("UPDATE `beleg_zwischenpositionen` SET pos = pos + 1 WHERE doctype = 'auftrag' AND doctypeid = '$auftrag' AND pos >= '" . ($sort - 1) . "'  ");
                }
              }
            }

            // MLM wenn mlm und der artikel explodiert ist alle punkte platt machen
            if($typ==='auftrag' && $this->Firmendaten('modul_mlm')=='1')
            {
              $this->app->DB->Update("UPDATE auftrag_position SET mlmdirektpraemie=0, bonuspunkte=0,punkte=0 WHERE explodiert_parent='$artikel_position_id'");
            }

            if($typ==='produktion')
            {
            }
            else
            {
              $this->app->DB->Update("UPDATE auftrag_position SET explodiert='1' WHERE id='$artikel_position_id' LIMIT 1");
            }
          }
        }
      }
    }

    if($typ==='produktion'){
      $this->ANABREGSNeuberechnen($auftrag, 'produktion');
    }
    if($typ==='auftrag'){
      $this->ANABREGSNeuberechnen($auftrag, 'auftrag');
    }
  }


  // @refactor Auftrag Modul
  public function AuftragEinzelnBerechnen($auftrag,$festreservieren=false)
  {
    if($auftrag <=0)
    {
      return;
    }
    $this->AuftragExplodieren($auftrag);

    $this->BerechneDeckungsbeitrag($auftrag,"auftrag");
    $auftragarr = $this->app->DB->SelectRow("SELECT projekt,internet FROM auftrag WHERE id = '$auftrag' LIMIT 1");
    if(empty($auftragarr))
    {
      return;
    }
    /*
    $internet = $auftragarr['internet'];//$this->app->DB->Select("SELECT internet FROM auftrag WHERE id = '$auftrag' LIMIT 1");
    if(empty($internet)){
      $this->LoadSteuersaetzeWaehrung($auftrag,'auftrag');
    }*/

    // reservieren nur wenn es manuell gemacht wurde oder im auftrag fest steht
    $projekt = $auftragarr['projekt'];
    $reservierung = $this->Projektdaten($auftragarr['projekt'], 'reservierung');// $this->app->DB->Select("SELECT reservierung FROM projekt WHERE id='$projekt' LIMIT 1");
    if($reservierung=="1" || $festreservieren){
      $this->AuftragReservieren($auftrag);
    }

    $this->AuftragAutoversandBerechnen($auftrag);
  }

  // @refactor Auftrag Modul
  function AuftragAutoversandBerechnen($auftrag)
  {
    $toleranz = (float)str_replace(',','.', $this->app->erp->GetKonfiguration('zahlungseingang_toleranz'));
    if($toleranz < 0)$toleranz = 0;
    $auftraege = $this->app->DB->SelectArr("SELECT * FROM auftrag WHERE id='$auftrag'");
    $adresse = $auftraege[0]['adresse'];
    $artikelarr= $this->app->DB->SelectArr("SELECT ap.id, ap.artikel, ap.menge, ap.geliefert_menge, art.lagerartikel as artlagerartikel FROM auftrag_position ap LEFT JOIN artikel art ON ap.artikel = art.id WHERE ap.auftrag='$auftrag' AND ap.geliefert_menge < ap.menge AND ap.geliefert=0");

    //pruefe ob es mindestens eine reservierung gibt
    $reservierte = $this->app->DB->Select("SELECT COUNT(id) FROM lager_reserviert WHERE adresse='$adresse' AND datum>=NOW() AND objekt!='lieferschein'");
    if($reservierte >0 && $auftraege[0]['reserviert_ok'] != 1) {
      $this->app->DB->Update("UPDATE auftrag SET reserviert_ok='1' WHERE id='$auftrag' LIMIT 1");
    }
    elseif($reservierte <= 0 && $auftraege[0]['reserviert_ok'] != 0) {
      $this->app->DB->Update("UPDATE auftrag SET reserviert_ok='0' WHERE id='$auftrag' LIMIT 1");
    }

    // liefertermin
    $liefertermincheck = $this->app->DB->Select("SELECT id FROM auftrag WHERE (tatsaechlicheslieferdatum<=NOW() OR tatsaechlicheslieferdatum IS NULL OR tatsaechlicheslieferdatum='0000-00-00') AND id='$auftrag'");
    if($liefertermincheck >0 && $auftraege[0]['liefertermin_ok'] != 1) {
      $this->app->DB->Update("UPDATE auftrag SET liefertermin_ok='1' WHERE id='$auftrag' LIMIT 1");
    }
    elseif($liefertermincheck <= 0 && $auftraege[0]['liefertermin_ok'] != 0) {
      $this->app->DB->Update("UPDATE auftrag SET liefertermin_ok='0' WHERE id='$auftrag' LIMIT 1");
    }
    //liefersperre
    $liefersperre = $this->app->DB->Select("SELECT liefersperre FROM adresse WHERE id='$adresse'");
    if($liefersperre >0 && $auftraege[0]['liefersperre_ok'] != 0) {
      $this->app->DB->Update("UPDATE auftrag SET liefersperre_ok='0' WHERE id='$auftrag' LIMIT 1");
    }
    elseif($liefersperre <= 0 && $auftraege[0]['liefersperre_ok'] != 1){
      $this->app->DB->Update("UPDATE auftrag SET liefersperre_ok='1' WHERE id='$auftrag' LIMIT 1");
    }

    //kreditlimit
    $kreditlimit_freigabe = $auftraege[0]['kreditlimit_freigabe'] ;// $this->app->DB->Select("SELECT kreditlimit_freigabe FROM auftrag WHERE id='$auftrag' LIMIT 1");
    $setKreditLimitOk = $kreditlimit_freigabe=='1'
      || $this->KundeHatZR($adresse)
      || $this->KreditlimitCheck($adresse)==true;
    if($setKreditLimitOk && $auftraege[0]['kreditlimit_ok'] != 1) {
      $this->app->DB->Update("UPDATE auftrag SET kreditlimit_ok='1' WHERE id='$auftrag' LIMIT 1");
    }
    elseif(!$setKreditLimitOk && $auftraege[0]['kreditlimit_ok'] != 0) {
      $this->app->DB->Update("UPDATE auftrag SET kreditlimit_ok='0' WHERE id='$auftrag' LIMIT 1");
    }

    if($auftraege[0]['ust_ok'] != 1 && ($auftraege[0]['ust_befreit']==0 || ($auftraege[0]['ust_befreit']==1 && $auftraege[0]['ustid']==''))) {
      $this->app->DB->Update("UPDATE auftrag SET ust_ok='1' WHERE id='$auftrag' LIMIT 1");
    }

    // Lager Check
    $positionen_vorhanden = 0;
    $artikelzaehlen=0;
    $cartikelarr = $artikelarr?count($artikelarr):0;
    for($k=0;$k<$cartikelarr; $k++)  {
      $menge = $artikelarr[$k]['menge'] - $artikelarr[$k]['geliefert_menge'];
      $artikel = $artikelarr[$k]['artikel'];
      $artikel_position_id = $artikelarr[$k]['id'];
      $lagerartikel = $artikelarr[$k]['artlagerartikel'];
      if($lagerartikel==1) {
        // wenn artikel oefters im Auftrag nehme gesamte summe her

        $gesamte_menge_im_auftrag= $this->app->DB->Select("SELECT SUM(menge-geliefert_menge) FROM auftrag_position WHERE auftrag='$auftrag' AND artikel='$artikel'");
        if($gesamte_menge_im_auftrag > $menge) {
          $menge = $gesamte_menge_im_auftrag;
        }
        $artikelzaehlen++;
        if($this->LagerCheck($adresse,$artikel,$menge,"auftrag",$auftrag)>0) {
          $positionen_vorhanden++;
        }
        elseif($positionen_vorhanden > 0) {
          break;
        }
        //else { if($auftrag==314) {echo "Artikel $artikel Menge $menge";exit;} }

      }
    }
    $projekt = $this->app->DB->Select("SELECT projekt FROM auftrag WHERE id='$auftrag' LIMIT 1");

    $this->app->DB->Update("UPDATE auftrag SET teillieferung_moeglich='0' WHERE id='$auftrag' LIMIT 1");
    //echo "$positionen_vorhanden $artikelzaehlen<hr>";
    if($positionen_vorhanden==$artikelzaehlen){
      $this->app->DB->Update("UPDATE auftrag SET lager_ok='1' WHERE id='$auftrag' LIMIT 1");
    }
    else {
      $kommissionierverfahren = $this->app->DB->Select("SELECT kommissionierverfahren FROM projekt WHERE id = '$projekt' LIMIT 1");
      if($kommissionierverfahren == 'rechnungsmail')
      {
        $this->app->DB->Update("UPDATE auftrag SET lager_ok='1' WHERE id='$auftrag' LIMIT 1");
      }else{
        $this->app->DB->Update("UPDATE auftrag SET lager_ok='0' WHERE id='$auftrag' LIMIT 1");
      }
      if($positionen_vorhanden > 0 && $artikelzaehlen > 0)
      {
        $this->app->DB->Update("UPDATE auftrag SET teillieferung_moeglich='1' WHERE id='$auftrag' LIMIT 1");
      }

    }


    // projekt check start
    $projektcheck = 0;
    $projektcheckname = 0;
    $projektportocheck = 0;
    $projektnachnahmecheck = 0;
    $projektarr = empty($projekt)?null:$this->app->DB->SelectRow("SELECT * FROM projekt WHERE id='$projekt' LIMIT 1");

    if(!empty($projektarr)){
      $projektcheck = $projektarr['checkok'];
      $projektcheckname = $projektarr['checkname'];
      $projektportocheck = $projektarr['portocheck'];
      $projektnachnahmecheck = $projektarr['nachnahmecheck'];
    }
    $altercheck = $this->app->DB->Select("SELECT check_ok FROM auftrag WHERE id='$auftrag' LIMIT 1");

    if($projektcheck=='1' && @is_file(dirname(__FILE__)."/../plugins/class.".$projektcheckname.".php"))
    {
      //echo "projekt check $projektcheckname notwendig";
      if(file_exists(dirname(__DIR__).'/plugins/class.'.$projektcheckname.'.php') && !class_exists('unishop'))
      {
        include_once dirname(__DIR__).'/plugins/class.'.$projektcheckname.'.php';
      }

      if(class_exists('unishop')){
        $tmp = new unishop($this->app);
        if($tmp->CheckOK($auftrag)) {
          $this->app->DB->Update("UPDATE auftrag SET check_ok='1' WHERE id='$auftrag' LIMIT 1");
        }
        else{
          $this->app->DB->Update("UPDATE auftrag SET check_ok='0' WHERE id='$auftrag' LIMIT 1");
        }
      }else{
        $this->app->DB->Update("UPDATE auftrag SET check_ok='1' WHERE id='$auftrag' LIMIT 1");
      }
    }
    else{
      $this->app->DB->Update("UPDATE auftrag SET check_ok='1' WHERE id='$auftrag' LIMIT 1");
    }
    $this->RunHook('auftragcheck', 2, $auftrag, $altercheck);

    // autopruefung anstubsen
    //$this->AutoUSTPruefung($adresse);

    // UST Check
    // pruefe adresse 23 ust innerhalb 3 tagen vorhanden? wenn nicht schaue ob selber ordern kann wenn ja ordern und auf gruen

    $ustprf = $this->app->DB->Select("SELECT id FROM ustprf WHERE DATE_FORMAT(datum_online,'%Y-%m-%d')=DATE_FORMAT(NOW(),'%Y-%m-%d') AND adresse='$adresse' AND status='erfolgreich' LIMIT 1");
    $ustid = '';
    $ust_befreit = '';
    $land = '';
    $auftragarr = $this->app->DB->SelectRow("SELECT * FROM auftrag WHERE id='$auftrag' LIMIT 1");
    if(!empty($auftragarr)){
      $ustid = $auftragarr['ustid'];
      $ust_befreit = $auftragarr['ust_befreit'];
      $land = $auftragarr['land'];
    }

    if($auftragarr['ust_ok'] != 1 && ($ust_befreit==0 || ($ust_befreit==1 && $ustid==''))) {
      $this->app->DB->Update("UPDATE auftrag SET ust_ok='1' WHERE id='$auftrag' LIMIT 1");
    }

    // Porto Check
    // sind versandkosten im auftrag
    $porto = $this->app->DB->Select("SELECT ap.id FROM auftrag_position ap, artikel a WHERE ap.auftrag='$auftrag' AND ap.artikel=a.id AND a.porto=1 AND ap.preis >= 0
        AND a.id=ap.artikel LIMIT 1");
    $keinporto = 0;
    $selbstabholer = '';
    $projekt = 0;
    $checkkeinportocheck = 0;
    if(!empty($auftragarr)) {
      $keinporto = $auftragarr['keinporto'];
      $selbstabholer = $auftragarr['versandart'];
      $projekt = $auftragarr['projekt'];

      // portocheck bei projekt
      $checkkeinportocheck = $this->app->DB->Select("SELECT keinportocheck FROM versandarten WHERE type = '".$this->app->DB->real_escape_string($auftragarr['versandart'])."' AND
        (projekt = '$projekt' OR projekt = 0) ORDER BY projekt = '$projekt' DESC LIMIT 1");


    }

    if($selbstabholer=='selbstabholer' || $selbstabholer=='keinversand' || $checkkeinportocheck=="1") {
      $keinporto=1;
    }

    if($projektportocheck==1)
    {
      if($porto > 0){
        $this->app->DB->Update("UPDATE auftrag SET porto_ok='1' WHERE id='$auftrag' LIMIT 1");
      }
      else{
        $portoFreeLimit = (double) $this->app->DB->Select("SELECT portofreiab FROM adresse WHERE id={$adresse} LIMIT 1");
        $parcelValue = (double) $auftragarr['gesamtsumme'];

        if(!empty($portoFreeLimit) && !empty($parcelValue) && $parcelValue > $portoFreeLimit){
          $this->app->DB->Update("UPDATE auftrag SET porto_ok='1' WHERE id='$auftrag' LIMIT 1");
        }else{
          $this->app->DB->Update("UPDATE auftrag SET porto_ok='0' WHERE id='$auftrag' LIMIT 1");
        }
      }
    } else {
      //projekt hat kein portocheck porto ist immer ok
      $this->app->DB->Update("UPDATE auftrag SET porto_ok='1' WHERE id='$auftrag' LIMIT 1");
    }



    if($keinporto==1 || $selbstabholer=='selbstabholer')
    {
      $this->app->DB->Update("UPDATE auftrag SET porto_ok='1' WHERE id='$auftrag' LIMIT 1");
      //$this->app->DB->Update("UPDATE auftrag_position ap, artikel a SET ap.preis='0' WHERE ap.auftrag='$auftrag' AND a.id=ap.artikel AND a.porto='1'");
    }

  // Vorkasse Check    
  $auftrag_ist_vorkasse = false;
  $summe_eingang = 0;
  $auftrag_gesamtsumme = 0;
  $zahlungsweise = '';
  $vorabbezahltmarkieren = 0;
  if(!empty($auftragarr)) {
    $auftrag_gesamtsumme = $auftragarr['gesamtsumme'];// $this->app->DB->Select("SELECT gesamtsumme FROM auftrag WHERE id='$auftrag' LIMIT 1");
    $zahlungsweise = $auftragarr['zahlungsweise'];// $this->app->DB->Select("SELECT zahlungsweise FROM auftrag WHERE id='$auftrag' LIMIT 1");
    $vorabbezahltmarkieren = $auftragarr['vorabbezahltmarkieren'];// $this->app->DB->Select("SELECT vorabbezahltmarkieren FROM auftrag WHERE id='$auftrag' LIMIT 1");
    $waehrung = $auftragarr['waehrung'];
  }
  $zahlungsweise = strtolower($zahlungsweise);

    // Check behaviour
    $zahlungsweisenmodule = $this->app->DB->SelectArr("SELECT id, modul, verhalten FROM zahlungsweisen WHERE type = '".$this->app->DB->real_escape_string($zahlungsweise)."' AND (projekt = '$projekt' OR projekt = 0) ORDER BY projekt = '$projekt' DESC LIMIT 1");
    if (!empty($zahlungsweisenmodule))   {
        if ($zahlungsweisenmodule[0]['verhalten'] == 'vorkasse') {
            $auftrag_ist_vorkasse = true;
        }
    } else if ($zahlungsweise == 'vorkasse') {
        $auftrag_ist_vorkasse = true;    
    }

   // Check fibu_buchungen saldo
    $saldo = $this->app->erp->GetSaldoDokument($auftrag,'auftrag');
    if (!empty($saldo)) {
        if ($saldo['waehrung'] == $waehrung && $saldo['betrag'] >= $auftrag_gesamtsumme) {
            $saldo_ok = true;
        } 
    }  

    // Decide condition
    if ($auftrag_ist_vorkasse && !$saldo_ok && !$vorabbezahltmarkieren) {
        $vorkasse_ok = '0';
    } else {
        $vorkasse_ok = '1';
    }

    $this->app->DB->Update("UPDATE auftrag SET vorkasse_ok='$vorkasse_ok' WHERE id='$auftrag'");

  //nachnahme gebuehr check!!!!
  //$nachnahme = $this->app->DB->Select("SELECT id FROM auftrag_position WHERE auftrag='$auftrag' AND nummer='200001' LIMIT 1");
  $nachnahme = $this->app->DB->Select("SELECT COUNT(ap.id) FROM auftrag_position ap, artikel a WHERE ap.auftrag='$auftrag' AND ap.artikel=a.id AND a.porto=1 AND ap.preis >= 0
      AND a.id=ap.artikel");

    if($zahlungsweise=="nachnahme" && $nachnahme <2 && $projektnachnahmecheck==1){
      $this->app->DB->Update("UPDATE auftrag SET nachnahme_ok='0' WHERE id='$auftrag' LIMIT 1");
    }
    else{
      $this->app->DB->Update("UPDATE auftrag SET nachnahme_ok='1' WHERE id='$auftrag' LIMIT 1");
    }

    $lieferungtrotzsperre = $this->app->DB->Select("SELECT lieferungtrotzsperre FROM auftrag WHERE id='$auftrag' LIMIT 1");
    if($lieferungtrotzsperre==1){
      $this->app->DB->Update("UPDATE auftrag SET liefersperre_ok='1' WHERE id='$auftrag' LIMIT 1");
    }
  }

  // @refactor Lieferschein Modul
  public function LieferscheinCheck($lieferschein)
  {
    $obj = $this->LoadModul('lieferschein');
    if(!empty($obj) && method_exists($obj, 'LieferscheinCheck')){
      return $obj->LieferscheinCheck($lieferschein);
    }
  }


  // @refactor Formater Komponente
  public function EUR($betrag)
  {
    return number_format($betrag,2,',','.');
  }

  // @refactor Adresse Modul
  public function KreditlimitCheck($adresse)
  {
    if($adresse <= 0)
    {
      return true;
    }
    $kreditlimit = $this->app->DB->Select("SELECT kreditlimit FROM adresse WHERE id='$adresse' LIMIT 1");
    if($kreditlimit <=0) {
      return true;
    }
    // offene Rechnungen
    $rechnungen = $this->SaldoAdresse($adresse);

    $auftraege = $this->SaldoAdresseAuftrag($adresse);

    return $kreditlimit >= ($rechnungen+$auftraege);
  }

  // @refactor FormHelper Komponente
  public function ReplaceBetrag($db,$value,$fromform = null)
  {
    // wenn ziel datenbank
    if($db)
    {
      // wenn . und , vorhanden dann entferne punkt
      $pos_punkt = strrpos($value, '.');
      $pos_komma = strrpos($value, ',');
      if(($pos_punkt !== false) && ($pos_komma !== false)){
        if($pos_punkt < $pos_komma){
          $value = str_replace('.', '', $value);
        }else{
          $value = str_replace(',', '', $value);
        }
      }
      return str_replace(',','.',$value);
    }
    // wenn ziel formular

	if ($value != "") {
	    //return $abkuerzung;
 
	    if($value == round((float) $value, 2)) {
	      return number_format((float)$value,2,',','');
	    }
	}

    return rtrim(str_replace('.',',',$value),'0');
  }

  // @refactor FormHelper Komponente
  function ReplaceAdresse($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(id,' ',name) FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;

      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM adresse WHERE id='$rest' AND geloescht=0 LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular

    return $abkuerzung;
  }

  // @refactor FormHelper Komponente
  function ReplaceMitarbeiter($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(mitarbeiternummer,' ',name) FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;

      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM adresse WHERE mitarbeiternummer='$rest' AND mitarbeiternummer!='' AND geloescht=0 LIMIT 1");
      if($id <=0) $id=0;

    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    return $abkuerzung;
  }

  // @refactor FormHelper Komponente
  function ReplaceGruppenKategorien($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(id,' ',bezeichnung) as name FROM gruppen_kategorien WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      // wenn nummer keine DB id ist!
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = (int)$rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM gruppen_kategorien WHERE id='$rest' LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    return $abkuerzung;
  }

  public function ReplacePreisgruppe($db,$value,$fromform)
  {
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(g.kennziffer,' ',g.name) as name FROM gruppen g WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung ='';
      }
      if($id==0 || $id=='') {
        $abkuerzung ='';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      // wenn nummer keine DB id ist!
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id 
        FROM gruppen AS g 
        WHERE (CONCAT(g.kennziffer,' ',g.name)='$value' OR g.kennziffer = '$rest') AND 
              (g.name!='' OR g.kennziffer != '') AND g.art = 'preisgruppe' AND g.aktiv=1 
        LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    return $abkuerzung;
  }

  // @refactor FormHelper Komponente
  function ReplaceArtikel($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(nummer,' ',name_de) as name FROM artikel WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung ='';
      }
      if($id==0 || $id=="") $abkuerzung ="";
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      // wenn nummer keine DB id ist!
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$rest' AND nummer!='' AND geloescht=0 LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    return $abkuerzung;
  }

  // @refactor Formater Komponente
  function FormatMengeBetrag($value)
  {
    if(strpos($value,'.') !== false)
    {
      $pos = strpos($value,'.');
      $value = rtrim($value,'0');
      if(strlen($value) <= $pos + 2) {
        $value .= '0';
      }
      if(strlen($value) <= $pos + 2) {
        $value .= '0';
      }
    }else {
      $value .= '.00';
    }
    if($value[0] === '.') {
      $value = '0'.$value;
    }
    return $value;
  }

  // @refactor FormHelper Komponente
  function ReplaceMengeBetrag($db,$value,$fromform)
  {
    $dbformat = 0;
    if(strpos($value,'.') > 0) {
      $dbformat = 1;
    }

    // wenn ziel datenbank
    if($db)
    {
      if($dbformat) {
        return $value;
      }
      if($value!=''){
        return str_replace(',', '.', $value);
      }
      return '';
    }
    // wenn ziel formular

    $value = str_replace('.',',',$this->FormatMengeBetrag($value));
    if($dbformat) {
      if($value!='') {
        return $value;
      }
      return '';
    }
    return $value;
  }

  // @refactor FormHelper Komponente
  function ReplaceMenge($db,$value,$fromform)
  {
    $tcheck = str_replace(',','.',$value);
    if($tcheck < 0) {
      return 1;
    }


    $dbformat = 0;
    if(strpos($value,'.') > 0) {
      $dbformat = 1;
    }

    // wenn ziel datenbank
    if($db)
    {
      if($dbformat) {
        return $value;
      }

      if($value!=''){
        return str_replace(',', '.', $value);
      }

      return '';
    }
    // wenn ziel formular
    if(strpos($value,'.') !== false)
    {
      $value = rtrim(rtrim($value,'0'),'.');
      if($value[0] === '.') {
        $value = '0'.$value;
      }
    }
    if($dbformat) {
      if($value!='') {
        return str_replace('.',',',$value);
      }
      return '';
    }

    return $value;
  }

  // @refactor FormHelper Komponente
  function ReplaceDecimal($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(strpos($value,'.') > 0) {
      $dbformat = 1;
    }

    // wenn ziel datenbank
    if($db)
    {
      if($dbformat) {
        return $value;
      }

      if($value!=''){
        return str_replace(',', '.', $value);
      }
      return '';
    }
    // wenn ziel formular

    if($dbformat) {
      if($value!='') {
        return $value;
      }
      return '';
    }

    return $value;
  }


  // @refactor FormHelper Komponente
  function ReplaceZeit($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(strlen($value) > 5) $dbformat = 1;

    // wenn ziel datenbank
    if($db)
    {
      if($dbformat) return $value;
      else return $this->app->String->Convert($value,"%1:%2","%1:%2:00");
    }
    // wenn ziel formular
    else
    {
      if($dbformat) return $this->app->String->Convert($value,"%1:%2:%3","%1:%2");
      else return $value;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceDatum($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(strpos($value,'-') > 0) $dbformat = 1;

    // wenn ziel datenbank
    if($db)
    {
      if($dbformat) {
        return $value;
      }

      if($value!=''){
        return $this->app->String->Convert($value, "%1.%2.%3", "%3-%2-%1");
      }
      return '';
    }
    // wenn ziel formular

    if($dbformat) {
      if($value!='') {
        return $this->app->String->Convert($value,'%1-%2-%3','%3.%2.%1');
      }
      return '';
    }

    return $value;
  }


  // @refactor FormHelper Komponente
  function ReplacePreisanfrage($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("preisanfrage",$db,$value,$fromform);
  }

  // @refactor FormHelper Komponente
  function ReplaceAngebot($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("angebot",$db,$value,$fromform);
  }

  // @refactor FormHelper Komponente
  function ReplaceLieferschein($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("lieferschein",$db,$value,$fromform);
  }

  // @refactor FormHelper Komponente
  function ReplaceAuftrag($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("auftrag",$db,$value,$fromform);
  }

  // @refactor FormHelper Komponente
  function ReplaceRechnung($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("rechnung",$db,$value,$fromform);
  }

  function ReplaceVerbindlichkeit($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("verbindlichkeit",$db,$value,$fromform);
  }

  function ReplaceRetoure($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE('retoure',$db,$value,$fromform);
  }

  // @refactor FormHelper Komponente
  function ReplaceBestellung($db,$value,$fromform)
  {
    return $this->ReplaceANABRELSGSBE("bestellung",$db,$value,$fromform);
  }

  // @refactor FormHelper Komponente
  function ReplaceANABRELSGSBE($table,$db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT belegnr as name FROM $table WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $abkuerzung = $value;
      $tmp = explode(' ', trim($value));
      $tmp = reset($tmp);
      $id =  $this->app->DB->Select("SELECT id FROM $table WHERE belegnr='$tmp' AND belegnr!='' LIMIT 1");
      if ($id <=0) {
        $id=0;
        $abkuerzung = '';
      } else {
        $abkuerzung = $tmp;
      }
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }

  }

  // @refactor FormHelper Komponente
  function ReplaceLagerPlatz($db, $value, $fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT kurzbezeichnung FROM lager_platz WHERE id ='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM lager_platz WHERE kurzbezeichnung LIKE '$value' AND kurzbezeichnung!='' LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular

    return $abkuerzung;
  }

  // @refactor FormHelper Komponente
  function ReplaceLager($db, $value, $fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT bezeichnung FROM lager WHERE id ='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM lager WHERE bezeichnung LIKE '$value' AND bezeichnung!='' LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceKasse($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT bezeichnung FROM konten WHERE id ='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM konten WHERE bezeichnung LIKE '$value' AND bezeichnung!='' LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceKostenstelle($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(nummer,' ',beschreibung) FROM kostenstelle WHERE nummer='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT nummer FROM kostenstelle WHERE CONCAT(nummer,' ',beschreibung)='$value' AND CONCAT(nummer,' ',beschreibung)!='' LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceGruppe($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(name,' ',kennziffer) as name FROM gruppen WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM gruppen WHERE CONCAT(name,' ',kennziffer)='$value' OR (kennziffer='$value' AND kennziffer!='') LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceWiedervorlageStages($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(id,' ',kurzbezeichnung,' (',name,')') FROM wiedervorlage_stages WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];

      $id =  $this->app->DB->Select("SELECT id FROM wiedervorlage_stages WHERE id='$rest' LIMIT 1");
      if($value=='') $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceArbeitspaket($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(a.id,' ',p.abkuerzung,' ',a.aufgabe) FROM arbeitspaket a LEFT JOIN projekt p ON a.projekt=p.id WHERE a.id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];

      $id =  $this->app->DB->Select("SELECT id FROM arbeitspaket WHERE id='$rest' LIMIT 1");
      if($value=='') $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceProjektNameDyn($db, $value, $fromform)
  {
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(abkuerzung,' ',name) FROM projekt WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM projekt WHERE CONCAT(abkuerzung,' ',name)='$value' AND abkuerzung!='' LIMIT 1");
      if($id != '')
      {
        $value = explode(' ', $value);
        $value = reset($value);
        $id =  $this->app->DB->Select("SELECT id FROM projekt WHERE abkuerzung='$value' AND abkuerzung!='' LIMIT 1");
      }
      if($value=='') $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular

      return $abkuerzung;
  }

  // @refactor FormHelper Komponente
  function ReplaceProjektName($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(abkuerzung,' ',name) FROM projekt WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung='';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM projekt WHERE CONCAT(abkuerzung,' ',name)='$value' AND abkuerzung!='' LIMIT 1");
      if($value=='') $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceProjekt($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $abkuerzung = $value;
      $id =  $this->app->DB->Select("SELECT id FROM projekt WHERE abkuerzung='$value' AND abkuerzung!='' LIMIT 1");
      if($value=='') $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceLieferantennummer($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) { // wenn es eine id ist!
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT lieferantennummer as name FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung = '';
      }
      if($id==0 || $id=="") $abkuerzung ="";
    } else {
      $rmodule = $this->app->Secure->GetGET("module");
      $raction = $this->app->Secure->GetGET("action");
      $rid = (int)$this->app->Secure->GetGET("id");
      $pruefemodule = array('artikel','auftrag','angebot','rechnung','lieferschein','gutschrift','bestellung');
      $filter_projekt = false;
      if($raction == 'edit' && $rid && in_array($rmodule, $pruefemodule))
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM $rmodule WHERE id = '$rid' LIMIT 1");
        if($projekt)
        {
          $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id = '$projekt' LIMIT 1");
          //if($eigenernummernkreis)
            $filter_projekt = $projekt;
        }
      }
      $abkuerzung = $value;
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM adresse WHERE lieferantennummer='$rest' AND lieferantennummer!='' AND geloescht=0 ORDER BY ".($filter_projekt?" projekt = '$filter_projekt' DESC, ":"")." projekt LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor Formater Komponente
  function FirstTillSpace($string)
  {
    $tmp = trim($string);
    $rest = explode(" ",$tmp);
    return $rest[0];
  }

  // @refactor FormHelper Komponente
  function ReplaceKundennummer($db,$value,$fromform)
  {


    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) { // wenn es eine id ist!
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT kundennummer as name FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $rmodule = $this->app->Secure->GetGET("module");
      $raction = $this->app->Secure->GetGET("action");
      $rid = (int)$this->app->Secure->GetGET("id");
      $pruefemodule = array('artikel','auftrag','angebot','rechnung','lieferschein','gutschrift','bestellung','produktion');
      $filter_projekt = 0;
      if($raction == 'edit' && $rid && in_array($rmodule, $pruefemodule))
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM $rmodule WHERE id = '$rid' LIMIT 1");
        if($projekt)
        {
          $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id = '$projekt' LIMIT 1");
          //if($eigenernummernkreis)
            $filter_projekt = $projekt;
        }
      }
      $abkuerzung = $value;
      $tmp = trim($value);
      //$rest = substr($tmp, 0, 5);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM adresse WHERE kundennummer='$rest' AND kundennummer!='' AND geloescht=0 ORDER BY  ".($filter_projekt?" projekt = '$filter_projekt' DESC, ":"")." projekt LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceKunde($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(kundennummer,' ',name) as name FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $rmodule = $this->app->Secure->GetGET("module");
      $raction = $this->app->Secure->GetGET("action");
      $rid = (int)$this->app->Secure->GetGET("id");
      $pruefemodule = array('artikel','auftrag','angebot','rechnung','lieferschein','gutschrift','bestellung');
      $filter_projekt = false;
      if($raction == 'edit' && $rid && in_array($rmodule, $pruefemodule))
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM $rmodule WHERE id = '$rid' LIMIT 1");
        if($projekt)
        {
          $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id = '$projekt' LIMIT 1");
          //if($eigenernummernkreis)
            $filter_projekt = $projekt;
        }
      }
      $dbformat = 0;
      $abkuerzung = $value;
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM adresse WHERE kundennummer='$rest' AND kundennummer!='' AND geloescht=0 ORDER BY  ".($filter_projekt?" projekt = '$filter_projekt' DESC, ":"")." projekt LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceSteuersatz($db,$value,$fromform)
  {
    if($db)
    {
      if($value === "" || $value === null)return -1;
      return str_replace(',','.', $value);
    }else{
      if($value < 0)return "";
      return str_replace('.',',', $value);;
    }
  }

  // @refactor FormHelper Komponente
  function ReplaceSteuergruppe($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
// Removed, table does not exist        $abkuerzung = $this->app->DB->Select("SELECT bezeichnung FROM steuerregelngruppe WHERE id='$id' LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $dbformat = 0;
      $value = $this->app->DB->real_escape_string($value);
// Removed, table does not exist      $id =  $this->app->DB->Select("SELECT id FROM steuerregelngruppe WHERE bezeichnung = '$value' ORDER BY aktiv = 1 DESC LIMIT 1");
      if($id <=0) $id=0;
    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

    function ReplaceKontorahmen($db,$value,$fromform = null) {
        $value = $this->app->DB->real_escape_string($value);

        if ($db) {
            $sachkonto = explode(' ',$value)[0];
            $kontoid = $this->app->DB->Select("SELECT id FROM kontorahmen WHERE sachkonto = '$sachkonto' LIMIT 1");
            return($kontoid);
        } else {
            $sachkonto = $this->app->DB->Select("SELECT CONCAT(sachkonto,' ',beschriftung) FROM kontorahmen WHERE id = '$value' LIMIT 1");
            return($sachkonto);
        }
    }

    function ReplaceKonto($db,$value,$fromform = null) {
        $value = $this->app->DB->real_escape_string($value);

        if ($db) {
            $konto = explode(' ',$value)[0];
            $kontoid = $this->app->DB->Select("SELECT id FROM konten WHERE kurzbezeichnung = '$konto' LIMIT 1");
            return($kontoid);
        } else {
            $konto = $this->app->DB->Select("SELECT CONCAT(kurzbezeichnung,' ',bezeichnung) FROM konten WHERE id = '$value' LIMIT 1");
            return($konto);
        }
    }

    function ReplaceSmartyTemplate($db,$value,$fromform = null) {
        $value = $this->app->DB->real_escape_string($value);

        if ($db) {
            $smarty_template = explode(' ',$value)[0];
            return($smarty_template);
        } else {
            $smarty_template = $this->app->DB->Select("SELECT CONCAT(id,' ',name) FROM smarty_templates WHERE id = '$value' LIMIT 1");
            return($smarty_template);
        }
    }


  // @refactor FormHelper Komponente
  function ReplaceLieferant($db,$value,$fromform)
  {
    //value muss hier vom format ueberprueft werden
    $dbformat = 0;
    if(!$fromform) {
      $dbformat = 1;
      $id = $value;
      if($id > 0){
        $abkuerzung = $this->app->DB->Select("SELECT CONCAT(lieferantennummer,' ',name) as name FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
      }else{
        $abkuerzung = '';
      }
    } else {
      $rmodule = $this->app->Secure->GetGET("module");
      $raction = $this->app->Secure->GetGET("action");
      $rid = (int)$this->app->Secure->GetGET("id");
      $pruefemodule = array('artikel','auftrag','angebot','rechnung','lieferschein','gutschrift','bestellung');
      $filter_projekt = false;
      if($raction == 'edit' && $rid && in_array($rmodule, $pruefemodule))
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM $rmodule WHERE id = '$rid' LIMIT 1");
        if($projekt)
        {
          $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id = '$projekt' LIMIT 1");
          //if($eigenernummernkreis)
            $filter_projekt = $projekt;
        }
      }
      $dbformat = 0;
      $abkuerzung = $value;
      $tmp = trim($value);
      $rest = explode(" ",$tmp);
      $rest = $rest[0];
      $id =  $this->app->DB->Select("SELECT id FROM adresse WHERE lieferantennummer='$rest' AND lieferantennummer!='' AND geloescht=0 ORDER BY ".($filter_projekt?" projekt = '$filter_projekt' DESC, ":"")." projekt LIMIT 1");
      if($id <=0) $id=0;

    }

    // wenn ziel datenbank
    if($db)
    {
      return $id;
    }
    // wenn ziel formular
    else
    {
      return $abkuerzung;
    }
  }

  /**@depreacated */
  function CheckSamePage()
  {
    $id = $this->app->Secure->GetGET("id");
    $check_id  = strstr($_SERVER['HTTP_REFERER'], 'id=');
    if($check_id!="id=".$id)
      return true;
    else
      return false;
  }

  /**
   * @depreacated
   * @refactor Artikel Modul
   */
  function SeitenSperrAuswahl($ueberschrift,$meldung)
  {
    /* $this->app->Tpl->Set(SPERRMELDUNG,  '$("a#inline").fancybox({
       \'modal\': true,
       \'autoDimensions\': false,
       \'width\': 500,
       \'height\': 300
       });
       $(\'#inline\').click();');

       $this->app->Tpl->Set(SPERRMELDUNGNACHRICHT,'<a id="inline" href="#data"></a>
       <div style="display:none"><div id="data"><h2>'.$ueberschrift.'</h2><hr>von Benedikt Sauter<br><br><div class="info">'.$meldung.'</div>
       <br><br><center><a href="'.$_SERVER['HTTP_REFERER'].'">Jetzt Zur&uuml;ck zum letzten Schritt</a>&nbsp;|&nbsp;
       <a href="javascript:;" onclick="$.fancybox.close();">Bitte Fenster dennoch freigeben</a></center></div></div>');
     */

    $this->app->Tpl->Set('SPERRMELDUNG',  '
        // a workaround for a flaw in the demo system (http://dev.jqueryui.com/ticket/4375), ignore!
        $( "#dialog:ui-dialog" ).dialog( "destroy" );

        $( "#dialog-message" ).dialog({
modal: true,
buttons: {
Ok: function() {
$( this ).dialog( "close" );
}
}
});
        ');


    $this->app->Tpl->Set('SPERRMELDUNGNACHRICHT','
        <div id="dialog-message" title="'.$ueberschrift.'">
        <p style="font-size: 9pt">
        '.$meldung.'
        </p>
        </div>
        ');
    }

/**@depreacated */
function SeitenSperrInfo($meldung)
{
  $this->app->Tpl->Set('SPERRMELDUNG',  '$("a#inline").fancybox({
        \'hideOnContentClick\': true,
        \'autoDimensions\': false,
        \'width\': 500,
        \'height\': 300
        });
      $(\'#inline\').click();');

  $this->app->Tpl->Set('SPERRMELDUNGNACHRICHT','<a id="inline" href="#data"></a>
      <div style="display:none"><div id="data"><h2>Infomeldung</h2><hr><br><br>'.$meldung.'</div></div>');

}

// @refactor Artikel Modul
function AddArtikel($felder)
{
  $this->app->DB->Insert("INSERT INTO artikel (id) VALUES ('')");
  $id = $this->app->DB->GetInsertID();
  if($felder['firma']<=0)
    $felder['firma'] = $this->app->DB->Select("SELECT MAX(f.id) FROM firma f INNER JOIN firmendaten fd ON f.id = fd.firma LIMIT 1");
  if($felder['firma']<=0)
    $felder['firma'] = $this->app->DB->Select("SELECT MAX(firma) FROM firmendaten LIMIT 1");

  if($felder['projekt']<=0)
    $felder['projekt'] = $this->app->DB->Select("SELECT standardprojekt FROM firma WHERE id='".$felder['firma']."' LIMIT 1");

  if($felder['firma']<=0) $felder['firma']=1;
  if($felder['projekt']<=0) $felder['projekt']=1;

  // so starten, dass alle uebertragen werden
  if($felder['cache_lagerplatzinhaltmenge']<=0) $felder['cache_lagerplatzinhaltmenge']=-999;

  if(!empty($felder['anhang']))
  {
    if(!is_array($felder['anhang'])){
      $data = $felder['anhang'];
      $felder['anhang'] = [];
      $felder['anhang'][] = ['datei' => $data, 'endung' => '', 'name' =>''];
    }

    foreach ($felder['anhang'] as $anhang){
      $dateiname = trim($anhang['name']);
      if(empty($dateiname)){
        $dateiname = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id ='$id'");
      }
      $fileid = $this->addBase64Bild($anhang['datei'],$dateiname,$anhang['endung']);
      if(!empty($fileid)){
        $this->AddDateiStichwort($fileid, 'Bild', 'artikel', $id);
      }

    }
    unset($felder['anhang']);
  }


  $this->app->DB->UpdateArr("artikel",$id,"id",$felder);


  return $id;
}

public function addBase64Bild($base64datei,$name = '',$endung = '',$titel='Anhang'){
  $decodedData = @base64_decode($base64datei);
  $tmpdatei = $this->app->erp->GetTMP().'anhangtmp'.microtime(true);
  file_put_contents($tmpdatei ,$decodedData);

  if(empty($endung)){
    $mimetype = explode('/',mime_content_type($tmpdatei));
    switch ($mimetype[0]){
      case 'image':
        if(strpos($mimetype[1],'jpg') !== false || strpos($mimetype[1],'jpeg') !== false){
          $endung = 'jpg';
        }
        if(strpos($mimetype[1],'png') !== false){
          $endung = 'png';
        }
        if(strpos($mimetype[1],'bmp') !== false){
          $endung = 'bmp';
        }
        break;
      case 'text':
        if(strpos($mimetype[1],'plain') !== false){
          $endung = 'txt';
        }
        if(strpos($mimetype[1],'php') !== false){
          $endung = 'php';
        }
        break;
      default:
        $endung = 'pdf';
        break;
    }
  }


  $datei = $this->app->Conf->WFuserdata.'/'.md5($name.'.'.$endung.microtime(true));
  move_uploaded_file($tmpdatei,$datei);

  $fileid = 0;
  if(file_put_contents($datei,$decodedData))
  {
    if(@is_file($datei) && @filesize($datei))
    {
      $fileid = $this->CreateDatei($name.'.'.$endung, $titel, '', '', $datei, $this->app->User->GetName());
      unlink($datei);
    }
  }

  return $fileid;
}

// @refactor API Modul
function SetzteSperreAPIArtikelPreise($artikel)
{
  $this->app->DB->Update("UPDATE verkaufspreise SET apichange=0 WHERE artikel=$artikel");
  //$this->app->DB->Update("UPDATE einkaufspreise SET apichange=0 WHERE artikel=$artikel");
}

// @refactor API Modul
function EntferneSperreAPIArtikelPreise($artikel)
{
  $this->app->DB->Update("UPDATE verkaufspreise SET gueltig_bis=DATE_SUB(NOW(),INTERVAL 1 DAY) WHERE apichange!=1 AND artikel=$artikel");
  //$this->app->DB->Update("UPDATE einkaufspreise SET gueltig_bis=DATE_SUB(NOW(),INTERVAL 1 DAY) WHERE apichange!=1 AND artikel=$artikel");
}

// @refactor Artikel Modul
function AddVerkaufspreisGruppe($artikel,$abmenge,$gruppe,$preis,$waehrung="EUR",$kundenartikelnummer="", $gueltig_ab = null, $interner_kommentar = null, $gueltig_bis = null)
{
  if($abmenge<=0)$abmenge=1;

  $gruppe = $this->app->DB->Select("SELECT id FROM gruppen WHERE id='$gruppe' LIMIT 1");
  if($gruppe <=0)
    return;
  $gueltigabwhere = 'curdate()';
  if($gueltig_ab)$gueltigabwhere = "'$gueltig_ab'";
  if($gruppe > 0)
    $check = $this->app->DB->Select("SELECT id FROM verkaufspreise WHERE ab_menge='".$abmenge."' AND gruppe='".$gruppe."' AND artikel='$artikel'  AND art='Gruppe'
        AND (gueltig_bis='0000-00-00' OR gueltig_bis >= $gueltigabwhere) AND geloescht!='1' AND adresse <= 0 LIMIT 1");
  else
    $check = $this->app->DB->Select("SELECT id FROM verkaufspreise WHERE ab_menge='".$abmenge."' AND (gruppe='' OR gruppe='0') AND artikel='$artikel'  AND art='Gruppe'
        AND (gueltig_bis='0000-00-00' OR gueltig_bis >= $gueltigabwhere) AND geloescht!='1' AND adresse <= 0 LIMIT 1");

  // soll man preis als ungueltig markieren?
  if($check > 0)
  {
    // noch nie dagewesen jetzt anlegen
    // ist der preis anders?
    $preis_alt = $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE id='$check' LIMIT 1");
    if($preis!=$preis_alt)
    {
      $this->app->DB->Update("UPDATE verkaufspreise SET gueltig_bis=DATE_SUB($gueltigabwhere,INTERVAL 1 DAY),apichange=1 WHERE id='$check' LIMIT 1");
      $this->app->DB->Insert("INSERT INTO verkaufspreise (id,gruppe,artikel,angelegt_am,
        ab_menge,waehrung,preis,firma,kundenartikelnummer,adresse,art,apichange,logdatei)
          VALUES ('','$gruppe','$artikel',NOW(),'$abmenge','$waehrung','$preis','".$this->app->User->GetFirma()."','".$kundenartikelnummer."',0,'Gruppe',1,now())");
      $insid = $this->app->DB->GetInsertID();
      if($waehrung !== 'EUR' && $waehrung !== ''){
      $kurs = $this->app->erp->GetWaehrungUmrechnungskurs('EUR', $waehrung, true);
    }else{
      $kurs = -1;
      $kursdatum = 'NULL';
    }
    if($kurs !== false){
      if($kurs !== -1){
        $kursdatum = "'" . date('Y-m-d') . "'";
      }
      $this->app->DB->Update("UPDATE verkaufspreise SET kurs = $kurs, kursdatum = $kursdatum WHERE id = $insid LIMIT 1");
    }
    if($gueltig_ab)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_ab = '$gueltig_ab' WHERE id = '$insid' LIMIT 1");
    if($interner_kommentar)$this->app->DB->Update("UPDATE verkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$insid' LIMIT 1");
  } else {
    // nur attribute update
    if($kundenartikelnummer!="")
    {
      $this->app->DB->Update("UPDATE verkaufspreise SET kundenartikelnummer='$kundenartikelnummer', apichange=1 WHERE id='$check' LIMIT 1");
    } else {
      $this->app->DB->Update("UPDATE verkaufspreise SET apichange=1 WHERE id='$check' LIMIT 1");
    }
    if($interner_kommentar)$this->app->DB->Update("UPDATE verkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$check' LIMIT 1");
  }
} else {
  $this->app->DB->Insert("INSERT INTO verkaufspreise (id,gruppe,artikel,angelegt_am,
    ab_menge,waehrung,preis,firma,kundenartikelnummer,adresse,art,apichange)
      VALUES ('','$gruppe','$artikel',NOW(),'$abmenge','$waehrung','$preis','".$this->app->User->GetFirma()."','".$kundenartikelnummer."',0,'Gruppe',1)");
  $insid = $this->app->DB->GetInsertID();
  if($waehrung !== 'EUR' && $waehrung !== ''){
    $kurs = $this->app->erp->GetWaehrungUmrechnungskurs('EUR', $waehrung, true);
  }else{
    $kurs = false;
  }
  if($kurs !== false){
    if($kurs !== -1){
      $kursdatum = "'" . date('Y-m-d') . "'";
    }
    $this->app->DB->Update("UPDATE verkaufspreise SET kurs = $kurs, kursdatum = $kursdatum WHERE id = $insid LIMIT 1");
  }
    if($gueltig_ab)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_ab = '".$this->app->DB->real_escape_string($gueltig_ab)."' WHERE id = '$insid' LIMIT 1");
    if($gueltig_bis)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_bis = '".$this->app->DB->real_escape_string($gueltig_bis)."' WHERE id = '$insid' LIMIT 1");
    if($interner_kommentar)$this->app->DB->Update("UPDATE verkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$insid' LIMIT 1");
  }
}

// @refactor Artikel Modul
function AddVerkaufspreis($artikel,$abmenge,$adresse,$preis,$waehrung="EUR",$kundenartikelnummer="", $gruppe = null, $gueltig_ab = null, $interner_kommentar = null, $gueltig_bis = null)
{
  if($adresse==="")
    return false;

  if($abmenge<=0)$abmenge=1;

  if($adresse > 0)
  {
    $adresse = $this->app->DB->Select("SELECT id FROM adresse WHERE id='$adresse' LIMIT 1");
    if($adresse <=0)
      return false;
  }

  if($waehrung == "EUR")
  {
    $where = " AND (waehrung = '' OR waehrung = 'EUR') ";
  }else{
    $where = " AND waehrung = '".$waehrung."' ";
  }

  $gueltigabwhere = 'curdate()';
  if($gueltig_ab)$gueltigabwhere = "'$gueltig_ab'";

  $preis = round($preis,8);

  if($adresse > 0)
    $check = $this->app->DB->Select("SELECT id FROM verkaufspreise WHERE ab_menge=".$abmenge." ".$where." AND adresse=".$adresse." AND artikel=$artikel AND art='Kunde'
        AND (gueltig_bis='0000-00-00' OR gueltig_bis >= $gueltigabwhere) AND (gueltig_ab='0000-00-00' OR gueltig_ab <= $gueltigabwhere) AND geloescht!='1' ".($gruppe?" AND gruppe = '$gruppe' ":'')." LIMIT 1");
  else
    $check = $this->app->DB->Select("SELECT id FROM verkaufspreise WHERE ab_menge=".$abmenge." ".$where." AND (adresse='' OR adresse=0) AND artikel=$artikel AND art='Kunde'
        AND (gueltig_bis='0000-00-00' OR gueltig_bis >= $gueltigabwhere) AND (gueltig_ab='0000-00-00' OR gueltig_ab <= $gueltigabwhere) AND geloescht!=1 ".($gruppe?" AND gruppe = '$gruppe' ":'')." LIMIT 1");

// soll man preis als ungueltig markieren?
if($check > 0)
{
  // noch nie dagewesen jetzt anlegen
  // ist der preis anders?
  $preis_alt = $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE id='$check' LIMIT 1");
  if($preis!=$preis_alt)
  {
    $this->app->DB->Update("UPDATE verkaufspreise SET gueltig_bis=DATE_SUB($gueltigabwhere,INTERVAL 1 DAY),apichange=1 WHERE id='$check' LIMIT 1");
    $this->app->DB->Insert("INSERT INTO verkaufspreise (id,adresse,artikel,angelegt_am,
      ab_menge,waehrung,preis,firma,kundenartikelnummer,art,apichange,logdatei)
        VALUES ('','$adresse','$artikel',NOW(),'$abmenge','$waehrung','$preis','1','".$kundenartikelnummer."','Kunde',1,now())");

    $insid = $this->app->DB->GetInsertID();
    if($waehrung !== 'EUR' && $waehrung !== ''){
      $kurs = $this->app->erp->GetWaehrungUmrechnungskurs('EUR', $waehrung, true);
    }else{
      $kurs = -1;
      $kursdatum = 'NULL';
    }
    if($kurs !== false){
      if($kurs !== -1){
        $kursdatum = "'" . date('Y-m-d') . "'";
      }
      $this->app->DB->Update("UPDATE verkaufspreise SET kurs = $kurs, kursdatum = $kursdatum WHERE id = $insid LIMIT 1");
    }

    if($gueltig_ab)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_ab = '$gueltig_ab' WHERE id = '$insid' LIMIT 1");
    $this->ObjektProtokoll('verkaufspreise',$insid,'AddVerkaufspreis',"Verkaufspreis von $preis_alt nach $preis ge&auuml;ndert");
    if($gruppe)
    {
      $this->app->DB->Update("UPDATE verkaufspreise set gruppe = '".$gruppe."' where id = '".$insid."'");
    }
    if($gueltig_bis)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_bis = '".$this->app->DB->real_escape_string($gueltig_bis)."' WHERE id = '$insid' LIMIT 1");
    if($interner_kommentar)$this->app->DB->Update("UPDATE verkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$insid' LIMIT 1");
    return $insid;
  } else {
    // nur attribute update
    if($kundenartikelnummer!="")
    {
      $this->app->DB->Update("UPDATE verkaufspreise SET kundenartikelnummer='$kundenartikelnummer',apichange=1 WHERE id='$check' LIMIT 1");
      $this->ObjektProtokoll('verkaufspreise',$check,'AddVerkaufspreis',"Kundenartikelnummer ge&auuml;ndert");
    } else {
      $this->app->DB->Update("UPDATE verkaufspreise SET apichange=1 WHERE id='$check' LIMIT 1");
    }
    if($interner_kommentar)$this->app->DB->Update("UPDATE verkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$check' LIMIT 1");
  }
  return $check;
} else {
  $this->app->DB->Insert("INSERT INTO verkaufspreise (id,adresse,artikel,angelegt_am,
    ab_menge,waehrung,preis,firma,kundenartikelnummer,art,apichange,logdatei)
      VALUES ('','$adresse','$artikel',NOW(),'$abmenge','$waehrung','$preis','1','".$kundenartikelnummer."','Kunde',1,now())");
      $insid = $this->app->DB->GetInsertID();
  if($waehrung !== 'EUR' && $waehrung !== ''){
    $kurs = $this->app->erp->GetWaehrungUmrechnungskurs('EUR', $waehrung, true);
  }else{
    $kurs = false;
  }
  if($kurs !== false){
    $kursdatum = "'" . date('Y-m-d') . "'";
    $this->app->DB->Update("UPDATE verkaufspreise SET kurs = $kurs, kursdatum = $kursdatum WHERE id = $insid LIMIT 1");
  }
    if($gueltig_ab)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_ab = '".$this->app->DB->real_escape_string($gueltig_ab)."' WHERE id = '$insid' LIMIT 1");
    if($gueltig_bis)$this->app->DB->Update("UPDATE verkaufspreise SET gueltig_bis = '".$this->app->DB->real_escape_string($gueltig_bis)."' WHERE id = '$insid' LIMIT 1");
    if($gruppe)
    {
      $this->app->DB->Update("UPDATE verkaufspreise set gruppe = '".$gruppe."' where id = '".$insid."'");
    }
    if($interner_kommentar)$this->app->DB->Update("UPDATE verkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$insid' LIMIT 1");
    $this->ObjektProtokoll('verkaufspreise',$insid,'AddVerkaufspreis',"Verkaufspreis angelegt");
    return $insid;
  }
}

// @refactor Artikel Modul
function AddEinkaufspreis($artikel,$abmenge,$adresse,$bestellnummer,$bezeichnunglieferant,$preis,$waehrung="",$vpe="", $testebestellnummer = false, $interner_kommentar = null)
{
  if($abmenge<=0) $abmenge=1;

  if($waehrung=="") $waehrung="EUR";
  if($waehrung == "EUR")
  {
    $where = " AND (waehrung = '' OR waehrung = 'EUR') ";
  }else{
    $where = " AND waehrung = '".$waehrung."' ";
  }

  if($testebestellnummer && $bestellnummer)$where = " AND bestellnummer = '".addslashes($bestellnummer)."' ";
  $check = $this->app->DB->Select("SELECT id FROM einkaufspreise WHERE ab_menge='".$abmenge."' AND adresse='".$adresse."' AND artikel='$artikel'
      AND (gueltig_bis='0000-00-00' OR gueltig_bis >= NOW()) AND geloescht!='1' ".$where." LIMIT 1");
  // soll man preis als ungueltig markieren?
  if($check > 0)
  {
    // noch nie dagewesen jetzt anlegen
    // ist der preis anders?
    $preis_alt = $this->app->DB->Select("SELECT preis FROM einkaufspreise WHERE id='$check' LIMIT 1");
    if($preis!=$preis_alt)
    {
      $this->app->DB->Update("UPDATE einkaufspreise SET gueltig_bis=DATE_SUB(NOW(),INTERVAL 1 DAY),apichange=1 WHERE id='$check' LIMIT 1");
      //$this->AddEinkaufspreis($artikel,$abmenge,$adresse,$bestellnummer,$bezeichnunglieferant,$preis,$waehrung);
      $this->app->DB->Insert("INSERT INTO einkaufspreise (id,adresse,artikel,bestellnummer,bezeichnunglieferant, preis_anfrage_vom,
        ab_menge,waehrung,preis,firma,vpe,apichange,logdatei) VALUES
          ('','$adresse','$artikel','$bestellnummer','$bezeichnunglieferant',NOW(),'$abmenge','$waehrung','$preis','".$this->app->User->GetFirma()."','$vpe',1, now())");
      if($interner_kommentar)$this->app->DB->Update("UPDATE einkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$insid' LIMIT 1");
      $insid = $this->app->DB->GetInsertID();
      $this->ObjektProtokoll('einkaufspreise',$insid,'AddEinkaufspreis',"Einkaufspreis von $preis_alt nach $preis ge&auuml;ndert");
      return $insid;
    } else {
      $this->app->DB->Update("UPDATE einkaufspreise SET bestellnummer='$bestellnummer', bezeichnunglieferant='$bezeichnunglieferant',apichange=1, logdatei = now()
          WHERE id='$check' LIMIT 1");
      $this->ObjektProtokoll('einkaufspreise',$check,'AddEinkaufspreis',"Einkaufspreis ge&auuml;ndert");
      if($interner_kommentar)$this->app->DB->Update("UPDATE einkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$check' LIMIT 1");
      return $check;
    }
  } else {
    //$this->AddEinkaufspreis($artikel,$abmenge,$adresse,$bestellnummer,$bezeichnunglieferant,$preis,$waehrung);
    $this->app->DB->Insert("INSERT INTO einkaufspreise (id,adresse,artikel,bestellnummer,bezeichnunglieferant,      preis_anfrage_vom,
      ab_menge,waehrung,preis,firma,vpe,apichange, logdatei) VALUES
        ('','$adresse','$artikel','$bestellnummer','$bezeichnunglieferant',NOW(),'$abmenge','$waehrung','$preis','".$this->app->User->GetFirma()."','$vpe',1,now())");
    $insid = $this->app->DB->GetInsertID();
    if($interner_kommentar)$this->app->DB->Update("UPDATE einkaufspreise SET bemerkung = '".$this->app->DB->real_escape_string($interner_kommentar)."' WHERE id = '$insid' LIMIT 1");
    $this->ObjektProtokoll('einkaufspreise',$insid,'AddEinkaufspreis',"Einkaufspreis angelegt");
    return $insid;

  }

}

// @refactor Artikel Modul
function EinkaufspreisBetrag($artikel,$menge,$lieferant,$projekt='')
{
  if(!$menge) {
    $menge = 1;
  }
  $id = $artikel;
  $adresse = $lieferant;

  $ek = $this->app->DB->Select("SELECT preis FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND ab_menge <= $menge order by ab_menge desc LIMIT 1");
  if($ek) {
    return $ek;
  }

  return $this->app->DB->Select("SELECT preis FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') order by ab_menge ASC LIMIT 1");
}

// @refactor Artikel Modul
function Einkaufspreis($artikel,$menge,$lieferant,$projekt="")
{
  $id = $artikel;
  $adresse = $lieferant;

  $ek = $this->app->DB->Select("SELECT id FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND ab_menge <= $menge order by ab_menge desc  LIMIT 1");
  if($ek) {
    return $ek;
  }
  return $this->app->DB->Select("SELECT id FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') order by ab_menge LIMIT 1");
}


// @refactor Bestellung Modul
function ArtikelBestellung($artikel, $format = false, $ohnebestellauftrag = false)
{
  $summe_in_bestellung  = $this->app->DB->Select("SELECT ".($format?"trim(SUM(bp.menge-bp.geliefert))+0":"SUM(bp.menge-bp.geliefert)")." 
  FROM bestellung_position bp 
  LEFT JOIN bestellung b ON b.id=bp.bestellung 
  WHERE bp.artikel='$artikel' ".($ohnebestellauftrag?" AND bp.auftrag_position_id = 0 ":"")." AND bp.geliefert < bp.menge AND (bp.abgeschlossen IS NULL OR bp.abgeschlossen!=1) AND b.status!='abgeschlossen' AND b.status!='freigegeben' AND b.status!='angelegt' AND b.status!='storniert'");

  if($summe_in_bestellung <= 0)
    return 0;

  return $summe_in_bestellung;
}

// @refactor Bestellung Modul
function ArtikelBestellungNichtVersendet($artikel, $format = false, $ohnebestellauftrag = false)
{
  //$summe_in_bestellung  = $this->app->DB->Select("SELECT SUM(bp.menge-bp.geliefert) FROM bestellung_position bp WHERE bp.artikel='$artikel' AND bp.geliefert < bp.menge AND bp.abgeschlossen!='1'");

  $summe_in_bestellung  = $this->app->DB->Select("SELECT ".($format?"trim(SUM(bp.menge-bp.geliefert))+0":"SUM(bp.menge-bp.geliefert)")." 
  FROM bestellung_position bp 
  LEFT JOIN bestellung b ON b.id=bp.bestellung 
  WHERE bp.artikel='$artikel' ".($ohnebestellauftrag?" AND bp.auftrag_position_id = 0 ":"")." AND bp.geliefert < bp.menge AND (bp.abgeschlossen IS NULL OR bp.abgeschlossen!=1) AND (b.status='freigegeben' OR b.status='angelegt')");


  if($summe_in_bestellung <= 0)
    return 0;

  return $summe_in_bestellung;
}


// @refactor Bestellung Modul
function ArtikelVerkaufGesamt($artikel, $format = false)
{
  if($format)
  {
    $summe_im_auftrag  = $this->app->DB->Select("SELECT trim(SUM(menge))+0 FROM auftrag_position ap LEFT JOIN auftrag a ON a.id=ap.auftrag WHERE ap.artikel='$artikel' AND a.status='abgeschlossen'");
    if($summe_im_auftrag<=0) $summe_im_auftrag=0;
    return $summe_im_auftrag;
  }
  $summe_im_auftrag  = $this->app->DB->Select("SELECT SUM(menge) FROM auftrag_position ap LEFT JOIN auftrag a ON a.id=ap.auftrag WHERE ap.artikel='$artikel' AND a.status='abgeschlossen'");
  if($summe_im_auftrag<=0) $summe_im_auftrag=0;
  return $summe_im_auftrag;
}

// @refactor Bestellung Modul
function ReserviertAuftrag($artikel, $von = null, $bis = null, $ohnebestellung = false)
{
  return $this->app->DB->Select("SELECT trim(SUM(ifnull(r.menge,0)))+0
  FROM lager_reserviert r INNER JOIN
  (SELECT ap.auftrag, ap.artikel, sum(ap.menge) as menge 
  FROM auftrag_position ap 
  ".($ohnebestellung?"  LEFT JOIN bestellung_position bp ON ap.id = bp.auftrag_position_id  ":"")."
  INNER JOIN auftrag a ON a.id=ap.auftrag 
  WHERE ap.artikel='$artikel' ".($ohnebestellung?" AND isnull(bp.id) ":"")." AND a.status='freigegeben' ".($auftrag?" AND ap.auftrag = '$auftrag' ":"").""
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' 
  ":"")." GROUP BY ap.auftrag, ap.artikel) ab ON r.parameter = ab.auftrag AND r.artikel = '$artikel' AND r.objekt = 'auftrag'"
  );
}

// @refactor Bestellung Modul
function ReserviertLieferschein($artikel, $von = null, $bis = null)
{
  return $this->app->DB->Select("SELECT trim(SUM(ifnull(r.menge,0)))+0
  FROM `lager_reserviert` AS `r` INNER JOIN
  (SELECT lp.lieferschein, lp.artikel, sum(lp.menge) as `menge` 
  FROM `lieferschein_position` AS `lp` 
  INNER JOIN `lieferschein` AS `l` ON l.id = lp.lieferschein 
  WHERE lp.artikel = '$artikel'  AND l.status = 'freigegeben'"
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' 
  ":"")." GROUP BY lp.lieferschein, lp.artikel) AS `lb` ON r.parameter = lb.lieferschein AND r.artikel = '$artikel' AND r.objekt = 'lieferschein'"
  );
}

// @refactor Bestellung Modul
function ReserviertAuftragLiefertermin($artikel, $von = null, $bis = null, $ohnebestellung = false)
{
  return $this->app->DB->Select("SELECT trim(SUM(ifnull(r.menge,0)))+0 
  FROM lager_reserviert r INNER JOIN
  (SELECT ap.auftrag, ap.artikel, sum(ap.menge) as menge 
  FROM auftrag_position ap 
  ".($ohnebestellung?"  LEFT JOIN bestellung_position bp ON ap.id = bp.auftrag_position_id  ":"")."
  INNER JOIN auftrag a ON a.id=ap.auftrag 
  WHERE ap.artikel='$artikel' ".($ohnebestellung?" AND isnull(bp.id) ":"")." AND a.status='freigegeben' ".($auftrag?" AND ap.auftrag = '$auftrag' ":"").""
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' 
  AND (ifnull(ap.lieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(ap.lieferdatum,'0000-00-00') <= '$bis')
  AND (ifnull(a.tatsaechlicheslieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(a.tatsaechlicheslieferdatum,'0000-00-00') <= '$bis')
  AND (ifnull(a.lieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(a.lieferdatum,'0000-00-00') <= '$bis')
  
  ":"")." GROUP BY ap.auftrag, ap.artikel) ab ON r.parameter = ab.auftrag AND r.artikel = '$artikel' AND r.objekt = 'auftrag'"
  );
}

// @refactor Bestellung Modul
function ArtikelImAuftragLiefertermin($artikel, $format = false, $von = null, $bis = null, $auftrag = 0, $ohnebestellung = false)
{
  return $this->app->DB->Select("SELECT ".($format?"trim(SUM(menge))+0":"sum(menge)")." 
  FROM auftrag_position ap 
  LEFT JOIN auftrag a ON a.id=ap.auftrag 
  ".($ohnebestellung?"  LEFT JOIN bestellung_position bp ON ap.id = bp.auftrag_position_id  ":"")."
  WHERE ap.artikel='$artikel' ".($ohnebestellung?" AND isnull(bp.id) ":"")." AND a.status='freigegeben' ".($auftrag?" AND ap.auftrag = '$auftrag' ":"").""
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' 
  AND (ifnull(ap.lieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(ap.lieferdatum,'0000-00-00') <= '$bis')
  AND (ifnull(a.tatsaechlicheslieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(a.tatsaechlicheslieferdatum,'0000-00-00') <= '$bis')
  AND (ifnull(a.lieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(a.lieferdatum,'0000-00-00') <= '$bis')
  
  ":"")
  );

  return $summe_im_auftrag;
}

// @refactor Bestellung Modul
function ArtikelImAuftrag($artikel, $format = false, $von = null, $bis = null, $auftrag = 0, $ohnebestellung = false)
{
  return $this->app->DB->Select("SELECT ".($format?"trim(SUM(ap.menge))+0":"SUM(ap.menge)")." 
  FROM auftrag_position ap 
  ".($ohnebestellung?"  LEFT JOIN bestellung_position bp ON ap.id = bp.auftrag_position_id  ":"")."
  LEFT JOIN auftrag a ON a.id=ap.auftrag 
  WHERE ap.artikel='$artikel' ".($ohnebestellung?" AND isnull(bp.id) ":"")."  AND a.status='freigegeben' ".($auftrag?" AND ap.auftrag = '$auftrag' ":"")."  "
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' ":"")
  );
}

// @refactor Bestellung Modul
function ArtikelImAuftragStuecklisteLiefertermin($artikel, $format = false, $von = null, $bis = null, $auftrag = 0, $ohnebestellung = false)
{

  return $this->app->DB->Select("SELECT ".($format?"trim(SUM(ap.menge * s.menge))+0":"SUM(ap.menge * s.menge)")." 
  FROM auftrag_position ap 
  ".($ohnebestellung?"  LEFT JOIN bestellung_position bp ON ap.id = bp.auftrag_position_id  ":"")."
  INNER JOIN auftrag a ON a.id=ap.auftrag 
  INNER JOIN stueckliste s ON ap.artikel = s.stuecklistevonartikel 
  INNER JOIN artikel a2 ON a2.id = s.stuecklistevonartikel  
  WHERE s.artikel='$artikel' ".($ohnebestellung?" AND isnull(bp.id) ":"")."  AND a.status='freigegeben' AND a2.produktion = 1 ".($auftrag?" AND ap.auftrag = '$auftrag' ":"")." "
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' 
    AND (ifnull(ap.lieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(ap.lieferdatum,'0000-00-00') <= '$bis')
  AND (ifnull(a.tatsaechlicheslieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(a.tatsaechlicheslieferdatum,'0000-00-00') <= '$bis')
  AND (ifnull(a.lieferdatum,'0000-00-00') = '0000-00-00' OR ifnull(a.lieferdatum,'0000-00-00') <= '$bis')
  ":"")
  );

  return $summe_im_auftrag;
}

// @refactor Bestellung Modul
function ArtikelImAuftragStueckliste($artikel, $format = false, $von = null, $bis = null, $auftrag = 0, $ohnebestellung = false)
{
  return $this->app->DB->Select("SELECT ".($format?" trim(SUM(ap.menge * s.menge))+0 ":" SUM(ap.menge * s.menge) ")." 
  FROM auftrag_position ap 
  ".($ohnebestellung?"  LEFT JOIN bestellung_position bp ON ap.id = bp.auftrag_position_id  ":"")."
  INNER JOIN auftrag a ON a.id=ap.auftrag 
  INNER JOIN stueckliste s ON ap.artikel = s.stuecklistevonartikel INNER JOIN artikel a2 ON a2.id = s.stuecklistevonartikel 
  WHERE s.artikel='$artikel'  ".($ohnebestellung?" AND isnull(bp.id) ":"")."  AND a.status='freigegeben' AND a2.produktion = 1 ".($auftrag?" AND ap.auftrag = '$auftrag' ":"").""
  .($von && $von != '0000-00-00'?" AND a.datum >= '$von' ":"")
  .($bis && $bis != '0000-00-00'?" AND a.datum <= '$bis' ":"")
  );
}

// @refactor Lager Modul
function ArtikelImLagerPlatz($artikel,$lager_platz, $format = false)
{
  if(!$lager_platz)return 0;
  if($format)return $this->app->DB->Select("SELECT trim(SUM(menge))+0 FROM lager_platz_inhalt WHERE artikel='$artikel' AND lager_platz='$lager_platz'");
  $summe_im_lager = $this->app->DB->Select("SELECT SUM(menge) FROM lager_platz_inhalt WHERE artikel='$artikel' AND lager_platz='$lager_platz'");
  return $summe_im_lager;
}

// @refactor Lager Modul
public function ArtikelImLager($artikel, $format = false)
{
  if($format){
    return $this->app->DB->Select("SELECT trim(SUM(menge))+0 FROM lager_platz_inhalt WHERE artikel='$artikel'");
  }
  $summe_im_lager = $this->app->DB->Select("SELECT SUM(menge) FROM lager_platz_inhalt WHERE artikel='$artikel'");
  return $summe_im_lager;
}

// @refactor Lager Modul
public function ArtikelImLagerOhneSperrlager($artikel, $format = false)
{

  if($format){
    return $this->app->DB->Select("SELECT trim(ifnull(SUM(lpi.menge),0))+0 FROM lager_platz_inhalt lpi 
      INNER JOIN lager_platz lp ON lpi.lager_platz = lp.id AND (ifnull(lp.sperrlager,0) = 0 OR lp.allowproduction)
      WHERE lpi.artikel='$artikel'");
  }
  $summe_im_lager = $this->app->DB->Select("SELECT ifnull(SUM(lpi.menge),0) FROM lager_platz_inhalt lpi 
    INNER JOIN lager_platz lp ON lpi.lager_platz = lp.id AND ifnull(lp.sperrlager,0) = 0
    WHERE lpi.artikel='$artikel'");
  return $summe_im_lager;
}

function VerbindlichkeitErweiterteBestellung($id)
{
  /** @var Verbindlichkeit $obj */
  $obj = $this->app->erp->LoadModul('verbindlichkeit');
  if(!empty($obj) && method_exists($obj, 'VerbindlichkeitErweiterteBestellung')) {
    return $obj->VerbindlichkeitErweiterteBestellung($id);
  }
  return [];
}

/**
 * @deprecated
 * @refactor Verbindlichkeit Modul
 */
function BestellungErweiterteVerbindlichkeiten($id)
{
  for($i=1;$i<=15;$i++)
  {
    $alleids[] = $this->app->DB->SelectArr("SELECT id, bestellung{$i}betrag as betrag FROM verbindlichkeit WHERE bestellung$i='$id'");
  }

  for($i=0;$i<(!empty($alleids)?count($alleids):0);$i++)
  {
    for($ij=0;$ij<count($alleids[$i]);$ij++)
    {
      $result[$alleids[$i][$ij]['id']] = $alleids[$i][$ij]['betrag'];
    }
  }
  return $result;
}

function BestellungErweiterteVerbindlichkeitenNeu($id){
  /** @var Verbindlichkeit $obj */
  $obj = $this->app->erp->LoadModul('verbindlichkeit');
  if(!empty($obj) && method_exists($obj, 'BestellungErweiterteVerbindlichkeitenNeu')) {
    return $obj->BestellungErweiterteVerbindlichkeitenNeu($id);
  }
  return [];
}


function get_emails ($str)
{
  $emails = array();
  $pattern="/([\s]*)([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*([ ]+|)@([ ]+|)([a-zA-Z0-9-]+\.)+([a-zA-Z]{2,}))([\s]*)/i";
  //preg_match_all("/\b\w+\@w+[\-\.\w+]+\b/", $str, $output);
  preg_match_all($pattern, $str, $output);
  foreach($output[0] as $email) array_push ($emails, trim(strtolower($email)));
  if ((!empty($emails)?count($emails):0) >= 1) return $emails;
  else return false;
}

/**@deprecated */
function AufragZuDTA($auftrag,$rechnung="1")
{
  $arr = $this->app->DB->Select("SELECT belegnr, bank_inhaber, bank_konto, bank_blz, gesamtsumme, adresse, name FROM auftrag WHERE id='$auftrag'");


  if($rechnung=="1")
  {
    $arr[0]['vz1'] = "RE ".$this->app->DB->Select("SELECT belegnr FROM rechnung WHERE auftrag='{$arr[0]['belegnr']}' LIMIT 1");
  } else
    $arr[0]['vz1'] = "";

  $this->app->DB->Insert("INSERT INTO dta (id,adresse,datum,name,konto,blz,betrag,vz1,firma)
      VALUES('','{$arr[0]['adresse']}',NOW(),'{$arr[0]['name']}','{$arr[0]['konto']}','{$arr[0]['blz']}','{$arr[0]['betrag']}','{$arr[0]['vz1']}','".$this->app->User->GetFirma()."')");

}

//@refactor versanddiestleister Modul
function TrackingNummerAnpassen($projekt,$tracking)
{

  if($this->Projektdaten($projekt,"tracking_substr_length") > 0)
    $tracking = substr($tracking,$this->Projektdaten($projekt,"tracking_substr_start"),$this->Projektdaten($projekt,"tracking_substr_length"));
  else
    $tracking = substr($tracking,$this->Projektdaten($projekt,"tracking_substr_start"));

  //TODO anpassung, damit die Nummer an schluss entfernt wird
  $kundennummerdpd = $this->app->DB->Select("SELECT dpdkundennr FROM projekt WHERE id='$projekt' LIMIT 1");

  if($this->Projektdaten($projekt,"tracking_remove_kundennummer") =="1")
    $tracking = str_replace($kundennummerdpd,"",$tracking);

  return $tracking;
}

//@refactor versanddiestleister Modul
function PaketmarkeGewichtForm($anzahl, $standardkg, $mindestgewicht = 0)
{
  $mitwaage = false;
  $mindestgewicht = (float)$mindestgewicht;
  if($this->app->erp->Firmendaten('paketmarke_mit_waage'))
  {
    $mitwaage = $this->app->DB->Select("SELECT seriennummer FROM adapterbox WHERE verwendenals = 'waage' AND seriennummer <> '' LIMIT 1");
  }
  if($anzahl==1)
  {
    $i=1;
    $this->app->Tpl->Add('GEWICHT','<tr><td nowrap>Gewicht:</td><td><input type="text" id="kg'.$i.'" name="kg'.$i.'" size="5" value="'.$standardkg.'">&nbsp;<i>in kg</i>');
    if($mitwaage)
    {
      $this->app->Tpl->Add('GEWICHT','&nbsp;<input type="button" value="Waage" onclick="Getgewicht('.$i.')" />');
      $this->app->Tpl->Set('SERIENNUMMER', $mitwaage);
      $this->app->Tpl->Set('MINDESTGEWICHT', $mindestgewicht);
      $this->app->Tpl->Parse('GEWICHT', 'paketmarke_waage.tpl');
    }
    $this->app->Tpl->Add('GEWICHT','</td></tr>');

  }
  else {
    for($i=1;$i<=$anzahl;$i++)
    {
      $this->app->Tpl->Add('GEWICHT','<tr><td nowrap>Gewicht:</td><td><input type="text" id="kg'.$i.'" name="kg'.$i.'" size="5" value="'.$standardkg.'">&nbsp;<i>in kg</i>');
      if($mitwaage)
      {
        $this->app->Tpl->Add('GEWICHT','&nbsp;<input type="button" value="Waage" onclick="Getgewicht('.$i.')" />');
        $this->app->Tpl->Set('SERIENNUMMER', $mitwaage);
        $this->app->Tpl->Set('MINDESTGEWICHT', $mindestgewicht);
        if($i == 1)$this->app->Tpl->Parse('GEWICHT', 'paketmarke_waage.tpl');
      }
      $this->app->Tpl->Add('GEWICHT','</td></tr>');
    }
  }
}

//@refactor versanddiestleister Modul
function VersandartMindestgewicht($id=0)
{
  $gewicht = $this->LieferscheinNettoGewicht($id);
  $versandart =""; $projekt=0; $intraship_weightinkg=0;
  $gewicht /= $this->GewichtzuKgFaktor();

if($id > 0)
{
  $versandart = $this->app->DB->Select("SELECT versandart FROM lieferschein WHERE id='$id' LIMIT 1");
  $projekt = $this->app->DB->Select("SELECT projekt FROM lieferschein WHERE id='$id' LIMIT 1");
  $intraship_weightinkg = $this->app->DB->Select("SELECT intraship_weightinkg FROM projekt WHERE id='$projekt' LIMIT 1");
  $versandart = strtolower($versandart);

  $modul = $this->app->DB->SelectArr("SELECT id, modul FROM `versandarten` WHERE aktiv = 1 AND ausprojekt = 0 AND modul <> '' AND type = '".$this->app->DB->real_escape_string($versandart)."' AND geloescht = 0 AND (projekt = 0 OR projekt = '$projekt') ORDER by projekt = '$projekt' DESC LIMIT 1");
  if($modul && @is_file(dirname(__FILE__).'/versandarten/'.$modul[0]['modul'].'.php'))
  {
    $obj = $this->LoadVersandModul($modul[0]['modul'], $modul[0]['id']);
    if($obj){
      if(method_exists($obj, 'VersandartMindestgewicht'))
        $mindestgewicht = $obj->VersandartMindestgewicht();
      return $mindestgewicht > $gewicht ? $mindestgewicht : $gewicht;
    }
  }
}

  if(($versandart=="dhl" || $versandart=="versandunternehmen") && $intraship_weightinkg > 0 && $gewicht <=0) return $intraship_weightinkg;
  else if ($gewicht > 0) return $gewicht;
  else return 2;
}


//@refactor ApplicationCore
function LoadVersandModul(string $modul, int $id): Versanddienstleister
{
  /** @var Versandarten $versandarten */
  $versandarten = $this->app->loadModule('versandarten');
  return $versandarten->loadModule($modul, $id);
}

//@refactor versanddiestleister Modul
function ExtractStreetnumber($street)
{
  $address = trim($street);
  $number = preg_replace('/^.*?(\d+).*$/i', '$1', $address);
  // suche erstes vorkommen
  $pos = strpos($address,$number);
  if($pos === 0)
  {
    $result = substr($address, 0, strpos($address ,' '));
  }else{
    $result = substr  ( $address, $pos);
  }
  return $result;
}
//@refactor versanddiestleister Modul
function RetoureNettoGewicht($id)
{
  return $this->LieferscheinNettoGewicht($id, 'retoure');
}
//@refactor versanddiestleister Modul
    /**
   * @param int    $id
   * @param string $doctype
   *
   * @return float|int
   */
  public function LieferscheinNettoGewicht($id=0, $doctype = 'lieferschein')
  {
    if($id <= 0) {
      return 0;
    }

    if($this->Firmendaten('stuecklistegewichtnurartikel')!='1') {
      $nettogewicht = $this->app->DB->Select(
          "SELECT SUM(REPLACE(a.gewicht,',','.')*ap.menge)
        FROM ".$doctype."_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id WHERE ap.".$doctype."='$id'");
    }
    else {
      $nettogewicht = $this->app->DB->Select(
          "SELECT SUM(REPLACE(if(a2.gewicht > 0,0,a.gewicht),',','.')*ap.menge)
        FROM ".$doctype."_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id 
        LEFT JOIN ".$doctype."_position ap2 ON ap2.id=ap.explodiert_parent 
        LEFT JOIN artikel a2 ON a2.id=ap2.artikel 
        WHERE ap.".$doctype."='$id'"
      );
    }

    if($nettogewicht > 0){
      return round($nettogewicht, 2);
    }
    return 0;
  }
//@refactor versanddiestleister Modul

  /**
   * @param int $id
   *
   * @return float|int
   */
  public function AuftragNettoGewicht($id=0)
  {
    if($id <= 0) {
      return 0;
    }

    if($this->Firmendaten('stuecklistegewichtnurartikel')!='1') {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(a.gewicht,',','.')*ap.menge)
        FROM auftrag_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id 
        WHERE ap.auftrag='$id'"
      );
    }
    else {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(if(a2.gewicht > 0,0,a.gewicht),',','.')*ap.menge)
        FROM auftrag_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id 
        LEFT JOIN auftrag_position ap2 ON ap2.id=ap.explodiert_parent 
        LEFT JOIN artikel a2 ON a2.id=ap2.artikel 
        WHERE ap.auftrag='$id'"
      );
    }

    if($nettogewicht > 0){
      return round($nettogewicht, 2);
    }

    return 0;
  }

function BestellungNettoGewicht($id=0){
  if($id <= 0) {
    return 0;
  }

    if($this->Firmendaten('stuecklistegewichtnurartikel')!='1') {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(a.gewicht,',','.')*bp.menge)
        FROM bestellung_position bp 
        INNER JOIN artikel a ON bp.artikel=a.id WHERE bp.bestellung='$id'");
    }
    else {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(if(a2.gewicht > 0,0,a.gewicht),',','.')*bp.menge)
        FROM bestellung_position bp 
        INNER JOIN artikel a ON bp.artikel=a.id 
        LEFT JOIN bestellung_position bp2 ON bp2.id=bp.explodiert_parent 
        LEFT JOIN artikel a2 ON a2.id=bp2.artikel 
        WHERE bp.bestellung='$id'"
      );
    }

  if($nettogewicht > 0){
    return round($nettogewicht, 2);
  }

  return 0;
}

function AngebotNettoGewicht($id=0){
  if($id <= 0) {
    return 0;
  }
    if($this->Firmendaten('stuecklistegewichtnurartikel')!='1')
    {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(a.gewicht,',','.')*ap.menge)
        FROM angebot_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id 
        WHERE ap.angebot='$id'"
      );
    } else {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(if(a2.gewicht > 0,0,a.gewicht),',','.')*ap.menge)
        FROM angebot_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id 
        LEFT JOIN angebot_position ap2 ON ap2.id=ap.explodiert_parent 
        LEFT JOIN artikel a2 ON a2.id=ap2.artikel 
        WHERE ap.angebot='$id'"
      );
    }

  if($nettogewicht > 0){
    return round($nettogewicht, 2);
  }

  return 0;
}

  //@refactor versanddiestleister Modul
  public function ProformarechnungNettoGewicht($id=0,$round=true)
  {
    if($id <= 0) {
      return 0;
    }
    if($this->Firmendaten('stuecklistegewichtnurartikel')!='1')
    {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(a.gewicht,',','.')*prp.menge)
        FROM proformarechnung_position prp 
        INNER JOIN artikel a ON prp.artikel=a.id 
        WHERE prp.proformarechnung='$id'"
      );
    }
    else {
      $nettogewicht = $this->app->DB->Select(
        "SELECT SUM(REPLACE(if(a2.gewicht > 0,0,a.gewicht),',','.')*ap.menge)
        FROM proformarechnung_position ap 
        INNER JOIN artikel a ON ap.artikel=a.id 
        LEFT JOIN proformarechnung_position ap2 ON ap2.id=ap.explodiert_parent_artikel 
        LEFT JOIN artikel a2 ON a2.id=ap2.artikel 
        WHERE ap.proformarechnung='$id'"
      );
    }

    if($nettogewicht > 0) {
      if($round){
        return round($nettogewicht,2);
      }
      return $nettogewicht;
    }

    return 0;
  }




//@refactor Exportvorlage Modul
function Gegenkonto($ust_befreit,$ustid='', $doctype = '', $doctypeId = 0)
{
  /** @var Buchhaltungexport $buchhaltungexport */
  $buchhaltungexport = $this->app->loadModule('buchhaltungexport', false);
  if($buchhaltungexport !== null && method_exists($buchhaltungexport, 'Gegenkonto')) {
    return $buchhaltungexport->Gegenkonto($ust_befreit, $ustid, $doctype, $doctypeId);
  }
  switch($ust_befreit)
  {
    case 0: $tmp['gegenkonto']=$this->Firmendaten("steuer_erloese_inland_normal"); break;
    case 1:
            if($ustid=="")
            {
              $tmp['gegenkonto']=$this->Firmendaten("steuer_erloese_inland_eunormal");
            } else {
              $tmp['gegenkonto']=$this->Firmendaten("steuer_erloese_inland_innergemeinschaftlich");
            }
            break;
    case 2: $tmp['gegenkonto']=$this->Firmendaten("steuer_erloese_inland_export"); break;
    case 3: $tmp['gegenkonto']=$this->Firmendaten("steuer_erloese_inland_nichtsteuerbar"); break;
    default:
            //TODO
            echo "FEHLER!";
            exit;
  }

  if($tmp['gegenkonto']=="") {
    $tmp['gegenkonto']=$this->Firmendaten("steuer_standardkonto");
  }

  return $tmp['gegenkonto'];
}



  /**
   * @deprecated Use the setValue() function in SystemConfigModule instead<br>
   * Retrieve data with the getValue() and tryGetValue() functions<br>
   * Mind the additional namespace parameter
   *
   * @param string $name
   * @param mixed  $value
   */
  public function SetKonfigurationValue($name,$value)
  {
    $this->app->DB->Delete(
      sprintf(
        "DELETE FROM konfiguration WHERE name='%s'",
        $name
      )
    );
    $this->app->DB->Insert(
      sprintf(
        "INSERT INTO konfiguration (name,wert,firma,adresse) 
        VALUES ('%s','%s',%d,%d)",
        $name, $value,
        isset($this->app->User) && method_exists($this->app->User, 'GetFirma')?$this->app->User->GetFirma():1,
        isset($this->app->User) && method_exists($this->app->User, 'GetAdresse')?$this->app->User->GetAdresse():0
      )
    );
  }

  /**
  * @deprecated Use the NOT COMPATIBLE setValue() function in SystemConfigModule instead<br>
  * Retrieve data with the getValue() and tryGetValue() functions<br>
  * Mind the additional namespace parameter
  *
  * @param string $name
  * @param bool   $dezimal
  */
  function SetKonfiguration($name,$dezimal=false)
  {

    $this->app->DB->Delete("DELETE FROM konfiguration WHERE name='$name' LIMIT 1");

    if($dezimal)
      $value = str_replace(',','.',$this->app->Secure->GetPOST($name));
    else
      $value = $this->app->Secure->GetPOST($name);

    $this->app->DB->Insert("INSERT INTO konfiguration (name,wert,firma,adresse) VALUES ('$name','$value','".$this->app->User->GetFirma()."','".$this->app->User->GetAdresse()."')");

  }

  /**
   * @deprecated Use the tryGetLegacyValue() function in SystemConfigModule instead
   *
   * @param string $name
   *
   * @return string|bool
  */
  function GetKonfiguration($name)
  {

    return $this->app->DB->Select("SELECT wert FROM konfiguration WHERE name='$name' LIMIT 1");// AND firma='".$this->app->User->GetFirma()."' LIMIT 1");
  }

  /**
   * @param bool   $active
   * @param string $type
   */
  public function setMaintainance($active = true, $type = 'backup') {
    $tags = json_encode('update');
    if(!$active) {
      if($this->GetKonfiguration('update_maintenance') == '0') {
        return;
      }
      $this->SetKonfigurationValue('update_maintenance', 0);
      $this->SetKonfigurationValue('update_maintenance_mode', '');
      //$this->app->DB->Delete("DELETE FROM notification_message WHERE tags = '$tags'");
      return;
    }

    if($type !== 'backup') {
      return; //@todo
    }
    $this->SetKonfigurationValue('update_maintenance_mode', $type);
    if($this->GetKonfiguration('update_maintenance') == '1') {
      $this->SetKonfigurationValue('update_maintenance_time', time());
      return;
    }

    /*
    $this->app->DB->Insert(
      "INSERT INTO notification_message
        (user_id, type, title, message, tags, options_json, priority, created_at)
      SELECT u.id, 'warning',
             'laufender Backup-Prozess',
             'Bitte schließen Sie Ihre Aufgaben','$tags','',1,NOW()
      FROM `user` AS `u`
      INNER JOIN `useronline` AS `uo` on u.id = uo.user_id AND uo.login = 1"
    );*/

    $this->SetKonfigurationValue('update_maintenance_time', time());
    $this->SetKonfigurationValue('update_maintenance', 1);
  }

  //@refactor Folgebestaetigung Modul
  function Folgebestaetigung($adresse)
  {

    $sperre = $this->app->DB->Select("SELECT folgebestaetigungsperre FROM adresse WHERE id='$adresse' LIMIT 1");
    if($sperre=="1") return 1;

    // hole alle freigebeben auftraege
    $auftragarr = $this->app->DB->SelectArr("SELECT id,belegnr,ihrebestellnummer,DATE_FORMAT(datum,'%d.%m.%Y') as datum2, DATE_FORMAT(lieferdatum,'%d.%m.%Y') as lieferdatum2,
        liefertermin_ok
        FROM auftrag WHERE adresse='$adresse' AND status='freigegeben' AND (lager_ok!=1 OR liefertermin_ok!=1) ORDER by lieferdatum");

    $to = $this->app->DB->Select("SELECT email FROM adresse WHERE id='$adresse' LIMIT 1");
    $to_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$adresse' LIMIT 1");

    for($iauftrag=0;$iauftrag<(!empty($auftragarr)?count($auftragarr):0);$iauftrag++)
    {
      $auftrag = $auftragarr[$iauftrag]['id'];

      $projekt = $this->app->DB->Select("SELECT projekt FROM auftrag WHERE id='$auftrag' LIMIT 1");
      $folgebestaetigung = $this->app->DB->Select("SELECT folgebestaetigung FROM projekt WHERE id='$projekt' LIMIT 1");
      if($folgebestaetigung!=1)
        continue;

    if($auftragarr[$iauftrag]['lieferdatum2']=="00.00.0000") $auftragarr[$iauftrag]['lieferdatum2'] = $this->app->erp->Beschriftung("dokument_lieferdatum_sofort");
      if($auftragarr[$iauftrag]['liefertermin_ok']!="1")
      {
        $artikeltabelleliefertermin .= "<br>-Auftrag ".$auftragarr[$iauftrag]['belegnr']." vom ".$auftragarr[$iauftrag]['datum2']." Bestellung/Kommission: ".$auftragarr[$iauftrag]['ihrebestellnummer']." (geplanter Liefertermin: ".$auftragarr[$iauftrag]['lieferdatum2'].")<br>";
      }
      else {
        $artikeltabelle .= "<br>-Auftrag ".$auftragarr[$iauftrag]['belegnr']." vom ".$auftragarr[$iauftrag]['datum2']." Bestellung/Kommission: ".$auftragarr[$iauftrag]['ihrebestellnummer']." (geplanter Liefertermin: ".$auftragarr[$iauftrag]['lieferdatum2'].")<br>";
      }
      //$to = $this->app->DB->Select("SELECT email FROM auftrag WHERE id='$auftrag' LIMIT 1");
      //$to_name = $this->app->DB->Select("SELECT name FROM auftrag WHERE id='$auftrag' LIMIT 1");

      $arr = $this->app->DB->SelectArr("SELECT ap.nummer, ap.bezeichnung, ap.menge, (SELECT SUM(lp.menge) FROM lager_platz_inhalt lp WHERE lp.artikel=ap.artikel) as lager,
          (SELECT SUM(lr.menge) FROM lager_reserviert lr WHERE lr.artikel=ap.artikel AND lr.datum>=NOW() AND lr.objekt!='lieferschein') as reserviert,
          if(((SELECT SUM(lp.menge) FROM lager_platz_inhalt lp WHERE lp.artikel=ap.artikel) - (SELECT SUM(lr.menge) FROM lager_reserviert lr WHERE lr.artikel=ap.artikel AND lr.datum>=NOW() AND lr.objekt!='lieferschein') - ap.menge)>=0,'',
            ((SELECT SUM(lp.menge) FROM lager_platz_inhalt lp WHERE lp.artikel=ap.artikel) - (SELECT SUM(lr.menge) FROM lager_reserviert lr WHERE lr.artikel=ap.artikel AND lr.datum>=NOW() AND lr.objekt!='lieferschein') - ap.menge)
            ) as fehlend
          FROM auftrag_position ap LEFT JOIN artikel a ON a.id=ap.artikel WHERE ap.auftrag='$auftrag' AND a.lagerartikel=1");

    foreach($arr as $value)
    {
        $artikel = $value['bezeichnung'];
        $nummer = $value['nummer'];
        $menge  = $value['menge'];
        $lager  = $value['lager'];
        $reserviert= $value['reserviert'];

        if(($lager-$reserviert < $menge) && $auftragarr[$iauftrag]['liefertermin_ok']=="1")
        {
          $artikeltabelle .= "--Artikel: ".$artikel." (Nummer: $nummer) Menge: ".$menge."<br>";
        }
        else
        {
          $artikeltabelleliefertermin .= "--Artikel: ".$artikel." (Nummer: $nummer) Menge: ".$menge."<br>";
        }
    }
  }

    if($artikeltabelle!="") $artikeltabelle ="Rückstand:<br><br>".$artikeltabelle."<br><br>";
    if($artikeltabelleliefertermin!="") $artikeltabelle .="Offene Aufträge:<br><br>".$artikeltabelleliefertermin;

    $artikeltabelle = $this->ReadyForPDF($artikeltabelle);

    if($artikeltabelle!="")
    {

      $text = $this->GetGeschaeftsBriefText('Folgebestaetigung',$sprache, $projekt,"",$auftrag);
      $betreff = $this->GetGeschaeftsBriefBetreff('Folgebestaetigung', $sprache,$projekt,"auftrag",$auftrag);

      if($text == "")
      {
        $text = 'Lieber Kunde,

        anbei übersenden wir Ihnen eine Liste mit den aktuell offenen Aufträgen (Rückstand und Aufträge mit Liefertermin):

          '.$artikeltabelle.'

            Bei Fragen zu Lieferungen wenden Sie sich gerne an unser Kundensupport-Center.';

      $betreff = "Folgebestätigung für offene Aufträge";
      } else {
        $text = str_replace('{ARTIKELTABELLE}',$artikeltabelle,$text);
      }

      if($to!="" && $to_name!="")
        $this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$to,$to_name,$betreff,$text,"",$projekt);
      //echo $text;
    }

  }



  // prueft datei anhang aus geschaeftsbriefvorlagen, wenn diese fehlen werden die ergänzt
  //@refactor Geschaeftsbrief_vorlagen Modul
  function GeschaeftsBriefAnhang($subjekt,$sprache="",$projekt="",$dokument="",$dokumentid="")
  {
    if($dokument!="")
    {
      $abweichend = $this->app->DB->Select("SELECT abweichendebezeichnung FROM $dokument WHERE id='$dokumentid' LIMIT 1");
      if($abweichend>0 && !preg_match('/_Abweichend/',$subjekt))
      {
        $idvorlage = $this->GetGeschaeftsBriefID($subjekt."_Abweichend",$sprache,$projekt);
      }
    }
    

    if($idvorlage <=0)
      $idvorlage = $this->GetGeschaeftsBriefID($subjekt,$sprache,$projekt);

    $stichwoerter = $this->app->DB->SelectArr("SELECT * FROM datei_stichwoerter WHERE objekt='geschaeftsbrief_vorlagen' AND parameter='$idvorlage' AND parameter > 0");
    $cstichwoerter = !empty($stichwoerter)?count($stichwoerter):0;
    $tmpresult = array();
    for($i=0;$i<$cstichwoerter;$i++)
    {
      $check = $this->app->DB->Select("SELECT id FROM datei_stichwoerter WHERE datei='".$stichwoerter[$i]['datei']."' AND objekt LIKE '$subjekt' AND parameter='$dokumentid' LIMIT 1");
      if($check<=0)
      {
        if($dokument!="")
        {
          $this->app->DB->Insert("INSERT INTO datei_stichwoerter (id,datei,subjekt,objekt,parameter) VALUES ('','".$stichwoerter[$i]['datei']."','".$stichwoerter[$i]['subjekt']."','$subjekt',$dokumentid)");
        } else {
          $tmpresult[] = $stichwoerter[$i]['datei'];
        }
      } 
    }
    return $tmpresult;
  }


  //@refactor Geschaeftsbrief_vorlagen Modul
  function GetGeschaeftsBriefText($subjekt,$sprache='',$projekt='',$dokument='',$dokumentid=0)
  {

    $text = '';
    if ($dokument != '') {
      $dbcheck = $this->app->DB->Select("SHOW TABLES LIKE '$dokument'");     
      if (!empty($dbcheck)) {
        $abweichend = $this->app->DB->Select("SELECT abweichendebezeichnung FROM $dokument WHERE id='$dokumentid' LIMIT 1");
      }
      if($abweichend>0 && !preg_match('/_Abweichend/',$subjekt))
      {
       $text = $this->GetGeschaeftsBriefText($subjekt."_Abweichend",$sprache,$projekt,$dokument,$dokumentid); 
      } 
    }

    if($text=='')
    {
      if($sprache==''){
        $sprache = 'deutsch';
      }

      if($projekt > 0){
        $text = $this->app->DB->Select("SELECT text FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' AND projekt='$projekt' LIMIT 1");
      }

      if($text == ''){
        $text = $this->app->DB->Select("SELECT text FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' AND (projekt='0' OR projekt='')  LIMIT 1");
      }

      if($text == ''){
        $text = $this->app->DB->Select("SELECT text FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' LIMIT 1");
      }

      if($text == ''){
        $text = $this->app->DB->Select("SELECT text FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' LIMIT 1");
      }
    }

    $text = str_replace('{FIRMA}',$this->Firmendaten("name"),$text);

    return $text;
  }

  //@refactor Geschaeftsbrief_vorlagen Modul
  function GetGeschaeftsBriefBetreff($subjekt,$sprache="",$projekt="",$dokument="",$dokumentid=0)
  {

    $text = '';
    if ($dokument != '') {
      $dbcheck = $this->app->DB->Select("SHOW TABLES LIKE '$dokument'");
      if ($dbcheck) {
        $abweichend = $this->app->DB->Select("SELECT abweichendebezeichnung FROM $dokument WHERE id='$dokumentid' LIMIT 1");
      }
      if($abweichend>0 && !preg_match('/_Abweichend/',$subjekt))
     {
       $text = $this->GetGeschaeftsBriefBetreff($subjekt."_Abweichend",$sprache,$projekt,$dokument,$dokumentid);
     }
    }

    if($text=="")
    {
      if($sprache=="")
        $sprache = "deutsch";

      if($projekt > 0)
        $text = $this->app->DB->Select("SELECT betreff FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' AND projekt='$projekt' LIMIT 1");

      if($text == "")
        $text = $this->app->DB->Select("SELECT betreff FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' AND (projekt='0' OR projekt='')  LIMIT 1");

      if($text == "")
        $text = $this->app->DB->Select("SELECT betreff FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' LIMIT 1");

      if($text == "")
        $text = $this->app->DB->Select("SELECT betreff FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' LIMIT 1");
    }

    $text = str_replace('{FIRMA}',$this->Firmendaten("name"),$text);
    return $text;
  }

  //@refactor Geschaeftsbrief_vorlagen Modul
  function GetGeschaeftsBriefID($subjekt,$sprache="",$projekt="")
  {

    if($sprache=="")
      $sprache = "deutsch";

    if($projekt > 0)
      $id = $this->app->DB->Select("SELECT id FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' AND projekt='$projekt' LIMIT 1");

    if($id == "")
      $id = $this->app->DB->Select("SELECT id FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' AND (projekt='0' OR projekt='')  LIMIT 1");

    if($id == "")
      $id = $this->app->DB->Select("SELECT id FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' AND sprache='$sprache' LIMIT 1");

    if($id == "")
      $text = $this->app->DB->Select("SELECT id FROM geschaeftsbrief_vorlagen WHERE subjekt='$subjekt' LIMIT 1");

    return $id;
  }



  public function Stornomail($auftrag)
  {
    if($auftrag > 0){
      $auftragarr = $this->app->DB->SelectRow("SELECT adresse,projekt,email,name,belegnr,keinestornomail,sprache  FROM auftrag WHERE id='$auftrag' LIMIT 1");
    }
    if(empty($auftragarr))
    {
      return;
    }
    $adresse = $auftragarr['adresse'];
    $projekt = $auftragarr['projekt'];
    $stornomail = $this->app->DB->Select("SELECT stornomail FROM projekt WHERE id='$projekt' LIMIT 1");

    // KEINE STORNOMAIL
    if($stornomail!=1){
      return;
    }

    $to = $auftragarr['email'];
    $to_name = $auftragarr['name'];

    $parameter = $auftrag;

    $belegnr = $auftragarr['belegnr'];
    $keinestornomail = $auftragarr['keinestornomail'];

  if($belegnr !='' && $keinestornomail==0)
  {
    $sprache = $auftragarr['sprache'];
    if($sprache == '')
    {
      //$adresse = $this->app->DB->Select("SELECT adresse FROM auftrag WHERE id = '$auftrag' LIMIT 1");
      if($adresse > 0){
        $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id = '$adresse' LIMIT 1");
      }
      if($sprache == ''){
        $sprache = 'deutsch';
      }
    }

    $text = $this->GetGeschaeftsBriefText('Stornierung',$sprache, $projekt,"",$auftrag);
    $betreff = $this->GetGeschaeftsBriefBetreff('Stornierung', $sprache,$projekt,"auftrag",$auftrag);

    if($sprache != 'deutsch' && ($text == '' || $betreff == ''))
    {
      $text = $this->GetGeschaeftsBriefText('Stornierung','deutsch',$projekt,"auftrag",$auftrag);
      $betreff = $this->GetGeschaeftsBriefBetreff('Stornierung','deutsch',$projekt,"auftrag",$auftrag);
    }

      $text = $this->ParseUserVars('auftrag',$auftrag,$text);
      $betreff = $this->ParseUserVars('auftrag',$auftrag,$betreff);

      if($to!='' && $to_name!=''){
        $this->MailSend($this->GetFirmaMail(), $this->GetFirmaAbsender(), $to, $to_name, $betreff, $text, "", $projekt);
      }
    }
  }

  public function ExportlinkZahlungsmail()
  {
    $exports = $this->app->DB->SelectArr("SELECT * FROM exportlink_sent WHERE mail='0'");
    $cexports = !empty($exports)?count($exports):0;
    for($i=0;$i<$cexports;$i++)
      //for($i=0;$i<5;$i++)
    {
      // mail
      $adresse = $exports[$i]['adresse'];
      $reg= $exports[$i]['reg'];
      $artikelid = $exports[$i]['objekt'];

      $to = $this->app->DB->Select("SELECT email FROM adresse WHERE id='$adresse' LIMIT 1");
      $to_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$adresse' LIMIT 1");
      $artikel = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikelid' LIMIT 1");
      $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id = '$adresse' LIMIT 1");
      if($sprache == '')$sprache = 'deutsch';
      $projekt=1;

    $text = $this->GetGeschaeftsBriefText('AlternativArtikel',$sprache, $projekt);
    $betreff = $this->GetGeschaeftsBriefBetreff('AlternativArtikel', $sprache,$projekt);

    if($sprache != 'deutsch' && ($text == '' || $betreff == ''))
    {
      $text = $this->GetGeschaeftsBriefText('AlternativArtikel','deutsch',$projekt);
      $betreff = $this->GetGeschaeftsBriefBetreff('AlternativArtikel','deutsch',$projekt);
    }

      $betreff = str_replace('[ARTIKEL]',$artikel,$betreff);
      $text= str_replace('[ARTIKEL]',$artikel,$text);
      $text = str_replace('[AUFTRAG]',$auftrag,$text);

      $text = str_replace('[REG]',$reg,$text);


      $this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$to,$to_name,$betreff,$text,"",$projekt);
      echo $to_name." <".$to.">\r\n";

      $this->app->DB->Update("UPDATE exportlink_sent SET mail=1 WHERE reg='$reg' LIMIT 1");

    }
  }


  public function AuftragZahlungsmail($id='',$force=0)
  {
    if(!is_numeric($id)){
      $id = $this->app->Secure->GetGET('id');
    }
    else {
      $intern=1;
    }
    if($id > 0)
    {
      $auftragarr = $this->app->DB->SelectRow("SELECT belegnr,adresse,gesamtsumme,projekt FROM auftrag WHERE id='$id' LIMIT 1");
    }
    if(!empty($auftragarr)){

      $belegnr = $auftragarr['belegnr'];
      $adresse = $auftragarr['adresse'];

      $summeimauftrag = 0;
      $auftragssumme = $auftragarr['gesamtsumme'];
      $projekt = $auftragarr['projekt'];
      if($projekt > 0 && $auftragssumme > 0){
        $projektarr = $this->app->DB->SelectRow("SELECT zahlungserinnerung,zahlungsmailbedinungen FROM projekt WHERE id='$projekt' LIMIT 1");
      }
      if(!empty($projektarr))
      {
        $zahlungsmail = $projektarr['zahlungserinnerung'];
        if($zahlungsmail){
          $zahlungsmailbedinungen = $projektarr['zahlungsmailbedinungen'];

          // sind vorbedingungen erfuellt?
          $vorbedinungen = 0;


          if(preg_match('/lager_ok/', $zahlungsmailbedinungen)){
            $lager_ok = $this->app->DB->Select("SELECT lager_ok FROM auftrag WHERE id='$id' LIMIT 1");
            if($lager_ok == 0)
              $vorbedinungen++;
          }

          // Kundencheck
          if(preg_match('/check_ok/', $zahlungsmailbedinungen)){
            $check_ok = $this->app->DB->Select("SELECT check_ok FROM auftrag WHERE id='$id' LIMIT 1");
            if($check_ok == 0)
              $vorbedinungen++;
          }

          //echo "zahlungsmail $zahlungsmail $vorbedinungen $auftragssumme $belegnr\r\n ";
          if(($zahlungsmail > 0) && ($vorbedinungen == 0) && ($auftragssumme > 0) && ($id > 0)){
            //echo "verschickt";
            $this->Zahlungsmail($adresse, $auftragssumme - $summeimauftrag, $id, $force);
          }
        }
      }
    }

    if($intern!=1)
    {
      header("Location: index.php?module=auftrag&action=edit&id=$id");
      exit;
    }
  }


  function KalenderMail($event,$betreff="",$text="",$emailcc="")
  {
    /** @var Kalender $obj */
    $obj = $this->LoadModul('kalender');
    if(!empty($obj) && method_exists($obj,'KalenderMail'))
    {
      return $obj->KalenderMail($event,$betreff,$text,$emailcc);
    }
  }


  function AufgabenMail($aufgabe,$vorabankuendigung=false)
  {
    /** @var Aufgaben $obj */
    $obj = $this->LoadModul('aufgaben');
    if(!empty($obj) && method_exists($obj,'sendAufgabenMail'))
    {
      return $obj->sendAufgabenMail($aufgabe,$vorabankuendigung);
    }
  }


  function Zahlungsmail($adresse,$rest="",$auftragid="",$force=0)
  {
    if(!is_numeric($auftragid))
      return;

    $to = $this->app->DB->Select("SELECT email FROM auftrag WHERE id='$auftragid' LIMIT 1");
    $to_name = $this->app->DB->Select("SELECT name FROM auftrag WHERE id='$auftragid' LIMIT 1");

    //$to = ""; //DEBUG
    $belegnr = $this->app->DB->Select("SELECT belegnr FROM auftrag WHERE id='$auftragid' LIMIT 1");
    $internetnummer = $this->app->DB->Select("SELECT internet FROM auftrag WHERE id='$auftragid' LIMIT 1");
    $projekt = $this->app->DB->Select("SELECT projekt FROM auftrag WHERE id='$auftragid' LIMIT 1");
    $zahlungsmail = $this->app->DB->Select("SELECT zahlungserinnerung FROM projekt WHERE id='$projekt' LIMIT 1");
    $zahlungsmailcounter = (int)$this->app->DB->Select("SELECT zahlungsmailcounter FROM auftrag WHERE id='$auftragid' LIMIT 1");
    $check_adresse = $this->app->DB->Select("SELECT adresse FROM auftrag WHERE id='$auftragid' LIMIT 1");

    $sprache = $this->app->DB->Select("SELECT sprache FROM auftrag WHERE id = '$auftragid' LIMIT 1");
    if($sprache == '')
    {
      $adresse = $this->app->DB->Select("SELECT adresse FROM auftrag WHERE id = '$auftragid' LIMIT 1");
      $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id = '$adresse' LIMIT 1");
      if($sprache == '')$sprache = 'deutsch';
    }
    // wenn der auftrag dem Kunden nicht gehört
    //if($adresse!=$check_adresse) return;

    $gesamt = $this->app->DB->Select("SELECT gesamtsumme FROM auftrag WHERE id='$auftragid' LIMIT 1");
    $zahlungok = false;
    if($rest!="")
    {

      //Falls projekt mail vorhanden sonst globalen firmen standard
      if($gesamt-$rest==0)
      {
        $text = $this->GetGeschaeftsBriefText('ZahlungMiss',$sprache,$projekt,"auftrag",$auftragid);
        $betreff = $this->GetGeschaeftsBriefBetreff('ZahlungMiss',$sprache,$projekt,"auftrag",$auftragid);
        if($sprache != 'deutsch' && ($text == '' || $betreff == ''))
        {
          $text = $this->GetGeschaeftsBriefText('ZahlungMiss','deutsch',$projekt,"auftrag",$auftragid);
          $betreff = $this->GetGeschaeftsBriefBetreff('ZahlungMiss','deutsch',$projekt,"auftrag",$auftragid);
        }
      } else {
        $text = $this->GetGeschaeftsBriefText('ZahlungDiff',$sprache,$projekt,"auftrag",$auftragid);
        $betreff = $this->GetGeschaeftsBriefBetreff('ZahlungDiff',$sprache,$projekt,"auftrag",$auftragid);
        if($sprache != 'deutsch' && ($text == '' || $betreff == ''))
        {
          $text = $this->GetGeschaeftsBriefText('ZahlungDiff','deutsch',$projekt,"auftrag",$auftragid);
          $betreff = $this->GetGeschaeftsBriefBetreff('ZahlungDiff','deutsch',$projekt,"auftrag",$auftragid);
        }
      }

      $rest = number_format($rest, 2, ',', '.');

      $text= str_replace('{REST}',$rest,$text);
      $betreff = str_replace('{FIRMA}',$this->Firmendaten("name"),$betreff);
      $text = str_replace('{FIRMA}',$this->Firmendaten("name"),$text);



      if($internetnummer>0)
        $text= str_replace('{AUFTRAG}',$internetnummer,$text);
      else
        $text= str_replace('{AUFTRAG}',$belegnr,$text);

      $text= str_replace('{INTERNET}',$internetnummer,$text);

      $text= str_replace('{GESAMT}',$this->app->DB->Select("SELECT gesamtsumme FROM auftrag WHERE id='$auftragid' LIMIT 1"),$text);
      $gesamtsummecheck = $rest;
      $text= str_replace('{DATUM}',$this->app->DB->Select("SELECT DATE_FORMAT(datum,'%d.%m.%Y') FROM auftrag WHERE id='$auftragid' LIMIT 1"),$text);

    } else
    {
      //TODO nette mail wenn kunde keine vorkasse macht, warum er das nicht macht etc.
      $zahlungok = true;
      $text = $this->GetGeschaeftsBriefText('ZahlungOK',$sprache,$projekt,"auftrag",$auftragid);
      $betreff = $this->GetGeschaeftsBriefBetreff('ZahlungOK',$sprache,$projekt);
      if($sprache != 'deutsch' && ($text == '' || $betreff == ''))
      {
        $text = $this->GetGeschaeftsBriefText('ZahlungOK','deutsch',$projekt,"auftrag",$auftragid);
        $betreff = $this->GetGeschaeftsBriefBetreff('ZahlungOK','deutsch',$projekt,"auftrag",$auftragid);
      }

      $gesamtsumme = $this->app->DB->Select("SELECT gesamtsumme FROM auftrag WHERE id='$auftragid' LIMIT 1");

      $text= str_replace('{AUFTRAG}',$belegnr,$text);
      $betreff= str_replace('{AUFTRAG}',$belegnr,$betreff);
      $text= str_replace('{GESAMT}',$gesamtsumme,$text);
      $betreff= str_replace('{GESAMT}',$gesamtsumme,$betreff);
      $gesamtsummecheck = $gesamtsumme;
      $text= str_replace('{DATUM}',$this->app->DB->Select("SELECT DATE_FORMAT(datum,'%d.%m.%Y') FROM kontoauszuege_zahlungseingang WHERE objekt='auftrag' AND parameter='$auftragid' LIMIT 1"),$text);
      $betreff= str_replace('{DATUM}',$this->app->DB->Select("SELECT DATE_FORMAT(datum,'%d.%m.%Y') FROM kontoauszuege_zahlungseingang WHERE objekt='auftrag' AND parameter='$auftragid' LIMIT 1"),$betreff);
      $zahlungok = true;
    }

  $text = $this->ParseUserVars("auftrag",$auftragid,$text);
  $betreff = $this->ParseUserVars("auftrag",$auftragid,$betreff);

  $mahnwesen_erinnerungsmail = (String)$this->app->erp->GetKonfiguration("mahnwesen_erinnerungsmail");
  if($mahnwesen_erinnerungsmail === '')
  {
    $mahnwesen_erinnerungsmail = 1;
  }
  $mahnwesen_klaerungsmail = (String)$this->app->erp->GetKonfiguration("mahnwesen_klaerungsmail");
  if($mahnwesen_klaerungsmail === '')
  {
    $mahnwesen_klaerungsmail = 1;
  }
  $mahnwesen_skontomail = (String)$this->app->erp->GetKonfiguration("mahnwesen_skontomail");
  if($mahnwesen_skontomail === '')
  {
    $mahnwesen_skontomail = 1;
  }

  $mahnwesen_zahlungserinnerungtage = (String)$this->app->erp->GetKonfiguration("mahnwesen_zahlungserinnerungtage");
  if($mahnwesen_zahlungserinnerungtage === '')
  {
    $mahnwesen_zahlungserinnerungtage = 6;
  }
  $mahnwesen_klaerungsmailtage = (String)$this->app->erp->GetKonfiguration("mahnwesen_klaerungsmailtage");
  if($mahnwesen_klaerungsmailtage === '')
  {
    $mahnwesen_klaerungsmailtage = 11;
  }

    $zahlungsmailauftrag = $this->app->DB->Select("SELECT zahlungsmail FROM auftrag WHERE id='$auftragid' LIMIT 1");

    if($zahlungsmailauftrag=="") $zahlungsmailauftrag = "0000-00-00";

    if($zahlungsmailauftrag == "0000-00-00") {
      $tmpzahlungsmailauftrag = $this->app->DB->Select("SELECT datum FROM auftrag WHERE id='$auftragid' LIMIT 1");
    } else {
      $tmpzahlungsmailauftrag = $zahlungsmailauftrag;
    }

    //$tage = ceil((mktime($zahlungsmailauftrag) - time())/60/60/24);
    $tage = $this->app->DB->Select("SELECT DATEDIFF(NOW(),'$tmpzahlungsmailauftrag')");
    $schwelle = (String)$this->app->erp->GetKonfiguration("mahnwesen_schwelle");
    if($schwelle === '')
    {
      $schwelle = 1;
    }
    $schwelle = (float)str_replace(',','.',$schwelle);
    if($schwelle < 0)$schwelle = 0;

    if(
      $to!="" &&
      $to_name!="" &&
      $zahlungsmail=="1" &&
      (
        $tage > $mahnwesen_klaerungsmailtage ||
        $tage > $mahnwesen_zahlungserinnerungtage ||
        $tmpzahlungsmailauftrag=="0000-00-00" ||
        ($zahlungok && $zahlungsmailauftrag != '00000-00-00') ||
        $force==1
      )
    )
    {
      $zahlungsmailcounter++;
      $this->app->DB->Update("UPDATE auftrag SET zahlungsmail=NOW(),zahlungsmailcounter='$zahlungsmailcounter' WHERE id='$auftragid' LIMIT 1");
      // wenn differenz groesser als ein EUR
      if($gesamtsummecheck>=$schwelle)// && $zahlungsmailcounter > 1)
      {
        if($zahlungok && $zahlungsmailauftrag != '00000-00-00')$zahlungsmailcounter--;
        if($zahlungsmailcounter<2)
        {
          if($mahnwesen_erinnerungsmail){
            $this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$to,$to_name,$betreff,$text,"",$projekt);
            $this->DokumentCreateQuick($adresse,$betreff,$text,$projekt);
          }
        }
        // automatisch Reservierungen entfernen
        elseif(!$zahlungok) {
          if($tage > $mahnwesen_klaerungsmailtage) {
            if($mahnwesen_klaerungsmail){
              $this->MailSend($this->GetFirmaMail(), $this->GetFirmaAbsender(),
                $this->GetFirmaMail(), "Buchhaltung", "Meldung fuer Buchhaltung: Offenen Auftrag $belegnr kl&auml;ren oder stornieren", $text, "", $projekt);
            }
            $this->app->DB->Update("UPDATE auftrag SET zahlungsmail=NOW(),zahlungsmailcounter='3' WHERE id='$auftragid' LIMIT 1");
          }else{
            $this->app->DB->Update("UPDATE auftrag SET zahlungsmail=NOW(),zahlungsmailcounter='1' WHERE id='$auftragid' LIMIT 1");
          }
        }
      }
      else {
        if($mahnwesen_skontomail)$this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$this->GetFirmaMail(),"Buchhaltung","Meldung fuer Buchhaltung: Bitte Skonto geben",$text,"",$projekt);
      }
    }

  }


  public function Rechnungsmail($id, $fromautoversand = true)
  {
    if(!$id){
      return;
    }

    $rechnungarr = $this->app->DB->SelectRow(
      "SELECT adresse, email, name,belegnr,projekt,sprache,schreibschutz,zuarchivieren,xmlrechnung
      FROM rechnung WHERE id='$id' LIMIT 1"
    );
    if(empty($rechnungarr)) {
      return;
    }
    if(!empty($rechnungarr['schreibschutz']) && !empty($rechnungarr['zuarchivieren'])) {
      $this->app->erp->RechnungArchivieren($id);
    }
    $adresse = $rechnungarr['adresse'];
    $to = $rechnungarr['email'];
    $to_name = $rechnungarr['name'];
    $belegnr = $rechnungarr['belegnr'];
    $projekt = $rechnungarr['projekt'];
    $xmlrechnung = $rechnungarr['xmlrechnung'];

    $sprache = $rechnungarr['sprache'];
    if($sprache=='' && $adresse > 0) {
      $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id='$adresse' LIMIT 1");
    }

    if($sprache==''){
      $sprache='deutsch';
    }

    $text = $this->GetGeschaeftsBriefText('Rechnung',$sprache,$projekt,"rechnung",$id);
    $betreff = $this->GetGeschaeftsBriefBetreff('Rechnung',$sprache,$projekt,"rechnung",$id);
    $this->GeschaeftsBriefAnhang('Rechnung',$sprache,$projekt,"rechnung",$id);
    if((String)$text === '' && $sprache !== 'deutsch')
    {
      $sprache = 'deutsch';
      $text = $this->GetGeschaeftsBriefText('Rechnung',$sprache,$projekt,"rechnung",$id);
      $betreff = $this->GetGeschaeftsBriefBetreff('Rechnung',$sprache,$projekt,"rechnung",$id);
    }

    $text = $this->ParseUserVars('rechnung',$id,$text); // heute mal wieder rein 21.12.2017 BS
    $betreff = $this->ParseUserVars('rechnung',$id,$betreff); // 19.01.2018 eingefuegt BW
    if($id > 0)
    {

      if (!$xmlrechnung) {
          $this->app->erp->BriefpapierHintergrunddisable = false;
          if(class_exists('RechnungPDFCustom'))
          {
            $Brief = new RechnungPDFCustom($this->app,$projekt);
          }else{
            $Brief = new RechnungPDF($this->app,$projekt);
          }
          $Brief->GetRechnung($id);
          $arrtmpfile[] = $Brief->displayTMP();

          if(!$Brief->DocumentArchiviert()) {
            $Brief->ArchiviereDocument(true, true);
          }
          $md5arr[] = @md5_file($arrtmpfile[(!empty($arrtmpfile)?count($arrtmpfile):0)-1]);
      } else {
        $arrtmpfile = Array();
        $md5arr = Array();
      }

      // anhaenge automatisch mitversenden
      $resultdateien = $this->app->DB->SelectArr("SELECT datei FROM datei_stichwoerter WHERE objekt LIKE 'Rechnung' AND parameter='$id'");
      $cResultdateien = !empty($resultdateien)?count($resultdateien):0;
      for($ri=0;$ri<$cResultdateien;$ri++)
      {
        $dateiname = str_replace(' ','_',$this->app->erp->GetDateiName($resultdateien[$ri]['datei']));
        if($dateiname)
        {
          $dateiinhalt = $this->app->erp->GetDatei($resultdateien[$ri]['datei']);
          if($handle = fopen (rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname, "wb"))
          {
            fwrite($handle, $dateiinhalt);
            fclose($handle);
            if(!in_array(rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname, $arrtmpfile))
            {
              $md5tmp = @md5_file(rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname);
              if(!in_array($md5tmp, $md5arr))
              {
                $md5arr[] = $md5tmp;
                $arrtmpfile[] = rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname;
              }
            }
          }
        }
      }

      //$this->DokumentSendShow(TAB1,"rechnung",$rechnung,$adresse);
      // temp datei wieder loeschen

      if($to != '')
      {
        $result = $this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$to,$to_name,$betreff,$text,$arrtmpfile,$projekt);
        $this->DokumentCreateQuick($adresse,$betreff,$text,$projekt);
      }else{
        $result = false;
      }
      //$tmpfilearray = array($arrtmpfile);
      $this->RunHook('rechnungsmail',5, $id,$betreff,$text,$arrtmpfile, $fromautoversand);
      $rechnung_cc = $this->app->DB->Select("SELECT rechnung_cc FROM adresse WHERE id = '$adresse' LIMIT 1");
      if($rechnung_cc != '')
      {
        $this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$rechnung_cc,$to_name,$betreff,$text,$arrtmpfile,$projekt);
      }

      foreach($arrtmpfile as $key=>$_tmpfile) {
        unlink($_tmpfile);
      }

      $betreff = $this->app->DB->real_escape_string($betreff);
      $text = $this->app->DB->real_escape_string($text);
      $to_name = $this->app->DB->real_escape_string($to_name);
      // als versendet markieren
      $this->closeInvoice($id);
      //$this->app->DB->Update("UPDATE rechnung SET status='versendet', versendet='1',schreibschutz='1' WHERE id='$id' LIMIT 1");
      if($result)
      {
        $this->RechnungProtokoll($id,'Rechnung versendet');

        $betreff = $this->app->DB->real_escape_string($betreff);
        $text = $this->app->DB->real_escape_string($text);
        $to_name = $this->app->DB->real_escape_string($to_name);
        // als versendet markieren
        $this->app->DB->Update("UPDATE rechnung SET versendet='1',schreibschutz='1' WHERE id='$id' LIMIT 1");
        $this->app->DB->Update("UPDATE rechnung SET status='versendet' WHERE status!='storniert' AND id='$id' LIMIT 1");

        $this->app->DB->Insert("INSERT INTO dokumente_send
              (dokument,zeit,bearbeiter,adresse,parameter,art,betreff,text,projekt,ansprechpartner,versendet,dateiid) VALUES ('rechnung',NOW(),'".$this->app->User->GetName()."',
                '$adresse','$id','email','$betreff','$text','$projekt','$to_name',1,'0')");
      }
    }
  }

  public function closeInvoice($invoiceId, $status = '')
  {
    $invoiceArr = $this->app->DB->SelectRow(sprintf('SELECT status FROM rechnung WHERE id = %d', $invoiceId));
    if(empty($invoiceArr) || (!empty($status) && $status !== $invoiceArr['status']))
    {
      return;
    }
    if($invoiceArr['status'] !== 'versendet')
    {
      $this->RunHook('closeInvoice',1, $invoiceId);
    }
    $this->app->DB->Update(sprintf("UPDATE rechnung SET versendet=1,schreibschutz=1 WHERE id=%d LIMIT 1",$invoiceId));
    $this->app->DB->Update(sprintf("UPDATE rechnung SET status='versendet' WHERE status!='storniert' AND id=%d LIMIT 1",$invoiceId));
  }

  function DokumentAbschicken()
  {
    $id = $this->app->Secure->GetGET('id');
    $cmd = $this->app->Secure->GetGET("cmd");
    $sid = $this->app->Secure->GetGET("sid");

    $type = $this->app->Secure->GetGET("type");
    if($cmd=="getvorlage")
    {
      $doc = $this->app->DB->SelectRow("SELECT sprache, projekt, abweichendebezeichnung FROM $type WHERE id='$sid' LIMIT 1");
      $data = $this->app->erp->Geschaeftsbriefvorlage($doc['sprache'],$type,$doc['projekt'],"Angebot".($doc['abweichendebezeichnung']=="1"?'_Abweichend':''),$sid);

      $footer = $this->Grussformel($doc['projekt'],$doc['sprache']);
      if($footer!="") $data['text'] = $data['text']."\r\n".$footer;


      if(!empty($data))
      {
        echo json_encode(array('subject'=>$data['betreff'],'body'=>$data['text'],'status'=>1));
      } else {
        echo json_encode(array('status'=>0));
      }
      $this->app->ExitXentral();
    }

    $frame = $this->app->Secure->GetGET('frame');

    $typ = $this->app->Secure->GetGET('module');
    if($frame!='')
    {
      echo "<iframe width=\"100%\" height=\"600\" src=\"index.php?module=$typ&action=abschicken&id=$id\" frameborder=\"0\"></iframe>";
      $this->app->ExitXentral();
    }

    $this->app->BuildNavigation=false;
    $this->app->Tpl->Set('TABTEXT',"Abschicken");
    $docRow = $this->app->DB->SelectRow(
      sprintf(
        'SELECT status, adresse, projekt FROM `%s` WHERE id=%d LIMIT 1',
        $typ, (int)$id
      )
    );
    $status = $docRow['status'];
    $adresse = $docRow['adresse'];
    $projekt = $docRow['projekt'];

    if($projekt=='' || $projekt==0){
      $projekt = $this->app->DB->Select("SELECT projekt FROM adresse WHERE id='$adresse' LIMIT 1");
    }

    if($status !=='angelegt')
    {
      $this->DokumentMask('TAB1',$typ,$id,$adresse,$projekt);
    } else
    {
      switch($typ)
      {
        case "rechnung": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Rechnung wurde noch nicht freigegeben!</div>"); break;
        case "angebot": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Das Angebot wurde noch nicht freigegeben!</div>"); break;
        case "auftrag": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Der Auftrag wurde noch nicht freigegeben!</div>"); break;
        case "lieferschein": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Der Lieferschein wurde noch nicht freigegeben!</div>"); break;
        case "retoure": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Retoure wurde noch nicht freigegeben!</div>"); break;
        case "bestellung": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Bestellung wurde noch nicht freigegeben!</div>"); break;
        case "gutschrift": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Gutschrift wurde noch nicht freigegeben!</div>"); break;
        case "arbeitsnachweis": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Der Arbeitsnachweis wurde noch nicht freigegeben!</div>"); break;
        case "preisanfrage": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Preisanfrage wurde noch nicht freigegeben!</div>"); break;
        case "proformarechnung": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Proformarechnung wurde noch nicht freigegeben!</div>"); break;
        case "produktion": $this->app->Tpl->Set('TAB1',"<div class=\"error\">Die Produktion wurde noch nicht freigegeben!</div>"); break;
      }
      $target = 'TAB1';
      $this->RunHook('DokumentAbschickenMeldungAngelegt', 3, $typ, $id, $target);
    }
    $this->app->Tpl->Set('ID',$id);
    $this->app->Tpl->Parse('PAGE','emptytab.tpl');
  }

  /**
   * @param int $id
   */
  public function VersandAbschluss($id)
  {
    if($id > 0) {
      $versandarr = $this->app->DB->SelectRow("SELECT * FROM versand WHERE id='$id' LIMIT 1");
    }
    if(empty($versandarr)) {
      return;
    }
    $adresse = $versandarr['adresse'];
    $lieferscheinid = $versandarr['lieferschein'];
    $rechnung = $versandarr['rechnung'];

    $rechnungarr = $rechnung <=0?null: $this->app->DB->SelectRow(
      "SELECT zahlungsweise,projekt FROM rechnung WHERE id='$rechnung' LIMIT 1"
    );

    $rechnung_zahlweise = empty($rechnungarr)?'':$rechnungarr['zahlungsweise'];
    $rechnung_projekt = empty($rechnungarr)?0:$rechnungarr['projekt'];

    $lieferscheinarr = $lieferscheinid <= 0?null: $this->app->DB->SelectRow(
      "SELECT auftragid,projekt FROM lieferschein WHERE id='$lieferscheinid' LIMIT 1"
    );

    $auftrag = empty($lieferscheinarr)?0: $this->app->DB->Select(
      "SELECT auftragid FROM lieferschein WHERE id='$lieferscheinid' LIMIT 1"
    );

    $auftragarr = $auftrag <= 0?null:$this->app->DB->SelectRow(
      "SELECT * FROM auftrag WHERE id='$auftrag' LIMIT 1"
    );

    if(!$rechnung && $auftrag) {
      //Fallback Zahlungsweise auf Auftrag
      $rechnung_zahlweise = $auftragarr['zahlungsweise'];
      $rechnung_projekt = $auftragarr['projekt'];
    }

    $auftragbelegnr = empty($auftragarr)?'': $auftragarr['belegnr'];
    $auftraginternet = empty($auftragarr)?'':$auftragarr['internet'];
    $ihrebestellnummer = empty($auftragarr)?'':$auftragarr['ihrebestellnummer'];

    $projekt = empty($lieferscheinarr)?0: $lieferscheinarr['projekt'];

    // wenn shop dann rueckmelden
    $shop = empty($auftragarr)?0:$auftragarr['shop'];

    $auftragabgleich = $shop <= 0?0: $this->app->DB->Select(
      "SELECT auftragabgleich FROM shopexport WHERE id='$shop' LIMIT 1"
    );

    //Reservierungen löschen
    if($lieferscheinid>0) {
      $this->app->DB->Delete(
        "DELETE FROM lager_reserviert WHERE objekt='lieferschein' AND parameter='$lieferscheinid'"
      );
    }
    if($auftrag <= 0) {
      return;
    }

    $this->app->DB->Delete(
      "DELETE FROM lager_reserviert WHERE objekt='auftrag' AND parameter='$auftrag'"
    );

    if($shop > 0 && $auftragabgleich=='1') {
      try {
        $this->app->remote->RemoteUpdateAuftrag($shop, $auftrag);
      }
      catch(Exception $e) {
        $this->AuftragProtokoll($auftag, 'Shopr&uuml;ckmeldung fehlgeschlagen');
      }
    }

    try {
      $this->sendPaymentStatus($id, $rechnung_zahlweise, $auftrag, $projekt, $rechnung_projekt);
    }
    catch(Exception $e) {

    }
  }

  /**
   * @param int         $id VersandId
   * @param string|null $rechnung_zahlweise
   * @param int|null    $auftrag
   * @param int|null    $projekt DeliveryNote ProjectId
   * @param int|null    $rechnung_projekt
   */
  public function sendPaymentStatus(
    $id,
    $rechnung_zahlweise = null,
    $auftrag = null,
    $projekt = null,
    $rechnung_projekt = null
  )
  {
    if($auftrag === null) {
      $versandarr = $this->app->DB->SelectRow(
        sprintf(
          'SELECT rechnung,lieferschein FROM versand WHERE id = %d',
          $id
        )
      );
      $lieferscheinid = $versandarr['lieferschein'];
      $rechnung = $versandarr['rechnung'];

      $rechnungarr = $rechnung <=0?null: $this->app->DB->SelectRow(
        "SELECT zahlungsweise,projekt FROM rechnung WHERE id='$rechnung' LIMIT 1"
      );

      $rechnung_zahlweise = empty($rechnungarr)?'':$rechnungarr['zahlungsweise'];
      $rechnung_projekt = empty($rechnungarr)?0:$rechnungarr['projekt'];

      $lieferscheinarr = $lieferscheinid <= 0?null: $this->app->DB->SelectRow(
        "SELECT auftragid,projekt FROM lieferschein WHERE id='$lieferscheinid' LIMIT 1"
      );

      $auftrag = empty($lieferscheinarr)?0: $this->app->DB->Select(
        "SELECT auftragid FROM lieferschein WHERE id='$lieferscheinid' LIMIT 1"
      );

      $auftragarr = $auftrag <= 0?null:$this->app->DB->SelectRow(
        "SELECT * FROM auftrag WHERE id='$auftrag' LIMIT 1"
      );

      if(!$rechnung && $auftrag) {
        //Fallback Zahlungsweise auf Auftrag
        $rechnung_zahlweise = $auftragarr['zahlungsweise'];
        $rechnung_projekt = $auftragarr['projekt'];
      }
    }
    if(empty($rechnung_zahlweise)) {
      return;
    }
    try {
      if($zahlungsweisenmodule = $this->app->DB->SelectArr(
        "SELECT id, modul 
      FROM zahlungsweisen 
      WHERE type = '" . $this->app->DB->real_escape_string($rechnung_zahlweise) . "' AND modul <> ''
        AND (projekt = '$projekt' OR projekt = 0) 
      ORDER BY projekt = '$projekt' DESC 
      LIMIT 1
    ")){
        foreach ($zahlungsweisenmodule as $zahlungsweisenmodul) {
          $_zahlungsweisenmodul = preg_replace('/[^a-zA-Z0-9\_]/', '', $zahlungsweisenmodul['modul']);
          if(!$_zahlungsweisenmodul){
            continue;
          }
          if(!file_exists(__DIR__ . '/zahlungsweisen/' . $_zahlungsweisenmodul . '.php')){
            continue;
          }

          $class = 'Zahlungsweise_' . $_zahlungsweisenmodul;
          if(!class_exists($class)){
            include_once __DIR__ . '/zahlungsweisen/' . $_zahlungsweisenmodul . '.php';
          }
          if(!class_exists($class)){
            continue;
          }

          $obj = new $class($this->app, $zahlungsweisenmodul['id']);
          if($obj && method_exists($obj, 'ZahlungFreigeben')){
            $obj->ZahlungFreigeben($auftrag, $id);
          }
          return;
        }
      }
    }
    catch(Exception $e) {

    }
  }

  public function Versandmail($id, $tracking_link = null, $sprache = null, $tracking = '', $forceautoversand = false, $autoversand = true)
  {
    //    $text = $this->app->DB->Select("SELECT text FROM geschaeftsbrief_vorlagen WHERE subjekt='Versand' AND sprache='deutsch' LIMIT 1");
    //    $betreff = $this->app->DB->Select("SELECT betreff FROM geschaeftsbrief_vorlagen WHERE subjekt='Versand' AND sprache='deutsch' LIMIT 1");

  if($id > 0){
    $versandarr = $this->app->DB->SelectRow("SELECT * FROM versand WHERE id='$id' LIMIT 1");
  }
  if(empty($versandarr))
  {
    return;
  }
  $adresse = $versandarr['adresse'];
  if($adresse > 0)
  {
    $adressearr = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id = $adresse LIMIT 1");
  }

  $lieferscheinid = $versandarr['lieferschein'];
  if($lieferscheinid > 0){
    $lieferscheinarr = $this->app->DB->SelectRow("SELECT * FROM lieferschein WHERE id='$lieferscheinid' LIMIT 1");
  }
  if(!empty($lieferscheinarr)){
    $auftrag = $lieferscheinarr['auftragid'];
  }else{
    $auftrag = 0;
  }
  if($auftrag > 0)
  {
    $auftragarr = $this->app->DB->SelectRow("SELECT email,name,belegnr,internet,ihrebestellnummer,sprache,DATE_FORMAT(datum,'%d.%m.%Y') as datum_de FROM auftrag WHERE id='$auftrag' LIMIT 1");
  }
  if(!empty($auftragarr))
  {
    $auftragbelegnr = $auftragarr['belegnr'];
    $auftraginternet = $auftragarr['internet'];
    $ihrebestellnummer = $auftragarr['ihrebestellnummer'];

    $auftragdatum = $auftragarr['datum_de'];
  }else{
    $auftragbelegnr = '';
    $auftraginternet = '';
    $ihrebestellnummer = '';
    $auftragdatum = '';
  }

  if(!empty($lieferscheinarr)){
    $projekt = $lieferscheinarr['projekt'];//$this->app->DB->Select("SELECT projekt FROM lieferschein WHERE id='$lieferscheinid' LIMIT 1");
  }else{
    $projekt = 0;
  }

  if(is_null($sprache)){
    if(!empty($auftragarr)){
      $sprache = $auftragarr['sprache'];
    }else{
      $sprache = '';
    }
  }

  if(!empty($auftragarr)){
    $to = $auftragarr['email'];
    $to_name = $auftragarr['name'];
  }else{
    $to = '';
    $to_name = '';
  }


  if($to==''){
    if(!empty($adressearr)){
      $to = $adressearr['email'];
    }
  }
  if($to_name==''){
    if(!empty($adressearr)){
      $to_name = $adressearr['name'];
    }
  }

  if(!$sprache){
    if(!empty($adressearr)){
      $sprache = $adressearr['sprache'];
    }
  }
  if($sprache == ''){
    $sprache = 'deutsch';
  }
  $text = $this->GetGeschaeftsBriefText('Versand',(!is_null($sprache) && $sprache?$sprache:'deutsch'),$projekt);
  $betreff = $this->GetGeschaeftsBriefBetreff('Versand',(!is_null($sprache) && $sprache?$sprache:'deutsch'),$projekt);
  if(((String)$text === "" || (String)$betreff === '') && (!is_null($sprache) && $sprache?$sprache:'deutsch') != 'deutsch')
  {
    $text = $this->GetGeschaeftsBriefText('Versand','deutsch',$projekt);
    $betreff = $this->GetGeschaeftsBriefBetreff('Versand','deutsch',$projekt);
  }


  // wenn Ansprechpartner
  if(!empty($lieferscheinarr)){
    $to_lieferschein_name = $lieferscheinarr['ansprechpartner'];
    $to_lieferschein_email = $lieferscheinarr['email'];
  }else{
    $to_lieferschein_name = '';
    $to_lieferschein_email = '';
  }

    if($to_lieferschein_email!=''){
      $to = $to_lieferschein_email;

      if($to_lieferschein_name!=''){
        $to_name = $to_lieferschein_name;
      }
    }
    if(!empty($adressearr)){
      $trackingsperre = $adressearr['trackingsperre'];
    }else{
      $trackingsperre = 0;
    }

    $tracking = $versandarr['tracking'];
    $keinetrackingmail = $versandarr['keinetrackingmail'];
    $versandunternehmen = $versandarr['versandunternehmen'];

    // FIX fuer selbstabholer Mail
    $versandart = $versandarr['versandart'];
    if($versandart=='selbstabholer') {
      $versandunternehmen='selbstabholer';
    }

    $text = str_replace('{BELEGNR}',$auftragbelegnr,$text);
    $betreff = str_replace('{BELEGNR}',$auftragbelegnr,$betreff);

    $text = str_replace('{AUFTRAGDATUM}',$auftragdatum,$text);
    $betreff = str_replace('{AUFTRAGDATUM}',$auftragdatum,$betreff);


    $text = str_replace('{INTERNET}',$auftraginternet,$text);
    $betreff = str_replace('{INTERNET}',$auftraginternet,$betreff);

    $text = str_replace('{IHREBESTELLNUMMER}',$ihrebestellnummer,$text);
    $betreff = str_replace('{IHREBESTELLNUMMER}',$ihrebestellnummer,$betreff);
    if(!is_null($tracking_link) && $tracking_link)$text = str_replace('{VERSAND}',$tracking_link.(($tracking && strpos($tracking_link,$tracking) === false)?' ('.$tracking.')':''),$text);
    if($versandunternehmen=="dhl" || $versandunternehmen=="dhlpremium" || $versandunternehmen=="intraship")
    $versandmodul = false;

    if(!$this->isHTML($text)){
      $text = str_replace("\r\n", "<br>", $text);
    }


    $typ = $versandunternehmen;
    if($typ === ''){
      $typ = $versandart;
    }
    //$versandartenmodul = $this->app->DB->SelectArr("SELECT id, modul FROM versanddienstleister WHERE aktiv = 1 AND modul = '".$this->app->DB->real_escape_string($typ)."' AND (projekt = 0 OR projekt = '$projekt') ORDER BY projekt DESC LIMIT 1");
    $versandartenmodul = $this->app->DB->SelectArr("SELECT * FROM versandarten WHERE aktiv = 1 AND ausprojekt = 0 AND modul != '' AND type = '".$this->app->DB->real_escape_string($typ)."' AND modul != '' AND (projekt = 0 OR projekt = '$projekt') ORDER BY projekt DESC LIMIT 1");
    $standard = true;
    if($versandartenmodul && @is_file(dirname(__FILE__).'/versandarten/'.$versandartenmodul[0]['modul'].'.php'))
    {
      if($versandartenmodul[0]['versandmail'] == -1)
      {
        $notsend = 1;
      }
      elseif($versandartenmodul[0]['versandmail'] && $versandartenmodul[0]['geschaeftsbrief_vorlage'])
      {
        $subjekt = $this->app->DB->Select("SELECT subjekt FROM geschaeftsbrief_vorlagen WHERE id = '".$versandartenmodul[0]['geschaeftsbrief_vorlage']."' LIMIT 1");
        $text = $this->GetGeschaeftsBriefText($subjekt,(!is_null($sprache) && $sprache?$sprache:'deutsch'),$projekt);
        $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,(!is_null($sprache) && $sprache?$sprache:'deutsch'),$projekt);
        if(((String)$text === '' || (String)$betreff === '') && (!is_null($sprache) && $sprache?$sprache:'deutsch') != 'deutsch')
        {
          $text = $this->GetGeschaeftsBriefText($subjekt,'deutsch',$projekt);
          $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,'deutsch',$projekt);
        }
        $text = str_replace('{BELEGNR}',$auftragbelegnr,$text);
        $betreff = str_replace('{BELEGNR}',$auftragbelegnr,$betreff);

        $text = str_replace('{AUFTRAGDATUM}',$auftragdatum,$text);
        $betreff = str_replace('{AUFTRAGDATUM}',$auftragdatum,$betreff);


        $text = str_replace('{INTERNET}',$auftraginternet,$text);
        $betreff = str_replace('{INTERNET}',$auftraginternet,$betreff);

      $text = str_replace('{IHREBESTELLNUMMER}',$ihrebestellnummer,$text);
      $betreff = str_replace('{IHREBESTELLNUMMER}',$ihrebestellnummer,$betreff);
      if(!is_null($tracking_link) && $tracking_link)$text = str_replace('{VERSAND}',$tracking_link.(($tracking && strpos($tracking_link,$tracking) === false)?' ('.$tracking.')':''),$text);
    }
    $obj = $this->LoadVersandModul($versandartenmodul[0]['modul'], $versandartenmodul[0]['id']);
    $class_name = 'Versandart_'.$versandartenmodul[0]['modul'];
    if(!empty($obj) && method_exists($obj, 'Trackinglink'))
    {
      if($obj->Trackinglink($tracking, $notsend, $link, $rawlink))
      {
        $versandpakete = $this->app->DB->SelectArr("SELECT tracking FROM versandpakete WHERE versand = '$id' AND tracking <> '' ORDER BY nr");
        if($versandpakete)
        {
          foreach($versandpakete as $kv => $vv)
          {
            $obj->Trackinglink($vv['tracking'], $tmpnotsend, $tmplink, $tmprawlink);
            $link .= ', '.$vv['tracking'].' ('.$tmprawlink.')';
            $tracking .= ', '.$vv['tracking'];
          }
        }

        $text = str_replace('{VERSAND}', $link ,$text);
        $text = str_replace('{VERSANDTYPE}', $versandartenmodul[0]['type'] ,$text);
        $text = str_replace('{VERSANDBEZEICHNUNG}', $versandartenmodul[0]['bezeichnung'] ,$text);
        $text = str_replace('{TRACKINGNUMMER}', $tracking,$text);
        $versandmodul = true;
      }
    }
  }elseif($versandartenmodul2 = $this->app->DB->SelectArr("SELECT * FROM versandarten WHERE aktiv = 1 AND ausprojekt = 0 AND type = '".$this->app->DB->real_escape_string($typ)."' AND (projekt = 0 OR projekt = '$projekt') ORDER BY projekt DESC LIMIT 1"))
  {
    if($versandartenmodul2[0]['versandmail'] == -1)
    {
      $notsend = 1;
    }
    elseif($versandartenmodul2[0]['versandmail'] && $versandartenmodul2[0]['geschaeftsbrief_vorlage'])
    {
      $standard = false;
      $subjekt = $this->app->DB->Select("SELECT subjekt FROM geschaeftsbrief_vorlagen WHERE id = '".$versandartenmodul2[0]['geschaeftsbrief_vorlage']."' LIMIT 1");
      $text = $this->GetGeschaeftsBriefText($subjekt,(!is_null($sprache) && $sprache?$sprache:'deutsch'),$projekt);
      $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,(!is_null($sprache) && $sprache?$sprache:'deutsch'),$projekt);
      if(((String)$text === "" || (String)$betreff === '') && (!is_null($sprache) && $sprache?$sprache:'deutsch') != 'deutsch')
      {
        $text = $this->GetGeschaeftsBriefText($subjekt,'deutsch',$projekt);
        $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,'deutsch',$projekt);
      }
      $text = str_replace('{BELEGNR}',$auftragbelegnr,$text);
      $betreff = str_replace('{BELEGNR}',$auftragbelegnr,$betreff);

        $text = str_replace('{INTERNET}',$auftraginternet,$text);
        $betreff = str_replace('{INTERNET}',$auftraginternet,$betreff);
        $text = str_replace('{AUFTRAGDATUM}',$auftragdatum,$text);
        $betreff = str_replace('{AUFTRAGDATUM}',$auftragdatum,$betreff);
        $text = str_replace('{VERSANDTYPE}', $versandartenmodul2[0]['type'] ,$text);

        $text = str_replace('{IHREBESTELLNUMMER}',$ihrebestellnummer,$text);
        $betreff = str_replace('{IHREBESTELLNUMMER}',$ihrebestellnummer,$betreff);
        if(!is_null($tracking_link) && $tracking_link)$text = str_replace('{VERSAND}',$tracking_link.(($tracking && strpos($tracking_link,$tracking) === false)?' ('.$tracking.')':''),$text);
        $notsend = 0;
      }
    }
    if(!$versandmodul && $standard)
    {
      if(strtolower($versandunternehmen)=='dhl' || strtolower($versandunternehmen)=='dhlpremium' || strtolower($versandunternehmen)=="intraship")
      {
        $text = str_replace('{VERSAND}','DHL Versand: '.$tracking.' (http://nolp.dhl.de/nextt-online-public/set_identcodes.do?lang=de&idc='.$tracking.')',$text);
        $notsend = 0;
      }
      else if (strtolower($versandunternehmen)=='logoix')
      {
        $text = str_replace('{VERSAND}','LogoiX Versand: '.$tracking.' (http://www.logoix.com/cgi-bin/tnt.pl?q='.$tracking.')',$text);
        $notsend = 0;
      }
      else if (strtolower($versandunternehmen)=='dpd')
      {
        $text = str_replace('{VERSAND}','DPD Versand: '.$tracking.' (https://tracking.dpd.de/parcelstatus/?locale=de_DE&query='.$tracking.')',$text);
        $notsend = 0;
      }
      else if (strtolower($versandunternehmen)=='gls')
      {
        $text = str_replace('{VERSAND}','GLS Versand: '.$tracking.' (https://www.gls-group.eu/276-I-PORTAL-WEB/content/GLS/DE03/DE/5004.htm?txtRefNo='.$tracking.'&txtAction=71000 )',$text);
        $notsend = 0;
      }
      else if (strtolower($versandunternehmen)=='rma')
      {
        $notsend = 1;
      }
      else if(strtolower($versandunternehmen)=='selbstabholer')
      {
        $notsend = 0;
        // selbstabholer

        $text = $this->GetGeschaeftsBriefText('Selbstabholer',$sprache,$projekt);
        $betreff = $this->GetGeschaeftsBriefBetreff('Selbstabholer',$sprache,$projekt);
        if(((String)$text === '' || (String)$betreff === '') && $sprache != 'deutsch')
        {
          $text = $this->GetGeschaeftsBriefText('Selbstabholer','deutsch',$projekt);
          $betreff = $this->GetGeschaeftsBriefBetreff('Selbstabholer','deutsch',$projekt);
        }

        //$text = $this->app->DB->Select("SELECT text FROM geschaeftsbrief_vorlagen WHERE subjekt='Selbstabholer' AND sprache='deutsch' LIMIT 1");
        $text = str_replace('{VERSAND}','',$text);

        // nur wenn option gesetzt ist
        $selbstabholermail = $this->app->DB->Select("SELECT selbstabholermail FROM projekt WHERE id='$projekt' LIMIT 1");
        if($selbstabholermail!='1') {
          $notsend = 1;
        }
      } else {
          // bei allen anderen lieferarten keine mail
          $notsend = $forceautoversand?0:1;
      }
    }

    if(!(!$versandmodul && $standard && strtolower($versandunternehmen)=='selbstabholer'))
    {
      if(!$forceautoversand && $this->Projektdaten($projekt,"automailversandbestaetigung")!='1'){
        $notsend = 1;
      }
    }

    $text = str_replace('{NAME}',$to_name,$text);

    $text = str_replace('{VERSAND}', '' ,$text);
    if(!empty($versandart)){
      $text = str_replace('{VERSANDTYPE}', $versandart, $text);
    }
    $text = $this->app->erp->ParseUserVars('auftrag',$auftrag,$text);
    $betreff = $this->app->erp->ParseUserVars('auftrag',$auftrag,$betreff);


    if($lieferscheinid > 0)
    {
      $text = $this->app->erp->ParseUserVars('lieferschein',$lieferscheinid,$text);
      $betreff = $this->app->erp->ParseUserVars('lieferschein',$lieferscheinid,$betreff);
    }

    if($to!='' && $to_name!='' && $trackingsperre!=1 && $notsend==0 && $keinetrackingmail!=1)
    {
      $this->MailSend($this->GetFirmaMail(),$this->GetFirmaAbsender(),$to,$to_name,$betreff,$text,"",$projekt);
      $this->DokumentCreateQuick($adresse, $betreff, $text, $projekt);
      

      $this->app->DB->Insert("INSERT INTO auftrag_protokoll (auftrag, zeit, bearbeiter, grund) values ('$auftrag',now(),'".(isset($this->app->User)?$this->app->DB->real_escape_string($this->app->User->GetName()):'Cronjob')."','Versandmail verschickt')");
      $dateien = null;
      $this->RunHook('versandmail', 5, $auftrag, $betreff, $text, $dateien, $autoversand);
    }
  }


  function DokumentCreateQuick($adresse,$betreff,$text,$projekt)
  {
    $data['adresse'] = $adresse;
    $data['betreff'] = $betreff;
    $data['content'] = $text;
    $data['projekt'] = $projekt;
    $this->DokumentCreate($data);
  }

  function DokumentCreate($data,$adressefromuser=0)
  {
    if($adressefromuser > 0)
    {
      if($data['bearbeiter']=="") $data['bearbeiter'] = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$adressefromuser' AND id > 0 LIMIT 1");
    }

    $this->app->DB->Insert('
        INSERT INTO
        dokumente
        SET
        adresse_from = "' . $adressefromuser . '",
        adresse_to = "' . $data['user'] . '",
        typ = "' . $data['typ'] . '",
        von = "' . $data['von'] . '",
        firma = "' . $data['firma'] . '",
        ansprechpartner = "' . $data['ansprechpartner'] . '",
        internebezeichnung = "' . $data['internebezeichnung'] . '",
        an = "' . $data['an'] . '",
        email_an = "' . $data['email_an'] . '",
        email_cc = "' . $data['email_cc'] . '",
        email_bcc = "' . $data['email_bcc'] . '",
        firma_an = "' . $data['firma_an'] . '",
        adresse = "' . $data['adresse'] . '",
        plz = "' . $data['plz'] . '",
        ort = "' . $data['ort'] . '",
        land = "' . $data['land'] . '",
        datum = NOW(),
        betreff = "' . $data['betreff'] . '",
        content = "' . $data['content'] . '",
        signatur = "' . $data['signatur'] . '",
        send_as = "' . $data['send_as'] . '",
        email = "' . $data['email'] . '",
        printer = "' . $data['printer'] . '",
        fax = "' . $data['fax'] . '",
        created = NOW(),
        uhrzeit = "' . $data['uhrzeit'] . '",
        projekt = "' . $data['projekt'] . '",
        bearbeiter = "' . $data['bearbeiter'] . '",
        sent = "' . $data['sent'] . '"
          ');

    return $this->app->DB->GetInsertID();
  }

  /**
   * @param int    $projekt
   * @param string $feld
   *
   * @return mixed|null
   */
  function Projektdaten($projekt,$feld)
  {
    return $projekt <= 0?null:$this->app->DB->Select(
      sprintf(
        'SELECT `%s` FROM projekt WHERE id=%d LIMIT 1',
        $feld, $projekt
      )
    );
  }

  function DumpVar($variable)
  {
    ob_start();
    var_dump($variable);
    $result = ob_get_clean();
    file_put_contents($this->GetTMP()."log", "$result\r\n", FILE_APPEND | LOCK_EX);
  }

  function VarAsString($variable)
  {
    ob_start();
    var_dump($variable);
    $result = ob_get_clean();
    return $result;
  }

  function ImportvorlageLog($importvorlage,$zeitstempel,$tabelle,$datensatz,$ersterdatensatz="0")
  {
    $this->app->DB->Insert("INSERT INTO importvorlage_log (id,importvorlage,zeitstempel,user,tabelle,datensatz,ersterdatensatz)
        VALUES ('','$importvorlage',FROM_UNIXTIME($zeitstempel),'".$this->app->User->GetID()."',
          '$tabelle','$datensatz','$ersterdatensatz')");
  }

  function ImportvorlageLogDelete($zeitstempel)
  {
    $tmp = $this->app->DB->SelectArr("SELECT * FROM importvorlage_log WHERE zeitstempel='$zeitstempel' AND user='".$this->app->User->GetID()."'");
    for($i=0;$i<(!empty($tmp)?count($tmp):0);$i++)
    {
      $datensatz = $tmp[$i]['datensatz'];
      switch($tmp[$i]['tabelle'])
      {
        case "adresse":
          if($tmp[$i]['ersterdatensatz']=="1")
          {
            //naechste zu vergebene nummer richtig setzten
            $tmp_adresse = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$datensatz' LIMIT 1");
            $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='".$tmp_adresse[0]['projekt']."' LIMIT 1");

            if($eigenernummernkreis=="1")
            {
              if($tmp_adresse[0]['kundennummer']!="" && $tmp_adresse[0]['kundennummer']!="0")
              {
                $this->app->DB->Update("UPDATE projekt SET next_kundennummer='".$tmp_adresse[0]['kundennummer']."'
                    WHERE id='".$tmp_adresse[0]['projekt']."' LIMIT 1");
              }
              if($tmp_adresse[0]['lieferantennummer']!="" && $tmp_adresse[0]['lieferantennummer']!="0")
              {
                $this->app->DB->Update("UPDATE projekt SET next_lieferantennummer='".$tmp_adresse[0]['lieferantennummer']."'
                    WHERE id='".$tmp_adresse[0]['projekt']."' LIMIT 1");
              }
              if($tmp_adresse[0]['mitarbeiternummer']!="" && $tmp_adresse[0]['mitarbeiternummer']!="0")
              {
                $this->app->DB->Update("UPDATE projekt SET next_mitarbeiternummer='".$tmp_adresse[0]['mitarbeiternummer']."'
                    WHERE id='".$tmp_adresse[0]['projekt']."' LIMIT 1");
              }
            } else {
              if($tmp_adresse[0]['kundennummer']!="" && $tmp_adresse[0]['kundennummer']!="0")
              {
                $this->FirmendatenSet("next_kundennummer",$tmp_adresse[0]['kundennummer']);
              }
              if($tmp_adresse[0]['lieferantennummer']!="" && $tmp_adresse[0]['lieferantennummer']!="0")
              {
                $this->FirmendatenSet("next_lieferantennummer",$tmp_adresse[0]['lieferantennummer']);
              }
              if($tmp_adresse[0]['mitarbeiternummer']!="" && $tmp_adresse[0]['mitarbeiternummer']!="0")
              {
                $this->FirmendatenSet("next_mitarbeiternummer",$tmp_adresse[0]['mitarbeiternummer']);
              }
            }
          }
          $this->app->DB->Delete("DELETE FROM adresse WHERE id='$datensatz'");
          $this->app->DB->Delete("DELETE FROM ansprechpartner WHERE adresse='$datensatz'");
          $this->app->DB->Delete("DELETE FROM lieferadressen WHERE adresse='$datensatz'");
          $this->app->DB->Delete("DELETE FROM adresse_rolle WHERE adresse='$datensatz'");
          break;

        case "artikel":

          break;

        case "einkaufspreise":

          break;



      }
      $this->app->DB->Delete("DELETE FROM importvorlage_log WHERE id='".$tmp[$i]['id']."'");
    }

  }


  function CreatePath($path) {
    if (file_exists($path))
    {
      return true;
    }
    $nextDirectoryPath = substr($path, 0, strrpos($path, '/', -2) + 1 );

    if($this->CreatePath($nextDirectoryPath) && is_writable($nextDirectoryPath))
    {
      return mkdir($path);
    }
    return false;
  }

  function ObjektProtokoll($objekt,$id,$action_long,$meldung="")
  {
    $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->User->GetName():'Import / Cronjob';

    $this->app->DB->Insert("INSERT INTO objekt_protokoll (id,objekt,objektid,meldung,zeitstempel,bearbeiter,action_long)
        VALUES ('','$objekt','$id','$meldung',NOW(),'$bearbeiter','$action_long')");

  }

  function InternesEvent($userid,$meldung,$type="",$sound=0)
  {
    //Cronjobs does not have an userid (prevent Exception)
    if((int)$userid <= 0) {
      return false;
    }
    /** @var \Xentral\Modules\SystemNotification\Service\NotificationServiceInterface $notification */
    if(empty($this->app->Container) || empty($userid))
    {
      return false;
    }
    $notification = $this->app->Container->get('NotificationService');
    if (!in_array($type, $notification->getValidTypes(), true)) {
      $type = 'default';
    }

    return $notification->create($userid, $type, 'Hinweis', $meldung, (bool)$sound);
  }

  function EventMitSystemLog($userid, $meldung, $level=-1,$dump="", $type = "", $sound=0, $module="", $action="",$functionname="")
  {
    $this->SystemLog($meldung, $level, $dump, $module, $action, $functionname);
    $this->InternesEvent($userid, $meldung, $type, $sound);

  }

  function SystemLog($meldung="",$level=0,$dump="",$module="",$action="",$functionname="")
  {
    /** @var Systemlog $obj */
    $obj = $this->app->erp->LoadModul('systemlog');
    if(!empty($obj) && method_exists($obj, 'addSystemLog')){
      return $obj->addSystemLog($meldung,$level,$dump,$module,$action,$functionname);
    }
    return 0;
  }


  function Protokoll($meldung="",$dump="",$module="",$action="",$functionname="")
  {
    /** @var Protokoll $obj */
    $obj = $this->app->erp->LoadModul('protokoll');
    if(!empty($obj) && method_exists($obj, 'addProtokoll')){
      return $obj->addProtokoll($meldung,$dump,$module,$action,$functionname);
    }
    return 0;
  }

  function LogRamAndTime($meldung)
  {
    if(self::$lasttime == 0)self::$lasttime = microtime(true);
    $akttime = microtime(true);
    $this->LogFile( addslashes((memory_get_peak_usage(true) >> 20).  " MB ".(round($akttime - self::$lasttime ,3)  )." sek ".$meldung));

  }


  function LogFile($meldung,$dump="",$module="",$action="",$functionname="")
  {

    $obj = $this->LoadModul('logfile');
    if(!empty($obj) && method_exists($obj,'addLogFile')) {
      return $obj->addLogFile($meldung,$dump,$module,$action,$functionname);
    }
    return null;
  }


  function KundeUpdate($adresse,$typ,$name,$abteilung,$unterabteilung,$ansprechpartner,$adresszusatz,$strasse,$land,$plz,$ort,$email,$telefon,$telefax,$ustid,$partner,$projekt)
  {
    //echo "Upate";
    $fields = array('typ','name','abteilung','unterabteilung','ansprechpartner','adresszusatz','strasse','land','plz',
        'ort','email','telefon','telefax','ustid','partner','projekt');

    foreach($fields as $key)
    {
      $check = $this->app->DB->Select("SELECT $key FROM adresse WHERE id='$adresse' LIMIT 1");
      if($check!=${$key})
      {
        $val = $this->app->DB->real_escape_string(${$key});
        $this->app->DB->Update("UPDATE adresse SET $key='$val' WHERE id='$adresse' LIMIT 1");
        $logfile = $this->app->DB->Select("SELECT `logfile` FROM adresse WHERE id='$adresse' LIMIT 1");
        $this->app->DB->Update("UPDATE adresse SET `logfile`='".$logfile." Update Feld $key alt:$check neu:".$val.";' WHERE id='$adresse' LIMIT 1");
      }

    }
    return $adresse;
  }

  function KundeAnlegen($typ,$name,$abteilung,$unterabteilung,$ansprechpartner,$adresszusatz,$strasse,$land,$plz,$ort,$email,$telefon,$telefax,$ustid,$partner,$projekt, $bundesstaat='', $rechnung_bundesstaat='')
  {
    $name = $this->app->DB->real_escape_string($name);
    $abteilung = $this->app->DB->real_escape_string($abteilung);
    $unterabteilung = $this->app->DB->real_escape_string($unterabteilung);
    $ansprechpartner = $this->app->DB->real_escape_string($ansprechpartner);
    $adresszusatz = $this->app->DB->real_escape_string($adresszusatz);
    $strasse = $this->app->DB->real_escape_string($strasse);
    $land = $this->app->DB->real_escape_string($land);
    $plz = $this->app->DB->real_escape_string($plz);
    $ort = $this->app->DB->real_escape_string($ort);
    $email = $this->app->DB->real_escape_string($email);
    $telefon = $this->app->DB->real_escape_string($telefon);
    $telefax = $this->app->DB->real_escape_string($telefax);
    $ustid = $this->app->DB->real_escape_string($ustid);
    $partner = $this->app->DB->real_escape_string($partner);
    $bundesstaat = $this->app->DB->real_escape_string($bundesstaat);
    $rechnung_bundesstaat = $this->app->DB->real_escape_string($rechnung_bundesstaat);

    $this->app->DB->Insert("INSERT INTO adresse (id,typ,name,abteilung,unterabteilung,ansprechpartner,adresszusatz,strasse,land,plz,ort,email,telefon,telefax,ustid,partner,projekt,firma,bundesstaat,rechnung_bundesstaat)
      VALUES('','$typ','$name','$abteilung','$unterabteilung','$ansprechpartner','$adresszusatz','$strasse','$land','$plz','$ort','$email','$telefon','$telefax','$ustid','$partner','$projekt','".$this->app->User->GetFirma()."','$bundesstaat','$rechnung_bundesstaat')");
    $adresse = $this->app->DB->GetInsertID();
    $this->ObjektProtokoll("adresse",$adresse,"adresse_create","Adresse angelegt");
    $zahlungsweise = $this->Firmendaten('zahlungsweise');
    if($zahlungsweise)$this->app->DB->Update("UPDATE adresse SET zahlungsweise = '".$this->app->DB->real_escape_string($zahlungsweise)."' WHERE id = '$adresse' LIMIT 1");
    if($zahlungsweise == 'rechnung')
    {
      $zahlungszieltage = $this->Firmendaten('zahlungszieltage');
      $zahlungszieltageskonto = $this->Firmendaten('zahlungszieltageskonto');
      $zahlungszielskonto = $this->Firmendaten('zahlungszielskonto');
      if($zahlungsweise)$this->app->DB->Update("UPDATE adresse SET
    zahlungszieltage = '".$this->app->DB->real_escape_string($zahlungszieltage)."',
    zahlungszielskonto = '".$this->app->DB->real_escape_string($zahlungszielskonto)."',
    zahlungszieltageskonto = '".$this->app->DB->real_escape_string($zahlungszieltageskonto)."'
    WHERE id = '$adresse' LIMIT 1");
    }

    $ust_befreit = $this->AdresseUSTCheck($adresse);
    $this->app->DB->Update("UPDATE adresse SET ust_befreit='$ust_befreit' WHERE id=$adresse");

    //adresse Kundennummer verpassen
    $this->KundennummerVergeben($adresse);

    $this->AddRolleZuAdresse($adresse, "Kunde", "von", "Projekt", $projekt);
    return $adresse;
  }

  function IstEU($land)
  {
    if($land==$this->Firmendaten("land"))
      return false;
    foreach($this->GetUSTEU() as $euland)
    {
      if($land==$euland)
        return true;
    }
    return false;
  }

  function Steuerbefreit($land,$ustid)
  {
    if($land==$this->Firmendaten("land"))
      return false;

    foreach($this->GetUSTEU() as $euland)
    {
      if($land==$euland && $ustid!="")
        return true;
      else if ($land==$euland && $ustid=="")
        return false;
    }

    // alle anderen laender sind export!
    return true;
  }

  /**
   * @param int            $artikel
   * @param null|array|int $parents
   *
   * @return bool
   */
  public function IstRohstoffeZirkel($artikel, $parents = null)
  {
    if($parents !== null && is_numeric($parents)) {
      $parents = [$parents];
    }
    if(is_array($parents) && (!empty($parents)?count($parents):0) > 0) {
      if(in_array($artikel, $parents)) {
        return $artikel;
      }
    }
    $parents[] = $artikel;

    $stueckliste = $this->app->DB->SelectArr(
      sprintf(
        'SELECT DISTINCT s.artikel 
        FROM rohstoffe AS s 
        INNER JOIN artikel AS a ON s.artikel = a.id 
        WHERE s.rohstoffvonartikel = %d AND a.geloescht <> 1',
        $artikel
      )
    );
    if(empty($stueckliste)) {
      return false;
    }

    foreach($stueckliste as $art) {
      if($art['artikel'] == $artikel) {
        return true;
      }
      if($this->IstRohstoffeZirkel($art['artikel'], $parents)) {
        return true;
      }
    }

    return false;
  }

  /**
   * @param int            $artikel
   * @param null|int|array $parents
   *
   * @return bool
   */
  public function IstStuecklistenZirkel($artikel, $parents = null)
  {
    if($parents !== null && is_numeric($parents)) {
      $parents = [$parents];
    }
    if(is_array($parents) && (!empty($parents)?count($parents):0) > 0) {
      if(in_array($artikel, $parents)) {
        return $artikel;
      }
    }
    $parents[] = $artikel;

    $stueckliste = $this->app->DB->SelectArr(
      sprintf(
        'SELECT DISTINCT s.artikel 
        FROM stueckliste AS s 
        INNER JOIN artikel AS a ON s.artikel = a.id 
        WHERE s.stuecklistevonartikel = %d AND a.geloescht <> 1',
        $artikel
      )
    );
    if(empty($stueckliste)) {
      return false;
    }

    foreach($stueckliste as $art) {
      if($art['artikel'] == $artikel) {
        return true;
      }
      if($this->IstStuecklistenZirkel($art['artikel'], $parents)) {
        return true;
      }
    }

    return false;
  }

  /**
   * @param string         $wert
   * @param int|array      $artikel
   * @param null|int|array $shop
   *
   * @return array|mixed|null
   */
  public function GetArtikelShopEinstellung($wert, $artikel, $shop = null)
  {
    $shopKorrekturwert = null;
    if(is_array($shop)) {
      $shopKorrekturwert = $shop;
      $shop = $shop['id'];
    }
    $shop = (int)$shop;
    if(is_array($artikel)) {
      $res = $artikel;
      $artikel = $artikel['id'];
    }
    $artikel = (int)$artikel;
    if($artikel <= 0) {
      return null;
    }
    if(empty($res)) {
      $res = $this->app->DB->SelectRow(
        sprintf('SELECT * FROM artikel WHERE id = %d LIMIT 1', $artikel)
      );
    }
    if(empty($res)) {
      return null;
    }
    if($shop) {
      $artikelarr = $this->app->DB->SelectRow(
        sprintf(
          'SELECT * FROM artikel_onlineshops 
          WHERE artikel = %d AND aktiv = 1 AND shop = %d AND ausartikel = 0 LIMIT 1',
          $artikel, $shop
        )
      );
      if(!empty($artikelarr)) {
        foreach($artikelarr as $k => $v) {
          if(!is_numeric($k) && $k !== 'id' && $k !== 'shop' && $k !== 'artikel'){
            $res[$k] = $v;
          }
        }
      }
      if($wert == '' || $wert === 'lagerkorrekturwert') {
        if($shopKorrekturwert === null) {
          $shopKorrekturwert = $this->app->DB->SelectRow(
            sprintf(
              'SELECT lagerkorrekturwert,ueberschreibe_lagerkorrekturwert FROM shopexport WHERE id = %d',
              $shop
            )
          );
        }
        if(!empty($shopKorrekturwert['ueberschreibe_lagerkorrekturwert'])) {
          $res['lagerkorrekturwert'] = $shopKorrekturwert['lagerkorrekturwert'];
        }
      }
    }

    if($wert == '') {
      return $res;
    }
    if(isset($res[$wert])) {
      return $res[$wert];
    }

    return null;
  }

  /**
   * @param int|array $artikel
   *
   * @return array|null
   */
  public function GetArtikelshops($artikel)
  {
    if(is_array($artikel)) {
      $artikelarr = $artikel;
      $artikel = $artikel['id'];
    }
    $artikel = (int)$artikel;
    if($artikel <= 0) {
      return null;
    }
    $shops = $this->app->DB->SelectArr(
      sprintf(
        'SELECT `shop`, `aktiv` FROM `artikel_onlineshops` WHERE `artikel` = %d',
        $artikel
      )
    );
    if(empty($shops)) {
      if(empty($artikelarr)) {
        $artikelarr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT `shop`, `shop2`, `shop3` FROM `artikel` WHERE `id` = %d LIMIT 1',
            $artikel
          )
        );
      }
      if(empty($artikelarr)) {
        return null;
      }
      $shops = null;
      if(!empty($artikelarr['shop'])){
        $shops[] = $artikelarr['shop'];
      }
      if(!empty($artikelarr['shop2'])){
        $shops[] = $artikelarr['shop2'];
      }
      if(!empty($artikelarr['shop3'])){
        $shops[] = $artikelarr['shop3'];
      }

      return $shops;
    }
    $res = null;
    foreach($shops as $shop) {
      if(empty($shop['aktiv'])) {
        continue;
      }
      if(empty($res) || !in_array($shop['shop'], $res)) {
        $res[] = $shop['shop'];
      }
    }

    return $res;
  }

function CheckShopTabelle($artikel)
{
  $artikel = (int)$artikel;
  if($artikel <= 0){
    return;
  }
  $artikelarr = $this->app->DB->SelectRow("SELECT * FROM artikel WHERE id = '$artikel' LIMIT 1");
  if(empty($artikelarr)){
    return;
  }

  $shops = null;
  if($artikelarr['shop']){
    $shops[] = $artikelarr['shop'];
  }
  if($artikelarr['shop2']){
    $shops[] = $artikelarr['shop2'];
  }
  if($artikelarr['shop3']){
    $shops[] = $artikelarr['shop3'];
  }
  if(!$shops){
    return;
  }
  $artikelarr['autolagerlampe'] = 0;
  $felder = array(
  'lagerkorrekturwert',
  'pseudolager',
  'autolagerlampe',
  'restmenge',
  'lieferzeitmanuell',
  'pseudopreis',
  'generierenummerbeioption',
  'variante_kopie',
  'unikat',
  'unikatbeikopie',
  'autoabgeleicherlaubt'
  );
  foreach($felder as $feld){
    if(isset($artikelarr[$feld]) && !empty($artikelarr[$feld]))
    {
      $inhalt[] = " '".$this->app->DB->real_escape_string($artikelarr[$feld])."' ";
    } else {
      $inhalt[] = " '' ";
    }
  }

  foreach($shops as $shop)
  {
    if(!$this->app->DB->Select("SELECT id FROM artikel_onlineshops WHERE artikel = '$artikel' AND shop = '$shop' LIMIT 1"))
    {
      $this->app->DB->Insert("INSERT INTO artikel_onlineshops (artikel, shop, aktiv, ausartikel,".implode(', ', $felder).") VALUES ('$artikel','$shop','1','1',".implode(', ', $inhalt).")");
      if(!$this->app->DB->error())
      {
        //$this->app->DB->Update("UPDATE artikel SET shop = 0 WHERE artikel = '$artikel' AND shop = '$shop' LIMIT 1");
        //$this->app->DB->Update("UPDATE artikel SET shop2 = 0 WHERE artikel = '$artikel' AND shop2 = '$shop' LIMIT 1");
        //$this->app->DB->Update("UPDATE artikel SET shop3 = 0 WHERE artikel = '$artikel' AND shop3 = '$shop' LIMIT 1");
      }
    }
  }
}

  function CopyArtikelVariante($artikel,$artikelvon, $optionen, $stuecklistenelement = 0, $option = "")
  {
    $art = $artikelvon;
    if($stuecklistenelement)$art = $stuecklistenelement;
    if($artikel != $artikelvon || $stuecklistenelement > 0)
    {
      $eks = $this->app->DB->SelectArr("SELECT * FROM einkaufspreise WHERE artikel = '$artikel'");
      if(!$eks)
      {
        $this->app->DB->Insert("INSERT into einkaufspreise (artikel, adresse, objekt, projekt, preis, waehrung,ab_menge, vpe, gueltig_bis, lieferzeit_standard,bezeichnunglieferant, bestellnummer)
        SELECT '".$artikel."', adresse, objekt, projekt, preis, waehrung,ab_menge, vpe, gueltig_bis,lieferzeit_standard,bezeichnunglieferant, bestellnummer FROM einkaufspreise WHERE artikel = '".$art."' AND geloescht <> 1 AND (isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' OR gueltig_bis > now())");

      }
    }

    if($artikel != $artikelvon)
    {
      $stueckliste = $this->app->DB->SelectArr("SELECT s.*, a.variante_kopie FROM stueckliste s INNER JOIN artikel a ON a.id = s.artikel WHERE stuecklistevonartikel = '$artikelvon'");
      if($stueckliste)
      {
        foreach($stueckliste as $stueck)
        {
          if($stueck['variante_kopie'])
          {

            $idnew = $this->app->DB->MysqlCopyRow("artikel","id",$stueck['artikel']);
            $this->KopiereArtikelDateistichwoerter($stueck['artikel'], $idnew);
            $this->KopiereArtikelEigenschaften($stueck['artikel'], $idnew);
            $nummer = $this->GetNextArtikelnummer('produkt',1,(int)$this->app->DB->Select("SELECT projekt FROM artikel WHERE id = '".$stueck['artikel']."' LIMIT 1"));
            $this->app->DB->Update("UPDATE artikel SET variante = 1 , variante_von = '".$stueck['artikel']."' WHERE id = '$idnew' LIMIT 1");
            if($nummer)$this->app->DB->Update("UPDATE artikel SET nummer = '$nummer' WHERE id = '$idnew' LIMIT 1");
            $this->ObjektProtokoll("artikel", $idnew, "artikel_create", "Shopimport: Automatisch Kopie angelegt");
            if($optionen)$this->app->DB->Update("UPDATE artikel SET anabregs_text = '".$optionen."', anabregs_text_en ='".$optionen."' WHERE id = '$idnew' LIMIT 1");

            $this->app->DB->Insert("INSERT INTO stueckliste (stuecklistevonartikel, artikel,  sort, referenz, place, layer, menge, firma, wert,bauform)
              SELECT '$artikel', '$idnew',  sort, referenz, place, layer, menge, firma, wert,bauform FROM stueckliste WHERE id = '".$stueck['id']."'");


            $this->CopyArtikelVariante($idnew, $stueck['artikel'], $stueck['artikel']);
          }else{
            $check = $this->app->DB->Select("SELECT id FROM stueckliste WHERE artikel = '".$stueck['artikel']."' AND stuecklistevonartikel = '".$artikel."' LIMIT 1");
            if(!$check)
            {
              $this->app->DB->Insert("INSERT INTO stueckliste (stuecklistevonartikel, artikel,  sort, referenz, place, layer, menge, firma, wert,bauform)
              SELECT '$artikel', artikel,  sort, referenz, place, layer, menge, firma, wert,bauform FROM stueckliste WHERE id = '".$stueck['id']."'");
            }
          }
        }
      }
    }
  }

  function GetArticleIDFromShopnumber($shop, $nummer, $herstellernummerUeberspringen = false)
  {
    $extart = $this->app->DB->Select("SELECT artikelnummernummerkreis FROM shopexport WHERE id = '$shop'");
    $projekt = $this->app->DB->Select("SELECT projekt FROM shopexport WHERE id = '$shop'");
    $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
    if($multiprojekt=='1' || !$eigenernummernkreis){
      $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$nummer' AND IFNULL(geloescht,0) = 0 AND IFNULL(intern_gesperrt,0) = 0 LIMIT 1");
    }
    else{
      $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$nummer' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 AND IFNULL(intern_gesperrt,0) = 0 LIMIT 1");
    }
    if($j_id){
      return $j_id;
    }

    $multiprojekt = $this->app->DB->Select("SELECT multiprojekt FROM shopexport WHERE id='$shop' LIMIT 1");


    if(!$j_id)
    {
      if($multiprojekt=='1' || !$eigenernummernkreis)
        $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='$nummer' AND nummer <> 'DEL' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");  //TODO BENE
      else
        $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='$nummer' AND nummer <> 'DEL' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");  //TODO BENE

      if($j_id)
      {
        return $j_id;
      }
    }

    if($herstellernummerUeberspringen){
      return false;
    }
    if(!$j_id)
    {
      if($multiprojekt=='1' || !$eigenernummernkreis)
        $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='$nummer' AND nummer <> 'DEL' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");  //TODO BENE
      else
        $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='$nummer' AND nummer <> 'DEL' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");  //TODO BENE
      if($j_id)
      {
        return $j_id;
      }
    }


  }

  /**
   * @param int    $auftrag
   * @param string $zahlungsstatus
   *
   * @throws Exception
   */
  public function ImportUpdateZahlungsstatus($auftrag, $zahlungsstatus = 'bezahlt')
  {
    $arr = $this->app->DB->SelectRow(
      sprintf(
        "SELECT a.shop, a.shopextid,s.modulename,s.shoptyp 
        FROM auftrag AS a 
        INNER JOIN shopexport AS s 
            ON a.shop = s.id AND s.aktiv = 1 AND s.demomodus = 0 AND s.auftragabgleich = 1 
            AND (s.shoptyp = 'intern' OR s.shoptyp = 'custom') 
        LEFT JOIN shopexport_zahlungsstatus sz ON a.shopextid = sz.auftrag 
        WHERE a.id = %d AND isnull(sz.id) AND a.shop <> 0 AND a.shopextid <> '' 
        LIMIT 1",
        $auftrag
      )
    );
    if(empty($arr)) {
      return;
    }

    $obj = null;
    if($arr['shoptyp'] === 'custom') {
      $file = dirname(__DIR__) . '/plugins/external/shopimporter/'.$arr['modulename'];
      $classa = explode('_',str_replace('_'.$arr['shop'].'.php','', $arr['modulename']));
      foreach($classa as $k => $v) {
        $classa[$k] = ucfirst($v);
      }
      $class = implode('_', $classa);

      if(file_exists($file)) {
        if(!class_exists($class)) {
          include_once $file;
        }
        if(class_exists($class)){
          $obj = new $class($this->app, true);
        }
      }
    }
    else {
      $obj = $this->app->erp->LoadModul($arr['modulename']);
    }
    if($obj) {
      if(method_exists($obj, 'EinstellungenStruktur')) {
        $struktur = $obj->EinstellungenStruktur();
        if(isset($struktur['functions']) && $struktur['functions']
          && in_array('updatezahlungsstatus', $struktur['functions'])) {
          $erg = $this->app->remote->RemoteCommand(
            $arr['shop'],
            'updatezahlungsstatus',
            array('auftrag'=>$arr['shopextid'],'zahlungsstatus'=>$zahlungsstatus)
          );
          if($erg === 'ok') {
            $this->app->DB->Insert(
              sprintf(
                "INSERT INTO shopexport_zahlungsstatus (shop, auftrag, status) 
                VALUES  (%d,'%s','%s')",
                $arr['shop'],
                $this->app->DB->real_escape_string($arr['shopextid']),
                $this->app->DB->real_escape_string($zahlungsstatus)
              )
            );
          }
          return;
        }
      }
    }
    $this->app->DB->Insert(
      sprintf(
        "INSERT INTO shopexport_zahlungsstatus (shop, auftrag, status) 
        VALUES (%d,'%s','')",
        $arr['shop'], $this->app->DB->real_escape_string($arr['shopextid'])
      )
    );
  }

  function getTaxRatesFromShopOrder($shopid, $warenkorb, $articlearray)
  {
    $taxrates = array();
    if(!empty($warenkorb['steuersatz_normal']))
    {
      if(!in_array($warenkorb['steuersatz_normal'], $taxrates))
      {
        $taxrates[] = $warenkorb['steuersatz_normal'];
      }
      if(!in_array($warenkorb['steuersatz_ermaessigt'], $taxrates))
      {
        $taxrates[] = $warenkorb['steuersatz_ermaessigt'];
      }
      if(!empty($articlearray))
      {
        foreach($articlearray as $k => $position)
        {
          if(!empty($position['steuersatz']) && is_numeric($position['steuersatz']) && !in_array($position['steuersatz'], $taxrates)
          )
          {
            $taxrates[] = $position['steuersatz'];
          }
        }
      }
    }
    if(!empty($warenkorb['lieferland']))
    {
      $country = $warenkorb['lieferland'];
    }elseif(!empty($warenkorb['land']))
    {
      $country = $warenkorb['land'];
    }else{
      $country = '';
    }
    if(!empty($country))
    {
      $taxes = array();
      $this->RunHook('getTaxRatesFromShopOrder',2 , $country, $taxes);
      if(!empty($taxes))
      {
        $taxrates = array_merge($taxrates, $taxes);
      }
    }

    return $taxrates;
  }

  function ImportAuftrag($adresse,$warenkorb,$projekt,$shop="",$auftrag=0) : array
  {
    $this->RunHook('ImportAuftragBefore',4, $adresse,$warenkorb,$projekt,$shop);
    if(!empty($this->app->stringcleaner)){
      $this->app->stringcleaner->XMLArray_clean($warenkorb);
    }
    $explodieren = true;
    $shopexportArr = $this->app->DB->SelectRow(
      sprintf(
        'SELECT * FROM shopexport WHERE id = %d LIMIT 1',
        (int)$shop
      )
    );

    $angeboteanlegen = $shopexportArr['angeboteanlegen'];
    $doctype = 'auftrag';

    if(isset($warenkorb['benutzergruppe'])){
      $gruppenid = $this->app->DB->Select("SELECT id FROM gruppen WHERE kennziffer ='".$warenkorb['benutzergruppekuerzel']."'");
      if(isset($warenkorb['benutzergruppeanlegen']) && $gruppenid < 1){
        if(!$gruppenid){
          $this->app->DB->Insert("INSERT INTO gruppen (name, art, kennziffer, dta_mail_text, dtavariablen, zahlungszielskonto, zahlungszieltageskonto,webid, aktiv) VALUES ('".$warenkorb['benutzergruppe']."','gruppe','".$warenkorb['benutzergruppekuerzel']."','','',0,0,0,1)");
        }
        $gruppenid = $this->app->DB->GetInsertID();
      }
      if($gruppenid){
        if(!$this->app->DB->Select("SELECT id FROM adresse_rolle WHERE adresse='$adresse' AND projekt='$projekt' AND subjekt='Mitglied' AND praedikat='von' AND objekt='Gruppe' AND parameter='$gruppenid'  LIMIT 1")){
          $this->app->DB->Insert("INSERT INTO adresse_rolle (adresse, projekt, subjekt, praedikat, objekt, parameter, von, bis) VALUES ('$adresse', '$projekt', 'Mitglied', 'von', 'Gruppe', '$gruppenid', 'CURRENT_DATE', '0000-00-00')");
        }
      }
    }

    if(!empty($warenkorb['doctype']) && $warenkorb['doctype']==='angebot'){
      $angeboteanlegen = 1;
    }

    if($shopexportArr['lastschriftdatenueberschreiben'] && isset($warenkorb['bankverbindung']) && is_array($warenkorb['bankverbindung'])){
      $anweisung = array();
      if(isset($warenkorb['bankverbindung']['inhaber'])){
        $anweisung[] = "inhaber='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['inhaber'])."'";
      }
      if(isset($warenkorb['bankverbindung']['bank'])){
        $anweisung[] = "bank='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['bank'])."'";
      }
      if(isset($warenkorb['bankverbindung']['iban'])){
        $anweisung[] = "iban='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['iban'])."'";
      }
      if(isset($warenkorb['bankverbindung']['bic'])){
        $anweisung[] = "swift='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['bic'])."'";
      }

      if(isset($warenkorb['bankverbindung']['firmensepa'])){
        $anweisung[] = "firmensepa='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['firmensepa'])."'";
      }
      if(isset($warenkorb['bankverbindung']['mandatsreferenzhinweis'])){
        $anweisung[] = "mandatsreferenzhinweis='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['mandatsreferenzhinweis'])."'";
      }
      if(isset($warenkorb['bankverbindung']['mandatsreferenzdatum'])){
        $anweisung[] = "mandatsreferenzdatum='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['mandatsreferenzdatum'])."'";
      }
      if(isset($warenkorb['bankverbindung']['mandatsreferenz'])){
        $anweisung[] = "mandatsreferenz='".$this->app->DB->real_escape_string($warenkorb['bankverbindung']['mandatsreferenz'])."'";
      }

      if((!empty($anweisung)?count($anweisung):0) > 0){
        $this->app->DB->Update('UPDATE adresse SET '.implode(', ',$anweisung)." WHERE id='$adresse'");
      }
    }

    if($angeboteanlegen)
    {
      $doctype = 'angebot';
    }
    if(empty($auftrag)){
      if($angeboteanlegen)
      {
          $auftrag = $this->CreateAngebot();
      }else{
          $auftrag = $this->CreateAuftrag();
      }
    }
  if($shopexportArr['rabatteportofestschreiben']) {
    $this->app->DB->Update("UPDATE $doctype SET rabatteportofestschreiben = 1 WHERE id = '$auftrag' LIMIT 1");
  }
  if($doctype === 'angebot')
  {
    $this->AngebotProtokoll($auftrag,'Angebot importiert vom Shop');
  }else{
    $this->AuftragProtokoll($auftrag,'Auftrag importiert vom Shop');
  }
  if(isset($warenkorb['subshop']) && $warenkorb['subshop'])
  {
    $subshopprojekt = $this->app->DB->Select("SELECT projekt FROM shopexport_subshop WHERE shop = '$shop' AND aktiv = 1 AND subshopkennung = '".$this->app->DB->real_escape_string($warenkorb['subshop'])."' LIMIT 1");
    if($subshopprojekt && $this->app->DB->Select("SELECT id FROM projekt WHERE id = '$subshopprojekt' AND geloescht <> 1 LIMIT 1")){
      $projekt = $subshopprojekt;
    }
  }
  $portocheck = $this->app->DB->Select("SELECT portocheck FROM projekt WHERE id = '$projekt'");


  if(isset($warenkorb['projekt']) && $warenkorb['projekt'] && is_numeric($warenkorb['projekt']))
  {
    if($this->app->DB->Select("SELECT id FROM projekt WHERE id = '".(int)$warenkorb['projekt']."' AND geloescht <> 1 LIMIT 1"))
    {
      $projekt = $warenkorb['projekt'];
      $warenkorbprojekt = $warenkorb['projekt'];
    }
  }

    $demomodus = $shopexportArr['demomodus'];
    if($doctype === 'angebot')
    {
      $this->LoadAngebotStandardwerte($auftrag,$adresse);
    }else{
      $this->LoadAuftragStandardwerte($auftrag,$adresse);
    }
    $vertriebid = $this->app->DB->Select("SELECT vertrieb FROM adresse WHERE id = '$adresse' LIMIT 1");
    $this->app->DB->Update("UPDATE $doctype SET vertriebid = '$vertriebid' WHERE id = '$auftrag' LIMIT 1");
    $vertrieb = '';
    if($vertriebid){
      $vertrieb = $this->app->DB->real_escape_string($this->app->DB->Select("SELECT name FROM adresse WHERE id = '$vertriebid' LIMIT 1"));
    }

    if(strpos($warenkorb['gesamtsumme'],',')!==false)
    {
      $warenkorb['gesamtsumme'] = str_replace(',','.',$warenkorb['gesamtsumme']);
    }

    if(!$this->CheckDateValidate($warenkorb['lieferdatum'])) {
      $warenkorb['lieferdatum']='';
    }

    if($warenkorb['lieferung']=='' || $warenkorb['lieferung']==='versandunternehmen'){
      $versand = $this->Firmendaten('versandart');
    }
    else{
      $versand = $warenkorb['lieferung'];
    }


    $versandarten = $this->GetVersandartAuftrag($projekt);
    if (empty($versandarten) || !array_key_exists($versand, $versandarten)){
      $versand = $this->Firmendaten('versandart');
    }
    $bekannteversandart = $this->GetVersandartAuftrag($projekt);
    if(!isset($bekannteversandart[$warenkorb['lieferung']]))
    {
      $versand = $this->Firmendaten('versandart');
    }

    $versandartenmapping = $shopexportArr['versandartenmapping'];
    $zahlungsweisenmapping = $shopexportArr['zahlungsweisenmapping'];
    $positionsteuersaetzeerlauben = $shopexportArr['positionsteuersaetzeerlauben'];
    $steuerfreilieferlandexport = $shopexportArr['steuerfreilieferlandexport'];

    $fastlane = 0;
    $autoversandvonMapping = false;
    if($versandartenmapping)
    {
      $extrasel = '';
      $lieferung1 = $this->app->DB->real_escape_string($warenkorb['lieferung']);
      $lieferung2 = $this->app->DB->real_escape_string($this->app->erp->ConvertForDBUTF8($warenkorb['lieferung']));
      if($lieferung2 !== '' && $lieferung2 != $lieferung1){
        $extrasel .= " OR versandart_shop = '$lieferung2' ";
      }
      $lieferung3 = $this->app->DB->real_escape_string($this->app->erp->ConvertForDB($warenkorb['lieferung']));
      if($lieferung3 !== '' && $lieferung3 != $lieferung1){
        $extrasel .= " OR versandart_shop = '$lieferung3' ";
      }
      $versandarten = $this->app->DB->SelectArr("SELECT * FROM shopexport_versandarten WHERE aktiv = 1 AND shop = '$shop' AND versandart_wawision <> '' AND (versandart_shop = '".$this->app->DB->real_escape_string($warenkorb['lieferung'])."' $extrasel)");
      if(!empty($versandarten))
      {
        $found = false;
        foreach($versandarten as $vers)
        {
          $land = !empty($warenkorb['lieferadresse_land'])?$warenkorb['lieferadresse_land']:$warenkorb['land'];
          if(!$land){
            $land = $this->Firmendaten("land");
          }
          if(strpos($vers['land'],$land) !== false)
          {
            $versand = $vers['versandart_wawision'];
            $warenkorb['autoversand'] = $vers['autoversand'];
            $autoversandvonMapping = true;
            if($vers['fastlane'] == 1)
            {
              $fastlane = 1;
            }
            $found = true;
            break;
          }
        }
        if(!$found)
        {
          //Fallback
          foreach($versandarten as $vers)
          {
            if($vers['land'] == '')
            {
              $versand = $vers['versandart_wawision'];
              $warenkorb['autoversand'] = $vers['autoversand'];
              $autoversandvonMapping = true;
              $found = true;
              if($vers['fastlane'] == 1)
              {
                $fastlane = 1;
              }
              break;
            }
          }
        }
        if(!$found)
        {
          $versandarten2 = $this->app->DB->SelectArr("SELECT * FROM shopexport_versandarten WHERE aktiv = 1 AND shop = '$shop' AND versandart_wawision <> '' AND versandart_shop = ''");
          foreach($versandarten2 as $vers)
          {
            $land = !empty($warenkorb['lieferadresse_land'])?$warenkorb['lieferadresse_land']:$warenkorb['land'];
            if(!$land){
                $land = $this->Firmendaten('land');
            }
            if(strpos($vers['land'],$land) !== false)
            {
              $versand = $vers['versandart_wawision'];
              $warenkorb['autoversand'] = $vers['autoversand'];
              $autoversandvonMapping = true;
              $found = true;
              if($vers['fastlane'] == 1)
              {
                $fastlane = 1;
              }
              break;
            }
          }
          if(!$found)
          {
            //Fallback
            foreach($versandarten2 as $vers)
            {
              if($vers['land'] == '')
              {
                $versand = $vers['versandart_wawision'];
                $warenkorb['autoversand'] = $vers['autoversand'];
                $autoversandvonMapping = true;
                $found = true;
                if($vers['fastlane'] == 1)
                {
                  $fastlane = 1;
                }
                break;
              }
            }
          }

      }
    }else{
      $checkversand = $this->app->DB->Select("SELECT id FROM shopexport_versandarten WHERE shop = '$shop' AND versandart_shop = '".$this->app->DB->real_escape_string($warenkorb['lieferung'])."' LIMIT 1");
      if(!$checkversand)
      {
        $this->app->DB->Insert("INSERT INTO shopexport_versandarten (shop, versandart_shop, aktiv) values ('$shop','".$this->app->DB->real_escape_string($warenkorb['lieferung'])."',0)");
      }
    }
  }

  $empfaengerLand = $warenkorb['land'];
  if(!empty($warenkorb['lieferadresse_name']) && !empty($warenkorb['lieferadresse_land'])
    && (
      $warenkorb['lieferadresse_name'] !== $warenkorb['name']
      || $warenkorb['lieferadresse_land'] !== $warenkorb['land']
      || $warenkorb['lieferadresse_strasse'] !== $warenkorb['strasse']
      || $warenkorb['lieferadresse_ort'] !== $warenkorb['ort']
      || $warenkorb['lieferadresse_plz'] !== $warenkorb['plz']
    )
  ) {
    $warenkorb['abweichendelieferadresse']=1;
    if($steuerfreilieferlandexport && !empty($warenkorb['lieferadresse_land'])){
      $empfaengerLand = $warenkorb['lieferadresse_land'];
    }
  }

  $ust_befreit=0;
  if(!empty($empfaengerLand) && $empfaengerLand !== $this->Firmendaten("land"))
  {
    if($this->IstEU($empfaengerLand)){
      $ust_befreit=1;
    }
    if($this->Export($empfaengerLand)){
      $ust_befreit=2;
    }
  }
  if(isset($warenkorb['ust_befreit']) && is_numeric($warenkorb['ust_befreit']))
  {
    $warenkorb_ustbefreit = (int)$warenkorb['ust_befreit'];
    if($warenkorb_ustbefreit >= 0 && $warenkorb_ustbefreit <= 3){
      $ust_befreit = $warenkorb_ustbefreit;
    }
  }

    if(isset($warenkorb['fastlane']))
    {
      $fastlane = $warenkorb['fastlane'];
    }

    if($fastlane)
    {
      $fastlane = 1;
    }else{
      $fastlane = 0;
    }


    $warenkorb['zahlungsweise'] = str_replace(array('&uuml;','&Uuml;','&auml;','&Auml;','&ouml;','&Ouml;','&szlig;'),array('ü','Ü','ä','Ä','ö','Ö','ß'), $warenkorb['zahlungsweise']);
    if($zahlungsweisenmapping)
    {
      $extrasel = "";
      $zahlungsweise1 = $this->app->DB->real_escape_string($warenkorb['zahlungsweise']);
      $zahlungsweise2 = $this->app->DB->real_escape_string($this->app->erp->ConvertForDBUTF8($warenkorb['zahlungsweise']));
      if($zahlungsweise2 !== '' && $zahlungsweise2 != $zahlungsweise1)$extrasel .= " OR zahlweise_shop = '$zahlungsweise2' ";
      $zahlungsweise3 = $this->app->DB->real_escape_string($this->app->erp->ConvertForDB($warenkorb['zahlungsweise']));
      if($zahlungsweise3 !== '' && $zahlungsweise3 != $zahlungsweise1)$extrasel .= " OR zahlweise_shop = '$zahlungsweise3' ";
      $shopexport_zahlweisen = $this->app->DB->SelectArr("SELECT * FROM shopexport_zahlweisen WHERE shop='$shop' AND aktiv = 1 AND zahlweise_wawision <> '' AND (zahlweise_shop = '".$this->app->DB->real_escape_string($warenkorb['zahlungsweise'])."' $extrasel )");
      if(!$shopexport_zahlweisen)
      {
        if($warenkorb['zahlungsweise']=="secupay_creditcard") $warenkorb['zahlungsweise']="secupay";
        if($warenkorb['zahlungsweise']=="Amazoncba") $warenkorb['zahlungsweise']="amazon";
        if($warenkorb['zahlungsweise'] == 'sofort_sofortueberweisung')$warenkorb['zahlungsweise'] = 'sofortueberweisung';
        $shopexport_zahlweisen = $this->app->DB->SelectArr("SELECT * FROM shopexport_zahlweisen WHERE aktiv = 1 AND shop='$shop' AND zahlweise_shop = '".$this->app->DB->real_escape_string($warenkorb['zahlungsweise'])."'");
        if(!$shopexport_zahlweisen)
        {
          $checkzahl = $this->app->DB->Select("SELECT id FROM shopexport_zahlweisen WHERE shop = '$shop' and zahlweise_shop = '".$this->app->DB->real_escape_string($warenkorb['zahlungsweise'])."' LIMIT 1");
          if(!$checkzahl)
          {
            $this->app->DB->Insert("INSERT INTO shopexport_zahlweisen (shop, zahlweise_shop, aktiv) values ('$shop','".$this->app->DB->real_escape_string($warenkorb['zahlungsweise'])."',0)");
          }
        }
      }

      $found = false;
      if($shopexport_zahlweisen)
      {
        foreach($shopexport_zahlweisen as $zahlung)
        {
          $warenkorb['zahlungsweise'] = $zahlung['zahlweise_wawision'];
          $warenkorb['vorabbezahltmarkieren'] = $zahlung['vorabbezahltmarkieren'];
          if(!$zahlung['autoversand']){
            $warenkorb['autoversand'] = 0;
          }
          if($zahlung['keinerechnung']){
            $warenkorb['auftragsart'] = 'lieferung';
          }
          if($zahlung['fastlane'] == 1) {
            $fastlane = 1;
          }
          $found = true;
          break;
        }
      }
      if(!$found)
      {
        $shopexport_zahlweisen2 = $this->app->DB->SelectArr("SELECT * FROM shopexport_zahlweisen WHERE shop='$shop' AND aktiv = 1 AND zahlweise_wawision <> '' AND zahlweise_shop = ''");
        if($shopexport_zahlweisen2)
        {
          foreach($shopexport_zahlweisen2 as $zahlung)
          {
            $warenkorb['zahlungsweise'] = $zahlung['zahlweise_wawision'];
            $warenkorb['vorabbezahltmarkieren'] = $zahlung['vorabbezahltmarkieren'];
            if(!$zahlung['autoversand']){
              $warenkorb['autoversand'] = 0;
            }
            if($zahlung['keinerechnung']){
              $warenkorb['auftragsart'] = 'lieferung';
            }
            if($zahlung['fastlane'] == 1) {
              $fastlane = 1;
            }
            $found = true;
            break;
          }
        }
      }
      if($warenkorb['zahlungsweise']==='bar')
      {
        $versand = 'selbstabholer';
      }
    }else{
      if($warenkorb['zahlungsweise'] === 'secupay_creditcard') {
        $warenkorb['zahlungsweise']='secupay';
      }
      if($warenkorb['zahlungsweise'] === 'Amazoncba') {
        $warenkorb['zahlungsweise']='amazon';
      }
      if($warenkorb['zahlungsweise'] === 'sofort_sofortueberweisung'){
        $warenkorb['zahlungsweise'] = 'sofortueberweisung';
      }

      $bekanntezahlungsweisen = $this->GetZahlungsweise();
      if(!isset($bekanntezahlungsweisen[$warenkorb['zahlungsweise']]))
      {
        $warenkorb['zahlungsweise'] = $this->Firmendaten("zahlungsweise");
      }

      if($warenkorb['zahlungsweise']==='bar')
      {
        $versand = 'selbstabholer';
      }

      $vorabbezahltmarkieren_ohnevorkasse_bar = $shopexportArr['vorabbezahltmarkieren_ohnevorkasse_bar'];

      if($vorabbezahltmarkieren_ohnevorkasse_bar=='1' && ($warenkorb['zahlungsweise']!=='rechnung' && $warenkorb['zahlungsweise']!=='nachnahme' && $warenkorb['zahlungsweise']!=='sofortueberweisung'
            && $warenkorb['zahlungsweise']!=='bar' && $warenkorb['zahlungsweise']!=='vorkasse' && $warenkorb['zahlungsweise']!=='paypal'))
      {
        $warenkorb['vorabbezahltmarkieren']='1';
      }

      if(empty($warenkorb['vorabbezahltmarkieren']) || $warenkorb['vorabbezahltmarkieren']!='1') {
        $warenkorb['vorabbezahltmarkieren']='0';
      }
    }

    switch($shopexportArr['autoversandoption']){
      case 'rechnungundlieferschein':
        $warenkorb['auftragsart'] = 'standardauftrag';
          break;
      case 'nurrechnung':
        $warenkorb['auftragsart'] = 'rechnung';
        break;
      case 'nurlieferschein':
        $warenkorb['auftragsart'] = 'lieferung';
        break;
    }


    if(!empty($warenkorb['lieferadresse_name'])){
      $warenkorb['abweichendelieferadresse'] = '1';
    }
    else{
      $warenkorb['abweichendelieferadresse'] = '0';
    }


    //belegnummer fuer auftrag erzeugen
    $belegnr = (String)$this->app->DB->Select("SELECT belegnr FROM $doctype WHERE id = '$auftrag' LIMIT 1");
    if($belegnr === '' || $belegnr === '0')
    {
      if((String)$demomodus === '1' || $doctype === 'angebot')
      {
        $belegnr = "";
        $demomodus = 1;
      }else{
        $belegnr = $this->GetNextNummer($doctype,$projekt,$auftrag);
      }
    }

    if($warenkorb['bestellnummer']!='') {
      $warenkorb['bestellnummer'] = 'Ihre Bestellnummer: '.$warenkorb['bestellnummer'];
    }


  if(!isset($warenkorb['aktion'])) {
    $warenkorb['aktion'] = "";
  }

  if(isset($warenkorb['aktionscode']) && $warenkorb['aktionscode']!="") {
    $warenkorb['aktion'] = $warenkorb['aktionscode'];
  }

  $shopfreitext = $shopexportArr['freitext'];
  if($shopfreitext === 'freitext' && !empty($warenkorb['internebemerkung']))
  {
    if(empty($warenkorb['freitext']))
    {
      $warenkorb['freitext'] = $warenkorb['internebemerkung'];
    }else{
      $warenkorb['freitext'] .= "\n".$warenkorb['internebemerkung'];
    }
    $warenkorb['internebemerkung'] = '';
    if(!empty($warenkorb['internebemerkung']))
    {
      $warenkorb['internebemerkung'] = '';
    }
  }elseif($shopfreitext === 'internebemerkung' && !empty($warenkorb['freitext']))
  {
    if(empty($warenkorb['internebemerkung']))
    {
      $warenkorb['internebemerkung'] = $warenkorb['freitext'];
    }else{
      $warenkorb['internebemerkung'] .= "\n".$warenkorb['freitext'];
    }
    $warenkorb['freitext'] = '';
  }

  $checksprache = $this->app->DB->Select("SELECT sprache FROM shopexport_sprachen WHERE shop = '$shop' AND (projekt = '$projekt' OR projekt = 0) AND 
  (land = '".(isset($warenkorb['land'])?$warenkorb['land']:$this->app->erp->Firmendaten('land'))."' OR land = '') ORDER BY projekt = '$projekt' DESC, land = '".$warenkorb['land']."' DESC LIMIT 1
  ");
  if(!isset($warenkorb['kunde_sprache']) || !$warenkorb['kunde_sprache']){
    $warenkorb['kunde_sprache'] = $checksprache;
  }

  if($warenkorb['bestellnummer']!=''){
    $warenkorb['freitext'] .= "\r\n" . $warenkorb['bestellnummer'];
  }

  $escapearr = array('ansprechpartner','lieferadresse_name', 'lieferadresse_strasse','lieferadresse_unterabteilung','lieferadresse_abteilung','lieferadresse_ansprechpartner','lieferadresse_ort','lieferadresse_adresszusatz','freitext');
  foreach($escapearr as $k)
  {
    if(isset($warenkorb[$k])){
      $warenkorb[$k] = $this->app->DB->real_escape_string($warenkorb[$k]);
    }
  }

  if($doctype === 'angebot'){
    $this->app->DB->Update("UPDATE angebot SET anfrage = '".$this->app->DB->real_escape_string($warenkorb['onlinebestellnummer'])."' WHERE id = '$auftrag' LIMIT 1");
  }
  if($doctype === 'auftrag'){
    $this->app->DB->Update("UPDATE auftrag SET ihrebestellnummer = '".$this->app->DB->real_escape_string($warenkorb['ihrebestellnummer'])."' WHERE id = '$auftrag' LIMIT 1");
  }

  $this->app->DB->Update("UPDATE $doctype SET
      belegnr='$belegnr',
      datum='{$warenkorb['bestelldatum']}',
      lieferdatum='{$warenkorb['lieferdatum']}',
      ustid='{$warenkorb['ustid']}',
      ust_befreit='{$ust_befreit}',
      internet='{$warenkorb['onlinebestellnummer']}',
      transaktionsnummer='{$warenkorb['transaktionsnummer']}',
      aktion='{$warenkorb['aktion']}',
      versandart='{$versand}',
      vertrieb='{$vertrieb}',
      zahlungsweise='{$warenkorb['zahlungsweise']}',
      freitext='{$warenkorb['freitext']}',
      bank_inhaber='{$warenkorb['kontoinhaber']}',
      bank_institut='{$warenkorb['bank']}',
      bank_blz='{$warenkorb['blz']}',
      bank_konto='{$warenkorb['kontonummer']}',
      ".($doctype !== 'angebot'?"vorabbezahltmarkieren='{$warenkorb['vorabbezahltmarkieren']}',":'')."
      autoversand='1',
      abweichendelieferadresse='{$warenkorb['abweichendelieferadresse']}',
      ansprechpartner='{$warenkorb['ansprechpartner']}',
      liefername='{$warenkorb['lieferadresse_name']}',
      lieferland='{$warenkorb['lieferadresse_land']}',
      lieferstrasse='{$warenkorb['lieferadresse_strasse']}',
      lieferabteilung='{$warenkorb['lieferadresse_abteilung']}',
      lieferunterabteilung='{$warenkorb['lieferadresse_unterabteilung']}',
      lieferansprechpartner='{$warenkorb['lieferadresse_ansprechpartner']}',
      lieferort='{$warenkorb['lieferadresse_ort']}',
      lieferplz='{$warenkorb['lieferadresse_plz']}',
      liefertitel='{$warenkorb['lieferadresse_titel']}',
      lieferemail='{$warenkorb['lieferadresse_email']}',
      lieferadresszusatz='{$warenkorb['lieferadresse_adresszusatz']}',
      packstation_inhaber='{$warenkorb['packstation_inhaber']}',
      packstation_station='{$warenkorb['packstation_nummer']}',
      packstation_ident='{$warenkorb['packstation_postidentnummer']}',
      packstation_plz='{$warenkorb['packstation_plz']}',
      packstation_ort='{$warenkorb['packstation_ort']}',
      ".($doctype !== 'angebot'?"partnerid='{$warenkorb['affiliate_ref']}',":'')."
      ".($doctype !== 'angebot'?"kennen='{$warenkorb['kennen']}',":'')."
      status=".((String)$demomodus === '1'?"'angelegt'":"'freigegeben'").",
      projekt='$projekt',
      shop='$shop',
      zahlungszielskonto = 0,
      bodyzusatz='{$warenkorb['bodyzusatz']}',
      gesamtsumme='{$warenkorb['gesamtsumme']}' WHERE id='$auftrag' LIMIT 1");

        if(!empty($warenkorb['angebot']) && $warenkorb['angebot']!='')
        {
          $angebotid = $this->app->DB->Select("SELECT id FROM angebot WHERE belegnr='".$this->app->DB->real_escape_string($warenkorb['angebot'])."' AND belegnr!='' LIMIT 1");
          if($angebotid > 0)
          {
            $this->app->DB->Update("UPDATE angebot SET auftrag='$belegnr', auftragid='$auftrag' WHERE id='$angebotid' LIMIT 1");
            $this->app->DB->Update("UPDATE auftrag SET angebot='".$this->app->DB->real_escape_string($warenkorb['angebot'])."', angebotid='$angebotid' WHERE id='$auftrag' LIMIT 1");
          }
        }

  if($projekt && $doctype === 'auftrag')
  {
    $bevorzugteslager = $this->app->DB->Select("SELECT l.id FROM projekt p INNER JOIN lager l ON p.standardlager = l.id WHERE p.id = '$projekt' LIMIT 1");
    if($bevorzugteslager){
      $this->app->DB->Update("UPDATE auftrag SET standardlager = '$bevorzugteslager' WHERE id='$auftrag' LIMIT 1");
    }
  }


  if($doctype === 'auftrag' && isset($warenkorb['ust_ok']) && (string)$warenkorb['ust_ok'] === '0') {
    $this->app->DB->Update(
      sprintf(
        'UPDATE `auftrag` SET `ust_ok` = 0 WHERE `id` = %d',
        $auftrag
      )
    );
  }


  if($this->app->DB->error())
  {
    $this->app->DB->Update("UPDATE $doctype SET versandart='{$versand}' WHERE id='$auftrag'");
    $this->app->DB->Update("UPDATE $doctype SET datum='{$warenkorb['bestelldatum']}' WHERE id='$auftrag'");
    $this->app->DB->Update("UPDATE $doctype SET shop='$shop' WHERE id='$auftrag'");
    $this->app->DB->Update("UPDATE $doctype SET zahlungsweise='{$warenkorb['zahlungsweise']}' WHERE id='$auftrag'  LIMIT 1");
  }
  $this->app->DB->Update("UPDATE $doctype SET 
    name = '".$this->app->DB->real_escape_string($warenkorb['name'])."'
    ,strasse = '".$this->app->DB->real_escape_string($warenkorb['strasse'])."'
    ,plz = '".$this->app->DB->real_escape_string($warenkorb['plz'])."'
    ,ort = '".$this->app->DB->real_escape_string($warenkorb['ort'])."'
    ,land = '".$this->app->DB->real_escape_string($warenkorb['land'])."'
    ,abteilung = '".$this->app->DB->real_escape_string($warenkorb['abteilung'])."'
    ,unterabteilung= '".$this->app->DB->real_escape_string($warenkorb['unterabteilung'])."'
    ,ansprechpartner= '".$warenkorb['ansprechpartner']."'
    ,adresszusatz= '".$this->app->DB->real_escape_string($warenkorb['adresszusatz'])."'
    ,email= '".$this->app->DB->real_escape_string($warenkorb['email'])."'
    ,telefon= '".$this->app->DB->real_escape_string($warenkorb['telefon'])."'
    ,telefax= '".$this->app->DB->real_escape_string($warenkorb['telefax'])."'
    WHERE id='$auftrag' LIMIT 1");

  if(!empty($warenkorb['anrede'])){
      $query = sprintf("UPDATE `%s` SET `typ` = '%s' WHERE `id` = %d",
          $doctype, $this->app->DB->real_escape_string($warenkorb['anrede']), $auftrag);
      $this->app->DB->Update($query);
  }
  if($warenkorb['ustid']){
    $this->app->DB->Update("UPDATE $doctype SET ustid= '" . $this->app->DB->real_escape_string($warenkorb['ustid']) . "' WHERE id='$auftrag' LIMIT 1");
  }
  if(!empty($warenkorb['abweichendelieferadresse'])){
    $abweichendeUstId = '';
    if(!empty($warenkorb['lieferadresse_ustid'])){
      $abweichendeUstId = $warenkorb['lieferadresse_ustid'];
    }
    $this->app->DB->Update("UPDATE $doctype SET ustid= '".$this->app->DB->real_escape_string($abweichendeUstId)."' WHERE id='$auftrag' LIMIT 1");
  }

  if($shopexportArr['vertrieb']) {
    $vertriebname = $this->app->DB->SelectRow(
      sprintf(
        'SELECT id, name FROM adresse WHERE id = %d AND geloescht <> 1', 
        $shopexportArr['vertrieb']
      )
    );
    if($vertriebname && $doctype === 'angebot'){
      $this->app->DB->Update(
        sprintf(
          "UPDATE angebot SET vertriebid = %d, vertrieb = '%s' WHERE id = %d",

          $shopexportArr['vertrieb'], $this->app->DB->real_escape_string($vertriebname['name']),  $auftrag
        )
      );
    }
    elseif($vertriebname && $doctype !== 'angebot') {
      $this->app->DB->Update(
        sprintf(
          "UPDATE auftrag SET vertriebid = %d, vertrieb = '%s' WHERE id = %d",
          $shopexportArr['vertrieb'], $this->app->DB->real_escape_string($vertriebname['name']), $auftrag
        )
      );
    }
  }

    if($fastlane)
    {
      $this->app->DB->Update("UPDATE $doctype SET fastlane= 1 WHERE id='$auftrag' LIMIT 1");
    }

    if(isset($warenkorb['auftragsart'])){
      $this->app->DB->Update("UPDATE $doctype SET art = '{$warenkorb['auftragsart']}' WHERE id='$auftrag'");
    }

    if(!empty($warenkorb['bundesland'])){
      $this->app->DB->Update("UPDATE $doctype SET bundesland = '".$this->app->DB->real_escape_string($warenkorb['bundesland'])."' WHERE id = '$auftrag' LIMIT 1");
    }
    if($this->app->erp->ModulVorhanden('bundesstaaten'))
    {
      if(!empty($warenkorb['bundesstaat']))
      {
        $bundesstaat = $this->app->DB->Select("SELECT iso FROM `bundesstaaten` WHERE land = '".$this->app->DB->real_escape_string($warenkorb['land'])."' AND (iso = '".$this->app->DB->real_escape_string($warenkorb['bundesstaat'])."' OR bundesstaat = '".$this->app->DB->real_escape_string($warenkorb['bundesstaat'])."') AND aktiv = 1 LIMIT 1");
        if($bundesstaat != ''){
          $this->app->DB->Update("UPDATE $doctype SET bundesstaat = '".$this->app->DB->real_escape_string($bundesstaat)."' WHERE id = '$auftrag' LIMIT 1");
        }
      }
      if(!empty($warenkorb['lieferbundesstaat']))
      {
        $bundesstaat = $this->app->DB->Select("SELECT iso FROM `bundesstaaten` WHERE land = '".$this->app->DB->real_escape_string($warenkorb['lieferland'])."' AND (iso = '".$this->app->DB->real_escape_string($warenkorb['lieferadresse_bundesstaat'])."' OR bundesstaat = '".$this->app->DB->real_escape_string($warenkorb['lieferadresse_bundesstaat'])."') AND aktiv = 1 LIMIT 1");
        if($bundesstaat != ''){
          $this->app->DB->Update("UPDATE $doctype SET lieferbundesstaat = '".$this->app->DB->real_escape_string($bundesstaat)."' WHERE id = '$auftrag' LIMIT 1");
        }
      }
    }

    $keinautoversandwegenkommentar = false;
    if((!empty($warenkorb['freitext']) || !empty($warenkorb['internebemerkung'])) && $shopexportArr['autoversandbeikommentardeaktivieren']){
      $keinautoversandwegenkommentar = true;
    }
    if((isset($warenkorb['autoversand']) && $warenkorb['autoversand'] == '0') || $keinautoversandwegenkommentar){
      $this->app->DB->Update("UPDATE $doctype SET autoversand='0' WHERE id='$auftrag'");
    }
    if(!empty($warenkorb['autoversandueberschreiben']) && $warenkorb['autoversandueberschreiben'] == '1'){
      $this->app->DB->Update("UPDATE $doctype SET autoversand='1' WHERE id='$auftrag'");
    }
    if(!empty($warenkorb['internebemerkung'])){
      $this->app->DB->Update("UPDATE $doctype set internebemerkung = '".$this->app->DB->real_escape_string( $warenkorb['internebemerkung'])."' WHERE id = '$auftrag' LIMIT 1");
    }
    if(!empty($warenkorb['internebezeichnung'])){
      $this->app->DB->Update("UPDATE $doctype set internebezeichnung = '".$this->app->DB->real_escape_string( $warenkorb['internebezeichnung'])."' WHERE id = '$auftrag' LIMIT 1");
    }

    if($this->app->DB->Select("SELECT `ust_ok` FROM `shopexport` WHERE `id` = '{$shop}' LIMIT 1")){
      $this->app->DB->Update("UPDATE `{$doctype}` SET `ust_ok` = 1 WHERE `id` = '{$auftrag}' LIMIT 1");
    }elseif(isset($warenkorb['ust_ok']) && $warenkorb['ust_ok'] == '1'){
      $this->app->DB->Update("UPDATE `{$doctype}` SET `ust_ok` = 1 WHERE `id` = '{$auftrag}' LIMIT 1");
    }elseif($doctype === 'auftrag'){
      $this->app->DB->Update("UPDATE `{$doctype}` SET `ust_ok` = 0 WHERE `id` = '{$auftrag}' LIMIT 1");
    }

  if($warenkorb['zahlungsweise'] === 'rechnung')
  {
    $fromstandard = true;
    $adressezahlungsweise = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id = '$adresse' LIMIT 1");
    if($adressezahlungsweise)
    {
      if($adressezahlungsweise['zahlungsweise'] === 'rechnung' && $adressezahlungsweise['zahlungszieltage'] > 0){
        $fromstandard = false;
      }
    }
    if($fromstandard)
    {
      $this->app->DB->Update("UPDATE $doctype SET
        zahlungszielskonto='".(float)$this->Firmendaten('zahlungszielskonto')."',
        zahlungszieltage='".(float)$this->Firmendaten('zahlungszieltage')."',
        zahlungszieltageskonto='".(float)$this->Firmendaten('zahlungszieltageskonto')."'
        WHERE id='$auftrag' LIMIT 1");
    }
  }

  if(!empty($warenkorb['kunde_sprache']))
  {
    $this->app->DB->Update("UPDATE $doctype SET sprache = '".$this->app->DB->real_escape_string($warenkorb['kunde_sprache'])."' WHERE id = '$auftrag' LIMIT 1");
    if(!$this->app->DB->Select("SELECT adressennichtueberschreiben FROM shopexport WHERE id = '$shop' LIMIT 1"))
    {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$auftrag' LIMIT 1");
      if('' === (String)$this->app->DB->Select("SELECT sprache FROM adresse WHERE id = '$adresse' LIMIT 1"))
      {
        $this->app->DB->Update("UPDATE adresse SET sprache = '".$this->app->DB->real_escape_string($warenkorb['kunde_sprache'])."' WHERE id = '$adresse' LIMIT 1");
      }
    }
  }

  if(!empty($warenkorb['anhang']))
  {
    if(!is_array($warenkorb['anhang'])){
      $data = $warenkorb['anhang'];
      $warenkorb['anhang'] = [];
      $warenkorb['anhang'][] = ['datei' => $data, 'endung' => ''];
    }

    foreach ($warenkorb['anhang'] as $anhang){
      $endung = ltrim($anhang['endung'],'.');
      $dateilabel = 'Anhang';
      $decodedData = @base64_decode($anhang['datei']);
      $tmpdatei = $this->app->erp->GetTMP().'anhangtmp'.microtime(true);
      file_put_contents($tmpdatei ,$decodedData);
      if(empty($endung)){
        $mimetype = explode('/',mime_content_type($tmpdatei));
        switch ($mimetype[0]){
          case 'image':
            if(strpos($mimetype[1],'jpg') !== false || strpos($mimetype[1],'jpeg') !== false){
              $endung = 'jpg';
            }
            if(strpos($mimetype[1],'png') !== false){
              $endung = 'png';
            }
            if(strpos($mimetype[1],'bmp') !== false){
              $endung = 'bmp';
            }
            break;
          case 'text':
            if(strpos($mimetype[1],'plain') !== false){
              $endung = 'txt';
            }
            if(strpos($mimetype[1],'php') !== false){
              $endung = 'php';
            }
            break;
          default:
            $endung = 'pdf';
            break;
        }
      }

      $datei = $this->app->Conf->WFuserdata.'/'.md5($warenkorb['onlinebestellnummer'].'.'.$endung.microtime(true));
      move_uploaded_file($tmpdatei,$datei);

      if(file_put_contents($datei,$decodedData))
      {
        if(@is_file($datei) && @filesize($datei))
        {
          if(!empty(trim($anhang['name']))){
            $dateilabel = $this->app->DB->real_escape_string(trim($anhang['name']));
          }
          $fileid = $this->CreateDatei($warenkorb['onlinebestellnummer'].'.'.$endung, $dateilabel, '', '', $datei, $this->app->User->GetName());
          $this->AddDateiStichwort($fileid, 'anhang', $doctype, $auftrag);
          unlink($datei);
        }
      }
    }
  }


  if(isset($warenkorb['zahlungszielskonto'])){
    $this->app->DB->Update("UPDATE $doctype SET zahlungszielskonto = '".(float)(str_replace(',','.',$warenkorb['zahlungszielskonto']))."' WHERE id = '$auftrag' LIMIT 1");
  }
  if(isset($warenkorb['zahlungszieltage'])){
    $this->app->DB->Update("UPDATE $doctype SET zahlungszieltage = '".(int)($warenkorb['zahlungszieltage'])."' WHERE id = '$auftrag' LIMIT 1");
  }
  if(isset($warenkorb['zahlungszieltageskonto'])){
    $this->app->DB->Update("UPDATE $doctype SET zahlungszieltageskonto = '".(int)($warenkorb['zahlungszieltageskonto'])."' WHERE id = '$auftrag' LIMIT 1");
  }
  if(isset($warenkorb['steuersatz_normal']) && (float)str_replace(',','.',$warenkorb['steuersatz_normal']) > 1){
    $this->app->DB->Update("UPDATE $doctype SET steuersatz_normal = '".(float)(str_replace(',','.',$warenkorb['steuersatz_normal']))."' WHERE id = '$auftrag' LIMIT 1");
  }
  if(isset($warenkorb['steuersatz_ermaessigt']) && (float)str_replace(',','.',$warenkorb['steuersatz_ermaessigt']) > 1){
    $this->app->DB->Update("UPDATE $doctype SET steuersatz_ermaessigt = '".(float)(str_replace(',','.',$warenkorb['steuersatz_ermaessigt']))."' WHERE id = '$auftrag' LIMIT 1");
  }

  $this->RunHook('import_auftrag_tax_changed',2, $doctype, $auftrag);
  if(isset($warenkorb['steuersatz_normal']) && (float)str_replace(',','.',$warenkorb['steuersatz_normal']) > 1){
    $warenkorb['steuersatz_normal'] = $this->app->DB->Select("SELECT steuersatz_normal FROM $doctype WHERE id = $auftrag LIMIT 1");
  }
  if(isset($warenkorb['steuersatz_ermaessigt']) && (float)str_replace(',','.',$warenkorb['steuersatz_ermaessigt']) > 1){
    $warenkorb['steuersatz_ermaessigt'] = $this->app->DB->Select("SELECT steuersatz_ermaessigt FROM $doctype WHERE id = $auftrag LIMIT 1");
  }

    $this->RunHook('import_auftrag_tax_changed',2, $doctype, $auftrag);
    if(isset($warenkorb['steuersatz_normal']) && (float)str_replace(',','.',$warenkorb['steuersatz_normal']) > 1){
      $warenkorb['steuersatz_normal'] = $this->app->DB->Select("SELECT steuersatz_normal FROM $doctype WHERE id = $auftrag LIMIT 1");
    }
    if(isset($warenkorb['steuersatz_ermaessigt']) && (float)str_replace(',','.',$warenkorb['steuersatz_ermaessigt']) > 1){
      $warenkorb['steuersatz_ermaessigt'] = $this->app->DB->Select("SELECT steuersatz_ermaessigt FROM $doctype WHERE id = $auftrag LIMIT 1");
    }

    $waehrung = 'EUR';
    if(!empty($warenkorb['waehrung'])) {
      $waehrung = $this->app->DB->real_escape_string(trim(strtoupper($warenkorb['waehrung'])));
      if(!$waehrung) {
        $waehrung = 'EUR';
      }
      else{
        $this->app->DB->Update("UPDATE $doctype SET waehrung = '$waehrung' WHERE id = '$auftrag' LIMIT 1");
      }
    }

    if(isset($warenkorb['auftragsart']) && $warenkorb['auftragsart']){
      $this->app->DB->Update("UPDATE $doctype SET art = '".$this->app->DB->real_escape_string($warenkorb['auftragsart'])."' WHERE id = '$auftrag' LIMIT 1");
    }
    if($shop){
      $shoptyp = $shopexportArr['typ'];
      $artikelimport = $shopexportArr['artikelimport'];
      $artikelimporteinzeln = $shopexportArr['artikelimporteinzeln'];
      $projekt = $shopexportArr['projekt'];
      if(!empty($subshopprojekt)){
        $projekt = $subshopprojekt;
      }
      if(!empty($warenkorbprojekt)){
        $projekt = $warenkorbprojekt;
      }
      $multiprojekt = $shopexportArr['multiprojekt'];
      $artikelnummernummerkreis = $shopexportArr['artikelnummernummerkreis'];
      $shopbezeichnung = $shopexportArr['bezeichnung'];
      $stuecklisteergaenzen = $shopexportArr['stuecklisteergaenzen'];
      $artikeltexteuebernehmen = $shopexportArr['artikeltexteuebernehmen'];
    }

    if($waehrung !== 'EUR') {
      $this->LoadKurs($auftrag, $doctype, $projekt);
    }

  if($doctype === 'auftrag'){
    $this->RunHook('ImportAuftrag', 4, $auftrag, $shop, $warenkorb, $projekt);
  }

  if(isset($warenkorb['vertrieb'])){
    $this->app->DB->Update("UPDATE $doctype SET vertrieb = '".$warenkorb['vertrieb']."' WHERE id = '$auftrag' LIMIT 1");
  }
  if(isset($warenkorb['vertriebid']) && $warenkorb['vertriebid'] > 0){
    $this->app->DB->Update("UPDATE $doctype SET vertriebid = '".$warenkorb['vertriebid']."' WHERE id = '$auftrag' LIMIT 1");
  }

    if(empty($warenkorb['steuerfrei']) && !empty($warenkorb['checksteuerfrei']))
    {
      if($doctype === 'angebot' && !$this->AngebotMitUmsatzeuer($auftrag))
      {
        $warenkorb['steuerfrei'] = 1;
      }elseif($doctype === 'auftrag' && !$this->AuftragMitUmsatzsteuer($auftrag))
      {
        $warenkorb['steuerfrei'] = 1;
      }
    }

    $parentcount = [];
    $rabattpositionen = array();
    if(!empty($warenkorb['articlelist'])){
      foreach ($warenkorb['articlelist'] as $key => $value) {//Leerzeichen entfernen in Artikelnummern
        unset($warenkorb['articlelist'][$key]['databaseId']);
        if(isset($warenkorb['articlelist'][$key]['articleid'])){
          $warenkorb['articlelist'][$key]['articleid'] = trim($value['articleid']);
        }
        if(isset($warenkorb['articlelist'][$key]['variante_von'])){
          $warenkorb['articlelist'][$key]['variante_von'] = trim($value['variante_von']);
        }
      }

      //Stücklisten mit einem Element auflösen
      foreach ($warenkorb['articlelist'] as $key => $value) {
        if($stuecklisteergaenzen){
          $warenkorb['articlelist'][$key]['stuecklisteergaenzen'] = true;
        }
        if(isset($value['posid']) && $value['posid']) {
          $posids[$value['posid']] = $key;
        }
        if(isset($value['parentid']) && $value['parentid']){
          if(empty($parentcount) || !isset($parentcount[$value['parentid']])){
            $parentcount[$value['parentid']] = 0;
          }
          $parentcount[$value['parentid']]++;
        }
      }
    }
    //if(true || !$stuecklisteergaenzen)
    if(true)
    {
      if(!empty($parentcount))
      {
        foreach($parentcount as $k => $v)
        {
          if($v == 1 && isset($posids[$k]))
          {
            foreach($warenkorb['articlelist'] as $key=>$value)
            {
              if(isset($value['parentid']) && $value['parentid'] && $value['parentid'] == $k)
              {
                if(isset($warenkorb['articlelist'][$posids[$k]]['options']) && $warenkorb['articlelist'][$posids[$k]]['options'])
                {
                  $warenkorb['articlelist'][$key]['options'] = (isset($warenkorb['articlelist'][$key]['options']) && $warenkorb['articlelist'][$key]['options']?$warenkorb['articlelist'][$key]['options'].' ':'').$warenkorb['articlelist'][$posids[$k]]['options'];
                }
                if((isset($warenkorb['articlelist'][$posids[$k]]['price']) && $warenkorb['articlelist'][$posids[$k]]['price'] != 0) || (isset($warenkorb['articlelist'][$posids[$k]]['price_netto']) && $warenkorb['articlelist'][$posids[$k]]['price_netto'] != 0))
                {
                  if(isset($warenkorb['articlelist'][$posids[$k]]['price'])){
                    $warenkorb['articlelist'][$key]['price'] = $warenkorb['articlelist'][$posids[$k]]['price'];
                  }
                  if(isset($warenkorb['articlelist'][$posids[$k]]['price_netto'])){
                    $warenkorb['articlelist'][$key]['price_netto'] = $warenkorb['articlelist'][$posids[$k]]['price_netto'];
                  }
                  $warenkorb['articlelist'][$key]['quantity'] = $warenkorb['articlelist'][$posids[$k]]['quantity'];
                }
                if(isset($warenkorb['articlelist'][$posids[$k]]['steuersatz']))
                {
                  $warenkorb['articlelist'][$key]['steuersatz'] = $warenkorb['articlelist'][$posids[$k]]['steuersatz'];
                }
                unset($warenkorb['articlelist'][$key]['parentid']);
                unset($warenkorb['articlelist'][$posids[$k]]);
              }
            }
          }
        }
      }
    }

      if(!empty($parentcount))
      {
        foreach($parentcount as $k => $v)
        {
          if($v > 1 && isset($posids[$k]))
          {
            if(((isset($warenkorb['articlelist'][$posids[$k]]['price']) && $warenkorb['articlelist'][$posids[$k]]['price'] > 0) ||
              (isset($warenkorb['articlelist'][$posids[$k]]['price_netto']) && $warenkorb['articlelist'][$posids[$k]]['price_netto'] > 0))){
              foreach($warenkorb['articlelist'] as $key=>$value)
              {
                if(isset($value['parentid']) && $value['parentid'] && $value['parentid'] == $k && ((isset($value['price']) && $value['price'] > 0) || (isset($value['price_netto']) && $value['price_netto'] > 0)) )
                {
                  $warenkorb['articlelist'][$key]['price'] = 0;
                  $warenkorb['articlelist'][$key]['price_netto'] = 0;
                }
              }
            }
          }
        }
      }

    if(isset($warenkorb['gutscheincode'])){
      $voucher = $this->app->DB->SelectRow( sprintf("SELECT v.id,v.agent_address_id, a.name AS agent_name, v.commission_rate, v.voucher_code FROM voucher v
        JOIN adresse a ON a.id=v.agent_address_id
        WHERE v.voucher_code<>'' AND v.voucher_code='%s' AND (v.project_id=0 OR v.project_id='%s') AND a.geloescht<>1 LIMIT 1",
        $warenkorb['gutscheincode'],$projekt));

      if(!empty($voucher['id'])){
        $this->app->DB->Insert(sprintf("INSERT INTO commission_rate_receipt (doctype_id,doctype,commission_rate,notice) 
            VALUES ('%s','%s','%s','%s')",$auftrag,$doctype,$voucher['commission_rate'],'Kommission für Gutschein: '.$voucher['voucher_code']));

        $this->app->DB->Update(sprintf("UPDATE $doctype SET vertrieb='%s', vertriebid='%s' WHERE id=%s",
          $voucher['agent_name'],$voucher['agent_address_id'],$auftrag));
      }
    }

    //artikelpositionen buchen
    foreach($warenkorb['articlelist'] as $key=>$value)
    {
      $value['articleid'] = trim($value['articleid']);
      if(isset($varj_id)){
        unset($varj_id);
      }
      if(!isset($warenkorb['articlelist'][$key]['ignorieren']))
      {
        // wenn es das produkt in dem projekt gibt
        $artikelimporteinzelngesetzt = $this->app->DB->Select("SELECT autoabgleicherlaubt FROM artikel WHERE nummer='{$value['articleid']}' AND projekt='$projekt' LIMIT 1");

        // pruefe ob auftrag auf anderes projekt gestellt werden muss
        if($multiprojekt=="1")
        {
          $artikelprojekt = $this->app->DB->Select("SELECT projekt FROM artikel WHERE nummer='{$value['articleid']}' LIMIT 1");// AND //TODO BENE
          if($artikelprojekt > 0)
          {
            $projekt = $artikelprojekt;
          }
        }
        else{
          $artikelprojekt = $this->app->DB->Select("SELECT projekt FROM artikel WHERE nummer='{$value['articleid']}' AND projekt='$projekt' LIMIT 1");// AND //TODO BENE
        }

        $zwangsprojekt = $this->app->DB->Select("SELECT shopzwangsprojekt FROM projekt WHERE id='$artikelprojekt' LIMIT 1");

        if($zwangsprojekt==1)
        {
          $this->app->DB->Update("UPDATE $doctype SET projekt='$artikelprojekt' WHERE id='$auftrag'");
        }

        $extart = $shopexportArr['artikelnummernummerkreis'];

        $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
          //$j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='{$value[articleid]}' AND (shop='$shop' OR shop2='$shop' OR shop3='$shop') LIMIT 1");

        $j_id = null;
        if(!empty($value['fremdnummer']))
        {
          $j_id = $this->app->DB->Select("SELECT a.id FROM artikelnummer_fremdnummern af INNER JOIN artikel a on af.artikel = a.id WHERE af.nummer='{$value['fremdnummer']}' AND af.aktiv = 1 AND af.nummer <> '' AND (a.projekt='$projekt' OR af.shopid = '$shop') AND a.nummer <> 'DEL' AND IFNULL(a.geloescht,0) = 0 ORDER BY af.shopid = '$shop' DESC,IFNULL(a.intern_gesperrt,0) = 0 DESC, af.id LIMIT 1");
        }
        if(empty($j_id)){
          if($multiprojekt == '1' || !$eigenernummernkreis){
            $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='{$value['articleid']}' AND IFNULL(intern_gesperrt,0) = 0 AND IFNULL(geloescht,0) = 0 LIMIT 1");  //TODO BENE
          }else{
            $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='{$value['articleid']}' AND IFNULL(intern_gesperrt,0) = 0 AND IFNULL(geloescht,0) = 0 AND projekt='$projekt' LIMIT 1");  //TODO BENE
          }
        }

        if(!$j_id)
        {
          if($multiprojekt=='1' || !$eigenernummernkreis){
            $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='{$value['articleid']}' AND nummer <> 'DEL' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");  //TODO BENE
          }
          else{
            $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='{$value['articleid']}' AND nummer <> 'DEL' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");  //TODO BENE
          }
        }
        if(!$j_id)
        {
          if($multiprojekt=='1' || !$eigenernummernkreis){
            $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='{$value['articleid']}' AND nummer <> 'DEL' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC  LIMIT 1");  //TODO BENE
          }
          else{
            $j_id = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='{$value['articleid']}' AND nummer <> 'DEL' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC  LIMIT 1");  //TODO BENE
          }

        }

        $check = false;
        if($j_id)
        {
          $check = $this->app->DB->Select("SELECT id FROM verkaufspreise WHERE artikel='$j_id'
              AND (gueltig_bis='0000-00-00' OR gueltig_bis >=NOW()) AND ab_menge=1
              AND ((objekt='Standard' AND adresse=0) OR (objekt='' AND adresse=0)) AND geloescht=0 LIMIT 1");
        }


        if($eigenernummernkreis)
        {
          $j_umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id = '$j_id' LIMIT 1");
        } else {
          $j_umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id = '$j_id' LIMIT 1");
        }

        if($artikelimport || ($artikelimporteinzeln && $artikelimporteinzelngesetzt))
        {
          if(isset($value['umsatzsteuer']))
          {
            $j_umsatzsteuer = $value['umsatzsteuer'];
          }elseif(isset($value['steuersatz']))
          {

            if(round((float)str_replace(',','.',$value['steuersatz']),2) == 7 || round(1+round((float)str_replace(',','.',$value['steuersatz']),2)/100,2) == round($this->GetSteuersatzErmaessigt(true,$auftrag,$doctype),2))
            {
              $j_umsatzsteuer="ermaessigt";
            }
            if(round((float)str_replace(',','.',$value['steuersatz']),2) == 19 || round(1+round((float)str_replace(',','.',$value['steuersatz']),2)/100,2) == round($this->GetSteuersatzNormal(true,$auftrag,$doctype),2))
            {
              $j_umsatzsteuer="normal";
            }
          }
          if(isset($value['variante_von']) && $value['variante_von'] && $value['variante_von'] != $value['articleid'])
          {
            $value['variante_von'] = trim($value['variante_von']);
            if($multiprojekt=='1' || !$eigenernummernkreis){
              $varj_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='{$value['variante_von']}' AND IFNULL(geloescht,0) = 0 AND IFNULL(intern_gesperrt,0) = 0 LIMIT 1");
            }
            else{
              $varj_id = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='{$value['variante_von']}' AND IFNULL(geloescht,0) = 0 AND projekt='$projekt' AND IFNULL(intern_gesperrt,0) = 0 LIMIT 1");
            }
            if(!$varj_id)
            {
              if($multiprojekt=='1' || !$eigenernummernkreis){
                $varj_id = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='{$value['variante_von']}' AND nummer <> 'DEL' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");
              }
              else{
                $varj_id = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='{$value['variante_von']}' AND nummer <> 'DEL' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");
              }
            }
            if(!$varj_id)
            {
              if($multiprojekt=='1' || !$eigenernummernkreis){
                $varj_id = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='{$value['variante_von']}' AND nummer <> 'DEL' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");
              }
              else{
                $varj_id = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='{$value['variante_von']}' AND nummer <> 'DEL' AND projekt='$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");
              }
            }

            if(!$varj_id)
            {
              $dataart = [];
              if($artikelnummernummerkreis)
              {
                $variante_von = $value['variante_von'];
                $value['variante_von'] = $this->GetNextArtikelnummer('produkt', 1, $projekt);
              }
              $dataart['nummer'] = $value['variante_von'];
              $dataart['generierenummerbeioption'] = 1;
              //$dataart['variante'] = 1;
              $dataart['projekt'] = $projekt;
              $dataart['art'] = 'produkt';
              if(isset($this->app->User))
              {
                $dataart['firma'] = $this->app->User->GetFirma();
              }else {
                $dataart['firma'] = 1;
              }
              if($j_umsatzsteuer==='ermaessigt'){
                $dataart['umsatzsteuer'] = 'ermaessigt';
              }
              if($j_umsatzsteuer==='befreit'){
                $dataart['umsatzsteuer'] = 'befreit';
              }
              $dataart['name_de'] = $value['variantename'];
              $dataart['kurztext_de'] = $value['variantekurztext_de'];
              if(isset($value['serviceartikel'])){
                $dataart['serviceartikel'] = $value['serviceartikel'];
              }
              if(isset($value['lagerartikel'])){
                $dataart['lagerartikel'] = $value['lagerartikel'];
              }
              if(isset($value['anhang'])){
                $dataart['anhang'] = $value['anhang'];
              }

              //$dataart['anabregs_text'] = $value['varianteanabregs_text'];
              $dataart['metakeywords_de'] = $value['variantemetakeywords_de'];
              $dataart['metadescription_de'] = $value['variantemetadescription_de'];
              $varj_id = $this->AddArtikel($dataart);
              $this->app->erp->ObjektProtokoll('artikel', $varj_id, 'artikel_create','Shopimport: Atikelvariante erstellt');
              $this->AddVerkaufspreis($varj_id, 1, 0, $value['varianteprice']);
              $value['articleid'] = $this->GetNextArtikelnummer("produkt", 1, $projekt);
            } else {
              $warenkorb['articlelist'][$key]['lagerartikel'] = $this->app->DB->Select("SELECT lagerartikel FROM artikel WHERE id = '$varj_id' LIMIT 1");
              $generierenummerbeioption = $this->app->DB->Select("SELECT generierenummerbeioption from artikel where id = '$varj_id' LIMIT 1");
              //$generierenummerbeioption = 1;
              if($generierenummerbeioption)
              {
                $value['generierenummerbeioption'] = true;
                $value['articleid'] = $this->GetNextArtikelnummer('produkt', 1, $projekt);
              }
            }
          }

          if(empty($value['name']) && !empty($value['name_de'])){
            $value['name'] = $value['name_de'];
          }
          if($warenkorb['steuerfrei']==1)
          {
            if($j_umsatzsteuer==='ermaessigt')
            {
              $ap = $this->AddPositionManuellPreisNummer($doctype,$auftrag, $projekt, $value['articleid'],$value['quantity'],$value['name'],
                  isset($value['price_netto'])?$value['price_netto']:$value['price'],'ermaessigt',$value['rabatt'],$shop,$waehrung, $warenkorb['articlelist'][$key],$warenkorb['articlelist']);
            }elseif($j_umsatzsteuer==="befreit"){
              $ap = $this->AddPositionManuellPreisNummer($doctype,$auftrag, $projekt, $value['articleid'],$value['quantity'],$value['name'],
                  isset($value['price_netto'])?$value['price_netto']:$value['price'],'befreit',$value['rabatt'],$shop,$waehrung, $warenkorb['articlelist'][$key],$warenkorb['articlelist']);
            } else {

              $ap = $this->AddPositionManuellPreisNummer($doctype,$auftrag, $projekt, $value['articleid'],$value['quantity'],$value['name'],
                  isset($value['price_netto'])?$value['price_netto']:$value['price'],'normal',$value['rabatt'],$shop,$waehrung, $warenkorb['articlelist'][$key],$warenkorb['articlelist']);
            }
          } else {
            if($j_umsatzsteuer==='ermaessigt')
            {

              $ap = $this->AddPositionManuellPreisNummer($doctype,$auftrag, $projekt, $value['articleid'],$value['quantity'],$value['name'],
                  isset($value['price_netto'])?$value['price_netto']:($value['price']/$this->GetSteuersatzErmaessigt(true,$auftrag,$doctype)),"ermaessigt",$value['rabatt'],$shop,$waehrung, $warenkorb['articlelist'][$key],$warenkorb['articlelist']);
              if($positionsteuersaetzeerlauben && !empty($warenkorb['steuersatz_ermaessigt']) && !isset($value['steuersatz']))
              {
                $this->app->DB->Update("UPDATE $doctype"."_position SET steuersatz = ".$warenkorb['steuersatz_ermaessigt']." WHERE id = '$ap' LIMIT 1");
              }
            }elseif($j_umsatzsteuer==='befreit')
            {
              $ap = $this->AddPositionManuellPreisNummer($doctype,$auftrag, $projekt, $value['articleid'],$value['quantity'],$value['name'],
                  isset($value['price_netto'])?$value['price_netto']:($value['price']),'befreit',$value['rabatt'],$shop,$waehrung, $warenkorb['articlelist'][$key],$warenkorb['articlelist']);
            } else {
              $ap = $this->AddPositionManuellPreisNummer($doctype,$auftrag, $projekt, $value['articleid'],$value['quantity'],$value['name'],
                  isset($value['price_netto'])?$value['price_netto']:($value['price']/$this->GetSteuersatzNormal(true,$auftrag,$doctype)),"normal",$value['rabatt'],$shop,$waehrung, $warenkorb['articlelist'][$key],$warenkorb['articlelist']);
              if($positionsteuersaetzeerlauben && !empty($warenkorb['steuersatz_normal']) && !isset($value['steuersatz']))
              {
                $this->app->DB->Update("UPDATE $doctype"."_position SET steuersatz = ".$warenkorb['steuersatz_normal']." WHERE id = '$ap' LIMIT 1");
              }
            }
          }
          if(!empty($ap)){
            $warenkorb['articlelist'][$key]['databaseId'] = $ap;
          }
          if(!empty($ap) && isset($value['rabatt'])){
            $rabattpositionen[$ap] = $value['rabatt'];
          }
          if(empty($ap)){
            $this->LogFile('Fehler '.$value['articleid']);
          }
          if(isset($artap)){
            unset($artap);
          }
          if(!empty($ap))
          {
            if(isset($value['webid'])){
              $this->app->DB->Update("UPDATE $doctype"."_position SET webid = '".$this->app->DB->real_escape_string($value['webid'])."' WHERE id = '$ap' LIMIT 1");
            }
            $artap = $this->app->DB->Select("SELECT artikel FROM $doctype"."_position WHERE id = '$ap' LIMIT 1");
            $this->CopyArtikelVariante($artap, ($varj_id?$varj_id:$artap),isset($value['options']) && !empty($value['options'])?$value['options']:(isset($value['anabregs_text'])?$value['anabregs_text']:''));
            if($positionsteuersaetzeerlauben && isset($value['steuersatz']) && is_numeric($value['steuersatz'])){
              $this->app->DB->Update("UPDATE $doctype"."_position SET steuersatz = ".$value['steuersatz']." WHERE id = '$ap' LIMIT 1");
            }
            if(isset($value['anhang'])){
              if(!is_array($value['anhang'])){
                $data = $value['anhang'];
                $value['anhang'] = [];
                $value['anhang'][] = ['datei' => $data, 'endung' => '', 'name' =>'', 'typ' => '', 'titel' => ''];
              }

              foreach ($value['anhang'] as $anhang){
                $dateiname = trim($anhang['name']);
                if(empty($dateiname)){
                  $dateiname = $this->app->DB->Select("SELECT sort FROM $doctype"."_position WHERE id=$ap");
                }
                $typ = trim($anhang['typ']);
                if(empty($typ)){
                  $typ = 'Bild';
                }
                $titel = trim($anhang['titel']);
                if(empty($titel)){
                  $titel = 'Anhang';
                }

                $fileid = $this->addBase64Bild($anhang['datei'],$dateiname,$anhang['endung'],$titel);
                if(!empty($fileid)){
                  $this->AddDateiStichwort($fileid, $typ, $doctype, $auftrag, false, $ap, 'position');
                }

              }
            }
          }
          if(!empty($value['variante_von']) && !empty($varj_id))
          {
            if($artap)
            {
              $lieferant = $this->app->DB->Select("SELECT adresse FROM artikel WHERE id = '$varj_id' LIMIT 1");
              if($lieferant)
              {
                $this->app->DB->Update("UPDATE artikel set adresse = '$lieferant' WHERE id = '$artap' LIMIT 1");
                $this->AddEinkaufspreis($artap,1,$lieferant, $value['articleid'], $value['name'],0);
              }
              $lagerpl = $this->app->DB->Select("SELECT lager_platz FROM artikel WHERE id = '$varj_id' LIMIT 1");
              $produktion = $this->app->DB->Select("SELECT produktion FROM artikel WHERE id = '$varj_id' LIMIT 1");
              if($produktion){
                $this->app->DB->Update("UPDATE artikel set produktion = '1' WHERE id = '$artap' LIMIT 1");
              }
              $stueckliste = $this->app->DB->Select("SELECT stueckliste FROM artikel WHERE id = '$varj_id' LIMIT 1");
              if($stueckliste){
                $this->app->DB->Update("UPDATE artikel set stueckliste = '1' WHERE id = '$artap' LIMIT 1");
              }
              if($lagerpl){
                $this->app->DB->Update("UPDATE artikel set lager_platz = '$lagerpl' WHERE id = '$artap' LIMIT 1");
              }
              $this->app->DB->Update("UPDATE artikel set variante = 1, variante_von = '$varj_id' WHERE id = '$artap' LIMIT 1");
            }
          }

          $ueberspringe = true;
          foreach($warenkorb['articlelist'] as $key2=>$value2)
          {
            if($ueberspringe)
            {
              if($key == $key2)$ueberspringe = false;
            }else{
              if(isset($value['posid']))
              {
                if(isset($value2['parentid']) && $value2['parentid'] == $value['posid'])
                {
                  $warenkorb['articlelist'][$key2]['parentap'] = $ap;
                  $explodieren = false;
                }
              }
            }
          }
        } else if ($check > 0)
        {
          // standardpreis aus wawision verwenden
          $anummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id = '$j_id' LIMIT 1");
          if(!empty($anummer)){
            $value['articleid'] = $anummer;
          }
          $gruppenpreis = $this->GetVerkaufspreisGruppe($j_id,$value['quantity'],$shopexportArr['preisgruppe'],$waehrung);
          if ($gruppenpreis) {
              $ap = $this->AddPositionManuellPreisNummer(
                    $doctype,
                    $auftrag,
                    $projekt,
                    $value['articleid'],
                    $value['quantity'],
                    $value['name'],
                    $gruppenpreis,
                    $j_umsatzsteuer,
                    $value['rabatt'],
                    $shop,
                    $waehrung,
                    $warenkorb['articlelist'][$key],
                    $warenkorb['articlelist']
              );
          } else {
              $ap = $this->AddAuftragPositionNummer($auftrag,$value['articleid'],$value['quantity'],$projekt,"",true, $doctype, $warenkorb['articlelist'][$key]);
          }
          if(isset($value['webid'])){
            $this->app->DB->Update("UPDATE $doctype"."_position SET webid = '".$this->app->DB->real_escape_string($value['webid'])."' WHERE id = '$ap' LIMIT 1");
          }
          $ueberspringe = true;
          foreach($warenkorb['articlelist'] as $key2=>$value2)
          {
            if($ueberspringe)
            {
              if($key == $key2){
                $ueberspringe = false;
              }
            }else{
              if(isset($value['posid']))
              {
                if(isset($value2['parentid']) && $value2['parentid'] == $value['posid'])
                {
                  $warenkorb['articlelist'][$key2]['parentap'] = $ap;
                }
              }
            }
          }
        }
        else {
          // fehler
          if($doctype !== 'angebot')
          {
            $this->AuftragProtokoll($auftrag,"Artikel nach Import nicht in interner Datenbank gefunden (Artikel: $j_nummer $j_name  Menge: $j_menge Preis: $j_preis) bzw. kein Verkaufspreis vorhanden. Bitte pr&uuml;fen Sie den Haken Automatischer Abgleich in der Shopschnittstelle");
          }else{
            $this->AngebotProtokoll($auftrag,"Artikel nach Import nicht in interner Datenbank gefunden (Artikel: $j_nummer $j_name  Menge: $j_menge Preis: $j_preis) bzw. kein Verkaufspreis vorhanden. Bitte pr&uuml;fen Sie den Haken Automatischer Abgleich in der Shopschnittstelle");
          }
        }
        if(!empty($ap) && !empty($value['artikeldaten'])){
          $artap = $this->app->DB->Select("SELECT artikel FROM $doctype"."_position WHERE id = '$ap' LIMIT 1");
          unset($value['artikeldaten']['id'],$value['artikeldaten']['nummer']);
          foreach($value['artikeldaten'] as $feldname => $wert){
            $query = sprintf("UPDATE artikel SET %s='%s' WHERE id=%d",
              $this->app->DB->real_escape_string($feldname), $this->app->DB->real_escape_string($wert), $artap);
            $this->app->DB->Update($query);
          }
        }
      }
    }

    foreach ($warenkorb['articlelist'] as $item){
      $commands = [];
      if(empty($item['databaseId'])){
          continue;
      }
      if(isset($item['parentInCart']) && !empty($warenkorb['articlelist'][$item['parentInCart']]['databaseId'])){
        $query = sprintf('UPDATE `%s_position` SET `explodiert` = 1 WHERE `id` = %d',
          $doctype, $warenkorb['articlelist'][$item['parentInCart']]['databaseId']);
        $this->app->DB->Update($query);
        $commands[] = sprintf('`explodiert_parent` = %d', $warenkorb['articlelist'][$item['parentInCart']]['databaseId']);
      }
      if(!empty($item['hidePrice'])){
        $commands[] = '`ohnepreis` = 1';
      }
      if(!empty($commands)){
        $query = sprintf('UPDATE `%s_position` SET %s WHERE `id` = %d',
            $doctype, implode(', ', $commands), $item['databaseId']);
        $this->app->DB->Update($query);
      }
    }

    if(!empty($warenkorb['versandkostenbrutto'])
      && empty($warenkorb['versandkostennetto'])
      && !empty($warenkorb['autoversandsteuer'])
      && empty($warenkorb['portosteuersatz'])) {
      if($doctype !== 'angebot'){
        $positions = $this->app->DB->SelectArr(
          sprintf(
            "SELECT IFNULL(steuersatz,-1) as steuersatz, umsatzsteuer 
            FROM auftrag_position 
            WHERE preis > 0 AND auftrag = %d
            GROUP BY steuersatz, umsatzsteuer", $auftrag
          )
        );
      }
      else {
        $positions = $this->app->DB->SelectArr(
          sprintf(
            "SELECT IFNULL(steuersatz,-1) as steuersatz, umsatzsteuer 
            FROM angebot_position 
            WHERE preis > 0 AND angebot = %d
            GROUP BY steuersatz, umsatzsteuer", $auftrag
          )
        );
      }
      if(!empty($positions)
        && (!empty($positions)?count($positions):0) === 1
        && $positions[0]['steuersatz'] < 0
        && $positions[0]['umsatzsteuer'] === 'ermaessigt'
      ) {
        $warenkorb['portosteuersatz'] = 'ermaessigt';
      }
    }

    if($shoptyp!=='wawision')
    {
      if($warenkorb['zahlungsweise']==='nachnahme')
      {
        $artikelnachnahme = $shopexportArr['artikelnachnahme'];
        $artikelnachnahme_extraartikel = $shopexportArr['artikelnachnahme_extraartikel'];
        $nachnahme = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikelnachnahme' LIMIT 1");
        $umsatzsteuer_nachnahme = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id='$artikelnachnahme' LIMIT 1");
        $nachnahmepreis = $this->GetVerkaufspreis($artikelnachnahme,1);
        if($umsatzsteuer_nachnahme!=='ermaessigt' && $umsatzsteuer_nachnahme!=='befreit') {
          $umsatzsteuer_nachnahme='normal';
        }
        if(isset($warenkorb['nachnahmepreisnetto']))
        {
          $nachnahmepreis = str_replace(',','.',$warenkorb['nachnahmepreisnetto']);
        }elseif($warenkorb['nachnahmepreis'])
        {
          if($umsatzsteuer_nachnahme==='ermaessigt')
          {
            $nachnahmepreis = str_replace(',','.',$warenkorb['nachnahmepreis'])/$this->GetSteuersatzErmaessigt(true,$auftrag,$doctype);
          }elseif($umsatzsteuer_nachnahme==='befreit')
          {
            $nachnahmepreis = str_replace(',','.',$warenkorb['nachnahmepreis']);
          }else{
            $nachnahmepreis = str_replace(',','.',$warenkorb['nachnahmepreis'])/$this->GetSteuersatzNormal(true,$auftrag,$doctype);
          }
        }
        //$warenkorb['zahlungsgebuehr'] //TODO

        if($artikelnachnahme_extraartikel==1)
        {
          $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelnachnahme,1,$nachnahme,$nachnahmepreis,$umsatzsteuer_nachnahme,0,$waehrung);
          if($tmpposid>0)
          {
            $this->app->DB->Update("UPDATE $doctype"."_position SET keinrabatterlaubt=1 WHERE id='$tmpposid' LIMIT 1");
            if(isset($warenkorb['nachnahmepreisnetto']) || isset($warenkorb['nachnahmepreis'])){
              $nachnahmepreis = 0;
            }
          }
        }
      } else {
        $nachnahmepreis=0;
      }

      //porto und nachnahme
      $artikelporto = $shopexportArr['artikelporto'];
      $artikelportoermaessigt = $shopexportArr['artikelportoermaessigt'];

      if( $artikelportoermaessigt && isset($warenkorb['portosteuersatz']) && $warenkorb['portosteuersatz'] === 'ermaessigt')
      {
        $artikelporto = $artikelportoermaessigt;
      }

        if(empty($artikelporto)) {
            if ($this->app->DB->Select("SELECT portoartikelanlegen FROM shopexport WHERE id = '$shop' LIMIT 1"))
            {
                if($warenkorb['versandkostennetto'] != 0 || $warenkorb['versandkostenbrutto'] != 0 || $portocheck == 1)
                {
                    $portoartikelarr = array('projekt'=>$projekt,'porto'=>1, 'lagerartikel'=>0,'name_de'=>'Porto','umsatzsteuer'=>'normal');
                    $artikelporto = $this->app->erp->InsertUpdateArtikel($portoartikelarr);
                    if($artikelporto)
                    {
                        $this->app->DB->Update("UPDATE shopexport SET artikelporto = '$artikelporto' WHERE id = '$shop' AND artikelporto = 0 LIMIT 1");
                    }
                }
            } else {
                $error_msg = 'Importauftrag Shop '.$shop.' Fehler: Kein Portoartikel vorhanden';
                $this->LogFile($error_msg,['Onlinebestellnummer' => $warenkorb['onlinebestellnummer']]);
                return(array("status" => false, "message" => $error_msg, "onlinebestellnummer" => $warenkorb['onlinebestellnummer']));
            }
        }
      $umsatzsteuer_porto = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id='$artikelporto' LIMIT 1");

      $versandname = '';
      if(isset($warenkorb['kunde_sprache']) && $warenkorb['kunde_sprache']){
        if($warenkorb['kunde_sprache'] === 'englisch') {
          $versandname = $this->app->DB->Select("SELECT name_en FROM artikel WHERE id = '$artikelporto'");
        }
      }
      else{
        if($this->app->DB->Select("SELECT adr.id FROM $doctype auf INNER JOIN adresse adr ON auf.adresse = adr.id AND adr.sprache = 'englisch' WHERE auf.id = '$auftrag' LIMIT 1")) {
          $versandname = $this->app->DB->Select("SELECT name_en FROM artikel WHERE id = '$artikelporto'");
        }
      }
      if($versandname === ''){
        $versandname = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id = '$artikelporto'");
      }

      $sprachen = $this->GetAdressSprachen();
      $belegsprache = $this->app->DB->Select("SELECT sprache FROM $doctype WHERE id = '$auftrag'");
      if(array_key_exists($belegsprache, $sprachen)){
        $belegsprache = $sprachen[$belegsprache];
      }
      $uebersetztername = $this->app->DB->Select("SELECT name FROM artikel_texte WHERE artikel='$artikelporto' AND sprache='$belegsprache' AND aktiv='1' AND (shop=0 OR shop='$shop') ORDER BY shop DESC LIMIT 1");
      if($uebersetztername != ''){
        $versandname = $uebersetztername;
      }

      $rabattartikel = $shopexportArr['artikelrabatt'];
      $rabattname = '';
      if(isset($warenkorb['kunde_sprache']) && $warenkorb['kunde_sprache']){
        if($warenkorb['kunde_sprache'] === 'englisch') {
          $rabattname = (String)$this->app->DB->Select("SELECT name_en FROM artikel WHERE id = '$rabattartikel'");
        }
      }
      else{
        if($this->app->DB->Select("SELECT adr.id FROM $doctype auf INNER JOIN adresse adr ON auf.adresse = adr.id AND adr.sprache = 'englisch' WHERE auf.id = '$auftrag' LIMIT 1")) {
          $rabattname = (String)$this->app->DB->Select("SELECT name_en FROM artikel WHERE id = '$rabattartikel'");
        }
      }
      if($rabattname === ''){
        $rabattname = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id = '$rabattartikel'");
      }
      $uebersetztername = $this->app->DB->Select("SELECT name FROM artikel_texte WHERE artikel='$rabattartikel' AND sprache='$belegsprache' AND aktiv='1' AND (shop=0 OR shop='$shop') ORDER BY shop DESC LIMIT 1");
      if($uebersetztername != ''){
        $rabattname = $uebersetztername;
      }

      $umsatzsteuer_rabatt = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id='$rabattartikel' LIMIT 1");


      $rabattsteuer = $this->app->DB->Select("SELECT artikelrabattsteuer FROM shopexport WHERE id = '$shop' LIMIT 1");
      if($this->app->DB->error()){
        $rabattsteuer = -1;
      }
      if(isset($warenkorb['rabattsteuer']) && is_numeric($warenkorb['rabattsteuer'])){
        $rabattsteuer = $warenkorb['rabattsteuer'];
      }
      //$this->DumpVar("Fall Porto Preis ".$warenkorb[versandkostennetto]);
      if(!empty($warenkorb['rabattname'])){
        $rabattname = $warenkorb['rabattname'];
      }
      if(isset($warenkorb['rabattnetto']))
      {
        $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $rabattartikel,1,$rabattname,$warenkorb['rabattnetto'],$umsatzsteuer_rabatt,0,$waehrung);
      }elseif(isset($warenkorb['rabattbrutto']))
      {
        $rabattbrutto = $warenkorb['rabattbrutto'];
        if(isset($warenkorb['rabattsteuer']) && is_numeric($warenkorb['rabattsteuer'])){
          $rabattsteuer = $warenkorb['rabattsteuer'];
        }
        if($warenkorb['steuerfrei'] == '1') {
          $rabattsteuer = 0;
        }
        if($umsatzsteuer_rabatt==='ermaessigt')
        {
          $rabattsteuerAdd = $rabattsteuer < 0?$this->GetSteuersatzErmaessigt(true,$auftrag,$doctype):(1+$rabattsteuer/100);
          $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $rabattartikel,1,$rabattname,$warenkorb['rabattbrutto']/$rabattsteuerAdd,$umsatzsteuer_rabatt,0,$waehrung);
        }elseif($umsatzsteuer_rabatt==='befreit')
        {
          $rabattsteuerAdd = $rabattsteuer < 0?1:(1+$rabattsteuer/100);
          $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $rabattartikel,1,$rabattname,$warenkorb['rabattbrutto']/$rabattsteuerAdd,$umsatzsteuer_rabatt,0,$waehrung);
        }else{
          $rabattsteuerAdd = $rabattsteuer < 0?$this->GetSteuersatzNormal(true,$auftrag,$doctype):(1+$rabattsteuer/100);
          $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $rabattartikel,1,$rabattname,$warenkorb['rabattbrutto']/$rabattsteuerAdd,$umsatzsteuer_rabatt,0,$waehrung);
        }
      }
      if($rabattsteuer >= 0){
        $this->app->DB->Update("UPDATE $doctype"."_position SET steuersatz = '$rabattsteuer' WHERE id = '$tmpposid' LIMIT 1");
      }
      if(isset($warenkorb['rabattsteuer']) && is_numeric($warenkorb['rabattsteuer'])){
        $this->app->DB->Update("UPDATE $doctype"."_position SET steuersatz = '".$warenkorb['rabattsteuer']."' WHERE id = '$tmpposid' LIMIT 1");
        if($warenkorb['rabattsteuer'] > 0){
          $ermaessigt = !empty($warenkorb['steuersatz_ermaessigt']) ? $warenkorb['steuersatz_ermaessigt'] : $this->app->DB->Select("SELECT steuersatz_ermaessigt FROM $doctype WHERE id = $auftrag");
          $normal = !empty($warenkorb['steuersatz_normal']) ? $warenkorb['steuersatz_normal'] : $this->app->DB->Select("SELECT steuersatz_normal FROM $doctype WHERE id = $auftrag");
          if($warenkorb['rabattsteuer'] == $ermaessigt){
            $this->app->DB->Update("UPDATE $doctype" . "_position SET umsatzsteuer = 'ermaessigt' WHERE id = '$tmpposid' LIMIT 1");
          }elseif($warenkorb['rabattsteuer'] == $normal){
            $this->app->DB->Update("UPDATE $doctype" . "_position SET umsatzsteuer = 'normal' WHERE id = '$tmpposid' LIMIT 1");
          }
        }elseif($warenkorb['rabattsteuer'] == 0)
        {
          $this->app->DB->Update("UPDATE $doctype" . "_position SET umsatzsteuer = 'befreit' WHERE id = '$tmpposid' LIMIT 1");
        }
      }
      if($umsatzsteuer_porto!=='ermaessigt') {
        $umsatzsteuer_porto='normal';
      }
      $umsatzsteuer_porto2 = $umsatzsteuer_porto;
      if(!empty($warenkorb['portosteuersatz']) && $artikelnachnahme_extraartikel!='1' && $warenkorb['portosteuersatz'] === 'ermaessigt')
      {
        $umsatzsteuer_porto2 = 'ermaessigt';
      }elseif(!empty($warenkorb['portosteuersatz']) && $artikelnachnahme_extraartikel!='1' && $warenkorb['portosteuersatz'] === 'normal')
      {
        $umsatzsteuer_porto2 = 'normal';
      }

      //if($this->Steuerbefreit($warenkorb['land'],$warenkorb['ustid']))
      if($warenkorb['versandkostennetto'] != 0 || $warenkorb['versandkostenbrutto'] != 0 || $portocheck == 1)
      {
        if($warenkorb['steuerfrei']=='1')
        {
          if($artikelnachnahme_extraartikel=='1'){
            $tmpposid = $this->AddPositionManuellPreis($doctype, $auftrag, $artikelporto, 1, $versandname, (isset($warenkorb['versandkostennetto']) ? $warenkorb['versandkostennetto'] : $warenkorb['versandkostenbrutto']) - $nachnahmepreis, $umsatzsteuer_porto, 0, $waehrung);
          }
          else{
            $tmpposid = $this->AddPositionManuellPreis($doctype, $auftrag, $artikelporto, 1, $versandname, isset($warenkorb['versandkostennetto']) ? $warenkorb['versandkostennetto'] : $warenkorb['versandkostenbrutto'], $umsatzsteuer_porto, 0, $waehrung);
          }
        }
        else
        {
          if($positionsteuersaetzeerlauben && isset($warenkorb['versandkostensteuersatz']) && is_numeric($warenkorb['versandkostensteuersatz']))
          {
            if($artikelnachnahme_extraartikel=='1')
            {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']/(1+$warenkorb['versandkostensteuersatz']/100)))- $nachnahmepreis,$umsatzsteuer_porto,0,$waehrung);
            } else {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']/(1+$warenkorb['versandkostensteuersatz']/100))),$umsatzsteuer_porto,0,$waehrung);
            }
            if($tmpposid)
            {
              $this->app->DB->Update("UPDATE $doctype"."_position SET steuersatz = ".$warenkorb['versandkostensteuersatz']." WHERE id = ".$tmpposid);
            }
          }elseif($umsatzsteuer_porto2==='ermaessigt')
          {
            if($artikelnachnahme_extraartikel=='1')
            {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']/$this->GetSteuersatzErmaessigt(true,$auftrag,$doctype)))- $nachnahmepreis,$umsatzsteuer_porto,0,$waehrung);
            } else {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']/$this->GetSteuersatzErmaessigt(true,$auftrag,$doctype))),$umsatzsteuer_porto,0,$waehrung);
              if($umsatzsteuer_porto2 !== $umsatzsteuer_porto)
              {
                $this->app->DB->Update("UPDATE $doctype"."_position SET umsatzsteuer = 'ermaessigt' WHERE id = ".$tmpposid);
              }
            }
          }elseif($umsatzsteuer_porto==='befreit'){
            if($artikelnachnahme_extraartikel=='1')
            {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']))- $nachnahmepreis,$umsatzsteuer_porto,0,$waehrung);
            } else {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto'])),$umsatzsteuer_porto,0,$waehrung);
            }
          } else {
            //normal
            if($artikelnachnahme_extraartikel=='1')
            {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']/$this->GetSteuersatzNormal(true,$auftrag,$doctype)))- $nachnahmepreis,$umsatzsteuer_porto,0,$waehrung);
            } else {
              $tmpposid = $this->AddPositionManuellPreis($doctype,$auftrag, $artikelporto,1,$versandname,
                          (isset($warenkorb['versandkostennetto'])?$warenkorb['versandkostennetto']:($warenkorb['versandkostenbrutto']/$this->GetSteuersatzNormal(true,$auftrag,$doctype))),$umsatzsteuer_porto,0,$waehrung);
              if($umsatzsteuer_porto2 !== $umsatzsteuer_porto)
              {
                $this->app->DB->Update("UPDATE $doctype"."_position SET umsatzsteuer = 'normal' WHERE id = ".$tmpposid);
              }
            }
          }
        }
      }

      // wenn versandkostennbrutto = 0 und versandkostennetto > 0 TODO neu ausrechnen

      if($tmpposid>0)
      {
        $this->app->DB->Update("UPDATE $doctype"."_position SET keinrabatterlaubt=1 WHERE id='$tmpposid' LIMIT 1");
        if(isset($warenkorb['versandkostenbeschreibung'])){
          $this->app->DB->Update("UPDATE $doctype" . "_position SET beschreibung='" . $this->app->DB->real_escape_string($warenkorb['versandkostenbeschreibung']) . "' WHERE id='$tmpposid' LIMIT 1");
        }
      }
    }

    if($waehrung && $waehrung !== 'EUR'){
      $this->app->DB->Update("UPDATE $doctype"."_position SET waehrung='$waehrung' WHERE $doctype='$auftrag' ");
    }

  $shoptyp='';

  if(isset($warenkorb['wawisionpreise']) && $warenkorb['wawisionpreise'])
  {
    $wpositionen = $this->app->DB->SelectArr("SELECT * FROM $doctype"."_position WHERE auftrag = '$auftrag'");
    if(!empty($wpositionen))
    {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$auftrag' LIMIT 1");
      foreach($wpositionen as $wpos)
      {
        $pr = $this->GetVerkaufspreis($wpos['artikel'], $wpos['menge'], $adresse);
        if($pr){
          $this->app->DB->Update("UPDATE $doctype"."_position SET preis = '$pr' WHERE id = '".$wpos['id']."' LIMIT 1");
        }
      }
    }
  }
  if(!empty($artikelimport)){
    $this->app->DB->Update("UPDATE $doctype"."_position set rabatt = 0, keinrabatterlaubt = 1, grundrabatt = 0, rabattsync = 1 WHERE $doctype = '$auftrag'");
  }
  if(!empty($rabattpositionen)){
    foreach ($rabattpositionen as $key => $value) {
      $this->app->DB->Update("UPDATE $doctype" . "_position SET rabatt='$value' WHERE id='$key'");
    }
  }

  // wenn reservierung aktiviert ist
  if($doctype !== 'angebot') {
    $reservierung = $this->app->DB->Select(
      sprintf(
        "SELECT pr.reservierung 
        FROM `projekt` AS `pr` 
        INNER JOIN `auftrag` AS `o` ON o.projekt = pr.id 
        WHERE o.id = %d LIMIT 1",
        $auftrag
      )
    );
    if((int)$reservierung >= 1) {
      $this->AuftragReservieren($auftrag);
    }

    $this->AuftragNeuberechnen($auftrag);
    $this->AuftragEinzelnBerechnen($auftrag);
    $this->app->DB->Update("
    UPDATE auftrag a 
    INNER JOIN adresse adr ON a.lieferant = adr.id 
    SET a.lieferantkdrnummer = if(a.lieferantennummer <> '',a.lieferantennummer,adr.lieferantennummer)
    WHERE a.lieferantkdrnummer = '' AND a.lieferantenauftrag = 1 AND a.id = '$auftrag'
    ");
    $this->app->DB->Update("
    UPDATE auftrag a 
    INNER JOIN adresse adr ON a.adresse = adr.id 
    SET a.lieferantkdrnummer = if(a.kundennummer <> '',a.kundennummer, adr.kundennummer)
    WHERE a.lieferantkdrnummer = '' AND a.lieferantenauftrag = 0 AND a.id = '$auftrag'
    ");
    if(!empty($warenkorb['auftragsstatus'])){
      if($warenkorb['auftragsstatus'] === 'abgeschlossen'){
        $this->app->DB->Update("UPDATE auftrag SET status = 'abgeschlossen', schreibschutz = 1 WHERE id = '$auftrag' LIMIT 1");
      }
      if($warenkorb['auftragsstatus'] === 'unbezahlt'){
        $this->app->DB->Insert("INSERT INTO shopimport_checkorder (shop_id, order_id, ext_order) VALUES ('$shop','$auftrag','".$warenkorb['auftrag']."')");
			$this->app->erp->AuftragProtokoll($auftrag, 'Kaufabwicklung noch nicht abgeschlossen');
      }
    }

    $this->app->DB->Update(
      "UPDATE artikel art 
      INNER JOIN auftrag_position ap ON art.id = ap.artikel AND ap.auftrag = '$auftrag' 
      SET art.cache_lagerplatzinhaltmenge = -999"
    );
    $this->app->DB->Update(
      sprintf(
        'UPDATE artikel_onlineshops AS ao
        INNER JOIN auftrag_position AS ap ON ao.artikel = ap.artikel
        SET ao.storage_cache = -999, ao.pseudostorage_cache = -999 
        WHERE ao.shop = %d AND ap.auftrag = %d',
        $shop,$auftrag
      )
    );
    $differenz = $this->app->DB->Select(
      sprintf(
        'SELECT gesamtbetragfestsetzendifferenz FROM shopexport WHERE id = %d LIMIT 1',
        (int)$shop
      )
    );
    if($this->app->DB->Select("SELECT gesamtbetragfestsetzen FROM shopexport WHERE id = '$shop' LIMIT 1"))
    {
      $gesamtsumme = $this->app->DB->Select("SELECT gesamtsumme FROM auftrag WHERE id = '$auftrag' LIMIT 1");
      if(abs($gesamtsumme - $warenkorb['gesamtsumme']) <= $differenz)
      {
        $this->app->DB->Update("UPDATE auftrag SET extsoll = '".$warenkorb['gesamtsumme']."', gesamtsumme = '".$warenkorb['gesamtsumme']."' WHERE id = '$auftrag' LIMIT 1");
      }
    }
    if(!empty($warenkorb['bestelldatum']) && strtotime($warenkorb['bestelldatum']) > 1)
    {
      $this->app->DB->Update("UPDATE auftrag SET datum = '".$this->app->DB->real_escape_string($warenkorb['bestelldatum'])."' WHERE belegnr <> '' AND id = ".$auftrag);
    }
    if(!$autoversandvonMapping &&
      $this->app->DB->Select(
        sprintf(
          'SELECT pr.deactivateautoshipping 
          FROM auftrag a 
          INNER JOIN projekt AS pr ON a.projekt = pr.id 
          WHERE a.id = %d AND a.autoversand = 1',
          $auftrag
        )
      )
    ) {
      $this->app->DB->Update(
        sprintf(
          'UPDATE auftrag SET autoversand = 0 WHERE id = %d',
          $auftrag
        )
      );
    }
    if(!empty($warenkorb['gesamtsumme'])) {
      $gesamtsumme = $this->app->DB->Select(
            sprintf(
              'SELECT gesamtsumme FROM auftrag WHERE id = %d LIMIT 1',
              $auftrag
            )
          );
      if($gesamtsumme != 0 &&
        abs(
          round((float)$warenkorb['gesamtsumme'] - (float)$gesamtsumme, 2)
        ) > round((float)$differenz, 2)
      ) {
        $this->app->DB->Update(
          sprintf(
            'UPDATE auftrag SET autoversand = 0 WHERE id = %d LIMIT 1',
            (int)$auftrag
          )
        );
        $this->AuftragProtokoll($auftrag, 'Online-Shop Differenz erkannt');
      }
    }
  }else{
    $this->AngebotNeuberechnen($auftrag);
    $this->BelegFreigabe('angebot', $auftrag);
    if(!empty($warenkorb['bestelldatum']) && strtotime($warenkorb['bestelldatum']) > 1)
    {
      $this->app->DB->Update("UPDATE angebot SET datum = '".$this->app->DB->real_escape_string($warenkorb['bestelldatum'])."' WHERE id = ".$auftrag);
    }
  }

  return array("status" => true, "auftragid" => $auftrag);
}


  function KundennummerVergeben($adresse,$projekt="")
  {
    $id = $adresse;
    $kundennummer = $this->app->DB->Select("SELECT kundennummer FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");
    $tmp_data_adresse = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");

    if($projekt=="")
      $projekt = $this->app->DB->Select("SELECT projekt FROM adresse WHERE id='$id' AND geloescht=0 LIMIT 1");

    if($kundennummer==0 || $kundennummer==""){
      // pruefe ob rolle kunden vorhanden
      $check = $this->app->DB->Select("SELECT adresse FROM adresse_rolle WHERE adresse='$id' AND subjekt='Kunde' LIMIT 1");
      if($check!="")
      {
        $kundennummer = $this->GetNextKundennummer($projekt,$tmp_data_adresse);
        $this->ObjektProtokoll("adresse",$id,"adresse_next_kundennummer","Kundennummer erhalten: $kundennummer");
        $this->app->DB->Update("UPDATE adresse SET kundennummer='$kundennummer' WHERE id='$id' AND (kundennummer='0' OR kundennummer='') LIMIT 1");
        return $kundennummer;
      }
    }
  }


  function CheckDateValidate($input="0000-00-00")
  {
    $inputa = explode('-', $input);
    if((!empty($inputa)?count($inputa):0) == 3 && strlen($inputa[1]) == 2 && strlen($inputa[2]) == 2 && strlen($inputa[0]) == 4 &&
      checkdate($inputa[1],$inputa[2],$inputa[0]))
    {
      return true;
    }

    $date_format = 'Y-m-d';

    $input = trim($input);
    $time = strtotime($input);

    $is_valid = date($date_format, $time) == $input;

    return $is_valid;
  }

  function AdresseUSTCheck($adresse)
  {
    //wenn land DE

    $land = $this->app->DB->Select("SELECT land FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    if($land ==$this->Firmendaten("land") || $land=="")
      return 0;

    foreach($this->GetUSTEU() as $euland)
    {
      if($land==$euland)
        return 1;
    }

    // alle anderen laender sind export!
    return 2;
  }


  function AutoUSTPruefung($adresse)
  {

    // schaue obs heute bereits eine pruefung gegeben hat die erfolgreich war
    $ustcheck = $this->app->DB->Select("SELECT id FROM ustprf WHERE DATE_FORMAT(datum_online,'%Y-%m-%d')=DATE_FORMAT(NOW(),'%Y-%m-%d') AND status='erfolgreich' AND adresse='$adresse' LIMIT 1");
    if($ustcheck>0 && is_numeric($ustcheck))
      return 1;


    $name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $ustid = $this->app->DB->Select("SELECT ustid FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $land = $this->app->DB->Select("SELECT land FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $ort = $this->app->DB->Select("SELECT ort FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $plz = $this->app->DB->Select("SELECT plz FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $strasse  = $this->app->DB->Select("SELECT strasse FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

    if($land==$this->Firmendaten("land") || $ustid=="") return 0;


    $ustcheck = $this->app->DB->Select("SELECT id FROM ustprf WHERE status='' AND adresse='$adresse' LIMIT 1");
    if(!($ustcheck>0 && is_numeric($ustcheck)))
    {
      $this->app->DB->Insert("INSERT INTO ustprf (id,adresse,name,ustid,land,ort,plz,rechtsform,strasse,datum_online,bearbeiter)
          VALUES('','$adresse','$name','$ustid','$land','$ort','$plz','$rechtsform','$strasse',NOW(),'".$this->app->User->GetName()."')");
      $ustprf_id = $this->app->DB->GetInsertID();
    }
    else
      $ustprf_id = $ustcheck;


    //$this->app->DB->Insert('INSERT INTO ustprf_protokoll (ustprf_id, zeit, bemerkung, bearbeiter)  VALUES ('.$ustprf_id.',"'.date("Y-m-d H:i:s").'","AUTO Pr&uuml;fung gestartet", "'.$this->app->User->GetName().'")');

    $ustid = str_replace(" ","",$ustid);
    $ust = $ustid;
    $result = 0;

    $UstStatus = $this->CheckUst("DE263136143", $ust, $name, $ort, $strasse, $plz, $druck="nein");
    if(is_array($UstStatus))
    {
      $tmp = new USTID();
      $msg = $tmp->errormessages($UstStatus['ERROR_CODE']);

      if($UstStatus['ERROR_CODE']==200)
      {
        $this->app->DB->Delete("DELETE FROM ustprf_protokoll WHERE ustprf_id='$ustprf_id' AND bemerkung='UST g&uuml;ltig aber Name, Ort oder PLZ wird anders geschrieben'");
        $this->app->DB->Insert('INSERT INTO ustprf_protokoll (ustprf_id, zeit, bemerkung, bearbeiter)  VALUES ('.$ustprf_id.',"'.date("Y-m-d H:i:s").'","UST g&uuml;ltig aber Name, Ort oder PLZ wird anders geschrieben", "'.$this->app->User->GetName().'")');
      }
      else
        $this->app->DB->Insert('INSERT INTO ustprf_protokoll (ustprf_id, zeit, bemerkung, bearbeiter)  VALUES ('.$ustprf_id.',"'.date("Y-m-d H:i:s").'","'.$UstStatus['ERROR_CODE'].'('.$msg.')", "'.$this->app->User->GetName().'")');

    } else if($UstStatus==1){

      //$this->app->Tpl->Set(STATUS,"<div style=\"background-color: green;\">Vollst&auml;ndig</div>");
      $result = 1;

      // jetzt brief bestellen!
      $UstStatus = $this->CheckUst("DE263136143", $ust, $firmenname, $ort, $strasse, $plz, $druck="ja");
      $this->app->DB->Insert('INSERT INTO ustprf_protokoll (ustprf_id, zeit, bemerkung, bearbeiter)  VALUES ('.$ustprf_id.',"'.date("Y-m-d H:i:s").'","Online-Abfrage OK + Brief bestellt", "'.$this->app->User->GetName().'")');
      $this->app->DB->Update('UPDATE ustprf SET datum_online=NOW(), status="erfolgreich" WHERE id='.$ustprf_id.'');
    } else {
      $this->app->DB->Insert('INSERT INTO ustprf_protokoll (ustprf_id, zeit, bemerkung, bearbeiter)  VALUES ('.$ustprf_id.',"'.date("Y-m-d H:i:s").'","'.$UstStatus.'", "'.$this->app->User->GetName().'")');
      $this->app->DB->Update('UPDATE ustprf SET datum_online=NOW(), status="allgemeiner fehler" WHERE id='.$ustprf_id.'');
    }

    return $result;
  }

  function ArtikelMindestlager($artikel)
  {
    if($artikel <= 0) {
      return 0;
    }
    // Fall ein 100R in vielen Listen dann muss man alle listen mit mindestmengen nehmen
    // Fall das ist eine
    $mindestlager =  $this->app->DB->Select("SELECT mindestlager FROM artikel WHERE id='$artikel' LIMIT 1");
    if($mindestlager > 0)
    {
      return $mindestlager;
    }
    return 0;
  }

  function AddChargeLagerOhneBewegung($artikel,$menge,$lagerplatz,$datum,$charge='',$internebemerkung='',$zid=0, $doctype = '', $doctypeid = 0, $isInterim = 0)
  {
    if($artikel <= 0) {
      return null;
    }
    $zid = (int)$zid;
    $this->app->DB->Insert("INSERT INTO lager_charge (artikel,menge,lager_platz,datum,internebemerkung,charge,zwischenlagerid) 
      VALUES ('$artikel','$menge','$lagerplatz','$datum','$internebemerkung','$charge','$zid')");
    $this->app->DB->Insert("INSERT INTO chargen_log (artikel,lager_platz,eingang,bezeichnung,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid, is_interim) 
      VALUES ('$artikel','$lagerplatz','1','$charge',NOW(),".$this->app->User->GetAdresse().",'$menge','$internebemerkung','$doctype','$doctypeid',".(int)$isInterim.")");
    $id = $this->app->DB->GetInsertID();
    $bestand = $this->app->DB->Select("SELECT ifnull(sum(menge),0) FROM lager_charge WHERE artikel = '$artikel' AND lager_platz = '$lagerplatz' AND charge = '$charge'");
    $this->app->DB->Update("UPDATE chargen_log SET bestand = '$bestand' WHERE id = '$id' LIMIT 1");
    return $id;
  }


  function AddMindesthaltbarkeitsdatumLagerOhneBewegung($artikel,$menge,$lagerplatz,$mhd,$charge='',$zid=0, $doctype = '', $doctypeid = 0, $internebemerkung = '', $adresse = 0, $isInterim = 0)
  {
    if($artikel <= 0) {
      return 0;
    }
    if (!$this->CheckDateValidate($mhd)) {
      $mhd = date('Y-m-d');
    }
    $zid = (int)$zid;
    $this->app->DB->Insert("INSERT INTO lager_mindesthaltbarkeitsdatum (artikel,menge,lager_platz,datum,internebemerkung,charge,zwischenlagerid,mhddatum) VALUES ('$artikel','$menge','$lagerplatz',NOW(),'$internebemerkung','$charge','$zid','$mhd')");
    $bestand = (float)$this->app->DB->Select("SELECT ifnull(sum(menge),0) FROM lager_mindesthaltbarkeitsdatum WHERE artikel = '$artikel' AND lager_platz = '$lagerplatz' AND mhddatum = '$mhd' AND ifnull(charge,'') = '$charge' ");
    $this->app->DB->Insert("INSERT INTO mhd_log (artikel,lager_platz,eingang,mhddatum,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid,bestand,adresse,is_interim) 
      VALUES ('$artikel','$lagerplatz','1','$mhd',NOW(),".$this->app->User->GetAdresse().",'$menge','$internebemerkung','$doctype','$doctypeid','$bestand','$adresse',".(int)$isInterim.")");
    $insid = $this->app->DB->GetInsertID();
    if($charge != '') {
      $this->app->DB->Update("UPDATE mhd_log SET charge = '$charge' WHERE id = '$insid' LIMIT 1");
    }

    return $insid;
  }


function AddChargeLager($artikel,$menge,$lagerplatz,$datum,$charge="",$internebemerkung="",$zid=0, $doctype = "", $doctypeid = 0, $adresse = 0, $isInterim = 0)
{
  if($artikel <= 0)
  {
    return;
  }
  $zid = (int)$zid;
  $this->LagerArtikelZusammenfassen($artikel, $lagerplatz);
  $this->app->DB->Insert("INSERT INTO lager_charge (artikel,menge,lager_platz,datum,internebemerkung,charge,zwischenlagerid) VALUES ('$artikel','$menge','$lagerplatz','$datum','$internebemerkung','$charge','$zid')");
  $this->app->erp->LagerEinlagern($artikel,$menge,$lagerplatz,$projekt,$internebemerkung,"","",$doctype,$doctypeid,0,0,$adresse);

  $this->Chargenlog($artikel, $lagerplatz, 1, $charge, $menge, $internebemerkung, $doctype, $doctypeid, $adresse,0, $isInterim);
  $this->LagerArtikelZusammenfassen($artikel, $lagerplatz);
}


  function AddMindesthaltbarkeitsdatumLager($artikel,$menge,$lagerplatz,$mhd,$charge="",$zid=0, $doctype = "", $doctypeid = 0)
  {
    if($artikel <= 0 || (empty($lagerplatz) && empty($zid))) {
      return 0;
    }
    $this->LagerArtikelZusammenfassen($artikel, $lagerplatz);
    if ($mhd == '' || $mhd==0 || $mhd=='0000-00-00') {
      return 0;
    }

    $this->app->DB->Insert("INSERT INTO lager_mindesthaltbarkeitsdatum (artikel,menge,lager_platz,datum,internebemerkung,charge,zwischenlagerid,mhddatum) VALUES ('$artikel','$menge','$lagerplatz',NOW(),'$internebemerkung','$charge','$zid','$mhd')");

    if(empty($lagerplatz)) {
      return 0;
    }

    if($menge > 0) {
      $this->app->DB->Insert("INSERT INTO lager_platz_inhalt (artikel,menge,lager_platz) VALUES ($artikel','$menge','$lagerplatz')");
    }

    if($charge!='') {
      $charge = ' Charge: '.$charge;
    }
    $bestand = $this->ArtikelImLagerPlatz($artikel,$lagerplatz);
    $vpe = '';
    $projekt = 0;
    $this->app->DB->Insert("INSERT INTO lager_bewegung (lager_platz, artikel, menge,vpe, eingang,zeit,referenz, bearbeiter,projekt,firma,logdatei,bestand,doctype,doctypeid)
        VALUES('$lagerplatz','$artikel','$menge','$vpe','1',NOW(),'MHD eingelagert $charge','".$this->app->User->GetName()."',
          '$projekt','".$this->app->User->GetFirma()."',NOW(),'$bestand','$doctype','$doctypeid')");
    $insId = $this->app->DB->GetInsertID();
    $this->LagerArtikelZusammenfassen($artikel, $lagerplatz);

    return $insId;
  }


function SeriennummernLog($artikel, $lagerplatz, $seriennummer, $eingang, $internebemerkung="",$zid=0,$mhd="",$charge="",$doctype="", $doctypeid=0, $adresse = 0)
{
  if(empty($lagerplatz) || (empty($seriennummer) && empty($artikel))) {
    return 0;
  }
  if($adresse == 0 && $doctypeid != 0 && $doctype != '')
  {
    $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
  }
  $this->app->DB->Insert("INSERT INTO seriennummern_log (artikel,lager_platz,eingang,bezeichnung,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid, adresse) 
    VALUES ('$artikel','$lagerplatz',$eingang,'$seriennummer',NOW(),".$this->app->User->GetAdresse().",1,'$internebemerkung','$doctype','$doctypeid','$adresse')");

  return (int)$this->app->DB->GetInsertID();
}

  function LagerEinlagerVomZwischenlager($zwischenlagerid,$menge,$regal,$projekt,$grund="",$doctype="", $doctypeid=0)
  {
    if($menge <= 0 || $regal <= 0) {
      return;
    }

    $zwischenlagerRow = $this->app->DB->SelectRow(
      sprintf(
        'SELECT * FROM zwischenlager WHERE id= %d',
        $zwischenlagerid
      )
    );
    if(empty($zwischenlagerRow) || empty($zwischenlagerRow['artikel'])) {
      return;
    }
    $artikel = $zwischenlagerRow['artikel'];
    $this->LagerArtikelZusammenfassen($artikel);
    $referenz  = $zwischenlagerRow['grund'];
    $vpe = $zwischenlagerRow['vpe'];
    $bestellung = $zwischenlagerRow['parameter'];
    $paketannahme = $zwischenlagerRow['paketannahme'];

    $this->app->DB->Insert("INSERT INTO lager_platz_inhalt (lager_platz,artikel,menge,vpe,bearbeiter,bestellung,projekt,firma,logdatei)
        VALUES ('$regal','$artikel','$menge','$vpe','".$this->app->User->GetName()."','$bestellung','$projekt','".$this->app->User->GetFirma()."',NOW())");

    $bestand = $this->ArtikelImLagerPlatz($artikel,$regal);
    // Bewegung
    $this->app->DB->Insert("INSERT INTO lager_bewegung (lager_platz, artikel, menge,vpe, eingang,zeit,referenz, bearbeiter,projekt,firma,logdatei,bestand,paketannahme,doctype,doctypeid)
        VALUES('$regal','$artikel','$menge','$vpe','1',NOW(),'$referenz:$grund','".$this->app->User->GetName()."','$projekt','".$this->app->User->GetFirma()."',NOW(),'$bestand','$paketannahme','$doctype','$doctypeid')");

    $this->app->DB->Update("UPDATE lager_seriennummern SET lager_platz='$regal',zwischenlagerid='0' WHERE zwischenlagerid='$zwischenlagerid'");
    $this->app->DB->Update("UPDATE lager_mindesthaltbarkeitsdatum SET lager_platz='$regal',zwischenlagerid='0' WHERE zwischenlagerid='$zwischenlagerid'");
    $this->app->DB->Update("UPDATE lager_charge SET lager_platz='$regal',zwischenlagerid='0' WHERE zwischenlagerid='$zwischenlagerid'");

    $menge_db = $zwischenlagerRow['menge'];
    if($menge_db - $menge > 0) {
      $tmp = $menge_db - $menge;
      $this->app->DB->Update("UPDATE zwischenlager SET menge='$tmp' WHERE id='$zwischenlagerid' LIMIT 1");
    }
    else {
      $this->app->DB->Update("DELETE FROM zwischenlager WHERE id='$zwischenlagerid' LIMIT 1");
    }
    $this->LagerArtikelZusammenfassen($artikel);
  }


  function LagerAutoAuslagernArtikel($artikel,$menge,$grund, $doctype = "", $doctypeid = 0, $posid = 0, $projektueberschreiben = "")
  {
    $this->LagerArtikelZusammenfassen($artikel);
    $artikelArr = $this->app->DB->SelectRow("SELECT * FROM artikel WHERE id='$artikel' LIMIT 1");
    $lager_platz = $artikelArr['lager_platz'];
    $projekt = $artikelArr['projekt'];
    if($projektueberschreiben != ''){
      $projekt = $projektueberschreiben;
    }

    $mindesthaltbarkeitsdatum = $artikelArr['mindesthaltbarkeitsdatum'];
    $chargenverwaltung = $artikelArr['chargenverwaltung'];

    if($lager_platz > 0){
      $tmparr = $this->app->DB->SelectArr("SELECT lager_platz,menge FROM lager_platz_inhalt WHERE artikel='$artikel' ORDER by lager_platz='$lager_platz' DESC, menge DESC");
    }
    else{
      $tmparr = $this->app->DB->SelectArr("SELECT lager_platz,menge FROM lager_platz_inhalt WHERE artikel='$artikel' ORDER by menge DESC");
    }

    $mhdchargemengen = null;

    // build common array
    $ctmparr = !empty($tmparr)?count($tmparr):0;
    for($i=0;$i<$ctmparr;$i++)
    {
      $lager_platz_id[] = array('lager_platz'=>$tmparr[$i]['lager_platz'],'menge'=>$tmparr[$i]['menge']);
      if($mindesthaltbarkeitsdatum) {
        if(!isset($mhdchargemengen[$tmparr[$i]['lager_platz']]))
        {
          $mhdchargemengen[$tmparr[$i]['lager_platz']] = $this->app->DB->Select("SELECT ifnull(sum(menge),0) FROM lager_mindesthaltbarkeitsdatum WHERE artikel = '$artikel' AND lager_platz = '".$tmparr[$i]['lager_platz']."'");
        }
      }elseif($chargenverwaltung) {
        if(!isset($mhdchargemengen[$tmparr[$i]['lager_platz']])) {
          $mhdchargemengen[$tmparr[$i]['lager_platz']] = $this->app->DB->Select("SELECT ifnull(sum(menge),0) FROM lager_charge WHERE artikel = '$artikel' AND lager_platz = '".$tmparr[$i]['lager_platz']."'");
        }
      }
    }
    // auslagern mit mhd/chargen
    if($mindesthaltbarkeitsdatum || $chargenverwaltung)
    {
      $clager_platz_id = !empty($lager_platz_id)?count($lager_platz_id):0;
      for($i=0;$i < $clager_platz_id;$i++)
      {
        if($menge <= 0)
        {
          return;
        }
        if(!isset($mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']]))
        {
          continue;
        }
        if($lager_platz_id[$i]['menge'] <= 0)
        {
          continue;
        }

        if($lager_platz_id[$i]['menge']>=$menge)
        {
          if($mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']] >= $menge)
          {
            // in dem regal ist genug restmenge nehmen
            $this->LagerAuslagernRegal($artikel,$lager_platz_id[$i]['lager_platz'],$menge,$projekt,$grund, $doctype, $doctypeid);
            $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_platz_id[$i]['lager_platz'],$menge,$projekt,$grund, "", $doctype, $doctypeid,$posid);
            $menge = 0;
            return;
          }else{
            $this->LagerAuslagernRegal($artikel,$lager_platz_id[$i]['lager_platz'],$mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']],$projekt,$grund, $doctype, $doctypeid);
            $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_platz_id[$i]['lager_platz'],$mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']],$projekt,$grund, "",$doctype, $doctypeid,$posid);
            $menge = round($menge - $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']],8);
            $lager_platz_id[$i]['menge'] = round($lager_platz_id[$i]['menge'] - $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']], 8);
            $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']] = 0;
          }
        } else {
          if($mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']] >= $lager_platz_id[$i]['menge'])
          {
            $this->LagerAuslagernRegal($artikel,$lager_platz_id[$i]['lager_platz'],$lager_platz_id[$i]['menge'],$projekt,$grund, $doctype, $doctypeid);
            $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_platz_id[$i]['lager_platz'],$lager_platz_id[$i]['menge'],$projekt,$grund, "",$doctype, $doctypeid,$posid);
            $menge = round($menge - $lager_platz_id[$i]['menge'],8);
            $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']] = round($mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']] - $lager_platz_id[$i]['menge'],8);
            $lager_platz_id[$i]['menge'] = 0;
          }else{
            $this->LagerAuslagernRegal($artikel,$lager_platz_id[$i]['lager_platz'],$mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']],$projekt,$grund, $doctype, $doctypeid);
            $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_platz_id[$i]['lager_platz'],$mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']],$projekt,$grund, "",$doctype, $doctypeid,$posid);
            $lager_platz_id[$i]['menge'] = round($lager_platz_id[$i]['menge'] - $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']], 8);
            $menge = round($menge - $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']], 8);
            $mhdchargemengen[$lager_platz_id[$i]['menge']['lager_platz']] = 0;
          }
        }
      }
    }

    //auslagern ohne mhd/charge
    $clager_platz_id = !empty($lager_platz_id)?count($lager_platz_id):0;
    for($i=0;$clager_platz_id;$i++)
    {
      if($menge <= 0)
      {
        return;
      }
      if($lager_platz_id[$i]['menge'] <= 0)
      {
        continue;
      }
      //$regal = $this->app->DB->Select("SELECT lager_platz FROM lager_platz_inhalt WHERE id='".$lager_platz_id[$i]['id']."' LIMIT 1");
      if($lager_platz_id[$i]['menge']>=$menge)
      {
        // in dem regal ist genug restmenge nehmen
        $this->LagerAuslagernRegal($artikel,$lager_platz_id[$i]['lager_platz'],$menge,$projekt,$grund, $doctype, $doctypeid);
        $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_platz_id[$i]['lager_platz'],$menge,$projekt,$grund, "", $doctype, $doctypeid,$posid);
        $menge = 0;
        return;
      } else {
        // komplettes regal und menge abziegen
        $this->LagerAuslagernRegal($artikel,$lager_platz_id[$i]['lager_platz'],$lager_platz_id[$i]['menge'],$projekt,$grund, $doctype, $doctypeid);
        $this->LagerAuslagernRegalMHDCHARGESRN($artikel,$lager_platz_id[$i]['lager_platz'],$lager_platz_id[$i]['menge'],$projekt,$grund, "",$doctype, $doctypeid,$posid);
        $menge = round($menge - $lager_platz_id[$i]['menge'],8);
      }
    }
    //$this->LagerArtikelZusammenfassen($artikel);
  }

  function GetVPEBezeichnung($vpeid)
  {
    if($vpeid <= 0)
    {
      return '';
    }
    return (String)$this->app->DB->Select("SELECT concat(' (VPE Menge: ',".$this->FormatMenge('menge').",' Gewicht: ',".$this->FormatMenge('gewicht').",' Abmessung: ',".$this->FormatMenge('breite').",' x ',".$this->FormatMenge('laenge').",' x ',".$this->FormatMenge('hoehe').",')') FROM `lager_platz_vpe` WHERE id = '$vpeid' LIMIT 1");
  }

  function LagerAuslagernRegal($artikel,$regal,$menge,$projekt,$grund,$importer="", $doctype = "", $doctypeid = 0, $lager_platz_vpe = 0, $lpiid = 0)
  {
    if(!$artikel)
    {
      return -1;
    }
    $break = false;
    $this->RunHook('LagerAuslagernRegal_before',8, $artikel, $menge, $regal, $projekt, $grund, $doctype,$doctypeid, $break);
    if($break)return;

    $this->LagerArtikelZusammenfassen($artikel, $regal);

    if($importer==1)
      $username = "Import";
    else{
      if(!empty($this->app->User) && method_exists($this->app->User,'GetName')){
        $username = $this->app->DB->real_escape_string($this->app->User->GetName());
      }else{
        $username = 'Cronjob';
      }
    }

    // abbrechen wenn es nicht so ist!
    $bestand = $this->ArtikelImLagerPlatz($artikel,$regal);

    if($menge > $bestand || $bestand <=0) return -1;

  if($menge > 0)
  {
    $subwhere = "";
    $vpe_found = false;
    if($lager_platz_vpe > 0)
    {
      $check = $this->app->DB->Select("SELECT id FROM lager_platz_inhalt WHERE lager_platz_vpe = '$lager_platz_vpe' AND menge >= $menge AND  artikel='$artikel' AND lager_platz='$regal' ORDER BY id = '$lpiid' DESC LIMIT 1");
      if($check)
      {
        $vpe_found = true;
        $subwhere = " AND id = '$check' ";
      }
    }else{
      $check = $this->app->DB->Select("SELECT id FROM lager_platz_inhalt WHERE lager_platz_vpe = '0' AND menge >= $menge AND  artikel='$artikel' AND lager_platz='$regal' LIMIT 1");
      if($check)
      {
        $subwhere = " AND id = '$check' ";
      }
    }
    if($check)
    {
      // lager in diesem Regal anpassen
      if($vpe_found)$grund .= $this->GetVPEBezeichnung($lager_platz_vpe);
      $this->app->DB->Update("UPDATE lager_platz_inhalt SET menge=menge-$menge WHERE artikel='$artikel' AND lager_platz='$regal' $subwhere LIMIT 1");
      $this->app->DB->Delete(
        sprintf(
          'DELETE FROM `lager_platz_inhalt` WHERE `id` = %d AND `menge` <= 0 AND `lager_platz_vpe` <= 0',
          $check
        )
      );
      // Bewegung buchen
      $bestand = $this->ArtikelImLagerPlatz($artikel,$regal);
      $this->app->DB->Insert("INSERT INTO lager_bewegung (id,lager_platz,artikel,menge,vpe,eingang,zeit,referenz,bearbeiter,projekt,firma,bestand,doctype,doctypeid) VALUES
          ('','$regal','$artikel','$menge','','0',NOW(),'$grund','" . $username. "','$projekt','','$bestand','$doctype','$doctypeid')");
    }else{
      $lpis = $this->app->DB->SelectArr("SELECT id, menge,lager_platz_vpe FROM lager_platz_inhalt WHERE artikel = '$artikel' AND lager_platz='$regal' ORDER BY ".($lager_platz_vpe && $lpiid?" id = '$lpiid' DESC, ":'')." lager_platz_vpe = '$lager_platz_vpe' DESC, id");
      if($lpis)
      {
        $vpemengen = null;
        $_menge = $menge;
        foreach($lpis as $v)
        {
          if($_menge <= 0)break;
          if($_menge < $v['menge'])
          {
            if(!isset($vpemengen[$v['lager_platz_vpe']]))$vpemengen[$v['lager_platz_vpe']] = 0;
            $vpemengen[$v['lager_platz_vpe']] += $_menge;
            $this->app->DB->Update("UPDATE lager_platz_inhalt SET menge=menge-$_menge WHERE id = '".$v['id']."' LIMIT 1");
            $this->app->DB->Delete(sprintf('DELETE FROM `lager_platz_inhalt` WHERE `id` = %d AND `menge` <= 0', $v['id']));
            $_menge = 0;
            break;
          }elseif($_menge == $v['menge'])
          {
            if(!isset($vpemengen[$v['lager_platz_vpe']]))$vpemengen[$v['lager_platz_vpe']] = 0;
            $vpemengen[$v['lager_platz_vpe']] += $_menge;
            $this->app->DB->Delete("DELETE FROM lager_platz_inhalt WHERE id = '".$v['id']."' LIMIT 1");
            $_menge = 0;
            break;
          }elseif($v['menge'] < $_menge)
          {
            if(!isset($vpemengen[$v['lager_platz_vpe']]))$vpemengen[$v['lager_platz_vpe']] = 0;
            $vpemengen[$v['lager_platz_vpe']] += $v['menge'];
            $this->app->DB->Delete("DELETE FROM lager_platz_inhalt WHERE id = '".$v['id']."' LIMIT 1");
            $_menge = round($_menge - $v['menge'],8);
          }
        }
        if($_menge > 0)$menge -= $_menge;
        if($menge > 0)
        {
          $bestand = $this->ArtikelImLagerPlatz($artikel,$regal);
          $bestandalt = round($bestand + $menge,8);

          foreach($vpemengen as $vpeid => $m)
          {
            $bestandalt = round($bestandalt - $m, 8);
            $_grund = $grund;
            if($vpeid)$_grund = $grund . $this->GetVPEBezeichnung($vpeid);
            $this->app->DB->Insert("INSERT INTO lager_bewegung (id,lager_platz,artikel,menge,vpe,eingang,zeit,referenz,bearbeiter,projekt,firma,bestand,doctype,doctypeid) VALUES
                ('','$regal','$artikel','$m','','0',NOW(),'$_grund','" . $username. "','$projekt','','$bestandalt','$doctype','$doctypeid')");
          }
        }
      }
    }
  }
  else
  {
    $this->Protokoll("Menge $menge fuer Artikel $artikel und lager_platz $regal konnte nicht entnommen werden");
  }

    $this->LagerArtikelZusammenfassen($artikel, $regal);
    $this->RunHook('LagerAuslagernRegal_after',7, $artikel, $menge, $regal, $projekt, $grund, $doctype,$doctypeid);
    $this->app->DB->Update(sprintf('UPDATE `artikel`SET `laststorage_changed` = NOW() WHERE `id` = %d', $artikel));
    return 1;
  }

  function AddBaugruppenChargeMHD($id, $artikel, $anzahl, $chargennummer,$mhd = '')
  {
    $bezeichnung = "";
    $kommentar = "";
    $typ = "";
    $this->app->DB->Insert("INSERT INTO produktion_charge (bezeichnung, kommentar, artikel, produktion,typ,anzahl,chargennummer,mhd,bearbeiter) VALUES ('$bezeichnung','$kommentar','$artikel','$id','$typ','$anzahl','$chargennummer','$mhd','".$this->app->DB->real_escape_string($this->app->User->GetName())."')");
    echo $this->app->DB->error();
    $newid = $this->app->DB->GetInsertID();
    $baugruppen = $this->app->DB->SelectArr("SELECT pb.id, ifnull(count(pbc.id),0) as co FROM produktion_baugruppen pb 
    LEFT JOIN produktion_baugruppen_charge pbc ON pbc.baugruppe = pb.id
    WHERE pb.produktion = '$id'
    GROUP BY pb.id ORDER by count(pbc.id), pb.id
    ");
    if($baugruppen)
    {
      $ind = 0;
      foreach($baugruppen as $baugruppe)
      {
        $ind+=$mengeprobaugruppe;
        $_mengebaugruppe = $mengeprobaugruppe;
        if($anzahl && $ind >= $anzahl)$_mengebaugruppe -= $ind - $anzahl;
        if($_mengebaugruppe > 0)$this->app->DB->Insert("INSERT INTO produktion_baugruppen_charge (produktion, baugruppe, charge, chargennummer,mhd,bearbeiter, menge) values ('$id','".$baugruppe['id']."','$newid','$chargennummer','$mhd','".$this->app->DB->real_escape_string($this->app->User->GetName())."','$_mengebaugruppe')");
        if($anzahl && $ind >= $anzahl)break;
      }
    }
  }

function ChargenMHDAuslagern($artikel, $menge, $lagerplatztyp, $lpid,$typ,$wert, $fifo=0, $projekt=0, $grund="",$doctype="",$doctypeid)
{
  $mindesthaltbarkeitsdatum = $this->app->DB->Select("SELECT mindesthaltbarkeitsdatum FROM artikel WHERE id = '$artikel' LIMIT 1");
  $chargenverwaltung = $this->app->DB->Select("SELECT chargenverwaltung FROM artikel WHERE id = '$artikel' LIMIT 1");
  $subwhere = '';
  $join = '';
  $sperrlagerWhere = ' lp.sperrlager <> 1 ';
  if($doctype === 'produktion') {
    $sperrlagerWhere = ' (lp.sperrlager <> 1 OR lp.allowproduction = 1) ';
  }
  switch($lagerplatztyp)
  {
    case 'lagerplatz':
      if($lpid) {
        $subwhere = " AND c.lager_platz = '$lpid' ";
      }
    break;
    case 'lager':
      if($lpid) {
        $join = " INNER JOIN lager_platz lp ON c.lager_platz = lp.id AND lp.lager = '$lpid' AND  ".$sperrlagerWhere;
      }
    break;
    case 'projektlager':
      if($projekt) {
        $join = " INNER JOIN lager_platz lp ON c.lager_platz = lp.id AND lp.projekt = '$projekt' AND ".$sperrlagerWhere;
      }
    break;
    case "poslager":
      if($lpid) {
        $join = " INNER JOIN lager_platz lp ON c.lager_platz = lp.id AND lp.lager = '$lpid' AND lp.poslager = 1";
      }
    break;
  }
  switch($typ)
  {
    case 'mhdcharge':
    case 'mhd':
      if(!$mindesthaltbarkeitsdatum || !$chargenverwaltung)return false;

      if($typ == 'mhdcharge')
      {
        $mhdcharge = $wert;
        if($mhdcharge && strlen($mhdcharge) > 10)
        {
          $mhd = substr($mhdcharge, 0,10);
          if(strpos($mhd,'.') !== false)
          {
            $mhd = $this->app->String->Convert($mhd,"%1.%2.%3","%3-%2-%1");
          }
          $mhdcharge = substr($mhdcharge, 11);
        }
      }else{
        $mhd = $wert;
        $mhdcharge = "";
      }

      $checkarr = $this->app->DB->SelectArr("SELECT c.* FROM lager_mindesthaltbarkeitsdatum c $join WHERE c.artikel = '$artikel' $subwhere ORDER BY mhddatum = '$mhd' DESC, ".($mhdcharge != ''?"charge= '$mdhcharge' DESC,":"")." mhddatum,charge, id ");
      if($checkarr)
      {
        $nochmenge = $menge;
        foreach($checkarr as $c)
        {
          if($nochmenge <= 0)break;
          if(!$fifo && $c['mhddatum'] != $mhd)break;
          if($nochmenge >= $c['menge'])
          {
            if($doctype == 'produktion')$this->AddBaugruppenChargeMHD($doctypeid, $artikel, $c['menge'], $c['charge'],$c['mhddatum']);
            $this->app->DB->Delete("DELETE FROM `lager_mindesthaltbarkeitsdatum` WHERE id = '".$c['id']."' LIMIT 1");
            if($chargenverwaltung)
            {
              $checkchargen = $this->app->DB->SelectArr("SELECT * FROM lager_charge WHERE artikel = '$artikel' AND lager_platz = '$lager_platz' AND charge = '".$c['charge']."' ORDER BY id ");
              if($checkchargen)
              {
                $cnochmenge = $c['menge'];
                foreach($checkchargen as $cc)
                {
                  if($cnochmenge <= 0)break;
                  if($cc['menge'] <= $cnochmenge)
                  {
                    $this->app->DB->Delete("DELETE FROM lager_charge WHERE id = '".$cc['id']."' LIMIT 1");
                    $cnochmenge -= $cc['menge'];
                  }else{
                    $this->app->DB->Update("UPDATE lager_mindesthaltbarkeitsdatum SET menge = menge - '".$cnochmenge."' WHERE  id = '".$cc['id']."' LIMIT 1");
                    break;
                  }
                }
              }
            }
            $nochmenge -= $c['menge'];
          }else{
            if($doctype == 'produktion')$this->AddBaugruppenChargeMHD($doctypeid, $artikel, $nochmenge, $c['charge'],$c['mhddatum']);
            $this->app->DB->Update("UPDATE lager_charge SET menge = menge - '".$nochmenge."' WHERE  id = '".$c['id']."' LIMIT 1");
            if($chargenverwaltung)
            {
              $checkchargen = $this->app->DB->SelectArr("SELECT * FROM lager_charge WHERE artikel = '$artikel' AND lager_platz = '$lager_platz' AND charge = '".$c['charge']."' ORDER BY id ");
              if($checkchargen)
              {
                $cnochmenge = $nochmenge;
                foreach($checkchargen as $cc)
                {
                  if($cnochmenge <= 0)break;
                  if($cc['menge'] <= $cnochmenge)
                  {
                    $this->app->DB->Delete("DELETE FROM lager_charge WHERE id = '".$cc['id']."' LIMIT 1");
                    $cnochmenge -= $cc['menge'];
                  }else{
                    $this->app->DB->Update("UPDATE lager_mindesthaltbarkeitsdatum SET menge = menge - '".$cnochmenge."' WHERE  id = '".$cc['id']."' LIMIT 1");
                    break;
                  }
                }
              }
            }
            $nochmenge = 0;
            break;
          }
        }
        return $menge - $nochmenge;
      }

    break;
    case 'charge':
      if(!$chargenverwaltung)return false;

      $checkarr = $this->app->DB->SelectArr("SELECT c.* FROM lager_charge c $join WHERE c.artikel = '$artikel' $subwhere ORDER BY charge = '$wert' DESC, charge, id ");
      if($checkarr)
      {
        $nochmenge = $menge;
        foreach($checkarr as $c)
        {
          if($nochmenge <= 0)break;
          if(!$fifo && $c['charge'] != $wert)break;
          if($c['menge'] <= $nochmenge)
          {
            if($doctype == 'produktion')$this->AddBaugruppenChargeMHD($doctypeid, $artikel, $c['menge'], $c['charge']);
            $this->app->DB->Delete("DELETE FROM lager_charge WHERE id = '".$c['id']."' LIMIT 1");
            $nochmenge -= $c['menge'];
          }else{
            if($doctype == 'produktion')$this->AddBaugruppenChargeMHD($doctypeid, $artikel, $nochmenge, $c['charge']);
            $this->app->DB->Update("UPDATE lager_charge SET menge = menge - $nochmenge WHERE id = '".$c['id']."' LIMIT 1");
            $nochmenge = 0;
            break;
          }
        }
        return $menge - $nochmenge;
      }
    break;
  }
  return false;
}

  function CreateBelegPositionMHDCHARGESRNArr($doctype,$doctypeid,$pos, $data, $lager_platz = 0)
  {
    if(!$data) {
      return;
    }
    $first = true;
    $sql = "INSERT INTO beleg_chargesnmhd (doctype,doctypeid,pos,type,wert,menge, type2, wert2, lagerplatz) VALUES ";
    foreach($data as $k => $v) {
      if(!$first) {
        $sql .= ', ';
      }
      $sql .= " ('$doctype','$doctypeid','$pos','".$v['type']."','".$v['wert']."','".$v['menge']."','".$v['type2']."','".$v['wert2']."','$lager_platz') ";
      $first = false;
    }
    $this->app->DB->Insert($sql);
  }

  function CreateBelegPositionMHDCHARGESRN($doctype,$doctypeid,$pos,$type,$wert,$menge=1, $type2 = "", $wert2 = "", $lager_platz = 0, $internebemerkung = '')
  {
    if($type === 'sn' && $menge == 0) {
      $menge = 1;
    }
    $this->app->DB->Insert(
      "INSERT INTO beleg_chargesnmhd (doctype,doctypeid,pos,type,wert,menge, type2, wert2) VALUES 
        ('$doctype','$doctypeid','$pos','$type','$wert','$menge','$type2','$wert2')"
    );
    $ind = $this->app->DB->GetInsertID();
    if($lager_platz) {
      $this->app->DB->Update("UPDATE beleg_chargesnmhd set lagerplatz = '".$lager_platz."' WHERE id = '$ind' LIMIT 1");
    }
    if($internebemerkung != '') {
      $this->app->DB->Update("UPDATE beleg_chargesnmhd set internebemerkung = '".$this->app->DB->real_escape_string($internebemerkung)."' WHERE id = '$ind' LIMIT 1");
    }
    if($type === 'sn') {
      $this->app->erp->SeriennummernLog($this->app->DB->Select("SELECT artikel FROM $doctype"."_position WHERE id = '$pos' LIMIT 1"), $lager_platz, $wert, 0, "",0,"","",$doctype, $doctypeid);
    }
    return $ind;
  }

  function MHDAuslagernLog($artikel, $lager_platz, $mhddatum, $charge, $menge, $internebemerkung = '', $doctype = "", $doctypeid = 0, $lager_chargenid = 0, $adresse = 0)
  {
    if($artikel <= 0 || $menge == 0) {
      return false;
    }
    if($lager_platz == 0 && $lager_chargenid == 0) {
      return false;
    }
    if(!$adresse && $doctype != '' && $doctypeid > 0) {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
    }
    if($lager_chargenid)
    {
      $arr = $this->app->DB->SelectArr("SELECT id, lager_platz, menge, charge,mhddatum FROM lager_mindesthaltbarkeitsdatum WHERE id = '$lager_chargenid' AND artikel = '$artikel' LIMIT 1");
    }else{
      $arr = $this->app->DB->SelectArr("SELECT id, lager_platz, menge, charge,mhddatum FROM lager_mindesthaltbarkeitsdatum 
        WHERE artikel = '$artikel' AND lager_platz = '$lager_platz'
        ".($mhddatum!=''?" AND mhddatum = '$mhddatum'":'')."  
        ".($charge!=''?" AND charge = '$charge'":'')." AND menge > 0");
    }
    if(!$arr) {
      return false;
    }
    foreach($arr as $v)
    {
      if($menge <= 0) {
        return true;
      }
      if($menge >= $v['menge'])
      {
        $menge -= $v['menge'];
        $this->app->DB->Delete("DELETE FROM lager_mindesthaltbarkeitsdatum WHERE id = '".$v['id']."' LIMIT 1");
        $this->MHDLog($artikel, $v['lager_platz'], 0, $v['mhddatum'], $v['menge'], $internebemerkung, $doctype, $doctypeid, $v['charge']);
      }else{
        $this->app->DB->Update("UPDATE lager_mindesthaltbarkeitsdatum SET menge = menge - $menge WHERE id = '".$v['id']."' LIMIT 1");
        $this->MHDLog($artikel, $v['lager_platz'], 0, $v['mhddatum'], $menge, $internebemerkung, $doctype, $doctypeid, $v['charge']);
        return true;
      }
    }

    return $menge <= 0;
  }

  function ChargeAuslagernLog($artikel, $lager_platz, $charge, $menge, $internebemerkung = '', $doctype = '', $doctypeid = 0, $lager_chargenid = 0, $adresse = 0, $isInterim = 0)
  {
    if($artikel <= 0 || $menge == 0) {
      return false;
    }
    if($lager_platz == 0 && $lager_chargenid == 0) {
      return false;
    }
    if(!$adresse && $doctype != '' && $doctypeid > 0) {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
    }
    if($lager_chargenid) {
      $arr = $this->app->DB->SelectArr("SELECT id, lager_platz, menge, charge FROM lager_charge WHERE id = '$lager_chargenid' AND artikel = '$artikel' LIMIT 1");
    }else{
      $arr = $this->app->DB->SelectArr("SELECT id, lager_platz, menge, charge FROM lager_charge WHERE artikel = '$artikel' AND lager_platz = '$lager_platz' AND charge = '$charge' AND menge > 0");
    }
    if(!$arr) {
      return false;
    }
    foreach($arr as $v) {
      if($menge <= 0) {
        return true;
      }
      if($menge >= $v['menge'])
      {
        $menge -= $v['menge'];
        $this->app->DB->Delete("DELETE FROM lager_charge WHERE id = '".$v['id']."' LIMIT 1");
        $this->Chargenlog($artikel, $v['lager_platz'], 0, $charge, $v['menge'], $internebemerkung, $doctype, $doctypeid, $adresse,0,$isInterim);
      }else{
        $this->app->DB->Update("UPDATE lager_charge SET menge = menge - $menge WHERE id = '".$v['id']."' LIMIT 1");
        $this->Chargenlog($artikel, $v['lager_platz'], 0, $charge, $menge, $internebemerkung, $doctype, $doctypeid, $adresse,0,$isInterim);
        return true;
      }
    }
    return $menge <= 0;
  }

  function Chargenlog($artikel, $lager_platz, $eingang, $charge, $menge, $internebemerkung = '', $doctype = "", $doctypeid = 0, $adresse = 0,$chargen_log_id = 0, $isInterim = 0)
  {
    if($artikel <= 0) {
      return null;
    }
    if(!$adresse && $doctype != '' && $doctypeid > 0) {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
    }
    $internebemerkung = $this->app->DB->real_escape_string($internebemerkung);
    $bestand = $this->app->DB->Select("SELECT ifnull(sum(menge),0) FROM lager_charge WHERE artikel = '$artikel' AND lager_platz = '$lager_platz' AND charge = '$charge'");
    $this->RunHook('chargenlog_bestand', 4, $artikel, $lager_platz, $charge, $bestand);
    if($chargen_log_id) {
      $chargen_log_id = $this->app->DB->Select("SELECT id FROM chargen_log WHERE id='$chargen_log_id' AND eingang = '$eingang' AND artikel = '$artikel' AND charge = '$charge' AND doctype = '$doctype' AND doctypeid = '$doctypeid' AND adresse = '$adresse' LIMIT 1");
    }
    if($chargen_log_id)
    {
      $this->app->DB->Update("UPDATE chargen_log SET menge = menge + $menge, bestand = '$bestand' WHERE id = '$chargen_log_id' LIMIT 1");
      return $chargen_log_id;
    }
    $this->app->DB->Insert("INSERT INTO chargen_log (artikel,lager_platz,eingang,bezeichnung,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid,bestand,adresse,is_interim) 
            VALUES ('$artikel','$lager_platz','$eingang','".$charge."',NOW(),".(int)$this->app->User->GetAdresse().",'".$menge."','$internebemerkung','$doctype','$doctypeid','$bestand','$adresse',".(int)$isInterim.")");
    return $this->app->DB->GetInsertID();
  }

  function ChargenLogArray($artikel, $lager_platz, $eingang, $data, $internebemerkung = '', $doctype = "", $doctypeid = 0, $adresse = 0)
  {
    if($artikel <= 0) {
      return;
    }
    if(!$adresse && $doctype != '' && $doctypeid > 0) {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
    }
    $internebemerkung = $this->app->DB->real_escape_string($internebemerkung);
    $sql = "INSERT INTO chargen_log (artikel,lager_platz,eingang,bezeichnung,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid,bestand,adresse) VALUES ";
    $first = true;
    $useradresse = 0;
    if(isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetAdresse')) {
      $useradresse = $this->app->User->GetAdresse();
    }
    foreach($data as $k => $v) {
      $this->RunHook('chargenlog_bestand', 4, $artikel, $lager_platz, $data[$k]['charge'], $data[$k]['bestand']);
      if(!$first) {
        $sql .= ', ';
      }
      $sql .= " ('$artikel','$lager_platz','$eingang','".$data[$k]['charge']."',NOW(),".$useradresse.",'".$data[$k]['menge']."','$internebemerkung','$doctype','$doctypeid','".$data[$k]['bestand']."','$adresse') ";
      $first = false;
    }
    $this->app->DB->Insert($sql);
  }

  function MHDLog($artikel, $lager_platz, $eingang, $mhd, $menge, $internebemerkung = '', $doctype = '', $doctypeid = 0, $charge = '', $adresse = 0, $isInterim = 0)
  {
    if($artikel <= 0) {
      return;
    }
    if(!$adresse && $doctype != '' && $doctypeid > 0) {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
    }
    $internebemerkung = $this->app->DB->real_escape_string($internebemerkung);
    $bestand = $this->app->DB->Select("SELECT ifnull(sum(menge),0) FROM lager_mindesthaltbarkeitsdatum WHERE artikel = '$artikel' AND lager_platz = '$lager_platz' AND mhddatum = '$mhd' AND ifnull(charge,'') = '$charge'");
    $this->RunHook('mhdlog_bestand', 4, $artikel, $lager_platz, $mhd, $bestand);
    $this->app->DB->Insert("INSERT INTO mhd_log (artikel,lager_platz,eingang,mhddatum,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid,bestand,adresse,is_interim) 
            VALUES ('$artikel','$lager_platz','$eingang','".$mhd."',NOW(),".(int)$this->app->User->GetAdresse().",'".$menge."','$internebemerkung','$doctype','$doctypeid','$bestand','$adresse',".(int)$isInterim.")");
    $insid = $this->app->DB->GetInsertID();
    if($charge != '') {
      $this->app->DB->Update("UPDATE mhd_log SET charge = '$charge' WHERE id = '$insid' LIMIT 1");
    }
  }

  function MHDLogArray($artikel, $lager_platz, $eingang, $data, $internebemerkung = '', $doctype = '', $doctypeid = 0, $adresse = 0)
  {
    if(empty($data)) {
      return;
    }
    $sql = "INSERT INTO mhd_log (artikel,lager_platz,eingang,mhddatum,zeit,adresse_mitarbeiter,menge,internebemerkung,doctype,doctypeid,bestand,adresse,charge) VALUES ";
    $first = true;
    foreach($data as $k => $v)
    {
      $this->RunHook('mhdlog_bestand', 4, $artikel, $lager_platz, $data[$k]['mhd'], $data[$k]['bestand']);
      if(!$first) {
        $sql .= ', ';
      }
      $sql .= "('$artikel','$lager_platz','$eingang','".$data[$k]['mhd']."',NOW(),".(int)$this->app->User->GetAdresse().",'".$data[$k]['menge']."','$internebemerkung','$doctype','$doctypeid','".$data[$k]['bestand']."','$adresse','".$data[$k]['charge']."')";
      $first = false;
    }
    $this->app->DB->Insert($sql);
  }

  public function removeBatchFromStock($articleId, $storageLocationId, $batch, $amount, $comment = '', $doctype = '', $doctypeid = 0, $docPosId = '') {
    if($articleId <= 0 || $storageLocationId <= 0 || $amount <= 0 || empty($batch)) {
      return 0;
    }
    $toRemove = $amount;
    while($toRemove > 0) {
      $this->app->erp->RunHook(
        'LagerAuslagernRegalMHDCHARGESRN_Charge',
        7,
        $articleId,
        $storageLocationId,
        $toRemove,
        $doctype,
        $doctypeid,
        $dokumentposid,
        $extraorder
      );
      $lager_chargen = $this->app->DB->SelectArr(
        sprintf(
          "SELECT id, menge, charge 
          FROM lager_charge 
          WHERE artikel=%d AND lager_platz=%d AND menge > 0 AND charge = '%s'
          ORDER BY $extraorder id 
          LIMIT %d",
          (int)$articleId, (int)$storageLocationId, $batch, ceil($toRemove)
        )
      );
      if(empty($lager_chargen)){
        break;
      }

      $chargen_log_arr = null;
      foreach ($lager_chargen as $v) {
        if($toRemove <= 0){
          break;
        }
        if($v['menge'] <= $toRemove){
          $this->app->DB->Update("UPDATE lager_charge SET menge = 0 WHERE id='" . $v['id'] . "' AND menge = '" . $v['menge'] . "' LIMIT 1");
          if($this->app->DB->affected_rows() > 0){
            $this->app->DB->Delete("DELETE FROM lager_charge WHERE id='" . $v['id'] . "' AND id > 0 LIMIT 1");
            if(!isset($chargen_log_arr['C' . $v['charge']])){
              $chargen_log_arr['C' . $v['charge']] = array('menge' => 0, 'bestand' => 0);
            }
            $chargen_log_arr['C' . $v['charge']]['menge'] += $v['menge'];
            $toRemove = round($toRemove - $v['menge'], 8);
          }else{
            break;
          }
        }elseif($toRemove > 0){
          $this->app->DB->Update("UPDATE lager_charge SET menge = menge - $toRemove WHERE id='" . $v['id'] . "' AND menge >= '$toRemove' LIMIT 1");
          if($this->app->DB->affected_rows() > 0){
            $this->app->DB->Delete("DELETE FROM lager_charge WHERE id='" . $v['id'] . "' AND id > 0 AND menge <= 0 LIMIT 1");
            if(!isset($chargen_log_arr['C' . $v['charge']])){
              $chargen_log_arr['C' . $v['charge']] = array('menge' => 0, 'bestand' => 0);
            }
            $chargen_log_arr['C' . $v['charge']]['menge'] += $toRemove;
            $toRemove = 0;
            break;
          }
          break;
        }
      }
      if($chargen_log_arr){
        $chargensqla = null;
        $bestandsql = "SELECT sum(menge) as bestand, charge FROM lager_charge WHERE  artikel='$articleId' AND lager_platz='$storageLocationId' AND menge > 0 ";
        foreach ($chargen_log_arr as $chargenkey => $arr) {
          $chargensqla[] = "'" . substr($chargenkey, 1) . "'";
        }
        $bestandsql .= " AND ifnull(charge,'') in (" . implode(', ', $chargensqla) . ")  GROUP BY  charge";
        $query = $this->app->DB->Query($bestandsql);
        if($query){
          while ($row = $this->app->DB->Fetch_Assoc($query)) {
            if(isset($chargen_log_arr['C' . $row['charge']])){
              $chargen_log_arr['C' . $row['charge']]['bestand'] = $row['bestand'];
            }
          }
        }
        $data = null;
        $data2 = null;
        foreach ($chargen_log_arr as $chargenkey => $arr) {
          $data[] = array('charge' => substr($chargenkey, 1), 'menge' => $arr['menge'], 'bestand' => $arr['bestand']);
          $data2[] = array('type' => 'charge', 'wert' => substr($chargenkey, 1), 'menge' => $arr['menge'], 'type2' => '', 'wert2' => '');
        }
        unset($chargen_log_arr);
        $this->ChargenLogArray($articleId, $storageLocationId, 0, $data, $comment, $doctype, $doctypeid);
        unset($data);
        if($doctypeid){
          $this->CreateBelegPositionMHDCHARGESRNArr($doctype, $doctypeid, $docPosId, $data2, $storageLocationId);
        }
        unset($data2);
      }

    }

    return round($amount - $toRemove, 7);
  }

  function LagerAuslagernRegalMHDCHARGESRN($artikel,$regal,$menge,$projekt,$grund,$importer="",$dokumenttyp="",$dokumentid="",$dokumentposid="", $chargenauslagern = 1, $mhdauslagern = 1, $seriennummernauslagern = 1)
  {
    $grundescaped = $this->app->DB->real_escape_string($grund);
    if($this->Verbrauchslagervorhanden())
    {
      $verbrauchslager = $this->app->DB->Select("SELECT verbrauchslager FROM lager_platz WHERE id = '$regal' LIMIT 1");
      if($verbrauchslager)$this->LagerArtikelZusammenfassen($artikel, $regal);
    }
    $artikelArr = $this->app->DB->SelectRow(
      sprintf('SELECT mindesthaltbarkeitsdatum, chargenverwaltung, seriennummern FROM artikel WHERE id= %d LIMIT 1',
        (int)$artikel
      )
    );
    $mhd = $artikelArr['mindesthaltbarkeitsdatum'];
    $chargenverwaltung = $artikelArr['chargenverwaltung'];
    $chargenverwaltung = $chargenverwaltung == 2 || $chargenverwaltung == 1;
    $seriennummern = $artikelArr['seriennummern'];

    if($seriennummernauslagern && $seriennummern==='vomprodukteinlagern') {
      if($mhd == '1') {
        $mhdauslagern = 1;
      }
      if($chargenverwaltung) {
        $chargenauslagern = 1;
      }
    }
    elseif($seriennummern==='vomprodukteinlagern' && !$seriennummernauslagern) {
      if($mhd == '1') {
        $mhdauslagern = 0;
      }
      if($chargenverwaltung) {
        $chargenauslagern = 0;
      }
    }
    elseif($mhd == '1' && $mhdauslagern && $chargenverwaltung) {
      $chargenauslagern = 1;
    }
    elseif($mhd == '1' && !$mhdauslagern && $chargenverwaltung) {
      $chargenauslagern = 0;
    }

    $mhd_menge = $menge;
    $charge_menge = $menge;
    $extraorder = '';
    if($mhd=='1' && $mhdauslagern) {
      $timeout=0;
      while($mhd_menge > 0 && $timeout < 1000) {
        $timeout++;
        $this->app->erp->RunHook('LagerAuslagernRegalMHDCHARGESRN_MHD', 7,$artikel, $regal, $menge, $dokumenttyp,$dokumentid,$dokumentposid, $extraorder);
        $lager_mindesthaltbarkeitsdatum = $this->app->DB->SelectArr(
          sprintf(
            "SELECT id,menge,mhddatum, charge 
            FROM lager_mindesthaltbarkeitsdatum 
            WHERE artikel=%d AND lager_platz=%d AND menge > 0 
            ORDER BY $extraorder mhddatum, datum 
            LIMIT %d",
            (int)$artikel, (int)$regal, ceil($mhd_menge)
          )
        );
        if($lager_mindesthaltbarkeitsdatum)
        {
          $mhd_log_arr = null;
          foreach($lager_mindesthaltbarkeitsdatum as $v)
          {
            if($mhd_menge <= 0) {
              break;
            }
            $charge_menge = 0;
            if($v['menge']<=$mhd_menge)
            {
              $this->app->DB->Update("UPDATE lager_mindesthaltbarkeitsdatum SET menge = 0 WHERE id='".$v['id']."' AND menge = '".$v['menge']."' LIMIT 1");
              if($this->app->DB->affected_rows() > 0)
              {
                $mhd_menge = round($mhd_menge - $v['menge'],8);
                $this->app->DB->Delete("DELETE FROM lager_mindesthaltbarkeitsdatum WHERE id='".$v['id']."' AND id > 0 LIMIT 1");
                if(!isset($mhd_log_arr[$v['mhddatum']]) || !isset($mhd_log_arr[$v['mhddatum']]['C'.$v['charge']]))
                {
                  $mhd_log_arr[$v['mhddatum']]['C'.$v['charge']] = array('menge'=>0, 'bestand'=>0);
                }
                $mhd_log_arr[$v['mhddatum']]['C'.$v['charge']]['menge'] += $v['menge'];

                if($chargenverwaltung) {
                  $stockedout = (float)$this->removeBatchFromStock($artikel, $regal, $v['charge'], $v['menge'], $grundescaped, $dokumenttyp, $dokumentid, $dokumentposid);
                  $charge_menge = round($charge_menge - $stockedout, 7);
                }

              }else {
                break;
              }
            }elseif($mhd_menge > 0)
            {
              $this->app->DB->Update("UPDATE lager_mindesthaltbarkeitsdatum SET menge = menge - $mhd_menge WHERE id='".$v['id']."' AND menge >= '$mhd_menge' LIMIT 1");
              if($this->app->DB->affected_rows() > 0)
              {
                $this->app->DB->Delete("DELETE FROM lager_mindesthaltbarkeitsdatum WHERE id='".$v['id']."' AND id > 0 AND menge <= 0 LIMIT 1");
                if(!isset($mhd_log_arr[$v['mhddatum']]) || !isset($mhd_log_arr[$v['mhddatum']]['C'.$v['charge']]))
                {
                  $mhd_log_arr[$v['mhddatum']]['C'.$v['charge']] = array('menge'=>0, 'bestand'=>0);
                }
                $mhd_log_arr[$v['mhddatum']]['C'.$v['charge']]['menge'] += $mhd_menge;
                if($chargenverwaltung) {
                  $stockedout = (float)$this->removeBatchFromStock($artikel, $regal, $v['charge'], $mhd_menge, $grundescaped, $dokumenttyp, $dokumentid, $dokumentposid);
                  $charge_menge = round($charge_menge - $stockedout, 7);
                }
                $mhd_menge = 0;
              }
              break;
            }
          }
          if($mhd_log_arr)
          {
            $mhdsqla = null;
            $chargensqla = null;
            $bestandsql = "SELECT sum(menge) as bestand, mhddatum, charge FROM lager_mindesthaltbarkeitsdatum WHERE  artikel='$artikel' AND lager_platz='$regal' AND menge > 0 ";
            foreach($mhd_log_arr as $mhdkey => $arr)
            {
              $mhdsqla[] = "'".$mhdkey."'";
              foreach($arr as $chargenkey => $arr2)
              {
                $chargensqla[] = "'".substr($chargenkey, 1)."'";
              }
            }
            $bestandsql .= " AND mhddatum in (".implode(', ',$mhdsqla).") AND ifnull(charge,'') in (".implode(', ', $chargensqla).")  GROUP BY mhddatum, charge";
            $query = $this->app->DB->Query($bestandsql);
            if($query)
            {
              while($row = $this->app->DB->Fetch_Assoc($query))
              {
                if(isset($mhd_log_arr[$row['mhddatum']]) && isset($mhd_log_arr[$v['mhddatum']]['C'.$row['charge']])) {
                  $mhd_log_arr[$v['mhddatum']]['C'.$row['charge']]['bestand'] = $row['bestand'];
                }
              }
            }
            $data = null;
            $data2 = null;
            foreach($mhd_log_arr as $mhdkey => $arr)
            {
              $mhdsqla[] = "'".$mhdkey."'";
              foreach($arr as $chargenkey => $arr2)
              {
                $data[] = array('mhd' => $mhdkey, 'charge'=> substr($chargenkey,1), 'menge'=>$arr2['menge'],'bestand'=>$arr2['bestand']);
                $data2[] = array('type'=>'mhd','wert'=>$mhdkey,'menge'=>$arr2['menge'],'type2'=>(substr($chargenkey,1) == ''?'':'charge'),'wert2'=>substr($chargenkey,1));
              }
            }
            unset($mhd_log_arr);
            $this->MHDLogArray($artikel, $regal, 0, $data, $grundescaped, $dokumenttyp, $dokumentid);
            unset($data);
            if($dokumentid) {
              $this->CreateBelegPositionMHDCHARGESRNArr($dokumenttyp,$dokumentid,$dokumentposid, $data2, $regal);
            }
            unset($data2);
          }
        }else {
          break;
        }
        /* 05.06.2018 Bruno Abfragen zusammengefuehrt
        */
      }
    }


    if($chargenverwaltung && $chargenauslagern)
    {
      while($charge_menge > 0)
      {
        $this->app->erp->RunHook('LagerAuslagernRegalMHDCHARGESRN_Charge', 7,$artikel, $regal, $menge, $dokumenttyp,$dokumentid,$dokumentposid, $extraorder);
        $lager_chargen = $this->app->DB->SelectArr(
          sprintf(
          "SELECT id, menge, charge 
            FROM lager_charge 
            WHERE artikel=%d AND lager_platz=%d AND menge > 0 
            ORDER BY $extraorder id 
            LIMIT %d",
            (int)$artikel, (int)$regal, ceil($menge)
          )
        );
        if($lager_chargen)
        {
          $chargen_log_arr = null;
          foreach($lager_chargen as $v)
          {
            if($charge_menge <= 0) {
              break;
            }
            if($v['menge'] <= $charge_menge)
            {
              $this->app->DB->Update("UPDATE lager_charge SET menge = 0 WHERE id='".$v['id']."' AND menge = '".$v['menge']."' LIMIT 1");
              if($this->app->DB->affected_rows() > 0)
              {
                $this->app->DB->Delete("DELETE FROM lager_charge WHERE id='".$v['id']."' AND id > 0 LIMIT 1");
                if(!isset($chargen_log_arr['C'.$v['charge']]))
                {
                  $chargen_log_arr['C'.$v['charge']] = array('menge'=>0, 'bestand'=>0);
                }
                $chargen_log_arr['C'.$v['charge']]['menge'] += $v['menge'];
                $charge_menge = round($charge_menge - $v['menge'],8);
              }else{
                break;
              }
            }elseif($charge_menge > 0)
            {
              $this->app->DB->Update("UPDATE lager_charge SET menge = menge - $charge_menge WHERE id='".$v['id']."' AND menge >= '$charge_menge' LIMIT 1");
              if($this->app->DB->affected_rows() > 0)
              {
                $this->app->DB->Delete("DELETE FROM lager_charge WHERE id='".$v['id']."' AND id > 0 AND menge <= 0 LIMIT 1");
                if(!isset($chargen_log_arr['C'.$v['charge']]))
                {
                  $chargen_log_arr['C'.$v['charge']] = array('menge'=>0, 'bestand'=>0);
                }
                $chargen_log_arr['C'.$v['charge']]['menge'] += $charge_menge;
                $charge_menge = 0;
              }
              break;
            }
          }
          if($chargen_log_arr)
          {
            $chargensqla = null;
            $bestandsql = "SELECT sum(menge) as bestand, charge FROM lager_charge WHERE  artikel='$artikel' AND lager_platz='$regal' AND menge > 0 ";
            foreach($chargen_log_arr as $chargenkey => $arr)
            {
              $chargensqla[] = "'".substr($chargenkey, 1)."'";
            }
            $bestandsql .= " AND ifnull(charge,'') in (".implode(', ', $chargensqla).")  GROUP BY  charge";
            $query = $this->app->DB->Query($bestandsql);
            if($query)
            {
              while($row = $this->app->DB->Fetch_Assoc($query))
              {
                if(isset($chargen_log_arr['C'.$row['charge']])) {
                  $chargen_log_arr['C'.$row['charge']]['bestand'] = $row['bestand'];
                }
              }
            }
            $data = null;
            $data2 = null;
            foreach($chargen_log_arr as $chargenkey => $arr)
            {
              $data[] = array('charge'=> substr($chargenkey,1), 'menge'=>$arr['menge'],'bestand'=>$arr['bestand']);
              $data2[] = array('type'=>'charge','wert'=>substr($chargenkey,1),'menge'=>$arr['menge'],'type2'=>'','wert2'=>'');
            }
            unset($chargen_log_arr);
            $this->ChargenLogArray($artikel, $regal, 0, $data, $grundescaped, $dokumenttyp, $dokumentid);
            unset($data);
            if($dokumentid) {
              $this->CreateBelegPositionMHDCHARGESRNArr($dokumenttyp,$dokumentid,$dokumentposid, $data2, $regal);
            }
            unset($data2);
          }
          unset($lager_chargen);
        }else {
          break;
        }
      }
      /*  05.06.2018 Bruno Abfragen zusammengefuehrt

      */
    }

    if($this->Verbrauchslagervorhanden())
    {
      if($verbrauchslager)$this->LagerArtikelZusammenfassen($artikel, $regal);
    }
  }


  function CreateLagerplatz($lager,$lagerplatz_name,$firma="1")
  {
    $lagerplatz_name = trim($lagerplatz_name);
    // pruefe ob es Lagerplatz bereits gibt
    $check_id = $this->app->DB->Select("SELECT id FROM lager_platz WHERE kurzbezeichnung='$lagerplatz_name' AND lager='$lager' LIMIT 1");

    if($check_id <= 0)
    {
      if($firma <= 0) $firma=1;
      $this->app->DB->Insert("INSERT INTO lager_platz (id,lager,kurzbezeichnung,firma) VALUES ('','$lager','$lagerplatz_name',$firma)");
      $check_id = $this->app->DB->GetInsertID();
    }
    return $check_id;
  }


  function LagerID($lager)
  {

    if(is_numeric($lager) && $lager > 0)
    {
      $lager = $lager + 0;
      $lager = $this->app->DB->Select("SELECT id FROM lager_platz WHERE id='$lager' LIMIT 1");
      if($lager > 0)
        return $lager;
    }

    if($lager !="")
    {
      $id = $this->app->DB->Select("SELECT id FROM lager_platz WHERE kurzbezeichnung='$lager' LIMIT 1");
      return $id;
    } else return "";
  }

  function IsArtikelInZwischenlager($artikel)
  {
    $check = $this->app->DB->Select("SELECT id FROM zwischenlager WHERE richtung='Eingang' AND artikel='$artikel' LIMIT 1");
    return $check > 0;
  }

  function ArtikelIDWennEAN($artikelnummer, $fremdnummern = false)
  {
    if($artikelnummer!="")
    {
      // artikelnummer hat hoechste Prio
      $nummer = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikelnummer' AND ifnull(geloescht,0) = 0 LIMIT 1");
      if($nummer > 0)
        return $nummer;

      // dann ean nummer
      $ean = $this->app->DB->Select("SELECT id FROM artikel WHERE ean='$artikelnummer' AND ifnull(geloescht,0) = 0 AND nummer != 'DEL' LIMIT 1");
      if($ean > 0)
        return $ean;

      // und zum Schluss Hersteller
      $herstellernummer = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer='$artikelnummer' AND ifnull(geloescht,0) = 0 AND nummer != 'DEL' LIMIT 1");
      if($herstellernummer > 0)
        return $herstellernummer;

      if($fremdnummern)
      {
        $artikel = $this->app->DB->Select("SELECT art.id FROM artikel art INNER JOIN artikelnummer_fremdnummern af ON art.id = af.artikel AND ifnull(art.geloescht,0) = 0 AND af.aktiv = 1 AND art.nummer <> 'DEL' 
        INNER JOIN shopexport s  ON af.shopid = s.id WHERE af.nummer = '$artikelnummer' LIMIT 1");
        if($artikel)
          return $artikel;
      }
/*
      $id = $this->app->DB->Select("SELECT id FROM artikel WHERE id='$artikelnummer' LIMIT 1");
      if($id > 0)
        return $id;
      else
        return 0;
*/
    }
    return 0;
  }

  function LagerEinlagern($artikel,$menge,$regal,$projekt,$grund="",$importer="",$paketannahme="",$doctype = "", $doctypeid = 0, $vpeid = 0, $permanenteinventur = 0, $adresse = 0)
  {
    if(empty($artikel) || empty($regal)){
      return;
    }
    $break = false;
    $this->RunHook('LagerEinlagern_before',8, $artikel, $menge, $regal, $projekt, $grund, $doctype,$doctypeid, $break);
    if($break) {
      return;
    }
    if(!$adresse && $doctypeid && $doctype != '') {
      $adresse = $this->app->DB->Select("SELECT adresse FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
    }
    //$this->LagerArtikelZusammenfassen($artikel);
    $vpe = 'einzeln';
    $username = 'Import';
    if($importer!=1) {
      $username = $this->app->DB->real_escape_string($this->app->User->GetName());
    }

    if($menge > 0 && is_numeric($menge)) {
      // inhalt buchen
      $this->app->DB->Insert("INSERT INTO lager_platz_inhalt (id,lager_platz,artikel,menge,vpe,bearbeiter,bestellung,projekt,firma,logdatei)
          VALUES ('','$regal','$artikel','$menge','$vpe','".$username."','','$projekt','',NOW())");
      $insid = $this->app->DB->GetInsertID();
      $bestand = $this->ArtikelImLagerPlatz($artikel,$regal);
      // Bewegung
      if($vpeid) {
        $grund .= $this->GetVPEBezeichnung($vpeid);
      }
      $this->app->DB->Insert("INSERT INTO lager_bewegung (id,lager_platz, artikel, menge,vpe, eingang,zeit,referenz, bearbeiter,projekt,firma,logdatei,bestand,paketannahme,doctype,doctypeid, permanenteinventur, adresse)
          VALUES('','$regal','$artikel','$menge','$vpe','1',NOW(),'$grund','".$username."','$projekt','',NOW(),'$bestand','$paketannahme','$doctype','$doctypeid', '$permanenteinventur','$adresse')");
      if($vpeid)$this->app->DB->Update("UPDATE lager_platz_inhalt SET lager_platz_vpe = '$vpeid' WHERE id = '$insid' LIMIT 1");
      $this->LagerArtikelZusammenfassen($artikel, $regal);
      $this->app->DB->Update("UPDATE artikel SET cache_lagerplatzinhaltmenge = -999, `laststorage_changed` = NOW() WHERE id = '$artikel' LIMIT 1");
      $this->app->DB->Update(
        sprintf(
          'UPDATE artikel_onlineshops SET storage_cache = -999, pseudostorage_cache = -999 WHERE artikel = %d',
          $artikel
        )
      );
    }

    $this->RunHook('LagerEinlagern_after',7, $artikel, $menge, $regal, $projekt, $grund, $doctype,$doctypeid);
    
    $this->SeriennummernCheckBenachrichtigung($artikel);
  }

  function CreateLagerPlatzInhaltVPE($artikel, $menge, $gewicht, $laenge, $breite, $hoehe, $menge2 = 0, $gewicht2 = 0, $laenge2 = 0, $breite2 = 0, $hoehe2 = 0)
  {
    $check = $this->app->DB->Select("SELECT id FROM `lager_platz_vpe` WHERE artikel = '$artikel' AND menge = '$menge' AND gewicht = '$gewicht' AND breite = '$breite' AND 
    hoehe = '$hoehe' ".($menge2 <= 1?" AND (menge2 = '0' OR menge2 = 1) ":" AND menge2 = '$menge2' ")." AND gewicht2 = '$gewicht' AND breite2 = '$breite' AND 
    hoehe2 = '$hoehe' LIMIT 1
    ");
    if($check)return $check;
    $this->app->DB->Insert("INSERT INTO `lager_platz_vpe` (artikel, menge, gewicht, laenge, breite, hoehe, menge2, gewicht2, laenge2, breite2, hoehe2 )
    VALUES ('$artikel', '$menge', '$gewicht', '$laenge', '$breite', '$hoehe', '$menge2', '$gewicht2', '$laenge2', '$breite2', '$hoehe2')
    ");
    return $this->app->DB->GetInsertID();
  }

  function LagerEinlagernDifferenz($artikel,$menge,$regal,$projekt,$grund="",$importer="", $vpeid = 0)
  {
    $grund = "Differenz: ".$grund;
    $this->LagerEinlagern($artikel,$menge,$regal,$projekt,$grund,$importer, "", "", 0, $vpeid);
  }

  function LagerArtikelZusammenfassen($artikel, $regal = 0)
  {
    $fp = $this->app->erp->ProzessLock("lager_artikelzusammenfassen");
    //$this->LagerSync($artikel);
    // all einzeln buchungen in einem Baum zusammenfassen

    if($artikel > 0) {
      $result = $this->app->DB->SelectArr("SELECT lager_platz,SUM(menge) as gesamt,projekt,max(firma) as firma,max(inventur) as inventur, min(id) as minid,lager_platz_vpe FROM lager_platz_inhalt WHERE artikel='$artikel' ".($regal?" AND lager_platz = '$regal' ":'')." GROUP by lager_platz,lager_platz_vpe  having count(id) > 1");
      //echo "DELETE FROM lager_platz_inhalt WHERE artikel='".$artikel."';";
      if($result) {
        $cresult = (!empty($result)?count($result):0);
        for($i=0;$i<$cresult;$i++)  {
          $this->app->DB->Delete("DELETE FROM lager_platz_inhalt WHERE  artikel='$artikel' AND lager_platz = '".$result[$i]['lager_platz']."' AND lager_platz_vpe = '".$result[$i]['lager_platz_vpe']."' ");
          if(empty($result[$i]['lager_platz'])) {
            continue;
          }
          $this->app->DB->Insert("INSERT INTO lager_platz_inhalt (id,lager_platz,artikel,menge,projekt,firma,inventur,lager_platz_vpe) VALUES ('".$result[$i]['minid']."','".$result[$i]['lager_platz']."','$artikel',
            '".$result[$i]['gesamt']."','".$result[$i]['projekt']."','".$result[$i]['firma']."',".(is_null($result[$i]['inventur'])?"NULL":"'".$result[$i]['inventur']."'").",'".$result[$i]['lager_platz_vpe']."')");
        }
      }
    }
    if($regal)
    {
      //$this->app->DB->Delete("DELETE lager_platz_inhalt FROM lager_platz_inhalt WHERE lager_platz = '$regal' AND ((menge<='0' and (isnull(inventur) or inventur <= 0)) or menge < 0)");
    }else{
      //$this->app->DB->Delete("DELETE lager_platz_inhalt FROM lager_platz_inhalt WHERE (menge<='0' and (isnull(inventur) or inventur <= 0)) or menge < 0");
    }
    if($this->Verbrauchslagervorhanden())
    {
      if($regal && $this->app->DB->Select("SELECT verbrauchslager FROM lager_platz WHERE id = '$regal' LIMIT 1"))
      {
        $this->app->DB->Delete("DELETE lager_platz_inhalt FROM lager_platz_inhalt INNER JOIN lager_platz ON lager_platz.id=lager_platz_inhalt.lager_platz
            WHERE lager_platz.verbrauchslager='1' AND lager_platz.id = '$regal'");
        //WHERE lager_platz_inhalt.artikel='".$artikel."' AND lager_platz.verbrauchslager='1'");

        $this->app->DB->Delete("DELETE lager_charge FROM lager_charge INNER JOIN lager_platz ON lager_platz.id=lager_charge.lager_platz
            WHERE lager_platz.verbrauchslager='1' AND lager_platz.id = '$regal'");

        $this->app->DB->Delete("DELETE lager_seriennummern FROM lager_seriennummern
            INNER JOIN lager_platz ON lager_platz.id=lager_seriennummern.lager_platz
            WHERE lager_platz.verbrauchslager='1' AND lager_platz.id = '$regal'");

      $this->app->DB->Delete("DELETE lager_mindesthaltbarkeitsdatum FROM lager_mindesthaltbarkeitsdatum
          LEFT JOIN lager_platz ON lager_platz.id=lager_mindesthaltbarkeitsdatum.lager_platz
          WHERE lager_platz.verbrauchslager='1' AND lager_platz.id = '$regal'");

    }else{

        // loesche verbrauchslager
        // aber ebenfalls chargen, seriennummern und mhd
        $this->app->DB->Delete("DELETE lager_platz_inhalt FROM lager_platz_inhalt INNER JOIN lager_platz ON lager_platz.id=lager_platz_inhalt.lager_platz
            WHERE lager_platz.verbrauchslager='1'");
        //WHERE lager_platz_inhalt.artikel='".$artikel."' AND lager_platz.verbrauchslager='1'");

        $this->app->DB->Delete("DELETE lager_charge FROM lager_charge INNER JOIN lager_platz ON lager_platz.id=lager_charge.lager_platz
            WHERE lager_platz.verbrauchslager='1'");

        $this->app->DB->Delete("DELETE lager_seriennummern FROM lager_seriennummern
            INNER JOIN lager_platz ON lager_platz.id=lager_seriennummern.lager_platz
            WHERE lager_platz.verbrauchslager='1'");

        $this->app->DB->Delete("DELETE lager_mindesthaltbarkeitsdatum FROM lager_mindesthaltbarkeitsdatum
            LEFT JOIN lager_platz ON lager_platz.id=lager_mindesthaltbarkeitsdatum.lager_platz
            WHERE lager_platz.verbrauchslager='1'");
      }
    }
    $this->app->erp->ProzessUnlock($fp);
  }


  // pruefe ob es artikel noch im lager gibt bzw. ob es eine reservierung gibt
  function LagerFreieMenge($artikel, $mitautolagersperre = false, $standardlager = 0, $projektlager = 0)
  {
    $summe_im_lager = (float)$this->app->DB->Select(
      sprintf(
        "SELECT SUM(li.menge) 
        FROM `lager_platz_inhalt` AS `li` 
        LEFT JOIN lager_platz AS lp ON lp.id=li.lager_platz 
        WHERE li.artikel = %d
        AND lp.sperrlager!='1'".($mitautolagersperre?' AND lp.autolagersperre != 1':''),
        $artikel
      )
    );
    if($summe_im_lager <= 0) {
      return 0;
    }
    $artikel_reserviert = (float)$this->app->DB->Select(
      "SELECT SUM(lr.menge) 
        FROM `lager_reserviert` AS `lr`
        WHERE lr.artikel = '{$artikel}' 
        AND (lr.datum >= NOW() OR lr.datum='0000-00-00')");

    $restmenge = $summe_im_lager - $artikel_reserviert;
    if($restmenge <= 0) {
      return 0;
    }

    if($standardlager > 0) {
      $summe_im_lager_standard = (float)$this->app->DB->Select(
        sprintf(
          "SELECT SUM(li.menge) 
        FROM `lager_platz_inhalt` AS `li` 
        INNER JOIN `lager_platz` AS `lp` ON lp.id=li.lager_platz AND lp.lager = %d 
        WHERE li.artikel = %d
        AND lp.sperrlager != '1'".($mitautolagersperre?' AND lp.autolagersperre != 1':''),
          $standardlager,$artikel
        )
      );
      if($summe_im_lager_standard <= 0) {
        return 0;
      }

      $artikelReserviertAuftrag = (float)$this->app->DB->Select(
        sprintf(
          "SELECT SUM(lr.menge) 
          FROM `lager_reserviert` AS `lr`
          INNER JOIN `auftrag` AS `o` ON lr.objekt LIKE 'auftrag' AND lr.parameter = o.id
            AND o.standardlager = %d AND o.status = 'freigegeben'
          WHERE lr.artikel = %d AND (lr.datum>=NOW() OR lr.datum='0000-00-00')",
          $standardlager, $artikel
        )
      );

      $artikelReserviertProduktion = (float)$this->app->DB->Select(
        sprintf(
          "SELECT SUM(lr.menge) 
          FROM `lager_reserviert` AS `lr`
          INNER JOIN `produktion` AS `p` ON lr.objekt LIKE 'produktion' AND lr.parameter = p.id
            AND p.standardlager = %d AND p.status IN ('freigegeben', 'gestartet')
          WHERE lr.artikel = %d AND (lr.datum>=NOW() OR lr.datum='0000-00-00')",
          $standardlager, $artikel
        )
      );

      $summe_im_lager_standard -= ($artikelReserviertAuftrag + $artikelReserviertProduktion);
      if($summe_im_lager_standard <= 0) {
        return 0;
      }

      if($summe_im_lager_standard < $restmenge) {
        return $summe_im_lager_standard;
      }
    }
    elseif($projektlager > 0) {
      $summe_im_lager_projekt = (float)$this->app->DB->Select(
        sprintf(
          "SELECT SUM(li.menge) 
        FROM `lager_platz_inhalt` AS `li` 
        INNER JOIN `lager_platz` AS `lp` ON lp.id=li.lager_platz 
        INNER JOIN `lager` AS `l` ON lp.lager = l.id AND l.projekt = %d
        WHERE li.artikel=%d
        AND lp.sperrlager!='1'".($mitautolagersperre?' AND lp.autolagersperre != 1':''),
          $projektlager, $artikel
        )
      );

      if($summe_im_lager_projekt <= 0) {
        return 0;
      }

      $artikelReserviertProjektAuftrag = (float)$this->app->DB->Select(
        sprintf(
          "SELECT SUM(lr.menge) 
          FROM `lager_reserviert` AS `lr`
          INNER JOIN `auftrag` AS `o` ON lr.objekt LIKE 'auftrag' AND lr.parameter = o.id
            AND o.projekt = %d AND o.status = 'freigegeben'
          WHERE lr.artikel = %d AND (lr.datum>=NOW() OR lr.datum='0000-00-00')",
          $projektlager, $artikel
        )
      );

      $artikelReserviertProjektProduktion = (float)$this->app->DB->Select(
        sprintf(
          "SELECT SUM(lr.menge) 
          FROM `lager_reserviert` AS `lr`
          INNER JOIN `produktion` AS `p` ON lr.objekt LIKE 'produktion' AND lr.parameter = p.id
            AND p.projekt = %d AND p.status IN ('freigegeben', 'gestartet')
          WHERE lr.artikel = %d AND (lr.datum>=NOW() OR lr.datum='0000-00-00')",
          $projektlager, $artikel
        )
      );

      $summe_im_lager_projekt -= ($artikelReserviertProjektAuftrag + $artikelReserviertProjektProduktion);
      if($summe_im_lager_projekt <= 0) {
        return 0;
      }

      if($summe_im_lager_projekt < $restmenge) {
        return $summe_im_lager_projekt;
      }
    }

    return $restmenge;
  }

  public function getPreproducedPartlistFromArticle($id)
  {
    return $this->app->DB->Select(
      "SELECT art.preproduced_partlist 
      FROM artikel AS art 
      INNER JOIN artikel art2 ON  art.preproduced_partlist = art2.id 
                    AND art2.lagerartikel = 1 AND (art2.geloescht = 0 OR art2.geloescht IS NULL) AND art.id != art2.id
      WHERE art.id = $id AND art.has_preproduced_partlist"
    );
  }

  public function PreproducedPartlistSellableFrom($id, $projektlager = 0, $shopid = 0, $modus = 0)
  {
    if($id <= 0) {
      return 0;
    }
    $preproduced_partlist = $this->getPreproducedPartlistFromArticle($id);
    if($preproduced_partlist <= 0) {
      return 0;
    }

    return $this->ArtikelAnzahlVerkaufbar($preproduced_partlist, $projektlager, $shopid, $modus);
  }

  public function ArtikelAnzahlLagerStueckliste($id, $projektlager = 0, $shopid = 0, $modus = 0)
  {
    // gehe stueckliste durch und schaue ob es maximal artikel ist
    //$offen = $this->app->DB->Select("SELECT SUM(ap.menge) FROM auftrag_position ap LEFT JOIN auftrag a ON a.id=ap.auftrag WHERE ap.artikel='$id' AND a.status='freigegeben'");
    if(empty($id)) {
      return 0;
    }

    $artikel = $this->app->DB->SelectArr("SELECT s.* FROM stueckliste s INNER JOIN artikel a ON s.artikel = a.id WHERE s.stuecklistevonartikel='$id' AND s.art!='it' AND a.lagerartikel = 1 and (a.geloescht = 0 OR a.geloescht IS NULL)");

    if(empty($artikel)) {
      return 0;
    }
    $offset = $this->PreproducedPartlistSellableFrom($id, $projektlager, $shopid, $modus);

    $stueck = 0;
    $kleinste_max_menge = 0;
    $cartikel = !empty($artikel)?count($artikel):0;
    for($i=0;$i<$cartikel;$i++)  {
      $artikelid = $artikel[$i]['artikel'];
      $mengeimlage = (float)$this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz 
        WHERE lpi.artikel='$artikelid' AND lp.sperrlager!=1");
      $mengereserviert = (float)$this->app->DB->Select("SELECT ifnull(SUM(menge),0) FROM lager_reserviert WHERE artikel='$artikelid'");
      $mengeoffen = $modus == 1 ? 0 : (float)$this->app->DB->Select(
        "SELECT ifnull(SUM(ap.menge),0)
        FROM `auftrag_position` AS `ap`
        INNER JOIN `auftrag` AS `a` ON a.id = ap.auftrag
        WHERE ap.artikel='{$artikelid}' AND a.status='freigegeben'"
      );
      $mengefrei = $mengeimlage - ($mengeoffen > $mengereserviert ? $mengeoffen : $mengereserviert);

      if($projektlager) {
        $mengeimlagerprojekt = (float)$this->app->DB->Select("SELECT SUM(lpi.menge) FROM lager_platz_inhalt lpi INNER JOIN lager_platz lp ON lp.id=lpi.lager_platz  INNER JOIN lager `lag` ON lp.lager = `lag`.id AND `lag`.projekt = '$projektlager' AND `lag`.geloescht <> 1
          WHERE lpi.artikel='$artikelid' AND lp.sperrlager!=1");
        $mengereserviertprojekt = (float)$this->app->DB->Select("SELECT ifnull(SUM(r.menge),0) FROM lager_reserviert r INNER JOIN auftrag a ON r.parameter = a.id AND r.objekt = 'auftrag' AND a.status = 'freigegeben' WHERE r.artikel='$artikelid' AND a.projekt = '$projektlager' ");
        $mengeoffenprojekt = $modus == 1 ? 0 : (float)$this->app->DB->Select(
          "SELECT ifnull(SUM(ap.menge),0)
          FROM `auftrag_position` AS `ap`
          INNER JOIN `auftrag` AS `a` ON a.id = ap.auftrag
          WHERE ap.artikel='{$artikelid}' AND a.status='freigegeben' AND a.projekt = '{$projektlager}'"
        );
        $mengefreiprojekt = $mengeimlage - ($mengeoffenprojekt > $mengereserviertprojekt?$mengeoffenprojekt:$mengereserviertprojekt);
        if($mengefreiprojekt < $mengefrei) {
          $mengefrei = $mengefreiprojekt;
        }
      }


      if($artikel[$i]['menge'] <= 0) {
        return $offset;
      }

      $max_menge = floor($mengefrei/$artikel[$i]['menge']);
      $collect[] = $max_menge;
    }

    sort($collect);
    $stueck = (float)$collect[0];

    if($stueck <= 0) {
      $stueck=0;
    }

    return $stueck+$offset;
  }

  function ArtikelAnzahlVerkaufbar($artikelid, $offset = 0, $projektlager = 0, $shopid = 0, $modus=0, $returnArray = false)
  {
    $ij=0;
    if(is_array($artikelid) && isset($artikelid['juststueckliste']) && isset($artikelid['lagerartikel'])) {
      $articleRow = $artikelid;
      $artikelid = $artikelid['id'];
    }
    else{
      $lagerartikel[$ij]['id'] = $artikelid;
      $articleRow = $this->app->DB->SelectRow(
        sprintf(
          'SELECT id, juststueckliste, lagerartikel FROM artikel WHERE id = %d',
          $artikelid
        )
      );
    }
    $lagerartikel[$ij]['juststueckliste'] = $articleRow['juststueckliste'];// $this->app->DB->Select("SELECT juststueckliste FROM artikel WHERE id='$artikelid' LIMIT 1");
    //$lagerartikel[$ij]['name_de'] = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikelid' LIMIT 1");
    //$lagerartikel[$ij]['nummer'] = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikelid' LIMIT 1");
    //$lagerartikel[$ij]['cache_lagerplatzinhaltmenge'] = $this->app->DB->Select("SELECT cache_lagerplatzinhaltmenge FROM artikel WHERE id='$artikelid' LIMIT 1");

    $keinestueckliste = false;
    if($lagerartikel[$ij]['juststueckliste'] && !$articleRow['lagerartikel']) {
      $offen = 0;
      $reserviert = 0;
      $lagernd = (float)$this->ArtikelAnzahlLagerStueckliste($lagerartikel[$ij]['id'], $projektlager, $shopid, $modus);
    }
    elseif($lagerartikel[$ij]['juststueckliste']) {
      $lagernd = (float)$this->ArtikelAnzahlLagerStueckliste($lagerartikel[$ij]['id'], $projektlager, $shopid, $modus);
      $offen = (float)$this->ArtikelAnzahlOffene($lagerartikel[$ij]['id'], $projektlager);
      $reserviert = (float)$this->ArtikelAnzahlReserviert($lagerartikel[$ij]['id'], $projektlager);
    }
    else {
      $lagernd = (float)$this->ArtikelAnzahlLager($lagerartikel[$ij]['id'],0 , $projektlager);
      $offen = (float)$this->ArtikelAnzahlOffene($lagerartikel[$ij]['id'], $projektlager);
      $reserviert = (float)$this->ArtikelAnzahlReserviert($lagerartikel[$ij]['id'], $projektlager);
      $keinestueckliste = true;
    }

    $lagermenge = $lagernd;
    $lagernd += (float)$offset;

    if($modus==1) //  lager minus reservierte
    {
      $blockierte_menge = $reserviert;
    }
    else {
      if($offen > $reserviert) {
        $blockierte_menge = $offen;
      }
      else {
        $blockierte_menge = $reserviert;
      }
    }

    $lagernd -= $blockierte_menge;
    $berechneterBestand = $lagernd;

    if($lagernd  < 0) {
      $lagernd = 0;
    }
    if($shopid) {
      $lagernd += (float)$this->GetArtikelShopEinstellung('lagerkorrekturwert', $artikelid, $shopid);
    }

    if ($returnArray === false){
      return $lagernd;
    }

    return [
      'lagernd' => (float)$lagermenge,
      'reserviert' => (float)$reserviert,
      'offene_auftraege' => (float)$offen,
      'offene_bestellungen' => (float)$this->ArtikelAnzahlBestellung($artikelid),
      'berechneter_bestand' => (float)$berechneterBestand,
      'verkaufbar' => (float)$lagernd,
    ];
  }

  /**
   * @param int $shopId
   * @param int $articleId
   *
   * @return array|null
   */
  public function getStorageCacheInfosByShopId(int $shopId, int $articleId)
  {
    return $this->app->DB->SelectRow(
      "SELECT `storage_cache`, `pseudostorage_cache`, `last_storage_transfer`,
       HOUR(TIMEDIFF(NOW(), `last_storage_transfer`)) AS `last_storage_transfer_hours`
      FROM `artikel_onlineshops` 
      WHERE `shop` = '{$shopId}' AND `artikel` = '{$articleId}' AND `storage_cache` IS NOT NULL
      LIMIT 1"
    );
  }

  /**
   * @param int $shopId
   * @param int $articleId
   * @param int $sellable
   * @param int $pseudoStorage
   *
   * @return bool
   */
  public function isArticleShopCacheDifferent(int $shopId, int $articleId, int $sellable, int $pseudoStorage): bool
  {
    $storageCache = $this->app->DB->SelectRow(
      "SELECT `storage_cache`, `pseudostorage_cache` 
        FROM `artikel_onlineshops` 
        WHERE `shop` = '{$shopId}' AND `artikel` = '{$articleId}' AND `storage_cache` IS NOT NULL
        LIMIT 1"
    );
    if(empty($storageCache)) {
      return true;
    }

    return $storageCache['storage_cache'] != $sellable || $storageCache['pseudostorage_cache'] != $pseudoStorage;
  }

  /**
   * @param int|array $artikelid
   * @param bool      $print_echo
   * @param array     $shopByIds
   *
   * @return string
   */
  public function LagerSync($artikelid, $print_echo=false, $shopByIds = [])
  {
    $ij=0;
    $message = '';
    if(!empty($artikelid) && is_array($artikelid) && !empty($artikelid['id'])){
      $artikelid = (int)$artikelid['id'];
    }
    elseif(!empty($artikelid) && is_array($artikelid)){
      $artikelid = (int)reset($artikelid);
    }
    if(!is_numeric($artikelid) || $artikelid <= 0){
      return '';
    }
    $lagerartikel = $this->app->DB->SelectArr(
      "SELECT * FROM `artikel` WHERE `id` = '{$artikelid}' LIMIT 1"
    );
    if(empty($lagerartikel)){
      return '';
    }

    $bestandalternativartikel = $lagerartikel[$ij]['bestandalternativartikel'];

    $shops = $this->GetArtikelshops($lagerartikel[$ij]);
    if(empty($shops)) {
      return $message;
    }

    foreach($shops as $shop) {
      if($shop <= 0){
        continue;
      }
      if(!empty($shopByIds[$shop])) {
        $shopArr = $shopByIds[$shop];
      }
      else {
        $shopArr = $this->app->DB->SelectRow(
          "SELECT `id`, `projekt`, `lagergrundlage`, `lagerkorrekturwert`, `ueberschreibe_lagerkorrekturwert` 
          FROM `shopexport` 
          WHERE `id` = '{$shop}' AND `aktiv` = 1
          LIMIT 1"
        );
      }
      if(empty($shopArr) && empty($this->app->DB->error())) {
        continue;
      }

      $shopAricleArr =  $this->GetArtikelShopEinstellung('', $lagerartikel[$ij], $shopArr);
      if(empty($shopAricleArr['autolagerlampe'])) {
        continue;
      }
      if(isset($shopAricleArr['pseudolager']) && trim($shopAricleArr['pseudolager']) !== '') {
        $pseudolager = !empty($shopAricleArr['pseudolager'])?(float)$shopAricleArr['pseudolager']:0;
      }
      else {
        $pseudolager = 0;
      }
      $this->app->erp->RunHook('remote_send_article_list_pseudostorage', 3, $shop, $artikelid, $pseudolager);
      if(is_numeric($pseudolager) && $pseudolager < 0) {
        $pseudolager = 0;
      }
      $projekt = $shopArr['projekt'];
      $lagergrundlage = $shopArr['lagergrundlage'];
      $projektlager = $this->Projektdaten($projekt, 'projektlager');
      if($projektlager)
      {
        if($bestandalternativartikel) {
          $verkaufbare_menge = (float)$this->ArtikelAnzahlVerkaufbar($bestandalternativartikel,0,$projekt);
          $verkaufbare_menge_korrektur = floor($this->ArtikelAnzahlVerkaufbar($bestandalternativartikel,0,$projekt, $shop, $lagergrundlage));
        }
        else{
          $verkaufbare_menge = (float)$this->ArtikelAnzahlVerkaufbar($artikelid,0,$projekt);
          $verkaufbare_menge_korrektur = floor((float)$this->ArtikelAnzahlVerkaufbar($artikelid,0,$projekt, $shop, $lagergrundlage));
        }
      }
      else{
        //$verkaufbare_menge = $verkaufbare_menge_alle;
        if($bestandalternativartikel) {
          $verkaufbare_menge = (float)$this->ArtikelAnzahlVerkaufbar($bestandalternativartikel,0,0);
          $verkaufbare_menge_korrektur = floor((float)$this->ArtikelAnzahlVerkaufbar($bestandalternativartikel,0,0,$shop,$lagergrundlage));
        }
        else{
          $verkaufbare_menge = (float)$this->ArtikelAnzahlVerkaufbar($artikelid,0,0);
          $verkaufbare_menge_korrektur = floor((float)$this->ArtikelAnzahlVerkaufbar($artikelid,0,0,$shop,$lagergrundlage));
        }
      }
      if($verkaufbare_menge_korrektur < 0) {
        $verkaufbare_menge_korrektur = 0;
      }
      $neuer_status = 'red';
      if ($verkaufbare_menge > 0){
        $neuer_status = 'gruen (Menge: ' . ($verkaufbare_menge . ' Pseudolager: ' . $pseudolager) . ')';
      }

      $isArticleCacheDifferent = $lagerartikel[$ij]['cache_lagerplatzinhaltmenge']
        != ((int) $verkaufbare_menge_korrektur + (int) $pseudolager);

      $storageCache = $isArticleCacheDifferent
        ? null : $this->getStorageCacheInfosByShopId((int)$shop, (int)$lagerartikel[$ij]['id']);

      $hasToSendStock = $isArticleCacheDifferent
        || $this->isArticleShopCacheDifferent(
          (int)$shop, (int)$lagerartikel[$ij]['id'], (int)$verkaufbare_menge_korrektur, (int)$pseudolager
        );

      $needUpdateShopStorageCache = $storageCache && !$isArticleCacheDifferent;

      $isZeroQuantity = (is_numeric($pseudolager) && $pseudolager == 0) || (int)$verkaufbare_menge_korrektur === 0;

      if(
        $storageCache !== null
        && $isZeroQuantity
        && ($storageCache['last_storage_transfer_hours'] === null || $storageCache['last_storage_transfer_hours'] > 48)
      ) {
        $hasToSendStock = true;
        $needUpdateShopStorageCache = true;
      }

      if(!$hasToSendStock) {
        continue;
      }

      if($needUpdateShopStorageCache) {
        // to prevent loops
        $this->app->DB->Update(
          "UPDATE `artikel_onlineshops` 
          SET `last_storage_transfer` = NOW(), `storage_cache` = {$verkaufbare_menge_korrektur} 
          WHERE `artikel` = {$lagerartikel[$ij]['id']} AND `shop` = {$shop}"
        );
        if(is_numeric($pseudolager)) {
          $this->app->DB->Update(
            "UPDATE `artikel_onlineshops` 
            SET `pseudostorage_cache` = {$pseudolager} 
            WHERE `artikel` = {$lagerartikel[$ij]['id']} AND `shop` = {$shop}"
          );
        }
      }     

        $extnummer = null;
        $anzges = 0;
        $anzfehler = 0;

        $result = null; // $result['status'] == 1 on success

        if(!empty($extnummer) && is_array($extnummer)) {
          foreach($extnummer as $nummer) {
            $anzges++;
            try {
                $result = $this->app->remote->RemoteSendArticleList($shop, array($lagerartikel[$ij]['id']), array($nummer['nummer']), true);
            }
            catch(Exception $e) {
              $this->app->erp->LogFile($this->app->DB->real_escape_string('Lagersync Fehler '.$shop.' '.$nummer['nummer'].' '.$e->getMessage()));
              $anzfehler++;
            }
          }
        }
        else{
          $anzges++;
          try {
              $result = $this->app->remote->RemoteSendArticleList($shop,array($lagerartikel[$ij]['id']),!empty($extnummer)? array($extnummer):'',true);
          }
          catch(Exception $e) {
            $this->app->erp->LogFile($this->app->DB->real_escape_string('Lagersync Fehler '.$shop.' '.(!empty($extnummer)? array($extnummer):$lagerartikel[$ij]['nummer']).' '.$e->getMessage()));
            $anzfehler++;
          }
        }
        $message .= 'Artikel: '.$lagerartikel[$ij]['name_de'].' ('.$lagerartikel[$ij]['nummer'].') Neuer Status: '.$neuer_status."\r\n";

        if($print_echo) {
          echo '*** UPDATE ' . $lagerartikel[$ij]['nummer'] . ' ' . $lagerartikel[$ij]['name_de'] . ' Lagernd: ' . ($verkaufbare_menge) . ' Korrekturwert: ' . round($verkaufbare_menge_korrektur - $verkaufbare_menge, 7) . "\r\n";
        }


        $this->LogFile('*** UPDATE '.$lagerartikel[$ij]['nummer'].' '.$lagerartikel[$ij]['name_de'].' Shop: '.$shop.' Lagernd: '.$verkaufbare_menge.' Korrektur: '.round((float) ($verkaufbare_menge_korrektur - $verkaufbare_menge),7).' Pseudolager: '.round((float) $pseudolager,8).' Result: '.(is_array($result)?$result['status']:$result), $result);

        if ((is_array($result)?$result['status'] == 1:false) || $result === 1) {
            $cacheQuantity = (int) $verkaufbare_menge_korrektur + (int) $pseudolager;
            $this->app->DB->Update(
              "UPDATE `artikel` SET `cache_lagerplatzinhaltmenge` = '{$cacheQuantity}'
              WHERE `id`= '{$lagerartikel[$ij]['id']}' LIMIT 1"
            );
        }


    }

    $this->app->DB->Update(
      "UPDATE `artikel` SET `laststorage_sync` = NOW() WHERE `id` = {$artikelid}"
    );

    return $message;
  }


  // pruefe ob es artikel noch im lager gibt bzw. ob es eine reservierung gibt
  public function LagerCheck($adresse,$artikel,$menge,$objekt='',$parameter='', $juststorage = false)
  {
    $projektlager = 0;
    $standardlager = 0;
    if($parameter > 0 && ($objekt==='auftrag' || $objekt==='lieferschein'))
    {
      $docArr = $this->app->DB->SelectRow(sprintf('SELECT * FROM `%s` WHERE id=%d LIMIT 1', $objekt, (int)$parameter));
      $projekt = $docArr['projekt'];
      $auftrag = $parameter;
      if($objekt === 'lieferschein')
      {
        $auftrag = $docArr['auftragid'];
      }
      if($projekt > 0)
      {
        $projectArr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT projektlager, standardlager,kommissionierverfahren FROM projekt WHERE id=%d',
            $projekt
          )
        );
        $kommissionierverfahren= $projectArr['kommissionierverfahren'];
        if(
        !($kommissionierverfahren==='lieferscheinlager' ||
          $kommissionierverfahren==='lieferscheinlagerscan' ||
          $kommissionierverfahren==='lieferscheinscan' ||
          $kommissionierverfahren === 'lieferschein') || $this->app->DB->Select('SELECT IFNULL(COUNT(id),0) FROM lager') <= 1
        )
        {
          $standardlager = 0;
        } else {
          $projektlager = $projectArr['projektlager'];
          if($objekt==='auftrag' || $objekt === 'lieferschein') {
            $standardlager = $docArr['standardlager'];
          } else{
            $standardlager = $this->app->DB->Select(sprintf('SELECT standardlager FROM auftrag WHERE id = %d LIMIT 1', (int)$auftrag));
          }
          if($standardlager && !$this->app->DB->Select(sprintf('SELECT id FROM lager WHERE id = %d LIMIT 1', (int)$standardlager))) {
            $standardlager = $this->app->DB->Select(sprintf('SELECT id FROM lager WHERE id = %d LIMIT 1', (int)$docArr['standardlager']));
          }
        }
      }
    }

    $articleArr = $this->app->DB->SelectRow(
      sprintf(
        'SELECT chargenverwaltung, mindesthaltbarkeitsdatum,seriennummern FROM artikel WHERE id = %d LIMIT 1',
        $artikel
      )
    );

    $isBestBefore = !empty($articleArr['mindesthaltbarkeitsdatum']);
    $isBatch = !empty($articleArr['chargenverwaltung']);
    $isSn = !empty($articleArr['seriennummern']) && $articleArr['seriennummern'] !== 'keine';
    if($juststorage) {
      $isBestBefore = false;
      $isBatch = false;
      $isSn = false;
    }
    if($standardlager > 0)
    {
      $summe_im_lager = round(
        $this->app->DB->Select(
          sprintf(
            "SELECT IFNULL(SUM(li.menge),0) 
            FROM lager_platz_inhalt AS li 
            INNER JOIN lager_platz AS lp ON lp.id=li.lager_platz 
            INNER JOIN lager AS lag ON lag.id=lp.lager 
            WHERE li.artikel= %d AND lp.autolagersperre!=1 AND lp.sperrlager!= 1  AND lag.id=%d",
            (int)$artikel, (int)$standardlager
          )
        ),
        $this->GetLagerNachkommastellen()
      );
      if($summe_im_lager > 0 && $isBestBefore) {
        $bestBeforeStorage = round(
          $this->app->DB->Select(
            sprintf(
              "SELECT IFNULL(SUM(li.menge),0) 
            FROM lager_mindesthaltbarkeitsdatum AS li 
            INNER JOIN lager_platz AS lp ON lp.id=li.lager_platz 
            INNER JOIN lager AS lag ON lag.id=lp.lager 
            WHERE li.artikel= %d AND lp.autolagersperre!=1 AND lp.sperrlager!= 1  AND lag.id=%d",
              (int)$artikel, (int)$standardlager
            )
          ),
          $this->GetLagerNachkommastellen()
        );
        if($bestBeforeStorage < $summe_im_lager) {
          $summe_im_lager = $bestBeforeStorage;
        }
      }elseif($summe_im_lager > 0 && $isBatch) {
        $batchStorage = round(
          $this->app->DB->Select(
            sprintf(
              "SELECT IFNULL(SUM(li.menge),0) 
            FROM lager_charge AS li 
            INNER JOIN lager_platz AS lp ON lp.id=li.lager_platz 
            INNER JOIN lager AS lag ON lag.id=lp.lager 
            WHERE li.artikel= %d AND lp.autolagersperre!=1 AND lp.sperrlager!= 1  AND lag.id=%d",
              (int)$artikel, (int)$standardlager
            )
          ),
          $this->GetLagerNachkommastellen()
        );
        if($batchStorage < $summe_im_lager) {
          $summe_im_lager = $batchStorage;
        }
      }

      $artikel_reserviert = round(
        $this->app->DB->Select(
          sprintf(
            "SELECT SUM(menge) 
              FROM lager_reserviert 
              WHERE artikel=%d AND (datum>=NOW() OR datum='0000-00-00')",
            (int)$artikel
          )
        ),
        $this->GetLagerNachkommastellen()
      );
      $summe_im_lager_gesamt = round(
        $this->app->DB->Select(
          sprintf(
            "SELECT SUM(li.menge) 
              FROM lager_platz_inhalt AS li 
              LEFT JOIN lager_platz lp ON lp.id=li.lager_platz WHERE li.artikel= %d
              AND lp.autolagersperre!=1 AND lp.sperrlager!=1",
            $artikel
          )
        ),
        $this->GetLagerNachkommastellen()
      );
    }elseif($projektlager > 0)
    {
      $summe_im_lager = round(
        $this->app->DB->Select(
          sprintf(
            "SELECT SUM(li.menge) 
              FROM lager_platz_inhalt AS li 
              INNER JOIN lager_platz AS lp ON lp.id=li.lager_platz 
              INNER JOIN lager AS lag ON lag.id=lp.lager 
              WHERE li.artikel=%d
        AND lp.autolagersperre!=1 AND lp.sperrlager!= 1 AND lag.projekt=%d",
            (int)$artikel, (int)$projekt
          )
        ),
        $this->GetLagerNachkommastellen()
      );
      if($summe_im_lager > 0 && $isBestBefore) {
        $bestBeforeStorage = round(
          $this->app->DB->Select(
            sprintf(
              "SELECT SUM(li.menge) 
              FROM lager_mindesthaltbarkeitsdatum AS li 
              INNER JOIN lager_platz AS lp ON lp.id=li.lager_platz 
              INNER JOIN lager AS lag ON lag.id=lp.lager 
              WHERE li.artikel=%d
        AND lp.autolagersperre!=1 AND lp.sperrlager!= 1 AND lag.projekt=%d",
              (int)$artikel, (int)$projekt
            )
          ),
          $this->GetLagerNachkommastellen()
        );
        if($bestBeforeStorage < $summe_im_lager) {
          $summe_im_lager = $bestBeforeStorage;
        }
      } elseif($summe_im_lager > 0 && $isBatch) {
        $batchStorage = round(
          $this->app->DB->Select(
            sprintf(
              "SELECT SUM(li.menge) 
              FROM lager_charge AS li 
              INNER JOIN lager_platz AS lp ON lp.id=li.lager_platz 
              INNER JOIN lager AS lag ON lag.id=lp.lager 
              WHERE li.artikel=%d
        AND lp.autolagersperre!=1 AND lp.sperrlager!= 1 AND lag.projekt=%d",
              (int)$artikel, (int)$projekt
            )
          ),
          $this->GetLagerNachkommastellen()
        );
        if($batchStorage < $summe_im_lager) {
          $summe_im_lager = $batchStorage;
        }
      }
      $artikel_reserviert = round($this->app->DB->Select("SELECT SUM(menge) 
        FROM lager_reserviert WHERE artikel='".$artikel."' AND projekt='$projekt' AND (datum>=NOW() OR datum='0000-00-00')"),$this->GetLagerNachkommastellen());
    } else {
      $summe_im_lager = round(
        $this->app->DB->Select(
          sprintf(
              "SELECT SUM(li.menge) 
              FROM lager_platz_inhalt AS li 
              LEFT JOIN lager_platz lp ON lp.id=li.lager_platz WHERE li.artikel= %d
              AND lp.autolagersperre!=1 AND lp.sperrlager!=1",
              $artikel
          )
        ),
        $this->GetLagerNachkommastellen()
      );
      if($summe_im_lager > 0 && $isBestBefore) {
        $bestBeforeStorage = round(
          $this->app->DB->Select(
            sprintf(
              "SELECT SUM(li.menge) 
              FROM lager_mindesthaltbarkeitsdatum AS li 
              LEFT JOIN lager_platz AS lp ON lp.id=li.lager_platz WHERE li.artikel= %d
              AND lp.autolagersperre!=1 AND lp.sperrlager!=1",
              $artikel
            )
          ),
          $this->GetLagerNachkommastellen()
        );
        if($bestBeforeStorage < $summe_im_lager) {
          $summe_im_lager = $bestBeforeStorage;
        }
      }elseif($summe_im_lager > 0 && $isBatch) {
        $batchStorage = round(
          $this->app->DB->Select(
            sprintf(
              "SELECT SUM(li.menge) 
              FROM lager_charge AS li 
              LEFT JOIN lager_platz AS lp ON lp.id=li.lager_platz WHERE li.artikel= %d
              AND lp.autolagersperre!=1 AND lp.sperrlager!=1",
              $artikel
            )
          ),
          $this->GetLagerNachkommastellen()
        );
        if($batchStorage < $summe_im_lager) {
          $summe_im_lager = $batchStorage;
        }
      }
      $artikel_reserviert = round($this->app->DB->Select("SELECT SUM(menge) FROM lager_reserviert WHERE artikel='".$artikel."' AND (datum>=NOW() OR datum='0000-00-00')"),$this->GetLagerNachkommastellen());
    }

    // wenn es reservierungen fuer den Auftrag  gibt
    if($objekt!='')
    {
      // auftrag reservierungen
      $artikel_fuer_adresse_reserviert = round($this->app->DB->Select("SELECT SUM(menge) 
        FROM lager_reserviert
          WHERE artikel='".$artikel."' ".($adresse > 0?" AND adresse='$adresse'":'')." AND ((objekt='$objekt' AND parameter='$parameter')".($objekt==='lieferschein' && $auftrag > 0?" OR (objekt='auftrag' AND parameter = '$auftrag') ":'').") AND (datum>=NOW() OR datum='0000-00-00')"),$this->GetLagerNachkommastellen());
    } else {
      $artikel_fuer_adresse_reserviert = round($this->app->DB->Select("SELECT SUM(menge) 
        FROM lager_reserviert
          WHERE artikel='".$artikel."' ".($adresse > 0?" AND adresse='$adresse'":'')." AND (datum>=NOW() OR datum='0000-00-00') AND objekt!='lieferschein'"),$this->GetLagerNachkommastellen());
    }

    if(round(($summe_im_lager - ($artikel_reserviert -$artikel_fuer_adresse_reserviert)),8) >= round($menge,8))
    {
      return 1;
    }

    if($standardlager) {
      $nichtStandardlager = round($summe_im_lager_gesamt - $summe_im_lager,8);
      if($nichtStandardlager > 0 ) {
        $artikel_reserviert -= $nichtStandardlager;
        if($artikel_reserviert < 0) {
          $artikel_reserviert = 0;
        }
        if(round(($summe_im_lager - ($artikel_reserviert -$artikel_fuer_adresse_reserviert)),8) >= round($menge,8))
        {
          return 1;
        }
      }
    }

    if($objekt === 'auftrag' && $artikel_fuer_adresse_reserviert > 0)
    {
      if($summe_im_lager >= $artikel_fuer_adresse_reserviert)
      {
        $gesamte_menge_im_auftrag= $this->app->DB->Select("SELECT SUM(menge-geliefert_menge) 
            FROM auftrag_position WHERE auftrag='$parameter' AND artikel='$artikel'");
        if($artikel_fuer_adresse_reserviert >= $menge && $artikel_fuer_adresse_reserviert >= $gesamte_menge_im_auftrag && $summe_im_lager >= $gesamte_menge_im_auftrag){
          return true;
        }
      }
    }
    elseif($objekt === 'lieferschein'  && $artikel_fuer_adresse_reserviert > 0)
    {
      if($summe_im_lager >= $artikel_fuer_adresse_reserviert)
      {
        $gesamte_menge_im_auftrag= $this->app->DB->Select("SELECT SUM(menge-geliefert) 
            FROM lieferschein_position WHERE lieferschein='$parameter' AND artikel='$artikel'");
        if($artikel_fuer_adresse_reserviert >= $menge && $artikel_fuer_adresse_reserviert >= $gesamte_menge_im_auftrag && $summe_im_lager >= $gesamte_menge_im_auftrag){
          return true;
        }
      }
    }

    return 0;
  }

  function AngebotSuche($parsetarget)
  {
    $treffer = $this->app->Secure->GetPOST("treffer");
    if($treffer > 0 ) {
      $_SESSION['angebottreffer'] = $treffer;
      $_SESSION['page'] = 1;
    }
    else
      if(!isset($_SESSION['angebottreffer']) || $_SESSION['angebottreffer'] <= 0)
        $_SESSION['angebottreffer'] = 10;

    $this->app->Tpl->Set('TREFFER',$_SESSION['angebottreffer']);


    $suchwort= $this->app->Secure->GetPOST("suchwort");
    $name= $this->app->Secure->GetPOST("name");
    $plz= $this->app->Secure->GetPOST("plz");
    $angebot= $this->app->Secure->GetPOST("angebot");
    $kundennummer= $this->app->Secure->GetPOST("kundennummer");

    $_SESSION['angebotsuchwort']=$suchwort; //$this->app->Tpl->Set(SUCHWORT,$_SESSION[angebotsuchwort]);
    $_SESSION['angebotname']=$name; $this->app->Tpl->Set('NAME',$_SESSION['angebotname']);
    $_SESSION['angebotplz']=$plz; $this->app->Tpl->Set('PLZ',$_SESSION['angebotplz']);
    $_SESSION['angebotangebot']=$angebot; $this->app->Tpl->Set('ANGEBOT',$_SESSION['angebotangebot']);
    $_SESSION['angebotkundennummer']=$kundennummer; $this->app->Tpl->Set('KUNDENNUMMER',$_SESSION['angebotkundennummer']);

    $suche = $this->app->Secure->GetPOST("suche");

    //$this->app->YUI->AutoComplete(PROJEKTAUTO,"projekt",array('name','abkuerzung'),"abkuerzung");

    if(($_SESSION['angebotsuchwort']!='' || $_SESSION['angebotname']!='' || $_SESSION['angebotplz']!='' || $_SESSION['angebotangebot']!='' || $_SESSION['angebotkundennummer']!='') && $suche!=""){

      //Jeder der in Nachbesserung war egal ob auto oder manuell wandert anschliessend in Manuelle-Freigabe");
      if($suchwort!="")
      {
        return "SELECT DATE_FORMAT(a.datum,'%d.%m.%y') as vom, if(a.belegnr,a.belegnr,'ohne Nummer') as Angebot, ad.kundennummer as kunde, a.name, p.abkuerzung as projekt, a.status, a.id
          FROM angebot a, projekt p, adresse ad WHERE
          (a.plz LIKE '%$suchwort%' OR a.name LIKE '%$suchwort%' OR a.belegnr LIKE '%$suchwort%')
          AND p.id=a.projekt AND a.adresse=ad.id
          order by a.datum DESC, a.id DESC";
      } else {
        return "SELECT DATE_FORMAT(a.datum,'%d.%m.%y') as vom, if(a.belegnr,a.belegnr,'ohne Nummer') as Angebot, ad.kundennummer as kunde, a.name, p.abkuerzung as projekt, a.status, a.id
          FROM angebot a, projekt p, adresse ad WHERE
          (ad.kundennummer LIKE '%{$_SESSION['angebotkundennummer']}%' AND a.plz LIKE '%{$_SESSION['angebotplz']}%'
           AND a.name LIKE '%{$_SESSION['angebotname']}%' AND a.belegnr LIKE '%{$_SESSION['angebotangebot']}%' )
          AND p.id=a.projekt AND a.adresse=ad.id
          order by a.datum DESC, a.id DESC";

      }

      /*
         return ("SELECT DISTINCT a.nummer, a.name_de as Artikel, p.abkuerzung, a.id FROM artikel a LEFT JOIN projekt p ON p.id=a.projekt WHERE
         a.name_de LIKE '%$name%' AND
         a.nummer LIKE '$nummer%'AND
         p.abkuerzung LIKE '%$projekt%'
         AND geloescht='0'
         ORDER by a.id DESC");
       */
      //      SELECT DISTINCT a.name, a.ort, a.telefon, a.email, a.id
      //      FROM adresse a LEFT JOIN adresse_rolle r ON a.id=r.adresse WHERE r.subjekt='Kunde' ORDER by a.id DESC

    } else {

      return "SELECT DATE_FORMAT(a.datum,'%d.%m.%y') as vom, if(a.belegnr,a.belegnr,'ohne Nummer') as Angebot, ad.kundennummer as kunde, a.name, p.abkuerzung as projekt, a.status, a.id
        FROM angebot a, projekt p, adresse ad WHERE p.id=a.projekt AND a.adresse=ad.id order by a.datum DESC, a.id DESC";

    }
    //$this->app->Tpl->Set(INHALT,"");
  }



  function WebmailSuche($parsetarget,$rolle)
  {
    $suche = $this->app->Secure->GetPOST("suche");

    $name = $this->app->Secure->GetPOST("name"); $this->app->Tpl->Set('SUCHENAME',$name);
    $nummer = $this->app->Secure->GetPOST("nummer"); $this->app->Tpl->Set('SUCHENUMMER',$nummer);
    $typ = $this->app->Secure->GetPOST("typ");

    $this->app->YUI->AutoComplete('PROJEKTAUTO',"projekt",array('name','abkuerzung'),"abkuerzung");

    $projekt = $this->app->Secure->GetPOST("projekt");  $this->app->Tpl->Set('SUCHEPROJEKT',$projekt);
    $limit = $this->app->Secure->GetPOST("limit"); if($limit=="" || $limit ==0) $limit=10; $this->app->Tpl->Set('SUCHELIMIT',$limit);

    if($name!='' && $suche!='')
    {
      $_SESSION['name_webmailsuche'] = $name;
    } elseif ($suche!="" && $name=='')
    $_SESSION['name_webmailsuche'] = '';

    if($name=='' && $suche!='')
    {
      $_SESSION['name_artikel'] = $name;
    }

    $_SESSION['nummer'] = $nummer;
    $_SESSION['projekt'] = $projekt;

    $adresse = $this->app->User->getAdresse();

    if($name==""){ $name = $_SESSION['name_webmailsuche'];  $this->app->Tpl->Set('SUCHENAME',$name);}
    if($nummer==""){$nummer= $_SESSION['nummer']; $this->app->Tpl->Set('SUCHENUMMER',$nummer);}
    if($projekt==""){$projekt= $_SESSION['projekt']; $this->app->Tpl->Set('SUCHEPROJEKT',$projekt);}

    if($name!="" || $nummer!="" || $projekt!="") $suche ="suche";


    $this->app->Tpl->Parse($parsetarget,"webmailsuche.tpl");
    if(($name!="" || $nummer!="" || $projekt!="") && $suche!=""){


      return("SELECT DATE_FORMAT(e.empfang,'%d.%m.%Y %H:%i') as zeit,CONCAT(LEFT(e.subject,30),'...') as betreff, e.sender,e.id
          FROM     emailbackup_mails e
          WHERE    e.webmail IN (SELECT id FROM emailbackup WHERE emailbackup.adresse = '$adresse' AND emailbackup.geloescht!=1)
          AND e.sender LIKE '%$name%' AND
          e.subject LIKE '$nummer%'
          ORDER BY e.empfang DESC");

      //p.abkuerzung LIKE '%$projekt%'

      //Jeder der in Nachbesserung war egal ob auto oder manuell wandert anschliessend in Manuelle-Freigabe");
      /*
         return("SELECT DATE_FORMAT(tn.zeit,'%d.%m.%Y %H:%i') as zeit,CONCAT(LEFT(tn.betreff,30),'...') as betreff, t.kunde, p.abkuerzung,
         tn.id FROM ticket_nachricht tn LEFT JOIN ticket t ON t.schluessel=tn.ticket LEFT JOIN projekt p ON p.id=t.projekt WHERE
         t.kunde LIKE '%$name%' AND
         tn.betreff LIKE '$nummer%'AND
         p.abkuerzung LIKE '%$projekt%'
         ORDER by tn.zeit DESC");
       */
      //      SELECT DISTINCT a.name, a.ort, a.telefon, a.email, a.id
      //      FROM adresse a LEFT JOIN adresse_rolle r ON a.id=r.adresse WHERE r.subjekt='Kunde' ORDER by a.id DESC
      //       $table->Display(INHALT,"auftrag","kundeuebernehmen","In Auftrag einf&uuml;gen");
    } else {
      return "SELECT DATE_FORMAT(e.empfang,'%d.%m.%Y %H:%i') as zeit,CONCAT(LEFT(e.subject,30),'...') as betreff, e.sender,e.id
        FROM     emailbackup_mails e
        WHERE    webmail IN (SELECT id FROM emailbackup WHERE emailbackup.adresse = '$adresse' AND emailbackup.geloescht!=1)
        ORDER BY e.empfang DESC";

      //      return "SELECT DATE_FORMAT(e.empfang,'%d.%m.%Y %H:%i') as zeit,CONCAT(LEFT(e.subject,30),'...') as betreff, e.sender,
      //      e.id FROM emailbackup_mails e WHERE
      //     ORDER by e.empfang DESC";
    }



    //$this->app->Tpl->Set(INHALT,"");
  }


  function TicketArchivSuche($parsetarget,$rolle)
  {
    /** @var Ticket $obj */
    $obj = $this->LoadModul('ticket');
    if(!empty($obj) && method_exists($obj, 'TicketArchivSuche'))
    {
      return $obj->TicketArchivSuche($parsetarget,$rolle);
    }
  }

  function ArtikelSuche($parsetarget,$rolle)
  {
    $suche = $this->app->Secure->GetPOST("suche");
    $suchwort= $this->app->Secure->GetPOST("suchwort");
    /* Auftrage fuer manuelle freigabe */

    $name = $this->app->Secure->GetPOST("name"); $this->app->Tpl->Set('SUCHENAME',$name);
    $nummer = $this->app->Secure->GetPOST("nummer"); $this->app->Tpl->Set('SUCHENUMMER',$nummer);
    $typ = $this->app->Secure->GetPOST("typ");

    $this->app->YUI->AutoComplete('PROJEKTAUTO',"projekt",array('name','abkuerzung'),"abkuerzung");

    $projekt = $this->app->Secure->GetPOST("projekt");  $this->app->Tpl->Set('SUCHEPROJEKT',$projekt);
    $limit = $this->app->Secure->GetPOST("limit"); if($limit=="" || $limit ==0) $limit=10; $this->app->Tpl->Set('SUCHELIMIT',$limit);

    if($name!="" && $suche!="")
    {
      $_SESSION['name_artikel'] = $name;
    } elseif ($suche!="" && $name=="")
    $_SESSION['name_artikel'] = "";


    if($name=="" && $suche!="")
    {
      $_SESSION['name_artikel'] = $name;
    }

    $_SESSION['nummer'] = $nummer;
    $_SESSION['projekt'] = $projekt;


    if($name==""){ $name = $_SESSION['name_artikel'];  $this->app->Tpl->Set('SUCHENAME',$name);}
    if($nummer==""){$nummer= $_SESSION['nummer']; $this->app->Tpl->Set('SUCHENUMMER',$nummer);}
    if($projekt==""){$projekt= $_SESSION['projekt']; $this->app->Tpl->Set('SUCHEPROJEKT',$projekt);}

    if($name!="" || $nummer!="" || $projekt!="") $suche ="suche";


    $this->app->Tpl->Parse($parsetarget,"artikelsuche.tpl");
    if(($name!="" || $nummer!="" || $projekt!="" || $suchwort!="") && $suche!=""){
      if($suchwort!="")
      {

        return ("SELECT DISTINCT a.nummer, a.name_de as Artikel, p.abkuerzung, a.id FROM artikel a LEFT JOIN projekt p ON p.id=a.projekt WHERE
            (a.name_de LIKE '%$suchwort%' OR
             a.nummer LIKE '%$suchwort%')
            AND geloescht='0'
            ORDER by a.id DESC");

      } else {
        return ("SELECT DISTINCT a.nummer, a.name_de as Artikel, p.abkuerzung, a.id FROM artikel a LEFT JOIN projekt p ON p.id=a.projekt WHERE
            a.name_de LIKE '%$name%' AND
            a.nummer LIKE '%$nummer%' AND
            p.abkuerzung LIKE '%$projekt%'
            AND a.geloescht='0'
            ORDER by a.id DESC");
      }

      //Jeder der in Nachbesserung war egal ob auto oder manuell wandert anschliessend in Manuelle-Freigabe");

      //      SELECT DISTINCT a.name, a.ort, a.telefon, a.email, a.id
      //      FROM adresse a LEFT JOIN adresse_rolle r ON a.id=r.adresse WHERE r.subjekt='Kunde' ORDER by a.id DESC
      //       $table->Display(INHALT,"auftrag","kundeuebernehmen","In Auftrag einf&uuml;gen");
    } else {

      return "SELECT DISTINCT a.nummer, a.name_de as Artikel, p.abkuerzung, a.id FROM artikel a LEFT JOIN projekt p ON p.id=a.projekt WHERE a.geloescht='0'
        ORDER by a.id DESC";

    }
    //$this->app->Tpl->Set(INHALT,"");
  }

  function AdressSuche($parsetarget,$rolle)
  {
    $suche = $this->app->Secure->GetPOST("suche");
    /* Auftrage fuer manuelle freigabe */
    if($rolle!="")
      $this->app->Tpl->Set('SUBHEADING',"$rolle suchen");
    else
      $this->app->Tpl->Set('SUBHEADING',"Adresse suchen");

    $name = $this->app->Secure->GetPOST("name"); $this->app->Tpl->Set('SUCHENAME',$name);
    $typ = $this->app->Secure->GetPOST("typ");
    $ansprechpartner = $this->app->Secure->GetPOST("ansprechpartner");  $this->app->Tpl->Set('SUCHEANSPRECHPARTNER',$ansprechpartner);
    $abteilung= $this->app->Secure->GetPOST("abteilung");
    $unterabteilung= $this->app->Secure->GetPOST("unterabteilung");
    $adresszusatz= $this->app->Secure->GetPOST("adresszusatz");
    $email= $this->app->Secure->GetPOST("email");
    $telefon= $this->app->Secure->GetPOST("telefon");
    $telefax= $this->app->Secure->GetPOST("telefax");
    $ustid= $this->app->Secure->GetPOST("ustid");
    $land= $this->app->Secure->GetPOST("land");
    $plz= $this->app->Secure->GetPOST("plz");  $this->app->Tpl->Set('SUCHEPLZ',$plz);
    $ort= $this->app->Secure->GetPOST("ort");  $this->app->Tpl->Set('SUCHEORT',$ort);
    $strasse= $this->app->Secure->GetPOST("strasse");  $this->app->Tpl->Set('SUCHESTRASSE',$strasse);
    $kundennummer= $this->app->Secure->GetPOST("kundennummer");  $this->app->Tpl->Set('KUNDENNUMMER',$kundennummer);

    if($name!="" && $suche!="")
    {
      $_SESSION['name'] = $name;
    } elseif ($suche!="" && $name=="")
    $_SESSION['name'] = "";


    if($name=="" && $suche!="")
    {
      $_SESSION['name'] = $name;
    }

    $_SESSION['ort'] = $ort;
    $_SESSION['plz'] = $plz;


    if($name==""){ $name = $_SESSION['name'];  $this->app->Tpl->Set('SUCHENAME',$name);}
    if($ort==""){$ort= $_SESSION['ort']; $this->app->Tpl->Set('SUCHEORT',$ort);}
    if($plz==""){$plz= $_SESSION['plz']; $this->app->Tpl->Set('SUCHEPLZ',$plz);}

    if($name!="" || $ort!="" || $plz!="") $suche ="suche";

    $this->app->Tpl->Parse($parsetarget,"kundensuche.tpl");

    if(($name!="" || $kundennummer!="" || $strasse!="" || $ort!="" || $plz!="") && $suche!=""){
      //Jeder der in Nachbesserung war egal ob auto oder manuell wandert anschliessend in Manuelle-Freigabe");
      return ("SELECT DISTINCT a.kundennummer, a.name, a.ort, a.telefon, a.email, a.id FROM adresse a LEFT JOIN adresse_rolle r ON a.id=r.adresse WHERE
          a.name LIKE '%$name%' AND
          a.ansprechpartner LIKE '%$ansprechpartner%' AND
          a.ort LIKE '%$ort%' AND
          a.strasse LIKE '%$strasse%' AND
          a.kundennummer LIKE '%$kundennummer%' AND
          a.plz LIKE '%$plz%' AND a.geloescht=0 ORDER by a.id DESC");
      //a.plz LIKE '%$plz%' AND r.subjekt='$rolle' ORDER by a.id DESC");

      //      SELECT DISTINCT a.name, a.ort, a.telefon, a.email, a.id
      //      FROM adresse a LEFT JOIN adresse_rolle r ON a.id=r.adresse WHERE r.subjekt='Kunde' ORDER by a.id DESC
      //       $table->Display(INHALT,"auftrag","kundeuebernehmen","In Auftrag einf&uuml;gen");
    } else {

      return "SELECT DISTINCT a.name, a.ort, a.telefon, a.email, a.id
        FROM adresse a WHERE a.geloescht=0 ORDER by a.name ASC";
      //FROM adresse a LEFT JOIN adresse_rolle r ON a.id=r.adresse WHERE r.subjekt='$rolle' ORDER by a.id DESC";

    }
    //$this->app->Tpl->Set(INHALT,"");
  }

  function string2array ($string, $template){
//#search defined dividers
    preg_match_all ("|%(.+)%|U", $template, $template_matches);
//#replace dividers with "real dividers"
    $template = preg_replace ("|%(.+)%|U", "(.+)", $template);
//#search matches
    preg_match ("|" . $template . "|", $string, $string_matches);
//#[template_match] => $string_match
    foreach ($template_matches[1] as $key => $value){
      $output[$value] = $string_matches[($key + 1)];
    }
    return $output;
  }


  function SelectLaenderliste($selected="")
  {
    if($selected=="") $selected=$this->Firmendaten("land");

    $laender = $this->GetSelectLaenderliste(true);
    $options = '';
    foreach ($laender as $land => $kuerzel) {
      $options = $options."<option value=\"$kuerzel\"";
      if ($selected == $kuerzel) $options = $options." selected";
      $options = $options.">$land</option>\n";
    }
    return $options;
  }


  function GetSelectStaatenliste($land = 'DE', $staatenliste=false){
    switch ($land) {
      case 'DE':
        $staaten = array(
          'Baden-Württemberg' => 'BW',
          'Bayern' => 'BY',
          'Berlin' => 'BE',
          'Brandenburg' => 'BB',
          'Bremen' => 'HB',
          'Hamburg' => 'HH',
          'Hessen' => 'HE',
          'Mecklenburg-Vorpommern' => 'MV',
          'Niedersachsen' => 'NI',
          'Nordrhein-Westfalen' => 'NW',
          'Rheinland-Pfalz' => 'RP',
          'Saarland' => 'SL',
          'Sachsen' => 'SN',
          'Sachsen-Anhalt' => 'ST',
          'Schleswig-Holstein' => 'SH',
          'Thüringen' => 'TH'
        );
        break;

      case 'AT':
        $staaten = array(
          'Burgenland' => '01',
          'Kärnten' => '02',
          'Niederösterreich' => '03',
          'Oberösterreich' => '04',
          'Salzburg' => '05',
          'Steiermark' => '06',
          'Tirol' => '07',
          'Vorarlberg' => '08',
          'Wien' => '09'
        );
        break;

      case 'CH':
        $staaten = array(
          'Aargau' => 'AG',
          'Appenzell Ausserrhoden' => 'AR',
          'Appenzell Innerrhoden' => 'AI',
          'Basel-Landschaft' => 'BL',
          'Basel-Stadt' => 'BS',
          'Bern' => 'BE',
          'Freiburg' => 'FR',
          'Genf' => 'GE',
          'Glarus' => 'GL',
          'Graubünden' => 'GR',
          'Jura' => 'JU',
          'Luzern' => 'LU',
          'Neuenburg' => 'NE',
          'Nidwalden' => 'NW',
          'Obwalden' => 'OW',
          'Schaffhausen' => 'SH',
          'Schwyz' => 'SZ',
          'Solothurn' => 'SO',
          'St. Gallen' => 'SG',
          'Tessin' => 'TI',
          'Thurgau' => 'TG',
          'Uri' => 'UR',
          'Waadt' => 'VD',
          'Wallis' => 'VS',
          'Zug' => 'ZG',
          'Zürich' => 'ZH'
        );
        break;

      case 'CA':
        $staaten = array(
          'Alberta' => 'AB',
          'British Columbia' => 'BC',
          'Manitoba' => 'MB',
          'Neufundland und Labrador' => 'NL',
          'New Brunswick' => 'NB',
          'Nordwest-Territorien' => 'NT',
          'Nova Scotia' => 'NS',
          'Nunavut' => 'NU',
          'Ontario' => 'ON',
          'Prince Edward Island' => 'PE',
          'Quebéc' => 'QC',
          'Saskatchewan' => 'SK',
          'Yukon' => 'YT'
        );
        break;

      case 'US':
        $staaten = array(
          'Alabama' => 'AL',
          'Alaska' => 'AK',
          'Arizona' => 'AZ',
          'Arkansas' => 'AR',
          'Colorado' => 'CO',
          'Connecticut' => 'CT',
          'Delaware' => 'DE',
          'Florida' => 'FL',
          'Georgia' => 'GA',
          'Hawaii' => 'HI',
          'Idaho' => 'ID',
          'Illinois' => 'IL',
          'Indiana' => 'IN',
          'Iowa' => 'IA',
          'Kalifornien' => 'CA',
          'Kansas' => 'KS',
          'Kentucky' => 'KY',
          'Louisiana' => 'LA',
          'Maine' => 'ME',
          'Maryland' => 'MD',
          'Massachusetts' => 'MA',
          'Michigan' => 'MI',
          'Minnesota' => 'MN',
          'Mississippi' => 'MS',
          'Missouri' => 'MO',
          'Montana' => 'MT',
          'Nebraska' => 'NE',
          'Nevada' => 'NV',
          'New Hampshire' => 'NH',
          'New Jersey' => 'NJ',
          'New Mexico' => 'NM',
          'New York' => 'NY',
          'North Carolina' => 'NC',
          'North Dakota' => 'ND',
          'Ohio' => 'OH',
          'Oklahoma' => 'OK',
          'Oregon' => 'OR',
          'Pennsylvania' => 'PA',
          'Rhode Island' => 'RI',
          'South Carolina' => 'SC',
          'South Dakota' => 'SD',
          'Tennessee' => 'TN',
          'Texas' => 'TX',
          'Utah' => 'UT',
          'Vermont' => 'VT',
          'Virginia' => 'VA',
          'Washington' => 'WA',
          'West Virginia' => 'WV',
          'Wisconsin' => 'WI',
          'Wyoming' => 'WY'
        );
        break;
    }

    $Values = array();
/*    while(list($Key,$Val) = each($staaten))
      $Values[$Val] = $Key; */

    foreach($staaten as $Key => $Val) {
       $$Values[$Val] = $Key;
    }

    if($staatenliste)
      return $staaten;
    else
      return $Values;


}


  function FindISOCountry($country)
  {
    if(strlen($country)==2) return $country;

    $check = $this->GetSelectLaenderliste();
    foreach($check as $iso=>$countryname)
    {
      if(strtolower($countryname)===strtolower($country)) return $iso;
    }
    $check = $this->GetSelectLaenderlisteEN();
    foreach($check as $iso=>$countryname)
    {
      if(strtolower($countryname)===strtolower($country)) return $iso;
    }
    return -1;
  }

  /**
   * @param bool $laenderliste
   *
   * @return array
   */
  public function GetSelectLaenderliste($laenderliste=false)
  {
    if($laenderliste) {
      $tmp = $this->app->DB->SelectPairs(
        'SELECT bezeichnung_de, iso FROM laender ORDER BY bezeichnung_de'
      );
    }
    else {
      $tmp = $this->app->DB->SelectPairs(
        'SELECT iso, bezeichnung_de FROM laender ORDER BY bezeichnung_de'
      );
    }
    if(!empty($tmp)) {
      return $tmp;
    }

    $laender = array(
        'Afghanistan'  => 'AF',
        '&Auml;gypten'  => 'EG',
        'Albanien'  => 'AL',
        'Algerien'  => 'DZ',
        'Amerikanische Jungferninseln' => 'VI',
        'Andorra'  => 'AD',
        'Angola'  => 'AO',
        'Anguilla'  => 'AI',
        'Antarktis'  => 'AQ',
        'Antigua und Barbuda'  => 'AG',
        '&Auml;quatorialguinea'  => 'GQ',
        'Argentinien'  => 'AR',
        'Armenien'  => 'AM',
        'Aruba'  => 'AW',
        'Aserbaidschan'  => 'AZ',
        '&Auml;thiopien'  => 'ET',
        'Australien'  => 'AU',
        'Bahamas'  => 'BS',
        'Bahrain'  => 'BH',
        'Bangladesch'  => 'BD',
        'Barbados'  => 'BB',
        'Belgien'  => 'BE',
        'Belize'  => 'BZ',
        'Benin'  => 'BJ',
        'Bermuda'  => 'BM',
        'Bhutan'  => 'BT',
        'Bolivien'  => 'BO',
        'Bosnien und Herzegowina'  => 'BA',
        'Botswana'  => 'BW',
        'Bouvetinsel'  => 'BV',
        'Brasilien'  => 'BR',
        'Britisch-Indischer Ozean'  => 'IO',
        'Britische Jungferninseln' => 'VG',
        'Brunei Darussalam'  => 'BN',
        'Bulgarien'  => 'BG',
        'Burkina Faso'  => 'BF',
        'Burundi'  => 'BI',
        'Chile'  => 'CL',
        'China'  => 'CN',
        'Cookinseln'  => 'CK',
        'Costa Rica'  => 'CR',
        'D&auml;nemark'  => 'DK',
        'Deutschland'  => 'DE',
        'Dominica'  => 'DM',
        'Dominikanische Republik'  => 'DO',
        'Dschibuti'  => 'DJ',
        'Ecuador'  => 'EC',
        'El Salvador'  => 'SV',
        'Elfenbeink&uuml;ste'  => 'CI',
        'Eritrea'  => 'ER',
        'Estland'  => 'EE',
        'Falklandinseln'  => 'FK',
        'F&auml;r&ouml;er Inseln'  => 'FO',
        'Fidschi'  => 'FJ',
        'Finnland'  => 'FI',
        'Frankreich'  => 'FR',
        'Franz&ouml;sisch-Guayana'  => 'GF',
        'Franz&ouml;sisch-Polynesien'  => 'PF',
        'Franz&ouml;sisches S&uuml;d-Territorium'  => 'TF',
        'Gabun'  => 'GA',
        'Gambia'  => 'GM',
        'Georgien'  => 'GE',
        'Ghana'  => 'GH',
        'Gibraltar'  => 'GI',
        'Grenada'  => 'GD',
        'Griechenland'  => 'GR',
        'Gr&ouml;nland'  => 'GL',
        'Gro&szlig;britannien'  => 'GB',
        'Guadeloupe'  => 'GP',
        'Guam'  => 'GU',
        'Guatemala'  => 'GT',
        'Guinea'  => 'GN',
        'Guinea-Bissau'  => 'GW',
        'Guyana'  => 'GY',
        'Haiti'  => 'HT',
        'Heard und McDonaldinseln'  => 'HM',
        'Honduras'  => 'HN',
        'Hongkong'  => 'HK',
        'Indien'  => 'IN',
        'Indonesien'  => 'ID',
        'Irak'  => 'IQ',
        'Iran'  => 'IR',
        'Irland'  => 'IE',
        'Island'  => 'IS',
        'Israel'  => 'IL',
        'Italien'  => 'IT',
        'Jamaika'  => 'JM',
        'Japan'  => 'JP',
        'Jemen'  => 'YE',
        'Jordanien'  => 'JO',
        'Kaimaninseln'  => 'KY',
        'Kambodscha'  => 'KH',
        'Kamerun'  => 'CM',
        'Kanada'  => 'CA',
        'Kap Verde'  => 'CV',
        'Kasachstan'  => 'KZ',
        'Katar'  => 'QA',
        'Kenia'  => 'KE',
        'Kirgisistan'  => 'KG',
        'Kiribati'  => 'KI',
        'Kokosinseln'  => 'CC',
        'Kolumbien'  => 'CO',
        'Komoren'  => 'KM',
        'Kongo'  => 'CG',
        'Kongo, Demokratische Republik'  => 'CD',
        'Kosovo' => 'XK',
        'Kroatien'  => 'HR',
        'Kuba'  => 'CU',
        'Kuwait'  => 'KW',
        'Laos'  => 'LA',
        'Lesotho'  => 'LS',
        'Lettland'  => 'LV',
        'Libanon'  => 'LB',
        'Liberia'  => 'LR',
        'Libyen'  => 'LY',
        'Liechtenstein'  => 'LI',
        'Litauen'  => 'LT',
        'Luxemburg'  => 'LU',
        'Macau'  => 'MO',
        'Madagaskar'  => 'MG',
        'Malawi'  => 'MW',
        'Malaysia'  => 'MY',
        'Malediven'  => 'MV',
        'Mali'  => 'ML',
        'Malta'  => 'MT',
        'Marianen'  => 'MP',
        'Marokko'  => 'MA',
        'Marshallinseln'  => 'MH',
        'Martinique'  => 'MQ',
        'Mauretanien'  => 'MR',
        'Mauritius'  => 'MU',
        'Mayotte'  => 'YT',
        'Mazedonien'  => 'MK',
        'Mexiko'  => 'MX',
        'Mikronesien'  => 'FM',
        'Moldawien'  => 'MD',
        'Monaco'  => 'MC',
        'Mongolei'  => 'MN',
        'Montenegro' => 'ME',
        'Montserrat'  => 'MS',
        'Mosambik'  => 'MZ',
        'Myanmar' => 'MM',
        'Namibia'  => 'NA',
        'Nauru'  => 'NR',
        'Nepal'  => 'NP',
        'Neukaledonien'  => 'NC',
        'Neuseeland'  => 'NZ',
        'Nicaragua'  => 'NI',
        'Niederlande'  => 'NL',
        'Niger'  => 'NE',
        'Nigeria'  => 'NG',
        'Niue'  => 'NU',
        'Nordkorea'  => 'KP',
        'Norfolkinsel'  => 'NF',
        'Norwegen'  => 'NO',
        'Oman'  => 'OM',
        '&Ouml;sterreich'  => 'AT',
        'Pakistan'  => 'PK',
        'Pal&auml;stina'  => 'PS',
        'Palau'  => 'PW',
        'Panama'  => 'PA',
        'Papua-Neuguinea'  => 'PG',
        'Paraguay'  => 'PY',
        'Peru'  => 'PE',
        'Philippinen'  => 'PH',
        'Pitcairninseln'  => 'PN',
        'Polen'  => 'PL',
        'Portugal'  => 'PT',
        'Puerto Rico'  => 'PR',
        'Réunion'  => 'RE',
        'Ruanda'  => 'RW',
        'Rum&auml;nien'  => 'RO',
        'Russland'  => 'RU',
        'Salomonen'  => 'SB',
        'Sambia'  => 'ZM',
        'Samoa, amerikanisch'  => 'AS',
        'Samoa'  => 'WS',
        'San Marino'  => 'SM',
        'São Tomé und Príncipe'  => 'ST',
        'Saudi-Arabien'  => 'SA',
        'Schweden'  => 'SE',
        'Schweiz'  => 'CH',
        'Senegal'  => 'SN',
        'Serbien' => 'RS',
        'Seychellen'  => 'SC',
        'Sierra Leone'  => 'SL',
        'Simbabwe' => 'ZW',
        'Singapur'  => 'SG',
        'Slowakei'  => 'SK',
        'Slowenien'  => 'SI',
        'Somalia'  => 'SO',
        'S&uuml;dgeorgien, s&uuml;dliche Sandwichinseln'  => 'GS',
        'Spanien'  => 'ES',
        'Sri Lanka'  => 'LK',
        'St. Helena'  => 'SH',
        'St. Kitts und Nevis'  => 'KN',
        'St. Lucia'  => 'LC',
        'St. Pierre und Miquelon'  => 'PM',
        'St. Vincent und die Grenadinen'  => 'VC',
        'S&uuml;dkorea'  => 'KR',
        'S&uuml;dafrika'  => 'ZA',
        'Sudan'  => 'SD',
        'Suriname'  => 'SR',
        'Svalbard und Jan Mayen'  => 'SJ',
        'Swasiland'  => 'SZ',
        'Syrien'  => 'SY',
        'Tadschikistan'  => 'TJ',
        'Taiwan'  => 'TW',
        'Tansania'  => 'TZ',
        'Thailand'  => 'TH',
        'Togo'  => 'TG',
        'Tokelau'  => 'TK',
        'Tonga'  => 'TO',
        'Trinidad und Tobago'  => 'TT',
        'Tschad'  => 'TD',
        'Tschechien'  => 'CZ',
        'Tunesien'  => 'TN',
        'T&uuml;rkei'  => 'TR',
        'Turkmenistan'  => 'TM',
        'Turks- und Caicosinseln'  => 'TC',
        'Tuvalu'  => 'TV',
        'Uganda'  => 'UG',
        'Ukraine'  => 'UA',
        'Ungarn'  => 'HU',
        'Uruguay'  => 'UY',
        'Usbekistan'  => 'UZ',
        'Vanuatu'  => 'VU',
        'Vatikanstadt'  => 'VA',
        'Venezuela'  => 'VE',
        'Vereinigte Arabische Emirate'  => 'AE',
        'Vereinigtes Königreich' => 'UK',
        'Vereinigte Staaten von Amerika'  => 'US',
        'Vietnam'  => 'VN',
        'Wallis und Futuna'  => 'WF',
        'Weihnachtsinsel' => 'CX',
        'Wei&szlig;russland'  => 'BY',
        'Westsahara'  => 'EH',
        'Zentralafrikanische Republik'  => 'CF',
        'Zypern'  => 'CY'
          );

    if($laenderliste) {
      return $laender;
    }

    return array_flip($laender);
  }


  /**
   * @param bool $laenderliste
   *
   * @return array
   */
  public function GetSelectLaenderlisteEN($laenderliste=false)
  {
    if($laenderliste) {
      $tmp = $this->app->DB->SelectPairs(
        'SELECT bezeichnung_en, iso FROM laender ORDER BY bezeichnung_en'
      );
    }
    else {
      $tmp = $this->app->DB->SelectPairs(
        'SELECT iso, bezeichnung_en FROM laender ORDER BY bezeichnung_en'
      );
    }
    if(!empty($tmp)) {
      return $tmp;
    }

    $laender = array(
        'Afghanistan'  => 'AF',
        'Albania'  => 'AL',
        'Algeria'  => 'DZ',
        'Andorra'  => 'AD',
        'Angola'  => 'AO',
        'Anguilla'  => 'AI',
        'Antarctica'  => 'AQ',
        'Antigua and Barbuda'  => 'AG',
        'Argentina'  => 'AR',
        'Armenia'  => 'AM',
        'Aruba'  => 'AW',
        'Australia'  => 'AU',
        'Austria'  => 'AT',
        'Azerbaijan'  => 'AZ',
        'Bahamas'  => 'BS',
        'Bahrain'  => 'BH',
        'Bangladesh'  => 'BD',
        'Barbados'  => 'BB',
        'Belarus'  => 'BY',
        'Belgium'  => 'BE',
        'Belize'  => 'BZ',
        'Benin'  => 'BJ',
        'Bermuda'  => 'BM',
        'Bhutan'  => 'BT',
        'Bolivia'  => 'BO',
        'Bosnia and Herzegovina'  => 'BA',
        'Botswana'  => 'BW',
        'Bouvet Island'  => 'BV',
        'Brazil'  => 'BR',
        'British Indian Ocean Territory'  => 'IO',
        'Brunei Darussalam'  => 'BN',
        'Bulgaria'  => 'BG',
        'Burkina Faso'  => 'BF',
        'Burundi'  => 'BI',
        'Cabo Verde'  => 'CV',
        'Cambodia'  => 'KH',
        'Cameroon'  => 'CM',
        'Canada'  => 'CA',
        'Cayman Islands'  => 'KY',
        'Central African Republic'  => 'CF',
        'Chad'  => 'TD',
        'Chile'  => 'CL',
        'China'  => 'CN',
        'Christmas Island'  => 'CX',
        'Cocos Islands'  => 'CC',
        'Colombia'  => 'CO',
        'Comoros'  => 'KM',
        'Congo'  => 'CG',
        'Congo (Democratic Republic)'  => 'CD',
        'Cook Islands'  => 'CK',
        'Costa Rica'  => 'CR',
        'Côte d\'Ivoire'  => 'CI',
        'Croatia'  => 'HR',
        'Cuba'  => 'CU',
        'Cyprus'  => 'CY',
        'Czech Republic'  => 'CZ',
        'Denmark'  => 'DK',
        'Djibouti'  => 'DJ',
        'Dominica'  => 'DM',
        'Dominican Republic'  => 'DO',
        'Ecuador'  => 'EC',
        'Egypt'  => 'EG',
        'El Salvador'  => 'SV',
        'Equatorial Guinea'  => 'GQ',
        'Eritrea'  => 'ER',
        'Estonia'  => 'EE',
        'Ethiopia'  => 'ET',
        'Falkland Islands'  => 'FK',
        'Faroe Islands'  => 'FO',
        'Fiji'  => 'FJ',
        'Finland'  => 'FI',
        'France'  => 'FR',
        'French Guiana'  => 'GF',
        'French Polynesia'  => 'PF',
        'French Southern Territories'  => 'TF',
        'Gabon'  => 'GA',
        'Gambia'  => 'GM',
        'Georgia'  => 'GE',
        'Germany' => 'DE',
        'Ghana'  => 'GH',
        'Gibraltar'  => 'GI',
        'Greece'  => 'GR',
        'Greenland'  => 'GL',
        'Grenada'  => 'GD',
        'Guadeloupe'  => 'GP',
        'Guam'  => 'GU',
        'Guatemala'  => 'GT',
        'Guinea'  => 'GN',
        'Guinea-Bissau'  => 'GW',
        'Guyana'  => 'GY',
        'Haiti'  => 'HT',
        'Heard Island and McDonald Islands'  => 'HM',
        'Holy See'  => 'VA',
        'Honduras'  => 'HN',
        'Hong Kong'  => 'HK',
        'Hungary'  => 'HU',
        'Iceland'  => 'IS',
        'India'  => 'IN',
        'Indonesia'  => 'ID',
        'Iran'  => 'IR',
        'Iraq'  => 'IQ',
        'Ireland'  => 'IE',
        'Israel'  => 'IL',
        'Italy'  => 'IT',
        'Jamaica'  => 'JM',
        'Japan'  => 'JP',
        'Jordan'  => 'JO',
        'Kazakhstan'  => 'KZ',
        'Kenya'  => 'KE',
        'Kiribati'  => 'KI',
        'Korea (Democratic Republic)'  => 'KP',
        'Korea (Republic of)' => 'KR',
        'Kosovo' => 'XK',
        'Kuwait'  => 'KW',
        'Kyrgyzstan'  => 'KG',
        'Lao'  => 'LA',
        'Latvia'  => 'LV',
        'Lebanon'  => 'LB',
        'Lesotho'  => 'LS',
        'Liberia'  => 'LR',
        'Libya'  => 'LY',
        'Liechtenstein'  => 'LI',
        'Lithuania'  => 'LT',
        'Luxembourg'  => 'LU',
        'Macao'  => 'MO',
        'Macedonia'  => 'MK',
        'Madagascar'  => 'MG',
        'Malawi'  => 'MW',
        'Malaysia'  => 'MY',
        'Maldives'  => 'MV',
        'Mali'  => 'ML',
        'Malta'  => 'MT',
        'Marshall Islands'  => 'MH',
        'Martinique'  => 'MQ',
        'Mauritania'  => 'MR',
        'Mauritius'  => 'MU',
        'Mayotte'  => 'YT',
        'Mexico'  => 'MX',
        'Micronesia'  => 'FM',
        'Moldova'  => 'MD',
        'Monaco'  => 'MC',
        'Mongolia'  => 'MN',
        'Montenegro' => 'ME',
        'Montserrat'  => 'MS',
        'Morocco'  => 'MA',
        'Mozambique'  => 'MZ',
        'Myanmar' => 'MM',
        'Namibia'  => 'NA',
        'Nauru'  => 'NR',
        'Nepal'  => 'NP',
        'New Caledonia'  => 'NC',
        'New Zealand'  => 'NZ',
        'Nicaragua'  => 'NI',
        'Netherlands'  => 'NL',
        'Niger'  => 'NE',
        'Nigeria'  => 'NG',
        'Niue'  => 'NU',
        'Norfolk Island'  => 'NF',
        'Northern Mariana Islands'  => 'MP',
        'Norway'  => 'NO',
        'Oman'  => 'OM',
        'Pakistan'  => 'PK',
        'Palau'  => 'PW',
        'Palestine'  => 'PS',
        'Panama'  => 'PA',
        'Papua New Guinea'  => 'PG',
        'Paraguay'  => 'PY',
        'Peru'  => 'PE',
        'Philippines'  => 'PH',
        'Pitcairn'  => 'PN',
        'Poland'  => 'PL',
        'Portugal'  => 'PT',
        'Puerto Rico'  => 'PR',
        'Qatar'  => 'QA',
        'Réunion'  => 'RE',
        'Romania'  => 'RO',
        'Russia'  => 'RU',
        'Rwanda'  => 'RW',
        'Saint Helena'  => 'SH',
        'Saint Kitts and Nevis'  => 'KN',
        'Saint Lucia'  => 'LC',
        'Saint Pierre and Miquelon'  => 'PM',
        'Saint Vincent and the Grenadines'  => 'VC',
        'Samoa (American)'  => 'AS',
        'Samoa'  => 'WS',
        'San Marino'  => 'SM',
        'Sao Tome and Principe'  => 'ST',
        'Saudi Arabia'  => 'SA',
        'Senegal'  => 'SN',
        'Serbia' => 'RS',
        'Seychelles'  => 'SC',
        'Sierra Leone'  => 'SL',
        'Singapore'  => 'SG',
        'Slovakia'  => 'SK',
        'Slovenia'  => 'SI',
        'Solomon Islands'  => 'SB',
        'Somalia'  => 'SO',
        'South Africa'  => 'ZA',
        'South Georgia, South Sandwich Isl.'  => 'GS',
        'Spain'  => 'ES',
        'Sri Lanka'  => 'LK',
        'Sudan'  => 'SD',
        'Suriname'  => 'SR',
        'Svalbard and Jan Mayen'  => 'SJ',
        'Swaziland'  => 'SZ',
        'Sweden'  => 'SE',
        'Switzerland'  => 'CH',
        'Syrian'  => 'SY',
        'Taiwan'  => 'TW',
        'Tajikistan'  => 'TJ',
        'Tanzania'  => 'TZ',
        'Thailand'  => 'TH',
        'Timor-Leste'  => 'TL',
        'Togo'  => 'TG',
        'Tokelau'  => 'TK',
        'Tonga'  => 'TO',
        'Trinidad and Tobago'  => 'TT',
        'Tunisia'  => 'TN',
        'Turkey'  => 'TR',
        'Turkmenistan'  => 'TM',
        'Turks and Caicos Islands'  => 'TC',
        'Tuvalu'  => 'TV',
        'Uganda'  => 'UG',
        'Ukraine'  => 'UA',
        'United Arab Emirates'  => 'AE',
        'United Kingdom'  => 'GB',
        'United States of America'  => 'US',
        'Uruguay'  => 'UY',
        'Uzbekistan'  => 'UZ',
        'Vanuatu'  => 'VU',
        'Venezuela'  => 'VE',
        'Viet Nam'  => 'VN',
        'Virgin Islands (Brit.)'  => 'VG',
        'Virgin Islands (USA)'  => 'VI',
        'Wallis and Futuna'  => 'WF',
        'Western Sahara'  => 'EH',
        'Yemen'  => 'YE',
        'Zambia'  => 'ZM',
        'Zimbabwe'  => 'ZW',

          );

    if($laenderliste) {
      return $laender;
    }

    return array_flip($laender);
  }

  /**
   * @return array
   */
  public function GetAdressSprachen()
  {
    return array('deutsch'=>'DE','englisch'=>'EN','franzoesisch'=>'FR','hollaendisch'=>'NL','italienisch'=>'IT','spanisch'=>'ES','tschechisch'=>'CZ','daenisch'=>'DK','slowakisch'=>'SK','schwedisch'=>'SW','polnisch'=>'PL' );
  }

  function RMAGrund(){
    $gruende = array(
                'gutschrift' => 'Gutschrift zu ausgew&auml;hlten Artikeln',
                'ersatzlieferung' => 'Kostenlose Ersatzlieferung veranlassen',
                'ruecksendung' => 'R&uuml;cksendung der ausgew&auml;hlten Artikel',
                'internreparatur' => 'ausgew&auml;hlte zur internen Reparatur geben',
                'externreparatur' => 'ausgew&auml;hlte f&uuml;r Reparatur zur&uuml;ckschicken',
                'abgeschlossen' => 'ausgew&auml;hlte Artikel auf abgeschlossen setzen',
                'offen' => 'ausgew&auml;hlte Artikel auf offen setzen');

    return $gruende;
  }

  /**
   * @param bool $sprachenliste
   *
   * @return array
   */
  public function GetSelectSprachenListe($sprachenliste=false)
  {
    if($sprachenliste) {
      $tmp = $this->app->DB->SelectPairs('SELECT bezeichnung_de, iso FROM sprachen ORDER BY bezeichnung_de');
    }
    else {
      $tmp = $this->app->DB->SelectPairs('SELECT iso, bezeichnung_de FROM sprachen ORDER BY bezeichnung_de');
    }
    if(!empty($tmp) && (!empty($tmp)?count($tmp):0) > 1) {
      return array_merge([''], $tmp);
    }

    $sprachen = array(
        'Afrikaans'  => 'AF',
        'Albanisch' => 'SQ',
        'Arabisch' => 'AR',
        'Armenisch' => 'HY',
        'Aserbeidschanisch' => 'AZ',
        'Bosnisch' =>'BS',
        'Bulgarisch' => 'BG',
        'Chinesisch' => 'ZH',
        'D&auml;nisch' => 'DA',
        'Deutsch' => 'DE',
        'Englisch' => 'EN',
        'Estnisch' => 'ET',
        'Finnisch' => 'FI',
        'Franz&ouml;sisch' => 'FR',
        'Georgisch' => 'KA',
        'Griechisch' => 'EL',
        'Holl&auml;ndisch' => 'NL',
        'Isl&auml;ndisch' => 'IS',
        'Italienisch' => 'IT',
        'Japanisch' => 'JA',
        'Kasachisch' => 'KK',
        'Koreanisch' => 'KO',
        'Kroatisch' => 'HR',
        'Lettisch' => 'LV',
        'Litauisch' => 'LT',
        'Norwegisch' => 'NO',
        'Polnisch' => 'PL',
        'Portugiesisch' => 'PT',
        'Rum&auml;nisch' => 'RO',
        'Russisch' => 'RU',
        'Schwedisch' => 'SV',
        'Serbisch' => 'SR',
        'Slowakisch' => 'SK',
        'Slowenisch' => 'SL',
        'Spanisch' => 'ES',
        'Tschechisch' => 'CZ',
        'T&uuml;rkisch' => 'TR',
        'Ukrainisch' => 'UK',
        'Ungarisch' => 'HU',
        'Wei&szlig;russisch' => 'BY'
    );
    if($sprachenliste) {
      return $sprachen;
    }

    return array_flip($sprachen);
  }

  /**
   * @param bool $sprachenliste
   *
   * @return array
   */
  public function GetSelectSprachenListeEN($sprachenliste=false)
  {
    if($sprachenliste) {
      $tmp = $this->app->DB->SelectPairs('SELECT bezeichnung_en, iso FROM sprachen ORDER BY bezeichnung_en');
    }
    else {
      $tmp = $this->app->DB->SelectPairs('SELECT iso, bezeichnung_en FROM sprachen ORDER BY bezeichnung_en');
    }
    if(!empty($tmp) && (!empty($tmp)?count($tmp):0) > 1) {
      return array_merge([''], $tmp);
    }

    $sprachen = array(
        'Afrikaans'  => 'AF',
        'Albanian' => 'SQ',
        'Arabic' => 'AR',
        'Armenian' => 'HY',
        'Azerbaijani' => 'AZ',
        'Bosnian' =>'BS',
        'Bulgarian' => 'BG',
        'Chinese' => 'ZH',
        'Danish' => 'DA',
        'German' => 'DE',
        'English' => 'EN',
        'Estonian' => 'ET',
        'Finnish' => 'FI',
        'French' => 'FR',
        'Georgian' => 'KA',
        'Greek' => 'EL',
        'Dutch' => 'NL',
        'Icelandic' => 'IS',
        'Italian' => 'IT',
        'Japanese' => 'JA',
        'Kazakh' => 'KK',
        'Korean' => 'KO',
        'Croatian' => 'HR',
        'Latvian' => 'LV',
        'Lithuanian' => 'LT',
        'Norwegian' => 'NO',
        'Polish' => 'PL',
        'Portuguese' => 'PT',
        'Romanian' => 'RO',
        'Russian' => 'RU',
        'Swedish' => 'SV',
        'Serbian' => 'SR',
        'Slovak' => 'SK',
        'Slovenian' => 'SL',
        'Spanish' => 'ES',
        'Czech' => 'CZ',
        'Turkish' => 'TR',
        'Ukrainian' => 'UK',
        'Hungarian' => 'HU',
        'Belarusian' => 'BE'
    );

    if($sprachenliste) {
      return $sprachen;
    }

    return array_flip($sprachen);
  }

  function GetFirmaBCC1()
  {
    return $this->Firmendaten('bcc1');
  }

  function GetFirmaBCC2()
  {
    return $this->Firmendaten('bcc2');
  }

  function GetFirmaMail()
  {
    return $this->Firmendaten('email');
  }

  function GetFirmaName()
  {
    return $this->Firmendaten('name');
  }

  function GetFirmaAbsender()
  {
    $name = $this->Firmendaten('absendername');
    if($name!='') {
      return $name;
    }
    return $this->Firmendaten('name');
  }


  function GetSelectEmailMitName($selected="")
  {
  /*  $own = $this->app->User->GetEmail();
    $name = $this->app->User->GetName();

    $selected = str_replace(' <',' &lt;',$selected);
    $selected = str_replace('>','&gt;',$selected);

    $email_addr[0]['email'] = $this->Firmendaten('email');
    $absendernamefirma[0]['absendername'] = $this->Firmendaten('absendername');
    $firmenname = $this->Firmendaten('name');

    if($absendernamefirma[0]['absendername']=="") $absendernamefirma[0]['absendername']= $firmenname;


    $emails = array();

    if($this->app->User->GetField("email_bevorzugen")=="1")
    {
      if($own!='' && $name!='')
        $emails[] = $name." &lt;".$own."&gt;";
    }

    $i=0;
    foreach($email_addr AS $mail)
    {
      if($absendernamefirma[$i]['absendername']!="" && $mail['email']!="")
        $emails[] = $absendernamefirma[$i]['absendername']." &lt;".$mail['email']."&gt;";
    }

    if($this->app->User->GetField("email_bevorzugen")!="1")
    {
      if($own!='' && $name!='')
        $emails[] = $name." &lt;".$own."&gt;";
    }

    $email_addr = $this->app->DB->SelectArr("SELECT if(smtp_frommail!='',smtp_frommail,email) as email,smtp_fromname FROM emailbackup WHERE (smtp_frommail!='' OR email!='') AND (adresse<=0 OR adresse='".$this->app->User->GetAdresse()."') AND geloescht!=1 ORDER BY email");
*/
// Force only existing emailbackup accounts

//    $tpl = "<option value=\"\">-</option>";

    $email_addr = $this->app->DB->SelectArr("SELECT email, angezeigtername FROM emailbackup WHERE email != '' AND (adresse<=0 OR adresse='".$this->app->User->GetAdresse()."') AND geloescht!=1 ORDER BY email");

    if (empty($email_addr)) {
      return "";
    }

    foreach($email_addr AS $mail)
    {
      if($mail['angezeigtername']!="") $emails[] = $mail['angezeigtername']." &lt;".$mail['email']."&gt;";
      else $emails[] = $firmenname." &lt;".$mail['email']."&gt;";
    }

    $emails = array_keys(array_flip($emails));

    for($i=0;$i<(!empty($emails)?count($emails):0);$i++)
    {
      if($emails[$i]===$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$emails[$i]}\" $mark>{$emails[$i]}</option>";
    }
    return $tpl;
  }


  function GetSelectEmail($selected="")
  {
/*
    $own = $this->app->User->GetEmail();
    $email_addr= $this->Firmendaten("email");

    $emails = array();

    if($this->app->User->GetField("email_bevorzugen")=="1")
    {
      if($own!='')
        $emails[] = $own;
    }

    if($email_addr!="")
      $emails[] = $email_addr;

    $email_addr = $this->app->DB->SelectArr("SELECT if(smtp_frommail!='',smtp_frommail,email) as email FROM emailbackup WHERE (smtp_frommail!='' OR email!='') AND (adresse<=0 OR adresse='".$this->app->User->GetAdresse()."') AND geloescht!=1 ORDER BY email");
*/
// Force only existing emailbackup accounts

    $tpl = "<option value=\"\">-</option>";

    $email_addr = $this->app->DB->SelectArr("SELECT email FROM emailbackup WHERE email != '' AND (adresse<=0 OR adresse='".$this->app->User->GetAdresse()."') AND geloescht!=1 ORDER BY email");

    if (empty($email_addr)) {
      return "";
    }

    foreach($email_addr AS $mail) {
      $emails[] = $mail['email'];
    }

    $emails = array_keys(array_flip($emails));

    for($i=0;$i<(!empty($emails)?count($emails):0);$i++)
    {
      if($emails[$i]==$selected) {
         $mark="selected"; 
      }
      else {
         $mark="";
      }
      $tpl .="<option value=\"{$emails[$i]}\" $mark>{$emails[$i]}</option>";
    }

    return $tpl;
  }

  function GetSelectTicketmail($selected="")
  {
    /** @var Ticket $obj */
    $obj = $this->LoadModul('ticket');
    if(!empty($obj) && method_exists($obj, 'GetSelectTicketmail'))
    {
      return $obj->GetSelectTicketmail($selected);
    }
    return '';
  }

  function GetSelectDokumentKunde($typ,$adresse,$select)
  {
    $typ_bezeichnung = ucfirst($typ);
    $result = $this->app->DB->SelectArr("SELECT CONCAT('$typ_bezeichnung ',if(status='angelegt','ENTWURF',belegnr),' (Status: ',status,') vom ',DATE_FORMAT(datum,'%d.%m.%Y')) as
        result,id  FROM $typ WHERE adresse='$adresse' ORDER by datum DESC");
    if(empty($result)) {
      return '';
    }
    $tmp = '';
    foreach ($result as $row) {
      $tmp .= "<option value=\"".$row['id']."\">".$row['result']."</option>";
    }

    return $tmp;
  }


  function GetSelectAuftragKunde($adresse,$select="")
  {
    return $this->GetSelectDokumentKunde("auftrag",$adresse,$select);
  }

  function GetSelectRechnungKunde($adresse,$select="")
  {

    return $this->GetSelectDokumentKunde("rechnung",$adresse,$select);
  }

  function GetSelectArbeitsnachweisKunde($adresse,$select="")
  {
    return $this->GetSelectDokumentKunde("arbeitsnachweis",$adresse,$select);
  }

  function GetSelectAnsprechpartner($adresse, $selected="")
  {
    $first = $this->app->DB->Select("SELECT CONCAT(ansprechpartner,' &lt;',email,'&gt;') FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $firstname = $this->app->DB->Select("SELECT ansprechpartner FROM adresse WHERE id='$adresse' LIMIT 1");
    if($firstname=="") $first = $this->app->DB->Select("SELECT CONCAT(name,' &lt;',email,'&gt;') FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

    $others = $this->app->DB->SelectArr("SELECT id, CONCAT(name,' (',bereich,')',' &lt;',email,'&gt;') as name FROM ansprechpartner WHERE adresse='$adresse'");

    $tpl ="<option value=\"0\">$first</option>";

    for($i=0;$i<(!empty($others)?count($others):0);$i++)
    {
      if($others[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"".$others[$i]['id']."\" $mark>{$others[$i]['name']}</option>";
    }
    return $tpl;
  }   

  function GetVorgaenger($projekt,$disableid="")
  {
    $user = $this->app->DB->SelectArr("SELECT * FROM arbeitspaket WHERE projekt='".$projekt."' AND id!='$disableid' AND art!='material'");
    $tpl[0]="keinen";
    for($i=0;$i<(!empty($user)?count($user):0);$i++)
    {
      $tpl[$user[$i]['id']]=$user[$i]['aufgabe'];
    }
    return $tpl;
  }

  function GetMitarbeiter()
  {
    $user = $this->app->DB->SelectArr("SELECT DISTINCT a.id,a.name FROM adresse a INNER JOIN adresse_rolle ar on ar.adresse=a.id AND ar.subjekt='Mitarbeiter'        WHERE a.mitarbeiternummer!='' AND a.geloescht!=1 AND (ar.bis = '0000-00-00' or ar.bis >= now()) ORDER by name");

    for($i=0;$i<(!empty($user)?count($user):0);$i++)
    {
      $tmp[$i]['id'] = $user[$i]['id'];
      $tmp[$i]['name'] = $user[$i]['name'];
    }
    return $tmp;
  }


  function GetReisekostenartAssoc()
  {
    $user = $this->app->DB->SelectArr("SELECT * FROM reisekostenart ORDER by nummer");
    for($i=0;$i<(!empty($user)?count($user):0);$i++)
    {
      $tmp[(string)$user[$i]['id']] = "{$user[$i]['nummer']}- {$user[$i]['beschreibung']}";
    }
    return $tmp;
  }

  function GetSelectBezahltWie()
  {
    $tmp = $this->GetBezahltWieAssoc();

    foreach($tmp as $key=>$value)
      $result .= "<option value=\"$key\">$value</option>";
    return $result;
  }



  function GetLagerRegalart($selected="")
  {
    $tmp = array('Fachboden','Palette');
    foreach($tmp as $key=>$value)
    {
      if($value==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"".$value."\" $mark>{$value}</option>";
    }
    return $tpl;
  }


  function GetLagerABCKategorie($selected="")
  {
    $tmp = array(''=>'keine','A'=>'A','B'=>'B','C'=>'C');
    foreach($tmp as $key=>$value)
    {
      if($key==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"".$key."\" $mark>{$value}</option>";
    }
    return $tpl;
  }


  function GetSelectEtiketten($art,$selected="")
  {
    $user = $this->app->DB->SelectArr("SELECT * FROM etiketten WHERE verwendenals='$art' ORDER by name");

	if (!is_null($user)) {

	    for($i=0;$i<(!empty($user)?count($user):0);$i++)
	    {
	      if($user[$i]['id']==$selected) $mark="selected"; else $mark="";
	      $tpl .="<option value=\"{$user[$i]['id']}\" $mark>{$user[$i]['name']}</option>";
	    }
	}
    return $tpl;
  }

  function GetKalkulationartAssoc()
  {
    $user['artikel']="Artikel aus Stammdaten";
    $user['stueckliste']="St&uuml;ckliste";
    $user['freieposition']="Freie Position";
    $user['maschinenzeit']="Maschinenzeit";
    $user['arbeitszeit']="Arbeitszeit";
    $user['einmalkosten']="Einmalkosten / Werkzeugkosten";

//    $user['teilprojekt']="Teilprojekt / Aufgabe";
//    $user['hauptpunkt']="Beschriftung f&uuml;r Gruppe";
//    $user['unterpunkt']="Beschriftung f&uuml;r Untergruppe";

    $user['zwischensumme']="Zwischensumme";
    $user['zwischensummemengex']="Zwischensumme f&uuml;r Menge X";

//    $user['geplantemenge']="Geplante Menge";
    return $user;
  }

  function GetSelectKalkulationart($selected="")
  {
    $user = $this->GetKalkulationartAssoc();
    foreach($user as $key=>$value)
    {
      if($key==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"$key\" $mark>$value</option>";
    }
    return $tpl;
  }


  function GetSelectReisekostenart($selected="")
  {
    $user = $this->app->DB->SelectArr("SELECT * FROM reisekostenart ORDER by nummer");
    for($i=0;$i<(!empty($user)?count($user):0);$i++)
    {
      if($user[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$user[$i]['id']}\" $mark>{$user[$i]['nummer']}- {$user[$i]['beschreibung']}</option>";
    }
    return $tpl;
  }

  function GetSelectUserVorlage($selected="",$disableid="")
  {
    $user = $this->app->DB->SelectArr("SELECT * FROM uservorlage WHERE id!='$disableid' ORDER by bezeichnung");
    for($i=0;$i<(!empty($user)?count($user):0);$i++)
    {
      if($user[$i]['id']==$selected) $mark=" selected"; else $mark="";
      $tpl .="<option value=\"{$user[$i]['id']}\"$mark>{$user[$i]['bezeichnung']}</option>";
    }
    return $tpl;
  }

  function GetSelectUser($selected="",$disableid="")
  {
    $user = $this->app->DB->SelectArr("SELECT * FROM user WHERE id!='$disableid'");
    for($i=0;$i<(!empty($user)?count($user):0);$i++)
    {
      $user[$i]['description'] = $this->app->DB->Select("SELECT name FROM adresse WHERE id='".$user[$i]['adresse']."' LIMIT 1");
      if($user[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$user[$i]['id']}\" $mark>{$user[$i]['description']}</option>";
    }
    return $tpl;
  }

  /**
   * @param array      $array
   * @param string|int $selected
   *
   * @return string
   */
  public function arrayToSelect($array, $selected = '')
  {
    $tpl = '';
    foreach($array as $id => $konto) {
      $mark = '';
      if($selected == $id) {
        $mark = 'selected';
      }
      $tpl .= '<option value="'.$id.'" '.$mark.'>'.$konto.'</option>';
    }

    return $tpl;
  }

  function GetIPAdapterbox($id)
  {
    return $this->app->DB->Select("SELECT adapterboxip FROM drucker WHERE id='$id' LIMIT 1");
  }

  function GetStandardPaketmarkendrucker($projekt="",$versandart="")
  {
    return $this->app->DB->Select("SELECT paketmarkendrucker FROM user WHERE id='".$this->app->User->GetID()."'");
  }

  function GetStandardVersanddrucker($projekt="",$versandart="")
  {
    return $this->app->DB->Select("SELECT standardversanddrucker FROM user WHERE id='".$this->app->User->GetID()."'");
  }

  function GetInstrashipExport($projekt="")
  {
    $export = $this->app->DB->Select("SELECT intraship_exportdrucker FROM projekt WHERE id = '$projekt' LIMIT 1");
    if($export)return $export;
    return $this->GetStandardVersanddrucker();
  }

  function GetSelectEtikettenDrucker($selected="")
  {
    if($selected=="")
      $selected = $this->app->DB->Select("SELECT standardetikett FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");

    $check = $this->app->DB->Select("SELECT id FROM drucker WHERE id='$selected' AND aktiv='1' LIMIT 1");
    if($check!=$selected) $selected="";

    if($selected=="")
      $selected = $this->Firmendaten("standardetikettendrucker");

    if($selected=="0" || $selected=="")
      $tpl .="<option value=\"0\" selected>-- kein --</option>";
    else
      $tpl .="<option value=\"0\">-- kein --</option>";

    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM  drucker WHERE aktiv='1' AND art='2'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      if($drucker[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$drucker[$i]['id']}\" $mark>{$drucker[$i]['name']}</option>";
    }
    return $tpl;
  }

  function GetSelectFax($selected="")
  {
    if($selected=="")
      $selected = $this->app->DB->Select("SELECT standardfax FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");

    $check = $this->app->DB->Select("SELECT id FROM drucker WHERE id='$selected' AND aktiv='1' LIMIT 1");
    if($check!=$selected) $selected="";

    if($selected=="")
      $selected = $this->Firmendaten("standardfax");

    //$tpl .="<option value=\"0\">-- kein --</option>";
    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM  drucker WHERE aktiv='1' AND art='1'");

	if (gettype($drucker) == 'array') {
	    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
	    {
	      if($drucker[$i]['id']==$selected) $mark="selected"; else $mark="";
	      $tpl .="<option value=\"{$drucker[$i]['id']}\" $mark>{$drucker[$i]['name']}</option>";
	    }
	}
    return $tpl;
  }

  function GetSelectBonDrucker($selected="")
  {
    if($selected=="")
      $selected = $this->Firmendaten("aufgaben_bondrucker");

    $drucker = $this->app->DB->SelectArr("SELECT id, bezeichnung FROM adapterbox WHERE verwendenals='bondrucker'");

    $tpl ="<option value=\"0\">-- kein --</option>";
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      if($drucker[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$drucker[$i]['id']}\" $mark>{$drucker[$i]['bezeichnung']}</option>";
    }
    return $tpl;
  }


  function GetPosAdapterbox()
  {
    $drucker = $this->app->DB->SelectArr("SELECT id, bezeichnung FROM adapterbox WHERE verwendenals='bondrucker' OR verwendenals='rksvlight'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      $result[$drucker[$i]['id']]=$drucker[$i]['bezeichnung'];
    }
    return $result;
  }


  function GetBondrucker()
  {
    $drucker = $this->app->DB->SelectArr("SELECT id, bezeichnung FROM adapterbox WHERE verwendenals='bondrucker'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      $result[$drucker[$i]['id']]=$drucker[$i]['bezeichnung'];
    }
    return $result;
  }

  function GetEtiketten()
  {
    //$tpl .="<option value=\"0\">-- kein --</option>";
    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM etiketten");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      $result[$drucker[$i]['id']]=$drucker[$i]['name'];
    }
    return $result;
  }


  function GetWaage()
  {
    //$tpl .="<option value=\"0\">-- kein --</option>";
    $drucker = $this->app->DB->SelectArr("SELECT id, bezeichnung FROM adapterbox WHERE verwendenals='waage'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      $result[$drucker[$i]['id']]=$drucker[$i]['bezeichnung'];
    }
    return $result;
  }


  function GetEtikettendrucker()
  {
    //$tpl .="<option value=\"0\">-- kein --</option>";
    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM  drucker WHERE aktiv='1' AND art='2'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      $result[$drucker[$i]['id']]=$drucker[$i]['name'];
    }
    return $result;
  }


  function GetDrucker()
  {
    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM  drucker WHERE aktiv='1' AND art='0'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      $result[$drucker[$i]['id']]=$drucker[$i]['name'];
    }
    return $result;
  }

  function GetSelectVersanddrucker($selected="")
  {
    if($selected=="")
      $selected = $this->app->DB->Select("SELECT standardversanddrucker FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");

    $check = $this->app->DB->Select("SELECT id FROM  drucker WHERE id='$selected' AND aktiv='1' LIMIT 1");
    if($check!=$selected) $selected="";

    $tpl ="<option value=\"0\">-- kein --</option>";
    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM  drucker WHERE aktiv='1' AND art='0'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      if($drucker[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$drucker[$i]['id']}\" $mark>{$drucker[$i]['name']}</option>";
    }
    return $tpl;
  }

  function GetSelectDrucker($selected="")
  {


    if($selected=="")
      $selected = $this->app->DB->Select("SELECT standarddrucker FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");

    $check = $this->app->DB->Select("SELECT id FROM  drucker WHERE id='$selected' AND aktiv='1' LIMIT 1");
    if($check!=$selected) $selected="";

    if($selected=="")
      $selected = $this->Firmendaten("standardversanddrucker");

    $tpl .="<option value=\"0\">-- kein --</option>";
    $drucker = $this->app->DB->SelectArr("SELECT id, name FROM  drucker WHERE aktiv='1' AND art='0'");
    for($i=0;$i<(!empty($drucker)?count($drucker):0);$i++)
    {
      if($drucker[$i]['id']==$selected) $mark="selected"; else $mark="";
      $tpl .="<option value=\"{$drucker[$i]['id']}\" $mark>{$drucker[$i]['name']}</option>";
    }
    return $tpl;
  }
  function DokumentSendVorlage($id)
  {
    $betreff = $this->app->DB->Select("SELECT betreff FROM dokumente_send WHERE id='$id' LIMIT 1");
    $text  = $this->app->DB->Select("SELECT text FROM dokumente_send WHERE id='$id' LIMIT 1");

    $this->app->Tpl->Set('BETREFF',$betreff);
    $this->app->Tpl->Set('TEXT',$text);
  }

  function Geschaeftsbriefvorlage($sprache,$subjekt,$projekt="",$name="",$id="", $intern = false)
  {
    if($sprache=="") $sprache="deutsch";

    $this->BeschriftungSprache($sprache);

    $belegnr = "";
    $adresse = "";
    $anschreiben = "";

    $lowersubjekt = strtolower($subjekt);
    if(
        $lowersubjekt=="angebot" ||
        $lowersubjekt=="auftrag" ||
        $lowersubjekt=="bestellung" ||
        $lowersubjekt=="produktion" ||
        $lowersubjekt=="lieferschein" ||
        $lowersubjekt=="retoure" ||
        $lowersubjekt=="rechnung" ||
        $lowersubjekt=="gutschrift" ||
        $lowersubjekt=="arbeitsnachweis" ||
        $lowersubjekt=="proformarechnung"
    ){
      if($id > 0) {

        if($name=="")
          $name = $this->app->DB->Select("SELECT name FROM $lowersubjekt WHERE id='$id' LIMIT 1");

        $belegnr = $this->app->DB->Select("SELECT belegnr FROM $lowersubjekt WHERE id='$id' LIMIT 1");
        $adresse = $this->app->DB->Select("SELECT adresse FROM $lowersubjekt WHERE id='$id' LIMIT 1");
        $anschreiben = $this->app->DB->Select("SELECT anschreiben FROM $lowersubjekt WHERE id='$id' LIMIT 1");
        $datum = $this->app->DB->Select("SELECT DATE_FORMAT(datum,'%d.%m.%Y') FROM $lowersubjekt WHERE id='$id' LIMIT 1");

        if($anschreiben=="")
        {
          $anschreiben = $this->app->DB->Select("SELECT anschreiben FROM adresse WHERE id='$adresse' LIMIT 1");
        }

        if($anschreiben=="")
        {
          $anschreiben = $this->Beschriftung("dokument_anschreiben");
        }

        if(!$intern)$this->GeschaeftsBriefAnhang($subjekt,$sprache,$projekt,$lowersubjekt,$id);
      }
    }

    $text = $this->GetGeschaeftsBriefText($subjekt,$sprache,$projekt,$lowersubjekt,$id);
    $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,$sprache,$projekt,$lowersubjekt,$id);

  if($text=="") $text = $this->GetGeschaeftsBriefText($subjekt,$sprache,$projekt,$lowersubjekt,$id);
  if($betreff=="") $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,$sprache,$projekt,$lowersubjekt,$id);

  if(($text === "" || $betreff === "") && $sprache != 'deutsch')
  {
    $text = $this->GetGeschaeftsBriefText($subjekt,'deutsch',$projekt,$lowersubjekt,$id);
    $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,'deutsch',$projekt,$lowersubjekt,$id);

      if($text=="") $text = $this->GetGeschaeftsBriefText($subjekt,'deutsch',$projekt,$lowersubjekt,$id);
      if($betreff=="") $betreff = $this->GetGeschaeftsBriefBetreff($subjekt,'deutsch',$projekt,$lowersubjekt,$id);
    }

    $text = str_replace('{BELEGNR}',$belegnr,$text);
    $text = str_replace('{DATUM}',$datum,$text);

    $betreff = str_replace('{BELEGNR}',$belegnr,$betreff);
    $betreff = str_replace('{DATUM}',$datum,$betreff);

    if($id > 0)
    {
      $betreff = $this->ParseUserVars($lowersubjekt,$id, $betreff);
      $text = $this->ParseUserVars($lowersubjekt,$id, $text);
    } 

    if($anschreiben=="") {
      $anschreiben = $this->app->erp->Beschriftung("dokument_anschreiben");
    }
    $betreff = str_replace('{ANSCHREIBEN}',$anschreiben,$betreff);
    $text = str_replace('{ANSCHREIBEN}',$anschreiben,$text);

    $betreff = str_replace('{NAME}',$name,$betreff);
    $text = str_replace('{NAME}',$name,$text);

    

    if(!$intern)$this->app->Tpl->Set('BETREFF',$betreff);

    if(!$this->isHTML($text) && $this->Firmendaten("briefhtml")=="1"){
      $texthtml = str_replace("\r\n", "<br>", $text);
      if(!$intern)$this->app->Tpl->Set('TEXT',$texthtml);
    } else {
      if(!$intern)$this->app->Tpl->Set('TEXT',$text);
    }

    return array("betreff"=>$betreff,"text"=>$text);
  }

  function GetAnsprechpartner($data)
  {
    // $data: 'Admin <admin@test.de>'
    // return id, name, email

    $first = strpos($data, '<');
    $last = strpos($data, '>');

    $name = trim(substr($data, 0, $first));
    $email = trim(substr($data, $first+1, $last-($first+1)));

    $id = $this->app->DB->Select("SELECT id FROM adresse WHERE email='$mail' LIMIT 1");
    if(!(is_numeric($id) && $id<1))
      $id = $this->app->DB->Select("SELECT id FROM adresse WHERE name='$name' LIMIT 1");

    if(!is_numeric($id)) $id = 0;

    return array('id'=>$id, 'name'=>$name, 'email'=>$email);
  }


  function RemoveReadonly($feld)
  {
    $this->app->Tpl->Add('JQUERY','$("#'.$feld.'").removeAttr("disabled","disabled");');
    $this->app->Tpl->Add('JQUERY','$("#'.$feld.'").removeAttr("readonly","readonly");');
    $this->app->Tpl->Add('JQUERY','$("#'.$feld.'").css("background-color", "white");');
  }


  function CommonReadonly()
  {
    $this->commonreadonly=1;
    $this->app->Tpl->Set('COMMONREADONLYINPUT',"readonly disabled style=\"background-color:#eee; border-color:#ddd;\"");
    $this->app->Tpl->Set('COMMONREADONLYSELECT',"disabled=\"disabled\" style=\"background-color:#eee;\"");

  }


  function BriefpapierHintergrundDisable($drucker)
  {
    $keinhintergrund = $this->app->DB->Select("SELECT keinhintergrund FROM drucker WHERE id='$drucker' LIMIT 1");
    if($keinhintergrund=="1")
      $this->app->erp->BriefpapierHintergrunddisable = true;
  }

  function BriefpapierHintergrundEnable()
  {
    $this->app->erp->BriefpapierHintergrunddisable = false;
  }


  function DokumentMask($parsetarget,$typ,$id,$adresse,$projekt="",$popup=false, $intern = false)
  {
    if(!$intern)
    {
      $this->app->Tpl->Set('SID',$id);
      $this->app->Tpl->Set('TYP',$typ);

      $ansprechpartnerManuell = $this->app->Secure->GetPOST('ansprechpartnermanuellverwenden');
      if($ansprechpartnerManuell == 'on'){
        $ansprechpartner = $this->app->Secure->GetPOST('ansprechpartnermanuell');
      }else{
        $ansprechpartner = $this->app->Secure->GetPOST('ansprechpartner');
      }


      $betreff = $this->app->Secure->GetPOST("betreff");
      
      $projekt_submit = $this->app->Secure->GetPOST("projekt");
      $text = $this->app->Secure->GetPOST("text");
      $art = $this->app->Secure->GetPOST("senden");

      $tmpcc = $this->app->Secure->GetPOST("cc");
      $tmpbcc = $this->app->Secure->GetPOST("bcc");

      $vorlage = $this->app->Secure->GetPOST("vorlage");
      if($vorlage!='' && !empty($this->app->User) && method_exists($this->app->User, 'SetParameter')) {
        $this->app->User->SetParameter("briefpapier_vorlage",$vorlage);
      }
    }else{
      $betreff = isset($intern["betreff"])?$intern["betreff"]:'';
      $projekt_submit = isset($intern["projekt"])?$intern["projekt"]:$projekt;
      $ansprechpartner = isset($intern["ansprechpartner"])?$intern["ansprechpartner"]:$this->app->DB->Select("SELECT concat(if(ansprechpartner <> '',ansprechpartner,name),'<',email,'>') FROM $typ WHERE id = '$id' LIMIT 1");
      $text = isset($intern["text"])?$intern["text"]:'';
      $art = isset($intern["senden"])?$intern["senden"]:'';
      $tmpcc = isset($intern["cc"])?$intern["cc"]:'';
      $tmpbcc = isset($intern["bcc"])?$intern["bcc"]:'';

      $vorlage = isset($intern["vorlage"])?$intern["vorlage"]:'';
      if($vorlage!='' && !empty($this->app->User) && method_exists($this->app->User, 'SetParameter')) {
        $this->app->User->SetParameter("briefpapier_vorlage",$vorlage);
      }
    }
    $ansprechpartner = str_replace('&lt;','<',$ansprechpartner);
    $ansprechpartner = str_replace('&gt;','>',$ansprechpartner);
    list($name, $email) = explode('<', trim($ansprechpartner,'>'));

    $betreff = str_replace('\"','"',$betreff);
    $betreff = str_replace("\'","'",$betreff);


    $partnerinfo['email'] = $email;
    $partnerinfo['name'] = $name;

    if(!$intern && $this->app->Secure->GetPOST('ansprechpartnermanuellverwenden')=='on'){
      $partnerinfo['email'] = $this->app->Secure->GetPOST("ansprechpartnermanuell");
      $partnerinfo['name'] = '';
    }


    if($projekt=="" && $projekt_submit!="")
      $projekt = $projekt_submit;

    if($projekt=="")
      $projekt = $this->app->DB->Select("SELECT projekt FROM $typ WHERE id='$id' LIMIT 1"); //04.07.2018 von Bruno hinzugefuegt
    // hole standard projekt von adresse
    if($projekt=="")
      $projekt = $this->app->DB->Select("SELECT projekt FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");


    if($typ!="brieffax")
      $projektbriefpapier = $this->app->DB->Select("SELECT projekt FROM $typ WHERE id='$id' LIMIT 1");

// START SCHLEIFE
    if(!$intern)
    {
      $tmpsenden = $this->app->Secure->GetPOST("senden");
    }else{
      $tmpsenden = isset($intern['senden'])?$intern['senden']:null;
    }

    if(!$intern && $tmpsenden && !empty($this->app->User) && method_exists($this->app->User, 'SetParameter')) {
      $this->app->User->SetParameter("dokumente_abschickenmask_".$typ."_brief","0");
      $this->app->User->SetParameter("dokumente_abschickenmask_".$typ."_email","0");
      $this->app->User->SetParameter("dokumente_abschickenmask_".$typ."_sonstiges","0");
      $this->app->User->SetParameter("dokumente_abschickenmask_".$typ."_telefon","0");
      $this->app->User->SetParameter("dokumente_abschickenmask_".$typ."_fax","0");
    }

    for($tmpis=0;$tmpis<(!empty($tmpsenden)?count($tmpsenden):0);$tmpis++)
    {
      $deckblatt = false;
      //BRIEFCHECKED
      $art = $tmpsenden[$tmpis];

      if($art!='' && !empty($this->app->User) && method_exists($this->app->User, 'SetParameter')){
        $this->app->User->SetParameter('dokumente_abschickenmask_' . $typ . '_' . $art, '1');
      }


      if($art == "brief") $drucker = $this->app->Secure->GetPOST("drucker_brief");
      else if($art == "fax") $drucker = $this->app->Secure->GetPOST("drucker_fax");
      else if ($art == "email") $drucker = $this->app->Secure->GetPOST("email_from");
      // Hintergrund ausschalten wenn drucker es erfordert
      $this->BriefpapierHintergrundDisable($drucker);
      if($art === 'email' || (!$intern && $this->app->Secure->GetPOST('sammelpdf'))) {
        if($intern)
        {
          if(isset($intern['dateianhaenge']) && $intern['dateianhaenge'] && is_array($intern['dateianhaenge']))
          {
            foreach($intern['dateianhaenge'] as $pk => $pv)
            {
              if(is_numeric($pv))
              {
                $dateiname = str_replace(' ','_',$this->app->erp->GetDateiName($pv));
              }else {
                $dateiname = $pv;
                if(!file_exists($dateiname))$dateiname = '';
              }

              if($dateiname != '')
              {
                if(is_numeric($pv)) {
                  $dateiinhalt = $this->app->erp->GetDatei($pv);
                  if($handle = fopen (rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname, "wb"))
                  {
                    fwrite($handle, $dateiinhalt);
                    fclose($handle);
                    $_dateien[] = rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname;
                    $dateisort = $pk;
                    if($dateisort)$dateiensort[$dateisort] = (!empty($_dateien)?count($_dateien):0)-1;
                    $zuloeschen[]  = rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname;
                  }
                }else{
                  $_dateien[] = $dateiname;
                  $dateisort = $pk;
                  if($dateisort)$dateiensort[$dateisort] = (!empty($_dateien)?count($_dateien):0)-1;
                  $zuloeschen[]  = $dateiname;
                }
              }
            }
          }
        }else{
          /*if($this->app->Secure->GetPOST('sammelpdf'))
            $_dateien = array($tmpfile);*/
          foreach($_POST as $pk => $pv)
          {
            $pka = explode('_',$pk);
            if($pka[0] == 'datei' && isset($pka[1]) && $pka[1] && is_numeric($pka[1])){
              $dateiname = str_replace(' ','_',$this->app->erp->GetDateiName($pka[1]));
              if($dateiname)
              {
                if($this->app->DB->Select("SELECT id FROM datei_stichwoerter WHERE datei=".$pka[1]." AND subjekt='Deckblatt' AND objekt='auftrag' AND parameter='$id'") && $this->app->Secure->GetPOST('sammelpdf')){
                  //Datei ist ein Deckblatt, vermerken
                  $deckblatt=true;
                }else{
                  $dateiinhalt = $this->app->erp->GetDatei($pka[1]);

                  if($handle = fopen (rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname, "wb"))
                  {
                    fwrite($handle, $dateiinhalt);
                    fclose($handle);
                    $_dateien[] = rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname;
                    $dateisort = (int)$this->app->Secure->GetPOST('dateisort_'.$pka[1]);
                    if($dateisort)$dateiensort[$dateisort] = (!empty($_dateien)?count($_dateien):0)-1;
                    $zuloeschen[]  = rtrim($this->app->erp->GetTMP(),'/')."/".$dateiname;
                  }
                }
              }
            }
          }
          if($this->app->Secure->GetPOST('sammelpdf') && isset($dateiensort))
          {
            foreach($dateiensort as $k => $v)
            {
              if(file_exists($_dateien[$v]))
              {
                $contenttyp = mime_content_type($_dateien[$v]);
                if($contenttyp == 'application/pdf')
                {
                  $sammelpdf[] = file_get_contents($_dateien[$v]);
                  unset($_dateien[$v]);
                }
              }
            }
          }
        }
      }
      // eigentliches dokument
      if($typ=="bestellung")
      {
        // sende
        if($this->Firmendaten('hintergrund') == 'kein'){
          $this->app->erp->BriefpapierHintergrunddisable = false;
        }
        else{
          $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        }
        if(class_exists('BestellungPDFCustom'))
        {
          $Brief = new BestellungPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new BestellungPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetBestellung($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('BestellungPDFCustom'))
        {
          $Brief = new BestellungPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new BestellungPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetBestellung($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('BestellungPDFCustom'))
          {
            $Brief = new BestellungPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new BestellungPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetBestellung($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }
      // eigentliches dokument
      if($typ=="angebot")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AngebotPDFCustom'))
        {
          $Brief = new AngebotPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new AngebotPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetAngebot($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AngebotPDFCustom'))
        {
          $Brief = new AngebotPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new AngebotPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetAngebot($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('AngebotPDFCustom'))
          {
            $Brief = new AngebotPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new AngebotPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetAngebot($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }
      // eigentliches dokument
      if($typ=="lieferschein")
      {
        // sende
        if($this->Firmendaten('hintergrund') == 'kein'){
          $this->app->erp->BriefpapierHintergrunddisable = false;
        }
        else{
          $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        }

        if(class_exists('LieferscheinPDFCustom'))
        {
          $Brief = new LieferscheinPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new LieferscheinPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetLieferschein($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('LieferscheinPDFCustom'))
        {
          $Brief = new LieferscheinPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new LieferscheinPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetLieferschein($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
      }
      if($typ=="retoure")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('RetourePDFCustom'))
        {
          $Brief = new RetourePDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new RetourePDF($this->app,$projektbriefpapier);
        }
        $Brief->GetRetoure($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('RetourePDFCustom'))
        {
          $Brief = new RetourePDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new RetourePDF($this->app,$projektbriefpapier);
        }
        $Brief->GetRetoure($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
      }
      // eigentliches dokument
      if($typ=="arbeitsnachweis")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ArbeitsnachweisPDFCustom'))
        {
          $Brief = new ArbeitsnachweisPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ArbeitsnachweisPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetArbeitsnachweis($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

      $tmpfile = $Brief->displayTMP();
      $Brief->ArchiviereDocument(true);
      unlink($tmpfile);
      $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
      if(class_exists('ArbeitsnachweisPDFCustom'))
      {
        $Brief = new ArbeitsnachweisPDFCustom($this->app,$projektbriefpapier);
      }else{
        $Brief = new ArbeitsnachweisPDF($this->app,$projektbriefpapier);
      }
      $Brief->GetArbeitsnachweis($id);
      $tmpfile = $Brief->displayTMP();
      $Brief->ArchiviereDocument(true);

      if(isset($sammelpdf))
      {
        unlink($tmpfile);
        if(class_exists('ArbeitsnachweisPDFCustom'))
        {
          $Brief = new ArbeitsnachweisPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ArbeitsnachweisPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetArbeitsnachweis($id);
        foreach($sammelpdf as $dat)
        {
          $Brief->AddPDF($dat);
        }
        $tmpfile = $Brief->displayTMP();
      }
    }
    // eigentliches dokument
    if($typ=="reisekosten")
    {
      // sende
      $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
      if(class_exists('ReisekostenPDFCustom'))
      {
        $Brief = new ReisekostenPDFCustom($this->app,$projektbriefpapier);
      }else{
        $Brief = new ReisekostenPDF($this->app,$projektbriefpapier);
      }
      $Brief->GetReisekosten($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ReisekostenPDFCustom'))
        {
          $Brief = new ReisekostenPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ReisekostenPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetReisekosten($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('ReisekostenPDFCustom'))
          {
            $Brief = new ReisekostenPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new ReisekostenPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetReisekosten($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }


      }

      // eigentliches dokument
      if($typ=="auftrag")
      {
        // sende
        if(class_exists('AuftragPDFCustom'))
        {
          $Brief = new AuftragPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new AuftragPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetAuftrag($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('AuftragPDFCustom'))
          {
            $Brief = new AuftragPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new AuftragPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetAuftrag($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          if($deckblatt){
            $containerpdf = new Fpdi('P','mm','A4');
            foreach($_POST as $pk => $pv){
              $pka = explode('_',$pk);
              if($pka[0] == 'datei' && isset($pka[1]) && $pka[1] && is_numeric($pka[1])){
                $dateiname = str_replace(' ','_',$this->app->erp->GetDateiName($pka[1]));
                if($dateiname){
                  $deckblattdatei = $this->app->DB->Select("SELECT datei FROM datei_stichwoerter WHERE datei=".$pka[1]." AND subjekt='Deckblatt' AND objekt='auftrag' AND parameter='$id'");
                  if($deckblattdatei){
                    //Zuerst alle Deckblätter der Reihe nach zum PDF Dokument hinzufügen
                    $deckblattdateitmp = $this->app->erp->GetUSERDATA()."/dms/".$this->app->Conf->WFdbname."/".$deckblattdatei;
                    $pages_count = $containerpdf->setSourceFile($deckblattdateitmp);
                    for($j = 1; $j <= $pages_count; $j++)
                    {
                      $containerpdf->AddPage();
                      $tplIdx = $containerpdf->importPage($j);
                      $containerpdf->useTemplate($tplIdx, 0, 0);
                    }
                  }
                }
              }
            }

            //Anschließend das eigentliche SammelPDF zum PDF mit den Deckblättern hinzufügen
            $pages_count = $containerpdf->setSourceFile($Brief->displayTMP());
            for($j = 1; $j <= $pages_count; $j++)
            {
              $containerpdf->AddPage();
              $tplIdx = $containerpdf->importPage($j);
              $containerpdf->useTemplate($tplIdx, 0, 0);
            }
            $containerpdf->Output($this->app->erp->GetTMP().$this->app->erp->Dateinamen($Brief->filename),'F');
            $tmpfile = $this->app->erp->GetTMP().$this->app->erp->Dateinamen($Brief->filename);
          }else{
            $tmpfile = $Brief->displayTMP();
          }
        }
      }
      // eigentliches dokument
      if($typ=="rechnung")
      {
        // sende
        $xmlrechnug = $this->app->DB->Select("SELECT xmlrechnung FROM rechnung WHERE id ='".$id."' LIMIT 1");
        if ($xmlrechnung) {
            $xmlrechnungresult = $this->app->erp->GetXMLRechnung($id);
            if ($xmlrechnungresult['success']) {
                $tmpfile = $xmlrechnungresult['xml'];
            } else {
                throw new exception("XML Rechnung fehlgeschlagen!");
            }
        } else {
            $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
            if(class_exists('RechnungPDFCustom'))
            {
              $Brief = new RechnungPDFCustom($this->app,$projektbriefpapier);
            }else{
              $Brief = new RechnungPDF($this->app,$projektbriefpapier);
            }
            $Brief->GetRechnung($id);

            if(isset($sammelpdf))
            {
              foreach($sammelpdf as $dat)
              {
                $Brief->AddPDF($dat);
              }
            }

            //$Brief->ArchiviereDocument();
            $tmpfile = $Brief->displayTMP();
            $Brief->ArchiviereDocument(true);
            unlink($tmpfile);
            $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
            if(class_exists('RechnungPDFCustom'))
            {
              $Brief = new RechnungPDFCustom($this->app,$projektbriefpapier);
            }else{
              $Brief = new RechnungPDF($this->app,$projektbriefpapier);
            }
            $Brief->GetRechnung($id);
            $tmpfile = $Brief->displayTMP();
            $Brief->ArchiviereDocument(true);
            if(isset($sammelpdf))
            {
              unlink($tmpfile);
              if(class_exists('RechnungPDFCustom'))
              {
                $Brief = new RechnungPDFCustom($this->app,$projektbriefpapier);
              }else{
                $Brief = new RechnungPDF($this->app,$projektbriefpapier);
              }
              $Brief->GetRechnung($id);
              foreach($sammelpdf as $dat)
              {
                $Brief->AddPDF($dat);
              }
              $tmpfile = $Brief->displayTMP();
            }
        }
        //$Brief->ArchiviereDocument();

      }

      // eigentliches dokument
      if($typ=="gutschrift")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('GutschriftPDFCustom'))
        {
          $Brief = new GutschriftPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new GutschriftPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetGutschrift($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('GutschriftPDFCustom'))
        {
          $Brief = new GutschriftPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new GutschriftPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetGutschrift($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('GutschriftPDFCustom'))
          {
            $Brief = new GutschriftPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new GutschriftPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetGutschrift($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }

      // eigentliches dokument
      if($typ=="anfrage")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AnfragePDFCustom'))
        {
          $Brief = new AnfragePDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new AnfragePDF($this->app,$projektbriefpapier);
        }
        $Brief->GetAnfrage($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('AnfragePDFCustom'))
        {
          $Brief = new AnfragePDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new AnfragePDF($this->app,$projektbriefpapier);
        }
        $Brief->GetAnfrage($id);
        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('AnfragePDFCustom'))
          {
            $Brief = new AnfragePDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new AnfragePDF($this->app,$projektbriefpapier);
          }
          $Brief->GetAnfrage($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }

      // eigentliches dokument
      if($typ=="preisanfrage")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('PreisanfragePDFCustom'))
        {
          $Brief = new PreisanfragePDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new PreisanfragePDF($this->app,$projektbriefpapier);
        }
        $Brief->GetPreisanfrage($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('PreisanfragePDFCustom'))
        {
          $Brief = new PreisanfragePDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new PreisanfragePDF($this->app,$projektbriefpapier);
        }
        $Brief->GetPreisanfrage($id);

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('PreisanfragePDFCustom'))
          {
            $Brief = new PreisanfragePDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new PreisanfragePDF($this->app,$projektbriefpapier);
          }
          $Brief->GetPreisanfrage($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }




      // eigentliches dokument
      if($typ=="produktion")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ProduktionPDFCustom'))
        {
          $Brief = new ProduktionPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ProduktionPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetProduktion($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ProduktionPDFCustom'))
        {
          $Brief = new ProduktionPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ProduktionPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetProduktion($id);

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('ProduktionPDFCustom'))
          {
            $Brief = new ProduktionPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new ProduktionPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetProduktion($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }


      // eigentliches dokument
      if($typ=="proformarechnung")
      {
        // sende
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ProformarechnungPDFCustom'))
        {
          $Brief = new ProformarechnungPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ProformarechnungPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetProformarechnung($id);

        if(isset($sammelpdf))
        {
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
        }

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        unlink($tmpfile);
        $this->app->erp->BriefpapierHintergrunddisable = !$this->app->erp->BriefpapierHintergrunddisable;
        if(class_exists('ProformarechnungPDFCustom'))
        {
          $Brief = new ProformarechnungPDFCustom($this->app,$projektbriefpapier);
        }else{
          $Brief = new ProformarechnungPDF($this->app,$projektbriefpapier);
        }
        $Brief->GetProformarechnung($id);

        $tmpfile = $Brief->displayTMP();
        $Brief->ArchiviereDocument(true);
        if(isset($sammelpdf))
        {
          unlink($tmpfile);
          if(class_exists('ProformarechnungPDFCustom'))
          {
            $Brief = new ProformarechnungPDFCustom($this->app,$projektbriefpapier);
          }else{
            $Brief = new ProformarechnungPDF($this->app,$projektbriefpapier);
          }
          $Brief->GetProformarechnung($id);
          foreach($sammelpdf as $dat)
          {
            $Brief->AddPDF($dat);
          }
          $tmpfile = $Brief->displayTMP();
        }
      }

    if($typ!="")
    {
      if($typ=="brieffax")
        $dateien = array($tmpbrief);
      else
      {
        $this->RunHook('DokumentMask', 5, $typ, $id, $tmpfile, $sammelpdf, $art);
        if(is_array($tmpfile))
        {
          if(isset($tmpbrief) && $tmpbrief)
          {
            $dateien = array($tmpbrief);
            foreach($tmpfile as $v)$dateien[] = $v;
          }else{
            $dateien = $tmpfile;
          }
        }else{
          $dateien = array($tmpbrief,$tmpfile);
        }
        if(isset($_dateien))foreach ($_dateien as $dat)if($dat)$dateien[] = $dat;
      }
    }

    if($intern || $this->app->Secure->GetPOST('submit')!='') {
      //echo "SENDEN";
      if($art=="fax"){
        $ret = $this->DokumentSend($adresse, $typ, $id, $art, $betreff, $text, $dateien, $drucker, $ansprechpartner, $projekt, $this->app->Secure->GetPOST("faxnummer"), "");
      }else{
        $weitereadressids = '';
        if($typ == 'preisanfrage'){
          $weitereadressids = $this->app->Secure->GetPOST('pran_adressids');
          if($weitereadressids != '' && $adresse > 0){
            $adresse .= ';'.$weitereadressids;
            $this->app->erp->RunHook('preisanfrage_mails_abschicken', 13, $adresse, $typ, $id, $art, $betreff, $text, $dateien, $drucker, $ansprechpartner, $projekt, $partnerinfo['email'], $tmpcc, $tmpbcc);
          }elseif($weitereadressids == ''){
            $ret = $this->DokumentSend($adresse, $typ, $id, $art, $betreff, $text, $dateien, $drucker, $ansprechpartner, $projekt, $partnerinfo['email'], $partnerinfo['name'], $tmpcc, $tmpbcc);
          }
        }else{
          $ret = $this->DokumentSend($adresse, $typ, $id, $art, $betreff, $text, $dateien, $drucker, $ansprechpartner, $projekt, $partnerinfo['email'], $partnerinfo['name'], $tmpcc, $tmpbcc);
        }
      }
      if($tmpis == 0)$this->RunHook('dokumentsend_email',6, $typ, $id,$betreff,$text,$dateien, $intern);
      if(isset($zuloeschen) && is_array($zuloeschen))
      {
        foreach($zuloeschen as $zl)unlink($zl);
        unset($zuloeschen);
      }

      $this->BriefpapierHintergrundEnable();

      /*
      // NEU ANLEGEN ODER UPDATE
      if($typ=="brieffax")
      {
      $check = $this->app->DB->Select("SELECT id FROM dokumente_send WHERE text='$text' AND betreff='$betreff' AND geloescht=0 AND versendet=0 ORDER by id DESC LIMIT 1");
      } else {
      $check = $this->app->DB->Select("SELECT id FROM dokumente_send WHERE dokument='$typ' AND parameter='$id' AND geloescht=0 AND versendet=0 ORDER by id DESC LIMIT 1"); // GEHT bei BE RE LS
      }
       */

      //Datei anlegen

      if($this->Firmendaten("belegeinanhang")=="1") {
        $fileid = $this->CreateDateiWithStichwort($Brief->filename,$module,"","",$tmpfile,$this->app->User->GetName() ,$typ,$typ,$id, "",false);
      /*$fileid = $this->CreateDatei($Brief->filename,$module,"","",$tmpfile,$this->app->User->GetName());

      $this->AddDateiStichwort($fileid,$typ,$typ,$id,$without_log=false);*/
      }

      if(is_numeric($check) && $check >0)
      {
        /*
           if($typ=="brieffax")
           {
        // das dokument gibt es so bereits 1:1 hier braucht man nichts machen
        //echo "DAS DOKUMENT GIBT ES UNVERSENDET SO";
        $this->app->DB->Update("UPDATE dokumente_send SET versendet=1 WHERE id='$check' LIMIT 1");
        }
        else
        {
        $this->app->DB->Update("UPDATE dokumente_send SET betreff='$betreff', text='$text',versendet=1 WHERE dokument='$typ' AND parameter='$id' AND geloescht=0 AND versendet=0 LIMIT 1");  // GEHT bei RE, LS ..
        }
         */
      } else {
        if($typ=="brieffax")
        {
          $this->app->DB->Insert("INSERT INTO dokumente_send
              (id,dokument,zeit,bearbeiter,adresse,parameter,art,betreff,text,projekt,ansprechpartner,versendet,dateiid) VALUES ('','$typ',NOW(),'".$this->app->User->GetName()."',
                '$adresse','$parameter','$art','$betreff','$text','$projekt','$ansprechpartner',1,'$fileid')");
          $tmpid = $this->app->DB->GetInsertID();
          $this->app->DB->Update("UPDATE dokumente_send SET parameter='$tmpid' WHERE id='$tmpid' LIMIT 1");
          //echo "INSERT brieffax dokument";
        } else {
          //echo "anlegen begleitschreiben RE, LS";
          //TODO ANSPRECHPARTNER
          if($weitereadressids == ''){
            $this->app->DB->Insert("INSERT INTO dokumente_send
              (id,dokument,zeit,bearbeiter,adresse,parameter,art,betreff,text,projekt,ansprechpartner,versendet,dateiid) VALUES ('','$typ',NOW(),'".$this->app->User->GetName()."',
                '$adresse','$id','$art','$betreff','$text','$projekt','$ansprechpartner',1,'$fileid')");
            $tmpid = $this->app->DB->GetInsertID();
          }
        }

      }

      if($ret == "")
      {
        if(!$intern)$this->app->Tpl->Set($parsetarget,"<div class=\"info\">Dokument wurde erfolgreich versendet</div>");

        /* Status gezielt von Dokument aendern */
        if($typ=="bestellung")
        {
          $this->app->DB->Update("UPDATE bestellung SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE bestellung SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->BestellungProtokoll($id,"Bestellung versendet");
          //TODO ARCHIVIEREN
        }
        else if($typ=="angebot")
        {
          $this->app->DB->Update("UPDATE angebot SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE angebot SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->AngebotProtokoll($id,"Angebot versendet");
          //TODO ARCHIVIEREN
        }
        else if($typ=="lieferschein")
        {
          $this->app->DB->Update("UPDATE lieferschein SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE lieferschein SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->LieferscheinProtokoll($id,"Lieferschein versendet");
          //TODO ARCHIVIEREN
        }
        else if($typ=="retoure")
        {
          $this->app->DB->Update("UPDATE retoure SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE retoure SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->RetoureProtokoll($id,"Retoure versendet");
          //TODO ARCHIVIEREN
        }
        else if($typ=="arbeitsnachweis")
        {
          $this->app->DB->Update("UPDATE arbeitsnachweis SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE arbeitsnachweis SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->ArbeitsnachweisProtokoll($id,"Arbeitsnachweis versendet");
          //TODO ARCHIVIEREN
        }
        else if($typ=="reisekosten")
        {
          $this->app->DB->Update("UPDATE reisekosten SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE reisekosten SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->ReisekostenProtokoll($id,"Reisekosten versendet");
          //TODO ARCHIVIEREN
        }

        else if($typ=="auftrag")
        {
          $this->app->DB->Update("UPDATE auftrag SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          //$this->app->DB->Update("UPDATE auftrag SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->AuftragProtokoll($id,"Auftrag versendet");
          //TODO ARCHIVIEREN
        }
        else if ($typ=="rechnung")
        {
          $this->app->DB->Update("UPDATE rechnung SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->closeInvoice($id,'freigegeben');
          $this->app->DB->Update("UPDATE rechnung SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->RechnungProtokoll($id,"Rechnung versendet");
          //TODO ARCHIVIEREN
        }
        else if ($typ=="gutschrift")
        {
          $this->app->DB->Update("UPDATE gutschrift SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE gutschrift SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->GutschriftProtokoll($id,"Gutschrift versendet");
          //TODO ARCHIVIEREN
        }
        else if ($typ=="proformarechnung")
        {
          $this->app->DB->Update("UPDATE  proformarechnung SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE proformarechnung SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->ProformarechnungProtokoll($id,"Proformarechnung versendet");
          //TODO ARCHIVIEREN
        }
        else if ($typ=="preisanfrage")
        {
          $this->app->DB->Update("UPDATE preisanfrage SET versendet=1, versendet_am=NOW(),
              versendet_per='$art',versendet_durch='".$this->app->User->GetName()."',schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE preisanfrage SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->PreisanfrageProtokoll($id,"Preisanfrage versendet");
          //TODO ARCHIVIEREN
        }else if ($typ=="spedition")
        {
          $this->app->DB->Update("UPDATE spedition SET versendet=1, schreibschutz='1' WHERE id='$id' LIMIT 1");
          $this->app->DB->Update("UPDATE spedition SET status='versendet' WHERE id='$id' AND status='freigegeben' LIMIT 1");
          $this->app->DB->Insert("INSERT INTO spedition_protokoll (bearbeiter, grund, avi) VALUES ('".$this->app->DB->real_escape_string($this->app->User->GetName())."', 'Spedition versendet', '$id')");
        }

        $this->RunHook('DokumentMaskVersendet', 2, $typ, $id);
      }
      else  {
        $this->BelegProtokoll($typ,$id,$ret);
        if(!$intern)$this->app->Tpl->Set($parsetarget,"<div class=\"error\">$ret</div>");
      }
    } elseif ($this->app->Secure->GetPOST("speichern")!="") {
      //echo "SPEICHERN";
      // Nur speichern
      $action =  $this->app->Secure->GetGET("action");
      $module =  $this->app->Secure->GetGET("module");

      if($module=="adresse")
      {
        $check = $this->app->DB->Select("SELECT id FROM dokumente_send WHERE dokument='brieffax' AND geloescht=0 AND versendet=0 ORDER by id DESC LIMIT 1");
      } else {
        $check = $this->app->DB->Select("SELECT id FROM dokumente_send WHERE dokument='$typ' AND parameter='$id' AND geloescht=0 AND versendet=0 ORDER by id DESC LIMIT 1"); // GEHT bei BE RE LS
      }

      if($module=="adresse")
      {
        $typ="brieffax";
        if(is_numeric($check))
        {
          $this->app->DB->Insert("UPDATE  dokumente_send  SET betreff='$betreff',text='$text',bearbeiter='".$this->app->User->GetName()."' WHERE id='$check' LIMIT 1");
          $this->app->Tpl->Set('MESSAGE',"<div class=\"info\">Die &Auml;nderungen wurden gespeichert.</div>");
        } else {
          $this->app->DB->Insert("INSERT INTO dokumente_send
              (id,dokument,zeit,bearbeiter,adresse,parameter,art,betreff,text,projekt,ansprechpartner,versendet) VALUES ('','$typ',NOW(),'".$this->app->User->GetName()."',
                '$adresse','$parameter','$art','$betreff','$text','$projekt','$ansprechpartner',0)");
          $this->app->Tpl->Set('MESSAGE',"<div class=\"error\">Es wurde ein neues Dokument wurde angelegt, da das alte Dokument bereits versendet worden ist.</div>");
        }
      } else {

        if(is_numeric($check))
        {
          $this->app->DB->Update("UPDATE  dokumente_send  SET betreff='$betreff',text='$text',bearbeiter='".$this->app->User->GetName()."' WHERE id='$check' LIMIT 1");
          $this->app->Tpl->Set('MESSAGE',"<div class=\"info\">Die &Auml;nderungen wurden gespeichert.</div>");
        } else {
          $parameter = $this->app->Secure->GetGET("id");
          $this->app->DB->Insert("INSERT INTO dokumente_send
              (id,dokument,zeit,bearbeiter,adresse,parameter,art,betreff,text,projekt,ansprechpartner,versendet) VALUES ('','$typ',NOW(),'".$this->app->User->GetName()."',
                '$adresse','$parameter','$art','$betreff','$text','$projekt','$ansprechpartner',0)");
          $this->app->Tpl->Set('MESSAGE',"<div class=\"error\">Es wurde ein neues Dokument wurde angelegt, da das alte Dokument bereits versendet worden ist.</div>");
        }
      }

    }elseif($this->app->Secure->GetPOST("download")!="") {
      header("Location: index.php?module=adresse&action=briefpdf&sid=$id&id=$adresse");
      exit;
    }
  }
// ENDE SCHLEIFE
    if(!$intern)
    {
      $tmp_fax = $this->app->DB->Select("SELECT telefax FROM $typ WHERE id='$id' LIMIT 1");
      $tmp_fax = str_replace('+','00',$tmp_fax);
      $n = preg_match_all("/[0-9]/", $tmp_fax, $treffer);
      for($i=0;$i<$n;$i++){
        $nummer = $nummer . $treffer[0][$i];
        if($n%2 == 1 && $i%2 == 0 && $i < $n-1){
          $nummer = $nummer . "";
        }elseif($n%2 == 0 && $i%2 == 1 && $i < $n-1){
          $nummer = $nummer . "";
        }
      }
      $this->app->Tpl->Set('FAXNUMMER',$nummer);
      if(!empty($this->app->User) && method_exists($this->app->User, 'GetParameter')){
        if($this->app->User->GetParameter('dokumente_abschickenmask_' . $typ . "_brief") == '1'){
          $this->app->Tpl->Set("BRIEFCHECKED", 'checked');
        }

        if($this->app->User->GetParameter('dokumente_abschickenmask_' . $typ . "_email") == '1') {
          $this->app->Tpl->Set("EMAILCHECKED", 'checked');
        }
        if($this->app->User->GetParameter('dokumente_abschickenmask_' . $typ . "_fax") == '1') {
          $this->app->Tpl->Set("FAXCHECKED", 'checked');
        }
        if($this->app->User->GetParameter('dokumente_abschickenmask_' . $typ . "_telefon") == '1') {
          $this->app->Tpl->Set("TELEFONCHECKED", 'checked');
        }
        if($this->app->User->GetParameter('dokumente_abschickenmask_' . $typ . "_sonstiges") == '1') {
          $this->app->Tpl->Set("SONSTIGESCHECKED", 'checked');
        }

        $selected = $this->app->User->GetParameter('drucker_dokumentmask_' . $typ);
        $this->app->Tpl->Set('DRUCKER', $this->GetSelectDrucker($selected));
      }
      $this->app->Tpl->Set('FAX',$this->GetSelectFax());
      $this->app->Tpl->Set('EMAILEMPFAENGER',$this->GetSelectEmail($this->Firmendaten("email")));
      $projektabkuerzung = $this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='$projekt'");
      $this->app->Tpl->Set('PROJEKT',$projektabkuerzung);
      //$this->app->Tpl->Set(PROJEKT,$this->GetProjektSelect($projekt));
      //        $this->app->Tpl->Set(ANSPRECHPARTNER,$this->GetSelectAnsprechpartner($adresse,$projekt));
      $tmp_mail = $this->app->DB->Select("SELECT email FROM $typ WHERE id='$id' LIMIT 1");
      $tmp_name = $this->app->DB->Select("SELECT ansprechpartner FROM $typ WHERE id='$id' LIMIT 1");
      if($tmp_name=="")
        $tmp_name = $this->app->DB->Select("SELECT name FROM $typ WHERE id='$id' LIMIT 1");

      //$this->app->Tpl->Set(ANSPRECHPARTNER,$tmp_name." <".$tmp_mail.">");


      $this->app->Tpl->Set('ANSPRECHPARTNER',$this->GetAdresseMail($adresse,$id,$typ));
      $this->app->Tpl->Set('SELECTUNSICHTBAR', '');
      $this->app->Tpl->Set('MANUELLUNSICHTBAR', 'display:none;');


      //$this->app->YUI->AutoComplete('ansprechpartner', 'emailname');
      $this->app->YUI->AutoComplete('projekt', 'projektname',1);

      $projekt = $this->app->DB->Select("SELECT projekt FROM $typ WHERE id='$id' LIMIT 1");
      $this->DokumentSendShow($parsetarget,$typ,$id,$adresse,$tmpfile,$popup,$projekt);
    }
    // temp datei wieder loeschen
    if(@is_file($tmpfile))unlink($tmpfile);
    if(@is_file($tmpbrief))unlink($tmpbrief);
  }

  function GetAdresseMail($adresse,$id="",$tabelle="") {
    // hole adresse aus feld ansprechpartner

    $tmp_mail = $this->app->DB->Select("SELECT email FROM $tabelle WHERE id='$id' LIMIT 1");
    $tmp_name = $this->app->DB->Select("SELECT ansprechpartner FROM $tabelle WHERE id='$id' LIMIT 1");

    if($tmp_name=="")
      $tmp_name = $this->app->DB->Select("SELECT name FROM $tabelle WHERE id='$id' LIMIT 1");

    $data[0]['name']=$tmp_name;
    $data[0]['email']=$tmp_mail;

    // doppelte eintraege loeschen

    if($data[0]['email']==$tmp_mail)
    {
      $result = "<option value=\"{$data[0]['name']} <{$data[0]['email']}>\" selected>{$data[0]['name']} &lt;{$data[0]['email']}&gt;</option>";
    }
    else
      $result = "<option value=\"{$data[0]['name']} <{$data[0]['email']}>\">{$data[0]['name']} &lt;{$data[0]['email']}&gt;</option>";

    $data = $this->app->DB->SelectArr("SELECT name, email FROM adresse WHERE id='$adresse' ORDER by name");
    $data2 = $this->app->DB->SelectArr("SELECT name, email FROM ansprechpartner WHERE adresse='$adresse' ORDER by name");

    foreach($data2 as $item)
    {
      $check=false;
      foreach($data as $check_item)
      {
        if($item['name']==$check_item['name'] && $item['email']==$check_item['email'])
          $check=true;
      }

      if($check!=true)
        $data[]=array('name'=>$item['name'],'email'=>$item['email']);
    }

    for($i=0;$i<(!empty($data)?count($data):0);$i++)
    {
      if($data[$i]['email']!=$tmp_mail && $data[$i]['name']!=$tmp_name)
      {
        if($data[$i]['email']==$tmp_mail)
          $result .= "<option value=\"".addslashes($data[$i]['name'])." &lt;{$data[$i]['email']}&gt;\" selected>{$data[$i]['name']} &lt;{$data[$i]['email']}&gt;</option>";
        else
          $result .= "<option value=\"".addslashes($data[$i]['name'])." &lt;{$data[$i]['email']}&gt;\">{$data[$i]['name']} &lt;{$data[$i]['email']}&gt;</option>";
      }
    }
    return $result;
  }


  function DokumentSendShow($parsetarget,$dokument,$id,$adresse,$attachments="",$popup=false,$projekt="", $intern = false)
  {
    $return = null;

    $this->BriefpapierHintergrunddisable = false;
    $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    $name2 = $this->app->DB->Select("SELECT name FROM $dokument WHERE id='$id' LIMIT 1");


    $abperfax = $this->app->DB->Select("SELECT abperfax FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
    if($abperfax=="1") $this->app->Tpl->Set('ABPERFAX',"checked");

    $testdata = null;//@todo check query $this->app->DB->SelectArr("SELECT betreff WHERE dokument='".$dokument."' AND parameter='$id' AND parameter!=0 ORDER BY zeit DESC LIMIT 1");

    if($sprache=="") $sprache="deutsch";



    switch($dokument)
    {
      case "bestellung":
        if($tmp_data[0]['betreff']!="")
          $this->DokumentSendVorlage($id);
        else
        {
          $return = $this->Geschaeftsbriefvorlage($sprache,"Bestellung",$projekt,$name2,$id, $intern);
          if(!$intern)
          {
            $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
          }else{
            $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
          }
        }
        break;
      case "angebot":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Angebot",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
      case "lieferschein":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Lieferschein",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
      case "retoure":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Retoure",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
      case "rechnung":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Rechnung",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
      case "gutschrift":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Gutschrift",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;

      case "auftrag":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Auftrag",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
      case "arbeitsnachweis":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Auftrag",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;

     case "proformarechnung":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Proformarechnung",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
     case "preisanfrage":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Preisanfrage",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;
      case "produktion":
        $return = $this->Geschaeftsbriefvorlage($sprache,"Produktion",$projekt,$name2,$id, $intern);
        if(!$intern)
        {
          $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
        }else{
          $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
        }
        break;


      case "brieffax":
        if($testdata!="")
          $this->DokumentSendVorlage($id);
        else
        {
          $return = $this->Geschaeftsbriefvorlage($sprache,"Korrespondenz",$projekt,$name2, $intern);
          if(!$intern)
          {
            $this->app->Tpl->Add('TEXT',"\n\n".$this->Grussformel($projekt,$sprache));
          }else{
            $return['text'] .= "\n\n".$this->Grussformel($projekt,$sprache);
          }
        }
        break;

    default: ;
  }

  if(!$intern && !empty($this->app->User) && method_exists($this->app->User, 'GetParameter') &&
    $this->app->User->GetParameter('dokument_absenden_alleartikel')=='1')
  {
    $tabelle = strtolower($dokument);
    $dateianhaenge = $this->app->DB->SelectArr("SELECT DISTINCT ds.id, ds.datei, d.titel,ds.subjekt, ds.objekt, ds.sort FROM datei_stichwoerter ds INNER JOIN datei d on ds.datei = d.id where d.geloescht <> 1 AND (ds.parameter = '$id' AND ds.objekt like '$dokument') OR ((ds.parameter IN (SELECT DISTINCT artikel FROM ".$tabelle."_position WHERE ".$tabelle."='$id') ) AND ds.objekt like 'artikel') ORDER BY ds.objekt like '$dokument' DESC, ds.sort");
  } else {
    $dateianhaenge = $this->app->DB->SelectArr("SELECT DISTINCT ds.id, ds.datei, d.titel,ds.subjekt, ds.objekt, ds.sort FROM datei_stichwoerter ds INNER JOIN datei d on ds.datei = d.id where d.geloescht <> 1 AND ds.parameter = '$id' AND ds.objekt like '$dokument' AND ds.subjekt!='$dokument' ORDER BY ds.sort");
    if($intern)$intern['dateianhaenge'] = $dateianhaenge;
  }
  if($intern)return $return;
  if($dateianhaenge)
  {
    $sort = 0;
    foreach($dateianhaenge as $dk => $dv)
    {
      $sort++;
      if(strtolower($dv['objekt']) == strtolower($dokument))
      {
        if($dv['sort'] != $sort)$this->app->DB->Update("UPDATE datei_stichwoerter SET sort = '$sort' WHERE id = '".$dv['id']."' LIMIT 1");
        $dateianhaenge[$dk]['sort'] = $sort;
      }
    }
    foreach($dateianhaenge as $dk => $dv)
    {
      if(strtolower($dv['subjekt'])=="anhang") $checked="checked"; else $checked="";
      $dateiname = $this->GetDateiName($dv['datei']);

      if($this->app->User->GetParameter("dokument_absenden_sammelpdf")=="1" && strtolower($dv['objekt']) == strtolower($dokument))
      {
        $extraspalte = "<td width=40 nowrap><img src=\"themes/new/images/down.png\" onclick=\"daup(".$dv['id'].")\" /><img src=\"themes/new/images/up.png\" onclick=\"dadown(".$dv['id'].")\" /></td>";
      } else $extraspalte="<td width=40>&nbsp;</td>";

        $this->app->Tpl->Add('DATEIANHAENGE','<tr><td width=20 id="td_'.$dv['id'].'"><input type="hidden" name="dateisort_'.$dv['datei'].'" value="'.($dk+1).'" /><input type="checkbox" value="1" name="datei_'.$dv['datei'].'" '.$checked.'></td><td><a target="_blank" style="font-weight:normal;color:black;" href="index.php?module=dateien&action=download&typ='.$dokument.'&id='.$dv['datei'].'">'.$dateiname.'</a></td>'.$extraspalte.'</tr>');

      }
    } else {
      $this->app->Tpl->Add('DATEIANHAENGE','<tr><td colspan="3" align="center"><i>Keine Anh&auml;nge vorhanden. <br>Dateien k&ouml;nnen unter dem Reiter "Dateien" <br>als Anhang dem Dokument <br>angeh&auml;ngt werden.</i></td></tr>');
    }

    $module = $this->app->Secure->GetGET("module");
    $id = $this->app->Secure->GetGET("id");

    if($module=="adresse")
    {
      //echo "Fall 1";
      // genau das eine dokument
      $tmp = $this->app->DB->SelectArr("SELECT DATE_FORMAT(zeit,'%d.%m.%Y %H:%i') as datum, dateiid, text, betreff, ansprechpartner, id, adresse, bearbeiter,art, dokument, parameter, versendet FROM dokumente_send WHERE dokument='".$dokument."'
          AND id='$id' AND parameter!=0  AND versendet=1 ORDER by zeit DESC");
      //echo ("SELECT DATE_FORMAT(zeit,'%d.%m.%Y %H:%i') as zeit, text, betreff, id, adresse, bearbeiter,art, dokument, parameter, versendet FROM dokumente_send WHERE dokument='".$dokument."'
      //       AND id='$id' parameter!=0  AND versendet=1 ORDER by zeit");

    }
    else
    {
      // alle passenden dokumente
      $tmp = $this->app->DB->SelectArr("SELECT DATE_FORMAT(zeit,'%d.%m.%Y %H:%i') as datum, text, dateiid, ansprechpartner, betreff, id, adresse, versendet, parameter, dokument, bearbeiter,art FROM dokumente_send WHERE dokument='".$dokument."' AND parameter='$id'  AND parameter!=0 ORDER by zeit DESC");
      //echo "Fall 2";

    }

    if((!empty($tmp)?count($tmp):0)>0)
    {
      $this->app->Tpl->Set('HISTORIE',"<table align=\"left\" width=780>");
      $this->app->Tpl->Add('HISTORIE',"<tr valign=\"top\"><td style=\"font-size: 8pt\"><b>Zeit</b></td><td style=\"font-size: 8pt\"><b>An</b></td><td style=\"font-size: 8pt\"><b>Von</b></td>
          <td style=\"font-size: 8pt\"><b>Art</b></td>
          <td style=\"font-size: 8pt\"><b>Anschreiben</b></td><td style=\"font-size: 8pt\"><b>Dokument</b></td></tr>");
      for($i=0;$i<(!empty($tmp)?count($tmp):0);$i++)
      {

        if($tmp[$i]['versendet']==0) $tmp[$i]['versendet'] = "nein"; else $tmp[$i]['versendet'] = "ja";
        //$tmp_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='{$tmp[$i]['adresse']}' AND geloescht=0 LIMIT 1");
        if(is_numeric($tmp[$i]['ansprechpartner']))
          $tmp_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='".$tmp[$i]['ansprechpartner']."'");
        else
          $tmp_name = htmlentities($tmp[$i]['ansprechpartner'],ENT_QUOTES, "UTF-8");

        //$tmp_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='{$tmp[$i]['adresse']}' AND geloescht=0 LIMIT 1");

        if($tmp[$i]['dateiid'] > 0) $tmppdf = '<a href="index.php?module=dateien&action=send&id='.$tmp[$i]['dateiid'].'"><img src="./themes/[THEME]/images/pdf.svg" border="0"></a>';
        else $tmppdf="";

        $this->app->Tpl->Add('HISTORIE','<tr valign="top"><td style="font-size: 8pt">'.$tmp[$i]['datum'].'</td>
            <td style="font-size: 8pt">'.$tmp_name.'</td><td style="font-size: 8pt">'.$tmp[$i]['bearbeiter'].'</td>
            <td style="font-size: 8pt">'.ucfirst($tmp[$i]['art']).'</td>
            <td style="font-size: 8pt" align="center"><a href="index.php?module=adresse&action=briefpdf&type='.$module.'&typeid='.$id.'&sid='.$tmp[$i]['id'].'"><img src="./themes/[THEME]/images/pdf.svg" border="0"></a></td>
            <td style="font-size: 8pt" align="center">'.$tmppdf.'</td>
            </tr>');
      }
      $this->app->Tpl->Add('HISTORIE',"</table>");

    } else { $this->app->Tpl->Set('HISTORIE',"<div class=\"info\">Dieses Dokument wurde noch nicht versendet!</div>"); }

	if (gettype($attachments) == 'string') {
		$attachments = (Array) $attachments;
	}

    for($i=0;$i<(!empty($attachments)?count($attachments):0);$i++)
    {
      $this->app->Tpl->Add('ANHAENGE',"<a href=\"\">".basename($attachments[$i])."</a>&nbsp;");
    }
    if((!empty($attachments)?count($attachments):0)==0) $this->app->Tpl->Add('ANHAENGE',"keine Anh&auml;nge vorhanden");

    if((!empty($tmp)?count($tmp):0)>0)
    {
      $tmp[0]['betreff'] = str_replace('{FIRMA}',$this->Firmendaten("name"),$tmp[0]['betreff']);
      $tmp[0]['text'] = str_replace('{FIRMA}',$this->Firmendaten("name"),$tmp[0]['text']);

      $tmp[0]['betreff'] = $this->ParseUserVars($dokument,$id, $tmp[0]['betreff']);
      $tmp[0]['text'] = $this->ParseUserVars($dokument,$id, $tmp[0]['text']);

      if($tmp[0]['betreff']!="")
        $this->app->Tpl->Set('BETREFF',$tmp[0]['betreff']);
      if($tmp[0]['text']!="")
        $this->app->Tpl->Set('TEXT',$tmp[0]['text']);
    }


    $tmp = new EasyTable($this->app);
    if($dokument == 'spedition'){
      $tmp->Query("SELECT zeit,bearbeiter,grund FROM ".$dokument."_protokoll WHERE avi='$id' ORDER by zeit DESC");
    }else{
      $tmp->Query("SELECT zeit,bearbeiter,grund FROM ".$dokument."_protokoll WHERE $dokument='$id' ORDER by zeit DESC");
    }
    $tmp->DisplayNew('PROTOKOLL',"Protokoll","noAction");

    $this->app->YUI->AutoSaveUserParameter("alleartikel","dokument_absenden_alleartikel","window.location.href='index.php?module=$dokument&action=abschicken&id=$id';");
    if(!empty($this->app->User) && method_exists($this->app->User, 'GetParameter') && $this->app->User->GetParameter("dokument_absenden_alleartikel")=="1")
    {
      $this->app->Tpl->Set("ALLEARTIKEL","checked");
    }

    $this->app->YUI->AutoSaveUserParameter("sammelpdf","dokument_absenden_sammelpdf","window.location.href='index.php?module=$dokument&action=abschicken&id=$id';");
    if(!empty($this->app->User) && method_exists($this->app->User, 'GetParameter') && $this->app->User->GetParameter("dokument_absenden_sammelpdf")=="1")
    {
      $this->app->Tpl->Set("SAMMELPDF","checked");
    }



    $this->app->YUI->CkEditor("text","internal",array("height"=>"450"));
    if(is_file('pages/content/dokument_absenden_vorlage.tpl'))
    {
      $this->app->Tpl->Set('EMPFAENGER',$name);
      $pTemplate = (($popup==true) ? 'dokument_absenden_popup.tpl' : 'dokument_absenden_vorlage.tpl');
      $this->app->Tpl->Parse($parsetarget, $pTemplate);
    } else {
      $this->app->Tpl->Set('EMPFAENGER',$name);
      $pTemplate = (($popup==true) ? 'dokument_absenden_popup.tpl' : 'dokument_absenden.tpl');
      if($popup != true)
      {
        $this->app->Tpl->Add('EMAILHOOK', '');
        $this->RunHook('dokument_absenden_email', 2, $dokument, $id);
      }
      $this->app->Tpl->Parse($parsetarget, $pTemplate);
    }
  }

  //art=email,betreff,text,dateien, email_to, email_name_to
  function DokumentSend($adresse,$dokument, $parameter, $art,$betreff,$text,$dateien,$drucker="",$ansprechpartner="",$projekt="",$email_to="", $email_name_to="",$cc="",$bcc="")
  {

    // $ret muss geleert werden wenn Dokument erfolgreich versendet wurde!!
    $ret = "Das Dokument konnte nicht versendet werden! (Bitte wählen Sie eine Versandoption aus um das Dokument zu versenden)";

    //$text = $this->ParseUserVars($dokument,$parameter,$text);
    //$betreff = $this->ParseUserVars($dokument,$parameter,$betreff);


    if($dokument!="" && $drucker!="")
      $this->app->User->SetParameter("drucker_dokumentmask_".$dokument,$drucker);


    switch($art)
    {
      case "email": // signatur + dokument als anhang
        $ret = "";
        if($email_to!='') {
          $to = $email_to;
          $to_name = $email_name_to;
        }else{
          if($ansprechpartner!=0)
          {
            $to = $this->app->DB->Select("SELECT email FROM ansprechpartner WHERE id='$ansprechpartner' LIMIT 1");
            $to_name = $this->app->DB->Select("SELECT name FROM ansprechpartner WHERE id='$ansprechpartner' LIMIT 1");
          } else
          {
            $to = $this->app->DB->Select("SELECT email FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
            $to_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
          }
        }

        $to_name = str_replace(",","",$to_name); // , is not allowed in names, because mailsend will interpret it as a list

        // wenn emailadresse from email from user name von benutzer sonst firmenname
        if($drucker==$this->app->User->GetEmail())
          $from_name = $this->app->User->GetName();
        else {
//          $from_name = $this->app->DB->Select("SELECT absendername FROM firmendaten WHERE absendername!='' AND email!='' AND email='$drucker' LIMIT 1");
          $from_name = $this->app->DB->Select("SELECT wert FROM firmendaten_werte WHERE name = 'absendername' LIMIT 1");

          if($from_name=="")
            $from_name = $this->app->DB->Select("SELECT smtp_fromname FROM emailbackup WHERE smtp_fromname!='' AND smtp_frommail!='' AND smtp_frommail='$drucker' AND geloescht!=1 LIMIT 1");
        }

        if($from_name=="")
          $from_name=$this->GetFirmaAbsender();

        if($drucker=="")
          $drucker=$this->GetFirmaMail();


        if($dokument=="auftrag")
        {
          $abweichendeemailab = $this->app->DB->Select("SELECT abweichendeemailab FROM adresse WHERE id='$adresse' AND geloescht!=1 LIMIT 1");
          if($abweichendeemailab!="") $to = $abweichendeemailab;
        }
        $cc_empfaengerausadresse = $this->app->DB->Select("SELECT ".$dokument."_cc FROM adresse WHERE id='$adresse' AND geloescht!=1 LIMIT 1");

        $cc_empfaenger = [];
        $bcc_empfaenger = [];

        if(!empty($cc_empfaengerausadresse)){
          $cc_empfaenger = explode(',',$cc_empfaengerausadresse);
        }

        $text = str_replace('\"','"',$text);

        if($cc!="") {
          if (strpos($cc, ',') !== false) {
            $tmpcc = explode(',',$cc);
            $cc_empfaenger = array_merge($cc_empfaenger, $tmpcc);
          } else
            $cc_empfaenger[] = trim($cc);
        }
        if($bcc!="") {
          if (strpos($bcc, ',') !== false) {
            $tmpbcc = explode(',',$bcc);
            $bcc_empfaenger = array_merge($bcc_empfaenger, $tmpbcc);
          } else
            $bcc_empfaenger[] = trim($bcc);
        }

        foreach($cc_empfaenger as $index => $empfaenger){
          $cc_empfaenger[$index] = trim(trim($empfaenger,'>'),'<');
        }
        foreach($bcc_empfaenger as $index => $empfaenger){
          $bcc_empfaenger[$index] = trim(trim($empfaenger,'>'),'<');
        }

        if($this->MailSend($drucker,$from_name,$to,$to_name,$betreff,$text,$dateien,$projekt,true,$cc_empfaenger,$bcc_empfaenger)){
          $ret = "";
          $this->RunHook('documentsend_email_success', 8, $dokument, $parameter, $drucker, $to, $to_name, $betreff, $text, $dateien);
        }
        else {
          if($to=="")
            $ret = "Keine Empfängeradresse gefunden. E-Mail konnte nicht versendet werden.";
          else
            $ret = "Die E-Mail konnte nicht versendet werden! (".$this->mail_error.")";
        }

        break;

      case "brief":
        foreach($dateien as $key=>$value)
          $this->app->printer->Drucken($drucker,$value);
        $ret = "";
        break;

      case "fax":
        foreach($dateien as $key=>$value)
          $this->app->printer->Drucken($drucker,$value,$email_to);
        $ret = "";
        break;

      case "telefon":
        $ret = "";
        break;
      case "sonstiges":
        $ret = "";
        break;

    }

    $this->app->erp->RunHook('dokumentsend_ende', 5, $dokument, $parameter, $projekt, $adresse, $art);

    return $ret;
  }


  function NewEvent($beschreibung, $kategorie, $objekt='',$parameter='')
  {

    $bearbeiter = $this->app->User->GetName();

    $this->app->DB->Insert("INSERT INTO event (id,beschreibung,kategorie,zeit,objekt,parameter,bearbeiter)
        VALUES('','$beschreibung','$kategorie',NOW(),'$objekt','$parameter','$bearbeiter')");

  }

  function UpdateChecksumShopartikel($projekt)
  {
    $tmp = $this->app->DB->SelectArr("SELECT id FROM artikel WHERE shop > 0");
    if(empty($tmp)) {
      return;
    }
    foreach($tmp as $row) {
      $this->UpdateArtikelChecksum($row['id'], $projekt);
    }
  }

  function UpdateArtikelChecksum($artikel,$projekt)
  {
    $tmp = $this->app->DB->SelectArr("SELECT typ,
        nummer, projekt, inaktiv, warengruppe, name_de, name_en, kurztext_de, ausverkauft,
        kurztext_en , beschreibung_de, beschreibung_en,standardbild, herstellerlink, hersteller, uebersicht_de,uebersicht_en,links_de,links_en, startseite_de, startseite_en,
        lieferzeit , lieferzeitmanuell, wichtig,  gewicht, sperrgrund,  gueltigbis,umsatzsteuer,  klasse,  adresse, shop, firma, neu,topseller,startseite,
        (SELECT MAX(preis) FROM verkaufspreise WHERE
         artikel='$artikel' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND ab_menge = 1 AND (adresse='0' OR adresse='')) as preis
        FROM artikel WHERE id='$artikel' LIMIT 1");

    //        artikel='$artikel' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND ab_menge = 1 AND (objekt='Standard' OR objekt='')) as preis
    serialize($tmp);

    $checksum = md5(serialize($tmp));

    $this->app->DB->Update("UPDATE artikel SET checksum='$checksum' WHERE id='$artikel' LIMIT 1");
  }

  function GetStandardMarge()
  {
    return $this->Firmendaten("standardmarge");
  }


  function GetStandardStundensatz()
  {
    return 57.62;
  }

  /** @deprecated */
  function GetProjektSelectMitarbeiter($adresse)
  {
    // Adresse ist Mitglied von Projekt xx
    // gibt man kein parameter an soll alles zurueck
    // entsprechen weitere parameter filtern die ausgabe
    $arr = $this->app->DB->SelectArr("SELECT adresse FROM bla bla where rolle=mitarbeiter von projekt xxx");
    foreach($arr as $value)
    {
      if($selected==$value) $tmp = "selected"; else $tmp="";
      $ret .= "<option value=\"$value\" $tmp>$value</option>";
    }
    return $ret;


  }

  function GetArtikelPreisvorlageProjekt($kunde,$projekt,$artikel,$menge)
  {
    //HACK!
    return $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE projekt='$projekt' AND artikel='$artikel'");
  }

  // do not use this function!
  function GetAuftragSteuersatz($auftrag)
  {
    //ermitteln aus Land und UST-ID Prüfung
    return 1.19;
  }

  function GetSteuersatzAssoc($id,$typ)
  {
    $steuersatzErmaessigt = $this->GetSteuersatzErmaessigt(false,$id,$typ);
    $steuersatzNormal = $this->GetSteuersatzNormal(false,$id,$typ);

    return [
      0=>'0 %',
      $steuersatzErmaessigt=>$steuersatzErmaessigt.' %',
      $steuersatzNormal=>$steuersatzNormal.' %'
    ];
  }

  function GetSteuersatz($id,$typ)
  {

    $tmp[] = 0;
    $tmp[] = $this->GetSteuersatzErmaessigt(false,$id,$typ);
    $tmp[] = $this->GetSteuersatzNormal(false,$id,$typ);

    return $tmp;
  }

  function GetSelectSteuersatz($selected,$id,$typ)
  {
    $tmp = $this->GetSteuersatz($id,$typ);
    $ret = '';
    foreach($tmp as $key=>$value)
    {
      $tmp = '';
      if($selected==$value) {
        $tmp = 'selected';
      }
      $ret .= "<option value=\"$value\" $tmp>$value %</option>";
    }
    return $ret;
  }


  function GetSteuersatzNormal($komma, $id, $typ)
  {
    $steuersatz = 0;
    if($typ==='provisionsgutschrift'){
      $steuersatz = $this->app->DB->Select("SELECT steuersatz FROM mlm_abrechnung_adresse WHERE id='$id' LIMIT 1");
    }
    elseif($typ !== 'lieferschein'){
      $steuersatz = $this->app->DB->Select("SELECT steuersatz_normal FROM $typ WHERE id='$id' LIMIT 1");
    }

    if($komma){
      return ($steuersatz / 100.0) + 1.0; //1.19
    }

    return $steuersatz;
  }

  function GetSteuersatzErmaessigt($komma, $id, $typ)
  {
    $steuersatz = 0;
    if($typ !== 'lieferschein'){
      $steuersatz = $this->app->DB->Select("SELECT steuersatz_ermaessigt FROM $typ WHERE id='$id' LIMIT 1");
    }

    if($komma){
      return ($steuersatz / 100.0) + 1.0; //1.19
    }

    return $steuersatz;
  }

  function GetSteuersatzBefreit($komma, $id, $typ)
  {
    if($komma){
      return 1.00;
    }

    return 0.00;
  }


  function GetKreditkarten()
  {

    return array('MasterCard','Visa','American Express');
  }

  function GetKreditkartenSelect($selected)
  {
    $ret = '';
    foreach($this->GetKreditkarten() as $value)
    {
      $tmp = '';
      if($selected==$value) {
        $tmp = 'selected';
      }
      $ret .= "<option value=\"$value\" $tmp>$value</option>";
    }
    return $ret;
  }


  function GetKundeSteuersatz($kunde)
  {


  }

  function AddUSTIDPruefungKunde($kunde)
  {
    //gebunden an eine adresse


  }

  function GetVersandkosten($projekt)
  {

    return 3.32;
  }



  function AuftraegeBerechnen()
  {
    $this->app->erp->SetKonfigurationValue('last_order_calc',date('d.m.Y H:i:s'));
    $this->app->DB->Delete("DELETE r FROM lager_reserviert r LEFT JOIN auftrag a ON r.objekt = 'auftrag' AND r.parameter = a.id AND a.status = 'freigegeben' WHERE r.objekt = 'auftrag' AND isnull(a.id)");
    if(!empty($this->app->User) && method_exists($this->app->User, 'GetID') && $this->app->User->GetID())
    {
      $limit = (int)$this->app->erp->Firmendaten('autoversand_maxauftraege');
    }else {
      $limit = 0;
    }
    $auftraege = $this->app->DB->SelectArr("SELECT id FROM auftrag WHERE status='freigegeben' AND inbearbeitung=0 AND autoversand=1 ORDER BY fastlane = 1 DESC, datum ".($limit > 0?" LIMIT $limit ":''));
    if(empty($auftraege)) {
      return;
    }
    foreach($auftraege as $auftrag) {
      //$this->app->erp->AuftragNeuberechnen($auftraege[$i][id]);
      $this->AuftragEinzelnBerechnen($auftrag['id']);
    }
  }

  function KalkulationNeuberechnen($id)
  {
    /** @var Kalkulation $obj */
    $obj = $this->LoadModul('kalkulation');
    if(!empty($obj) && method_exists($obj,'KalkulationNeuberechnen'))
    {
      $obj->KalkulationNeuberechnen($id);
    }
  }


  function AddArtikelAuftrag($artikel,$auftrag,$menge=1)
  {
    if(!is_numeric($menge)) {
      $menge = 1;
    }
    $articleRow = $this->app->DB->SelectRow("SELECT name_de,anabregs_text FROM artikel WHERE id='$artikel' LIMIT 1");
    $name = $articleRow['name_de'];
    $beschreibung = $articleRow['anabregs_text'];

    $this->AddPositionManuell("auftrag",$auftrag, $artikel,$menge,$name,$beschreibung);
  }

  function DelArtikelAuftrag($id)
  {
    //loesche artikel von auftrag und schiebe positionen nach


  }


  function GetAuftragStatus($auftrag)
  {



  }


  function IsEU($land)
  {
    foreach($this->GetUSTEU() as $euland)
    {
      if($land==$euland)
        return true;
    }

    // alle anderen laender sind export!
    return false;
  }


  function Export($land)
  {
    if($land == '' || $land==$this->Firmendaten('land')){
      return false;
    }

    return !$this->IsEU($land);
  }


  function GetEU()
  {
    return $this->GetUSTEU(false);
  }

  function GetUSTEU($ust=false)
  {
    $isoGreece = 'GR';
    if($ust){
      $isoGreece = 'EL';
    }

    $checklaender = $this->app->DB->Select('SELECT id FROM laender LIMIT 1');
    if($checklaender > 0 )
    {
      $laender = $this->app->DB->SelectArr("SELECT iso FROM laender WHERE eu=1 ORDER by iso");
      $ret = null;
      foreach($laender as $land) {
        if($land['iso'] === 'GR'){
          $ret[] = $isoGreece;
        }else{
          $ret[] = $land['iso'];
        }
      }
      return $ret;
    }

    return
        array('DE','BE','IT','RO',
          'BG','LV','SE',
          'DK','LT','SK',
          'DE','LU','SI',
          'EE','MT','ES',
          'FI','NL','CZ',
          'FR','AT','HU',
          $isoGreece,'PL',
          'IE','PT','CY','HR');
  }


  function CheckUSTFormat($ust)
  {
    /*
     * method not removed for downward compatibility
     */
    return USTID::CheckUSTFormat($ust);
  }


  function CheckUst($ust1,$ust2, $firmenname, $ort, $strasse, $plz, $druck="nein")
  {
    $tmp = new USTID();
    //$status = $tmp->check("DE263136143","SE556459933901","Wind River AB","Kista","Finlandsgatan 52","16493","ja");
    $status = $tmp->check($ust1, $ust2, $firmenname, $ort, $strasse, $plz, $druck,$onlinefehler);

/*
    if($tmp->answer['Erg_Name'] == 'A')$tmp->answer['Erg_Name'] = '';
    if($tmp->answer['Erg_Ort'] == 'A')$tmp->answer['Erg_Ort'] = '';
    if($tmp->answer['Erg_Str'] == 'A')$tmp->answer['Erg_Str'] = '';
    if($tmp->answer['Erg_PLZ'] == 'A')$tmp->answer['Erg_PLZ'] = '';
*/
    $erg = array(
        'ERG_NAME' => $tmp->answer['Erg_Name'],
        'ERG_ORT' => $tmp->answer['Erg_Ort'],
        'ERG_STR' => $tmp->answer['Erg_Str'],
        'ERG_PLZ' => $tmp->answer['Erg_PLZ'],
        'ERROR_MSG' => $tmp->answer['ErrorMSG'],
        'ERROR_CODE' => $tmp->answer['ErrorCode']);

    return $erg;
  }

  function MailSend($from,$from_name,$to,$to_name,$betreff,$text,$files="",$projekt="",$signature=true,$cc="",$bcc="", $system = false)
  {
    $bcc1 = $this->Firmendaten('bcc1');
    $bcc2 = $this->Firmendaten('bcc2');

    if($bcc1!="") {
      $this->MailSendFinal($from,$from_name,$bcc1,"Xentral Kopie 1","KOPIE ".$betreff,$text,$files,$projekt,$signature,'','', $system);
    }
    if($bcc2!="") $this->MailSendFinal($from,$from_name,$bcc2,"Xentral Kopie 2","KOPIE ".$betreff,$text,$files,$projekt,$signature,'','', $system);

    return $this->MailSendFinal($from,$from_name,$to,$to_name,$betreff,$text,$files,$projekt,$signature,$cc,$bcc, $system);
  }

/*
* Return 0 = not ok, return 1 = ok
* $to, $to_name, $cc, $bcc can be csv or arrays
*/
function MailSendFinal($from,$from_name,$to,$to_name,$betreff,$text,$files="",$projekt="",$signature=true,$cc="",$bcc="", $system = false)
{
  // keine leeren email versenden
  if($text=="" && $betreff=="") {
     $this->mail_error =  "Mailer Error: " . "Empty mail.";
     return 0;  
  }

/*  $isSystemTemplate = $system && is_file(dirname(__DIR__, 2) .'/classes/Modules/Company/templates/systemmail.tpl');
  if($isSystemTemplate) {
    $signature = false;
  }*/

  if($projekt > 0 && $this->Projektdaten($projekt,"absendeadresse")!=""){
    $from = $this->Projektdaten($projekt, "absendeadresse");
  }

    $from_name = $this->ClearDataBeforeOutput($from_name);
    $from_name = $this->ReadyForPDF($from_name);
    $betreff  =  $this->ReadyForPDF($betreff);
    $text =  $this->ReadyForPDF($text);
    $text = str_replace('€','&euro;',$text);

/*    $text = htmlspecialchars_decode( 
      htmlentities($text, ENT_NOQUOTES, 'UTF-8', false)
    , ENT_NOQUOTES
    ); */

    if($signature)
    {
      $eigenesignatur = $this->app->DB->Select("SELECT eigenesignatur FROM emailbackup WHERE email='$from' AND email !='' AND geloescht!=1 LIMIT 1");

      if(strlen(trim($this->Signatur($from))) > 0 && $eigenesignatur == 1)
      {
        $signaturtext = $this->Signatur($from);
        if($this->isHTML($signaturtext))
          $body = str_replace('\r\n',"\n",$text)."<br>".$signaturtext;
        else
          $body = str_replace('\r\n',"\n",$text)."<br>".nl2br($signaturtext);
      }else{
        if($projekt > 0 && $this->Projektdaten($projekt,"absendesignatur")!=""){
          $signaturtext = $this->Projektdaten($projekt,"absendesignatur");
          if($this->isHTML($signaturtext))
            $body = str_replace('\r\n',"\n",$text)."<br><br>".$signaturtext;
          else
            $body = str_replace('\r\n',"\n",$text)."<br><br>".$this->ReadyForPDF(nl2br($signaturtext));
        }else{
          if(strlen(trim($this->Signatur($from))) > 0 && $eigenesignatur == 0){
            $signaturtext = $this->Signatur($from);
            if($this->isHTML($signaturtext))
              $body = str_replace('\r\n',"\n",$text)."<br>".$signaturtext;
            else
              $body = str_replace('\r\n',"\n",$text)."<br>".nl2br($signaturtext);
          }else{
            $body = str_replace('\r\n',"\n",$text);
          }
        }

      }
    } else {
      $body = str_replace('\r\n',"\n",$text);
    }

    {
      $email_html_template = $this->Projektdaten($projekt, "email_html_template");
      if($email_html_template == ""){
        $email_html_template = $this->Firmendaten('email_html_template');
      }
    } 
    if($email_html_template!="" && preg_match("/{CONTENT}/",$email_html_template))
    {
      $email_html_template = preg_replace('~\x{00a0}~siu',' ',$email_html_template);
      $email_html_template = preg_replace( "#((&nbsp;|\s|<br>)+$)#", "", trim($email_html_template) );
      $body = str_replace('{CONTENT}',$body,$email_html_template);
    }

    $sysMailerSent = false;
    $sysMailer = null;
    $emailObj = null;
    if ($this->app->Container->has('SystemMailer')) {
        $sysMailer = $this->app->Container->get('SystemMailer');
    }

    if ($sysMailer !== null) {
      
      $recipients = [];

      $to_csv = "";
      $to_array = array();
      $to_name_array = array();
      $to_name_csv = "";

      // Prepare names and addresses
      if (is_array($to)) {
        foreach ($to as $item)  {
          $to_array[] = $item;
          $to_csv .= $item;
        }
      } else if (!empty($to)) {
        foreach (explode(',',str_replace(" ","",$to)) as $item)  {
          $to_array[] = $item;
          $to_csv .= $item;
        }
      }
      if (is_array($to_name)) {
        foreach ($to_name as $item)  {
          $to_name_array[] = $item;
          $to_name_csv .= $item;
        }
      } else if (!empty($to_name)) {
        foreach (explode(',',$to_name) as $item)  {
          $to_name_array[] = $item;
          $to_name_csv .= $item;
        }
      }

      // Fill empty names with address

      $number_of_names = empty($to_name_array)?0:count($to_name_array);

      if (count($to_array) > $number_of_names) {
        $itemcount = 0;
        foreach ($to_array as $item) {
          $itemcount++;
          if ($itemcount > $number_of_names) {
            $to_name_array[] = $item;
          }
        }
      }

      $to_combined_array = array_combine($to_array,$to_name_array);

      foreach ($to_combined_array as $key => $value) {
        $value = $this->ClearDataBeforeOutput($value);
        $value = $this->ReadyForPDF($value);
        $recipients[] = new EmailRecipient($key, $value);
      }

      $ccRecipients = [];
      if (is_array($cc)) {
        foreach ($cc as $item)  {
          $ccRecipients[] = new EmailRecipient($item, $item);
        }
      } else if (!empty($cc)) {
        foreach (explode(',',str_replace(" ","",$cc)) as $item)  {
          $ccRecipients[] = new EmailRecipient($item, $item);
        }
      }

      $bccRecipients = [];
      if (is_array($bcc)) {
        foreach ($bcc as $item)  {
          $bccRecipients[] = new EmailRecipient($item, $item);
        }
      } else if (!empty($bcc)) {
        foreach (explode(',',str_replace(" ","",$bcc)) as $item)  {
          $bccRecipients[] = new EmailRecipient($item, $item);
        }
      }

      $bcc3 = $this->Firmendaten('bcc3');
      if($bcc3!="")
      {
        $bccRecipients[] = new EmailRecipient($bcc3, $bcc3);
      }

      if (!empty($recipients)) {
          // This will build the mail with phpmailer 6 and send it out
          // There is no way to retrieve the created mail e.g. for IMAP output
          // This should be migrated to laminas-mail (used for imap)
          // Phpmailer 6 can then be removed
          $sysMailerSent = $sysMailer->composeAndSendEmail(
              $from,
              $from_name,
              $recipients,
              $betreff,
              $body,
              $files,
              $ccRecipients,
              $bccRecipients,
              $sendmail_error
          );
      } else {
        $sendmail_error = "Kein Empf&auml;nger angegeben";
      }    
    }    

    if($sysMailerSent === false) {

      $this->MailLogFile($from,$from_name,$to_csv,$to_name_csv,$betreff,$text,$files,$projekt,$signature,$cc,$bcc,$system);
      $this->mail_error =  "Mailer Error: " . $sendmail_error;

      if(isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetID'))
      {
        $this->app->erp->InternesEvent($this->app->User->GetID(),"Fehler bei Mailversand: ".$sendmail_error,"alert",1);
      }
      return 0;
    } else {

      $this->MailLogFile($from,$from_name,$to_csv,$to_name_csv,$betreff,$text,$files,$projekt,$signature,$cc,$bcc,$system);

      // Put the mail in IMAP sent folder
      // Note that this is implemented with laminas-mail and only this
      // The created mail may differ from the sent one because it is created by different libraries 

      $imap_aktiv = $this->app->DB->Select("SELECT imap_sentfolder_aktiv FROM emailbackup WHERE email='".$from."' AND imap_sentfolder!='' AND geloescht!=1 LIMIT 1");
      if($imap_aktiv=="1" && !preg_match("/Xentral Kopie/",$to_name_csv) && !preg_match("/WaWision Kopie/",$to_name_csv))
      {

        // This will build the mail as EmailMessage (Xentral\Components\Mailer\Data) and then rebuild it with laminas-mail message to produce the raw output
        $emailObj = $sysMailer->composeEmail(
            $recipients,
            $betreff,
            $body,
            $files,
            $ccRecipients,
            $bccRecipients
        );

        if ($emailObj !== null) {
          /** @var MimeMessageFormatterInterface $formatter */

          $formatter = $this->app->Container->get('MailClientMimeMessageFormatter');
          $imapCopyMessage = $formatter->formatMessage(
            $emailObj,
            new EmailRecipient($from, $from_name)
          );
        } else {
          $this->app->erp->LogFile("Mailer Error: Email could not be composed!");
        }

        // Load the mail to IMAP using laminas
        try {
          $imap_data = $this->app->DB->SelectRow("SELECT * FROM emailbackup WHERE email='".$from."' AND geloescht!=1 LIMIT 1");
          $account = EmailBackupAccount::fromDbState($imap_data);
          /** @var MailClientProvider $clientProvider */
          $clientProvider = $this->app->Container->get('MailClientProvider');
          $client = $clientProvider->createMailClientFromAccount($account);
          $client->connect();
          $client->appendMessage($imapCopyMessage, $account->getImapOutgoingFolder());
        } catch (Exception $e) {
          $this->app->erp->LogFile("Mailer IMAP Error: " . (string) $e);
          if(isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetID'))
          {
            $this->app->erp->InternesEvent($this->app->User->GetID(),"IMAP-Fehler","alert",1);
          }
          $this->mail_error =  "Mailer IMAP Error";
          return 0;
        }
      }
    } // sysMailersent
    $this->mail_error = "";
    return 1;
  }


  function MailLogFile($from,$from_name,$to,$to_name,$betreff,$text,$files="",$projekt="",$signature=true,$cc="",$bcc="", $system = false)
  {
    $subject = $subject;
    $body =   $body;
    $status = $errorinfo;

    if($status!="") {
      $status .= " (Host: ".$host." User: ".$username.") ";
    }

    $from =   $this->app->DB->real_escape_string($from);
    $to =   $this->app->DB->real_escape_string($to);

    $this->app->DB->Insert("INSERT INTO mailausgang (id,`subject`,`body`,`from`,`to`,`status`,zeit) VALUES ('','$subject','$body','$from','$to','$status',NOW())");
    if($cc && (!empty($cc)?count($cc):0) > 0){
      for ($i=0; $i < (!empty($cc)?count($cc):0); $i++) {
      $this->app->DB->Insert("INSERT INTO mailausgang (id,`subject`,`body`,`from`,`to`,`status`,zeit, art) VALUES ('','$subject','$body','$from','".$cc[$i][0]."','$status',NOW(), '1')");
      }
    }
    if($bcc && (!empty($bcc)?count($bcc):0) > 0){
      for ($i=0; $i < (!empty($bcc)?count($bcc):0); $i++) {
      $this->app->DB->Insert("INSERT INTO mailausgang (id,`subject`,`body`,`from`,`to`,`status`,zeit, art) VALUES ('','$subject','$body','$from','".$bcc[$i][0]."','$status',NOW(), '2')");
      }
    }
    $this->app->DB->Delete("DELETE FROM `mailausgang` WHERE DATE_SUB(CURDATE(), INTERVAL 90 DAY) >= zeit");
  }


  function isMailAdr($mailadr){
    return preg_match("/^[_a-z0-9!#$%&\\'*+-\/=?^_`.{|}~]+(\.[_a-z0-9!#$%&\'*+-\\/=?^_`.{|}~]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,20})$/i", $mailadr, $treffer)?1:0;
  }


  function BeschriftungSprache($sprache='')
  {

    if ($sprache === '') {
        $this->beschriftung_sprache='deutsch';
    } else {
        $this->beschriftung_sprache=strtolower(trim($sprache));
    }

  }

  function BeschriftungStandardwerte($field,$sprache="deutsch",$getvars=false)
  {
    $uebersetzung['dokument_rechnung_titel']['deutsch'] = "Rechnung";
    $uebersetzung['dokument_position']['deutsch'] = "Pos";
    $uebersetzung['dokument_anschreiben']['deutsch'] = "Sehr geehrte Damen und Herren";
    $uebersetzung['dokument_artikelnummer']['deutsch'] =  "Artikelnr";
    $uebersetzung['dokument_artikel']['deutsch'] = "Artikel";
    $uebersetzung['dokument_lieferdatum']['deutsch'] = "Liefertermin";
    $uebersetzung['dokument_lieferdatumkw']['deutsch'] = "KW";
    $uebersetzung['dokument_artikelnummerkunde']['deutsch'] = "Ihre Artikelnummer";
    $uebersetzung['dokument_menge']['deutsch'] = "Menge";
    $uebersetzung['dokument_gesamt']['deutsch'] = "Gesamt";
    $uebersetzung['dokument_gesamt_optional']['deutsch'] = "Gesamt optional";
    $uebersetzung['dokument_gesamt_total']['deutsch'] = "Gesamt";
    $uebersetzung['dokument_mwst']['deutsch'] = "MwSt.";
    $uebersetzung['dokument_zzglmwst']['deutsch'] = "zzgl. MwSt.";
    $uebersetzung['dokument_inklmwst']['deutsch'] = "inkl. MwSt.";
    $uebersetzung['dokument_gesamtnetto_zzglmwst']['deutsch'] = "Gesamt netto";
    $uebersetzung['dokument_rabatt']['deutsch'] = "Rabatt";
    $uebersetzung['dokument_stueck']['deutsch'] = "Stck";
    $uebersetzung['dokument_einzel']['deutsch'] = "Einzel";
    $uebersetzung['dokument_einheit']['deutsch'] = "Einheit";
    $uebersetzung['dokument_gewicht']['deutsch'] = "Gewicht";
    $uebersetzung['dokument_laenge']['deutsch'] = "Länge";
    $uebersetzung['dokument_breite']['deutsch'] = "Breite";
    $uebersetzung['dokument_hoehe']['deutsch'] = "Höhe";
    $uebersetzung['dokument_optional']['deutsch'] = "Optional: ";
    $uebersetzung['dokument_ursprungsregion']['deutsch'] = "Ursprungsregion";
    $uebersetzung['dokument_gewicht']['deutsch'] = "Gewicht";
    $uebersetzung['dokument_gesamtnetto']['deutsch'] = "Gesamt netto";
    $uebersetzung['dokument_gesamtnetto_optional']['deutsch'] = "Gesamt netto optional";
    $uebersetzung['dokument_seite']['deutsch'] = "Seite";
    $uebersetzung['dokument_seitevon']['deutsch'] = "von";
    $uebersetzung['dokument_datum']['deutsch'] = "Datum";
    $uebersetzung['dokument_angebot_anfrage']['deutsch'] = "Ihre Anfrage";
    $uebersetzung['dokument_angebot']['deutsch'] = "Angebot";
    $uebersetzung['dokument_bestellung']['deutsch'] = "Bestellung";
    $uebersetzung['dokument_bestellung_angebotnummer']['deutsch'] = "Ihr Angebot";
    $uebersetzung['dokument_bestellung_unserekundennummer']['deutsch'] = "Unsere Kunden-Nr.";
    $uebersetzung['dokument_bestelldatum']['deutsch'] = "Bestelldatum";
    $uebersetzung['dokument_bestellung_einkauf']['deutsch'] = "Einkauf";
    $uebersetzung['dokument_bestellung_keineartikelnummer']['deutsch'] = "siehe Artikel-Nr.";
    $uebersetzung['dokument_lieferdatum_sofort']['deutsch'] = "sofort";
    $uebersetzung['dokument_bestellung_unsereartikelnummer']['deutsch'] = "Unsere Artikel-Nr.";
    $uebersetzung['dokument_bestellung_bestellnummer']['deutsch'] = "Best-Nr.";
    $uebersetzung['dokument_bestellung_mengeinvpe']['deutsch'] = "Menge in VPE";
    $uebersetzung['dokument_bestellung_bestaetigung']['deutsch'] = "Die Bestellung ist erst nach Eingang einer Bestätigung Ihrerseits gültig. Wird die Bestellung nicht innerhalb einer Woche bestätigt verfällt diese.";
    $uebersetzung['dokument_auftrag']['deutsch'] = "Auftrag";
    $uebersetzung['dokument_auftrag_auftragsbestaetigung']['deutsch'] = "Auftragsbestätigung";
    $uebersetzung['dokument_lieferdatum']['deutsch'] = "Lieferdatum";
    $uebersetzung['dokument_lieferschein']['deutsch'] = "Lieferschein";
    $uebersetzung['dokument_retoure']['deutsch'] = "Retoure";
    $uebersetzung['dokument_kommissionierschein']['deutsch'] = "Kommissionierschein";
    $uebersetzung['dokument_ansprechpartner']['deutsch'] = "Ansprechpartner";
    $uebersetzung['dokument_rechnungsdatum']['deutsch'] = "Rechnungsdatum";
    $uebersetzung['dokument_proformarechnungsdatum']['deutsch'] = "Datum";
    $uebersetzung['dokument_auftragsdatum']['deutsch'] = "Auftragsdatum";
    $uebersetzung['dokument_rechnung']['deutsch'] = "Rechnung";
    $uebersetzung['dokument_gutschrift']['deutsch'] = "Gutschrift";
    $uebersetzung['dokument_kalkulation']['deutsch'] = "Kalkulation";
    $uebersetzung['dokument_stueckliste']['deutsch'] = "(Stückliste)";
    $uebersetzung['dokument_proformarechnung']['deutsch'] = "Proformarechnung";
    $uebersetzung['dokument_preisanfrage']['deutsch'] = "Preisanfrage";
    $uebersetzung['dokument_entwurf']['deutsch'] = "Entwurf";
    $uebersetzung['dokument_rechnung_kopie']['deutsch'] = "doppel";
    $uebersetzung['dokument_skonto']['deutsch'] = "Skonto";
    $uebersetzung['dokument_innerhalb']['deutsch'] = "innerhalb";
    $uebersetzung['dokument_tagen']['deutsch'] = "Tagen";
    $uebersetzung['dokument_tagebiszum']['deutsch'] = "Tage bis zum";
    $uebersetzung['dokument_zahlung_per']['deutsch'] = "Bezahlung per";
    $uebersetzung['dokument_offene_lastschriften']['deutsch'] = "Der Betrag wird mit offenen Lastschriften verrechnet.";
    $uebersetzung['dokument_auszahlungskonditionen']['deutsch'] = "aus Zahlungskonditionen";
    $uebersetzung['dokument_zahlung_rechnung_anab']['deutsch'] = "Rechnung zahlbar innerhalb von {ZAHLUNGSZIELTAGE} Tagen.";
    $uebersetzung['dokument_telefon']['deutsch'] = "Telefon";
    $uebersetzung['dokument_email']['deutsch'] = "E-Mail";
    $uebersetzung['dokument_teillieferung']['deutsch'] = "Teillieferung von Auftrag";
    $uebersetzung['dokument_herstellernummer']['deutsch'] = "Herstellernummer";
    $uebersetzung['dokument_abmessung']['deutsch'] = "Abmessung";

    $uebersetzung['dokument_zolltarifnummer']['deutsch'] = "Zolltarifnummer";
    $uebersetzung['dokument_ean']['deutsch'] = "EAN";
    $uebersetzung['dokument_mhd']['deutsch'] = "MHD";
    $uebersetzung['dokument_herkunftsland']['deutsch'] = "Herkunftsland";
    $uebersetzung['dokument_charge']['deutsch'] = "Charge";
    $uebersetzung['dokument_seriennummer']['deutsch'] = "S/N";
    $uebersetzung['dokument_ihreartikelnummer']['deutsch'] = "Ihre Artikelnummer";
    $uebersetzung['dokument_projekt']['deutsch'] = "Projekt";

    $uebersetzung['dokument_skontoanderezahlungsweisen']['deutsch'] = "Skonto {ZAHLUNGSZIELSKONTO} % aus Zahlungskonditionen ";
    $uebersetzung['dokument_staffelpreis_von']['deutsch'] = "ab";
    $uebersetzung['dokument_staffelpreis_stueck']['deutsch'] = "St.";

    $uebersetzung['auftrag_bezeichnung_vertrieb']['deutsch'] = "Vertrieb";
    $uebersetzung['auftrag_bezeichnung_bearbeiter']['deutsch'] = "Bearbeiter";
    $uebersetzung['auftrag_bezeichnung_bestellnummer']['deutsch'] = "Ihre Bestellnummer";
    $uebersetzung['beschriftunginternetnummer']['deutsch'] = "Internetnummer";
    $uebersetzung['bezeichnungkundennummer']['deutsch'] = "Kundennummer";
    $uebersetzung['bezeichnungstornorechnung']['deutsch'] = "Stornorechnung";
    $uebersetzung['bezeichnungangebotersatz']['deutsch'] = "";
    $uebersetzung['bezeichnungauftragersatz']['deutsch'] = "";
    $uebersetzung['bezeichnungproformarechnungersatz']['deutsch'] = "";
    $uebersetzung['bezeichnungrechnungersatz']['deutsch'] = "";
    $uebersetzung['bezeichnunglieferscheinersatz']['deutsch'] = "";
    $uebersetzung['bezeichnungbestellungersatz']['deutsch'] = "";
    $uebersetzung['entspricht_rechnungsadresse']['deutsch'] = "entspricht Rechnungsadresse";
    $uebersetzung['entspricht_hauptadresse']['deutsch'] = "entspricht Hauptadresse";
    $uebersetzung['gruppenrechnung_lieferschein_freitext']['deutsch'] = "Lieferschein {BELEGNR} vom {DATUM}";
    $uebersetzung['gruppenrechnung_lieferschein_anzahl']['deutsch'] = "Lieferschein Anzahl: {ANZAHL}";

    $uebersetzung['proformarechnung_lieferschein_freitext']['deutsch'] = "Lieferschein {BELEGNR} vom {DATUM}";
    $uebersetzung['proformarechnung_lieferschein_anzahl']['deutsch'] = "Lieferschein Anzahl: {ANZAHL}";
    $uebersetzung['proformarechnung_ohnezolltarifnummer']['deutsch'] = "Ohne Zolltarifnummer";




    $uebersetzung['dokument_zahlungserinnerung']['deutsch'] = "Zahlungserinnerung";

    $uebersetzung['mahnwesen_betreff']['deutsch'] = "Buchhaltung: Ihre offene Rechnung";
    $uebersetzung['mahnwesen_betreff']['englisch'] = "Accounting: Your outstanding account";
    $uebersetzung['dokument_mahnung1']['deutsch'] = "1. Mahnung";
    $uebersetzung['dokument_mahnung2']['deutsch'] = "2. Mahnung";
    $uebersetzung['dokument_mahnung3']['deutsch'] = "3. Mahnung";
    $uebersetzung['dokument_mahnunginkasso']['deutsch'] = "Inkasso-Mahnung";

    $uebersetzung['zahlung_proformarechnung_sofort_de']['deutsch'] = "Proformarechnung zahlbar sofort";
    $uebersetzung['zahlung_auftrag_sofort_de']['deutsch'] = "Rechnung zahlbar sofort";

    for($ifreifeld=1;$ifreifeld<=40;$ifreifeld++)
    {
      if($this->app->erp->Firmendaten("freifeld".$ifreifeld)!="")
      {
        $uebersetzung['artikel_freifeld'.$ifreifeld]['deutsch'] = $this->app->erp->Firmendaten("freifeld".$ifreifeld);
        $uebersetzung['artikel_freifeld'.$ifreifeld]['englisch'] = $this->app->erp->Firmendaten("freifeld".$ifreifeld);
      }
      else
      {
        $uebersetzung['artikel_freifeld'.$ifreifeld]['deutsch'] = "Freifeld ".$ifreifeld;
        $uebersetzung['artikel_freifeld'.$ifreifeld]['englisch'] = "Field ".$ifreifeld;
      }
    }


    for($ifreifeld=1;$ifreifeld<=20;$ifreifeld++)
    {
      if($this->app->erp->Firmendaten("projektfreifeld".$ifreifeld)!="")
      {
        $uebersetzung['projekt_freifeld'.$ifreifeld]['deutsch'] = $this->app->erp->Firmendaten("projektfreifeld".$ifreifeld);
        $uebersetzung['projekt_freifeld'.$ifreifeld]['englisch'] = $this->app->erp->Firmendaten("projektfreifeld".$ifreifeld);
      }
      else
      {
        $uebersetzung['projekt_freifeld'.$ifreifeld]['deutsch'] = "Freifeld ".$ifreifeld;
        $uebersetzung['projekt_freifeld'.$ifreifeld]['englisch'] = "Field ".$ifreifeld;
      }
    }

    if($this->app->erp->Firmendaten("freitext1inhalt")!="")
    {
      $uebersetzung['freitext1inhalt']['deutsch'] = $this->app->erp->Firmendaten("freitext1inhalt");
      $uebersetzung['freitext1inhalt']['englisch'] = $this->app->erp->Firmendaten("freitext1inhalt");
    }
    else
    {
      $uebersetzung['freitext1inhalt']['deutsch'] = '';
      $uebersetzung['freitext1inhalt']['englisch'] = '';
    }
    if($this->app->erp->Firmendaten("freitext2inhalt")!="")
    {
      $uebersetzung['freitext2inhalt']['deutsch'] = $this->app->erp->Firmendaten("freitext2inhalt");
      $uebersetzung['freitext2inhalt']['englisch'] = $this->app->erp->Firmendaten("freitext2inhalt");
    }
    else
    {
      $uebersetzung['freitext2inhalt']['deutsch'] = '';
      $uebersetzung['freitext2inhalt']['englisch'] = '';
    }


    if($getvars) return $uebersetzung;



    if(isset($uebersetzung[$field][$sprache]))
      return $uebersetzung[$field][$sprache];

    return "";
  }

  function getUebersetzung($field, $sprache, $id = true)
  {
    $sprache = strtolower($sprache);
    if(empty($this->uebersetzungId))
    {
      $arr = $this->app->DB->SelectArr('SELECT id, label, sprache, beschriftung, original 
          FROM uebersetzung 
          WHERE sprache <> "" AND label <> ""');
      if(!empty($arr))
      {
        foreach($arr as $row)
        {
          $this->uebersetzungId[$row['label']][strtolower($row['sprache'])] = $row['id'];

          if ($row['beschriftung'] != '') {
              $this->uebersetzungBeschriftung[$row['label']][strtolower($row['sprache'])] = $row['beschriftung'];
          } else {
              $this->uebersetzungBeschriftung[$row['label']][strtolower($row['sprache'])] = $row['original'];
          }
        }
      }
    }

    if($id){
      if(!empty($this->uebersetzungId[$field]) && isset($this->uebersetzungId[$field][$sprache])){
        return $this->uebersetzungId[$field][$sprache];
      }
    }else{
      if(!empty($this->uebersetzungBeschriftung[$field]) && isset($this->uebersetzungBeschriftung[$field][$sprache])){
        return $this->uebersetzungBeschriftung[$field][$sprache];
      }
    }

    return null;
  }

  function Beschriftung($field,$sprache='')
  {
 
   if($sprache!='') {
      $this->BeschriftungSprache($sprache);
    }

    if($this->beschriftung_sprache==''){
      $this->beschriftung_sprache = 'deutsch';
    } 

  // wenn feld mit artikel_freifeld beginnt dann freifeld draus machen
  //$field = str_replace('artikel_freifeld','freifeld',$field);

    // schaue ob es das wort in uebesetzungen gibt

    $check = $this->getUebersetzung($field, $this->beschriftung_sprache);
    $uebersetzung = '';
    if($check > 0){
      $uebersetzung =  $this->getUebersetzung($field, $this->beschriftung_sprache, false);
    }

    if($check > 0 && $uebersetzung!='')
    {
      // eintrag eindeutig gefunden
      return $uebersetzung;
    }
    // schaueb ob es das wort in firmendaten gibt achtung hier gibtes nur deutsche woerter!
    if($this->beschriftung_sprache==='deutsch')
    {
      $wert = $this->Firmendaten($field);
      if($wert!='') {
        return $wert;
      }
      // Gibt es eine Konstante?
      return $this->BeschriftungStandardwerte($field,$this->beschriftung_sprache);
    }
    //gibt es eine Vorlage?
    $wert = $this->BeschriftungStandardwerte($field,$this->beschriftung_sprache);
    if($wert!='')
    {
      return $wert;
    }
    return $field; // Not found!
  }



  function FirmendatenSet($field,$value)
  {
    $firmendatenid = $this->app->DB->Select('SELECT MAX(id) FROM firmendaten LIMIT 1');
    $check = $this->app->DB->SelectRow(
      sprintf('SELECT id, typ FROM firmendaten_werte WHERE name = \'%s\' LIMIT 1',$field)
    );
    if(!empty($check))
    {
      if($check['typ'] === 'int' || $check['typ'] === 'tinyint')
      {
        $this->app->DB->Update("UPDATE firmendaten_werte SET wert = '".(int)$value."' WHERE id = '".$check['id']."'");
      }else{
        $this->app->DB->Update("UPDATE firmendaten_werte SET wert = '".$this->app->DB->real_escape_string($value)."' WHERE id = '".$check['id']."'");
      }
    }
	else {
	
	    $column_exists = $this->app->DB->Select("SHOW COLUMNS FROM firmendaten WHERE field = '".$field."'");
	
	    if ($column_exists) {
    	    $this->app->DB->Update("UPDATE firmendaten SET " . $field . "='$value' WHERE id='" . $firmendatenid . "'");
	    } else {
            $this->AddNeuenFirmendatenWert($field, $typ, $typ1, $typ2, $value, $default_value, $default_null, $darf_null);
	    }	    		   
	}
    $db = $this->app->Conf->WFdbname;
    if(!empty($this->firmendaten[$db])) {
      $this->firmendaten[$db][$field] = $value;
    }
    else {
      $this->firmendaten = null;
    }
  }

  function Firmendaten($field,$projekt='', $clearcache = false)
  {
    if($field === 'mysql55') {
      return '1';
    }

    if(strpos($field,'next') != false)
    {
      $firmendatenid = (int)$this->app->DB->Select('SELECT MAX(id) FROM firmendaten LIMIT 1');

    	if ($this->app->DB->Select("SHOW COLUMNS FROM firmendaten LIKE '$field'")) {
        $firmendaten_value = $this->app->DB->Select(
         sprintf(
           'SELECT `%s` FROM firmendaten WHERE id = %d LIMIT 1',
           $field, $firmendatenid)
        );
  	  }

      if(!$this->app->DB->error()) {
        return $firmendaten_value;
      }

      $firmendaten_value = $this->app->DB->SelectRow(
        sprintf('SELECT id, wert FROM firmendaten_werte WHERE `name` = \'%s\' LIMIT 1', $field)
      );
      if(!empty($firmendaten_value)) {
        return $firmendaten_value['wert'];
      }
      return $this->app->DB->Select(
        sprintf("SELECT `%s` FROM `firmendaten` WHERE id = %d LIMIT 1",$field, $firmendatenid)
      );
    }
    $db = $this->app->Conf->WFdbname;
    if($clearcache) {
      $this->firmendaten = null;
    }
    if(empty($this->firmendaten[$db]))
    {
      $firmendatenid = (int)$this->app->DB->Select('SELECT MAX(id) FROM firmendaten LIMIT 1');
      $this->firmendaten[$db] = $this->app->DB->SelectRow(
        sprintf('SELECT * FROM firmendaten WHERE id = %d LIMIT 1', $firmendatenid)
      );
      $firmendaten_value = $this->app->DB->SelectArr('SELECT id, wert,name,typ FROM firmendaten_werte');

      if($firmendaten_value)
      {
        foreach($firmendaten_value as $key => $value)
        {
          if(!isset($this->firmendaten[$db][$value['name']]))
          {
            $this->firmendaten[$db][$value['name']] = $value['wert'];
            if($value['typ'] === 'int' || $value['typ'] === 'tinyint') {
              $this->firmendaten[$db][$value['name']] = (int)$this->firmendaten[$db][$value['name']];
            }
          }
        }
      }
    }
    $value = null;
    if(isset($this->firmendaten[$db][$field])) {
      $value = $this->firmendaten[$db][$field];
    }

    // Umstellung 08.01.2015 von DE auf land zursicherheit wenn jemand der Wert DE fehlen sollte.
    if($field==='land' && $value=='') {
      return 'DE';
    }
    if($field==="schriftart" && $value=='') {
      return 'Arial';
    }

    return $value;
  }

  function TplFirmendaten($field)
  {
    $ret = $this->Firmendaten($field);
    if($ret != "")return $ret;
    switch($field)
    {
      case 'firmenfarbehell':
        //return "#42B8C4";
        return '#404040';
      break;
      case 'firmenfarbedunkel':
        //return "#2F9099";
        return '#2F2F2F';
      break;
      case 'firmenfarbeganzdunkel':
        return "#018fa3";
      break;
      case 'navigationfarbe':
        return "#48494b";
      break;
      case 'navigationfarbeschrift':
        return "#c9c9cb";
      break;
      case 'unternavigationfarbe':
        return "#d5ecf2";
      break;
      case 'unternavigationfarbeschrift':
        return $this->TplFirmendaten('firmenfarbeganzdunkel');
        //return "#027d8d";
      break;
      case 'firmenfarbe':
        return "#48494b";
      break;
      case 'tabsnavigationfarbeschrift':
        return $this->TplFirmendaten('firmenfarbeganzdunkel');
        //return '#018fa3';
        //return "#26727a";
      break;
      case 'tabsnavigationfarbe':
        return $this->TplFirmendaten('firmenfarbehell');
        return "#c2e3ea";
      break;
      case 'tabsnavigationfarbe2':
        return $this->TplFirmendaten('tabsnavigationfarbeschrift');
      break;
      case 'navigationfarbe2':
        return $this->TplFirmendaten('navigationfarbeschrift');
      break;
      case 'navigationfarbeschrift2':
        return $this->TplFirmendaten('navigationfarbe');
      break;
    }


  return $ret;
}

/*
function Firmendaten($field,$projekt="")
{
  $firmendatenid = $this->app->DB->Select("SELECT MAX(id) FROM firmendaten LIMIT 1");
  $value = $this->app->DB->Select("SELECT ".$field." FROM firmendaten WHERE id='".$firmendatenid."' LIMIT 1");

    // Umstellung 08.01.2015 von DE auf land zursicherheit wenn jemand der Wert DE fehlen sollte.
    if($field=="land" && $value=="") $value="DE";

    return $value;
  }*/


  function Grusswort($sprache="")
  {
    //abhaenig von Zeit usw.. passende Grußformel
    /*
       return "Grüße aus dem sonnigen Ausgburg.";
       return "Grüße aus Ausgburg.";
       return "Frohe Ostern.";
       return "Schöne Feierabend.";
       return "Frohe Weihnachten.";
       return "Schönes Wochenende.";
     */
    if($sprache=="englisch") return "\nKind regards,";
    return "\nMit freundlichen Grüßen";

  }

  function Grussformel($projekt=0,$sprache="")
  {

    if($projekt > 0)
    {
      $result = $this->app->DB->Select("SELECT absendegrussformel FROM projekt WHERE id='$projekt' LIMIT 1");
    }

    if($result=="")
    {
      $this->app->erp->BeschriftungSprache($sprache);

      $gruss =  $this->app->erp->Beschriftung("mailgrussformel");
      if($gruss!=$this->app->erp->Firmendaten("mailgrussformel"))
      {
        $result = "<br><br>".nl2br($gruss);
      }

      if($result=="")
      {
        $result = $this->app->erp->Firmendaten("mailgrussformel");
      }
    }

    //if($sprache=="englisch") $result = "\nKind regards,";

    $result = str_replace('{MITARBEITER}',$this->app->User->GetName(),$result);

    $data = $this->app->DB->SelectArr("SELECT telefon, telefax,email,mobil FROM adresse WHERE id='".$this->app->User->GetAdresse()."'");

    $result= str_replace('{MITARBEITER}',$this->app->User->GetName(),$result);
    $result = str_replace('{MITARBEITER_TELEFON}',$data[0]['telefon'],$result);
    $result = str_replace('{MITARBEITER_TELEFAX}',$data[0]['telefax'],$result);
    $result = str_replace('{MITARBEITER_MOBIL}',$data[0]['mobil'],$result);
    $result = str_replace('{MITARBEITER_EMAIL}',$data[0]['email'],$result);

    return $result;
    //return "\r\n\r\n".$this->ReadyForPDF($signatur);
  }
  function Signatur($from="",$language="")
  {
    $signatur = $this->app->DB->Select("SELECT signatur FROM emailbackup WHERE email='$from' AND email!='' AND eigenesignatur=1 AND geloescht!=1 LIMIT 1");

    if($signatur=="")
    {
      $firmendatenid = $this->app->DB->Select("SELECT MAX(id) FROM firmendaten LIMIT 1");
      $signatur = base64_decode($this->Beschriftung("signatur",$language));
    }

    $data = $this->app->DB->SelectArr("SELECT telefon, telefax,email,mobil FROM adresse WHERE id='".$this->app->User->GetAdresse()."'");

    $signatur = str_replace('{MITARBEITER}',$this->app->User->GetName(),$signatur);
    $signatur = str_replace('{MITARBEITER_TELEFON}',$data[0]['telefon'],$signatur);
    $signatur = str_replace('{MITARBEITER_TELEFAX}',$data[0]['telefax'],$signatur);
    $signatur = str_replace('{MITARBEITER_MOBIL}',$data[0]['mobil'],$signatur);
    $signatur = str_replace('{MITARBEITER_EMAIL}',$data[0]['email'],$signatur);

    if($this->isHTML($signatur)) return "<br><br>".$signatur;
    return "\r\n\r\n".$this->ReadyForPDF($signatur);
  }


  function GetQuelleTicket()
  {
    return array('Telefon','Fax','Brief','Selbstabholer');
  }

  /** @deprecated */
  function GetStatusTicketSelect($status)
  {
    $stati = array('neu'=>'neu','offen'=>'offen','warten_e'=>'warten auf Intern','warten_kd'=>'warten auf Kunde','klaeren'=>'kl&auml;ren','abgeschlossen'=>'abgeschlossen','spam'=>'Papierkorb');

    foreach($stati as $key=>$value)
    {
      if($status==$key) $selected="selected"; else $selected="";
      $ret .="<option value=\"$key\" $selected>$value</option>";
    }
    return $ret;
  }

  /** @depracated */
  function GetPrioTicketSelect($prio)
  {
    $prios = array('4'=>'niedrig','3'=>'normal','2'=>'hoch');

    foreach($prios as $key=>$value)
    {
      if($prio==$key) $selected="selected"; else $selected="";
      $ret .="<option value=\"$key\" $selected>$value</option>";
    }
    return $ret;
  }


  function GetZeiterfassungArt()
  {
    return array('arbeit'=>'Arbeit','pause'=>'Pause','urlaub'=>'Urlaub','krankheit'=>'Krankheit','ueberstunden'=>'Freizeitausgleich','feiertag'=>'Feiertag');
  }

  function GetVPE()
  {
    return array('einzeln'=>'Einzeln','tray'=>'Tray','rolle'=>'Rolle','stueckgut'=>'St&uuml;ckgut','stange'=>'Stange','palette'=>'Palette');
  }

  function GetUmsatzsteuerklasse()
  {
    return array('normal'=>'normal','ermaessigt'=>'erm&auml;&szlig;gt','befreit'=>'befreit');
  }

  function GetEtikett()
  {
    $tmp = array('artikel_klein'=>'Artikel klein');

    $result = $this->app->DB->SelectArr("SELECT * FROM etiketten WHERE (verwendenals='artikel_klein' OR verwendenals='seriennummer') AND ausblenden!=1 ORDER by name");
    if((!empty($result)?count($result):0) > 0) $tmp = array();
    for($i=0;$i<(!empty($result)?count($result):0);$i++)
    {
      $tmp[$result[$i]['id']]=$result[$i]['name'];
    }
    $tmp['keineetiketten']="Kein Etikett";
    return $tmp;
  }


  function AddWaehrungumrechnung($waehrung_von, $waehrung_nach, $kurs, $gueltig_bis = "", $kommentar = "", $user = "")
  {
    /** @var Waehrungumrechnung $obj */
    $obj = $this->LoadModul('waehrungumrechnung');
    if(!empty($obj) && method_exists($obj,'AddWaehrungumrechnung'))
    {
      return $obj->AddWaehrungumrechnung($waehrung_von, $waehrung_nach, $kurs, $gueltig_bis, $kommentar, $user);
    }
  }

  function GetWaehrung($onlytable = false)
  {
    /** @var Waehrungumrechnung $obj */
    $obj = $this->LoadModul('waehrungumrechnung');
    if(!empty($obj) && method_exists($obj,'GetWaehrung'))
    {
      return $obj->GetWaehrung($onlytable);
    }
    return array('EUR'=>'EUR','USD'=>'USD','JPY'=>'JPY','BGN'=>'BGN','CZK'=>'CZK','DKK'=>'DKK','GBP'=>'GBP','HUF'=>'HUF','PLN'=>'PLN','RON'=>'RON','SEK'=>'SEK','CHF'=>'CHF','ISK'=>'ISK','NOK'=>'NOK','HRK'=>'HRK','RUB'=>'RUB','TRY'=>'TRY','AUD'=>'AUD','BRL'=>'BRL','CAD'=>'CAD','CNY'=>'CNY','HKD'=>'HKD','IDR'=>'IDR','ILS'=>'ILS','INR'=>'INR','KRW'=>'KRW','MXN'=>'MXN','MYR'=>'MYR','NZD'=>'NZD','PHP'=>'PHP','SGD'=>'SGD','THB'=>'THB','ZAR'=>'ZAR');
  }

  function GetWaehrungUmrechnungskurseTabelle($von = 'EUR')
  {
    /** @var Waehrungumrechnung $obj */
    $obj = $this->LoadModul('waehrungumrechnung');
    if(!empty($obj) && method_exists($obj,'GetWaehrungUmrechnungskurseTabelle'))
    {
      return $obj->GetWaehrungUmrechnungskurseTabelle($von);
    }
  }

  /**
   * @param bool $mitstandardlager
   * @param bool $forceZwischenlager
   *
   * @return array
   */
  function GetLager($mitstandardlager=false, $forceZwischenlager = false)
  {
    $tmp = [];
    if($forceZwischenlager || $this->Firmendaten('wareneingang_zwischenlager')=='1') {
      $tmp['zwischenlager'] = 'Zwischenlager';
    }
    if($mitstandardlager) {
      $tmp['standardlager'] = 'Standardlager';
    }

    $result = $this->app->DB->SelectArr(
      "SELECT lp.id, CONCAT(l.bezeichnung,'->',lp.kurzbezeichnung) as kurzbezeichnung 
        FROM lager_platz AS lp 
        INNER JOIN lager AS l ON lp.lager=l.id 
        WHERE lp.kurzbezeichnung!='' AND lp.geloescht <> 1 AND l.geloescht <> 1
        ORDER BY l.bezeichnung,lp.kurzbezeichnung"
    );
    if(empty($result)) {
      return $tmp;
    }
    foreach($result as $row) {
      $tmp[$row['id']] = $row['kurzbezeichnung'];
    }
    
    return $tmp;
  }

  function GetArtikelart()
  {
    return array('produkt'=>'Produkt','material'=>'Material','dienstleistung'=>'Dienstleistung','muster'=>'Muster',
        'gebuehr'=>'Geb&uuml;hr','betriebsstoff'=>'Betriebsstoff','buerobedarf'=>'B&uuml;robedarf',
        'inventar'=>'Inventar','porto'=>'Porto','literatur'=>'Literatur');
  }


  function StartMessung()
  {
    $this->start_messung = $this->uniqueTimeStamp();
  }

  function EndeMessung()
  {
    $this->ende_messung = $this->uniqueTimeStamp();
  }

  function ErgebnisMessung()
  {
    $differenz = $this->ende_messung-$this->start_messung;
    $differenz = $differenz/10; // warum auch immer
    $differenz = (int)$differenz;

    echo "Die Ausführung dauerte $differenz ms";
  }

  function uniqueTimeStamp() {
    $milliseconds = microtime();
    $timestring = explode(" ", $milliseconds);
    $sg = $timestring[1];
    $mlsg = substr($timestring[0], 2, 4);
    $timestamp = $sg.$mlsg;
    return $timestamp;
  }

  /** @deprecated */
  function GetWartezeitTicket($zeit)
  {
    $timestamp = strToTime($zeit, null);


    $td = $this->makeDifferenz($timestamp,time());
    return $td['day'][0] . ' ' . $td['day'][1] . ', ' . $td['std'][0] . ' ' . $td['std'][1] .
      ', ' . $td['min'][0] . ' ' . $td['min'][1];// . ', ' . $td['sec'][0] . ' ' . $td['sec'][1];
  }

  function makeDifferenz($first, $second){

    if($first > $second)
      $td['dif'][0] = $first - $second;
    else
      $td['dif'][0] = $second - $first;

    $td['sec'][0] = $td['dif'][0] % 60; // 67 = 7

    $td['min'][0] = (($td['dif'][0] - $td['sec'][0]) / 60) % 60;

    $td['std'][0] = (((($td['dif'][0] - $td['sec'][0]) /60)-
          $td['min'][0]) / 60) % 24;

    $td['day'][0] = floor( ((((($td['dif'][0] - $td['sec'][0]) /60)-
              $td['min'][0]) / 60) / 24) );

    $td = $this->makeString($td);

    return $td;

  }


  function makeString($td){

    if ($td['sec'][0] == 1)
      $td['sec'][1] = 'Sekunde';
    else
      $td['sec'][1] = 'Sekunden';

    if ($td['min'][0] == 1)
      $td['min'][1] = 'Minute';
    else
      $td['min'][1] = 'Minuten';

    if ($td['std'][0] == 1)
      $td['std'][1] = 'Stunde';
    else
      $td['std'][1] = 'Stunden';

    if ($td['day'][0] == 1)
      $td['day'][1] = 'Tag';
    else
      $td['day'][1] = 'Tage';

    return $td;
  }


  function GetProjektSelect($projekt,$color_selected='')
  {
    $sql = "SELECT id,name,farbe FROM projekt order by id";
    $tmp = $this->app->DB->SelectArr($sql);
    $ctmp = !empty($tmp)?count($tmp):0;
    for($i=0;$i<$ctmp;$i++)
    {
      if($tmp[$i]['farbe']=='') $tmp[$i]['farbe']='white';
      if($projekt==$tmp[$i]['id']){
        $options = (isset($options)?$options:'')."<option value=\"{$tmp[$i]['id']}\" selected
          style=\"background-color:{$tmp[$i]['farbe']};\">{$tmp[$i]['name']}</option>";
        $color_selected = $tmp[$i]['farbe'];
      }
      else{
        $options = (isset($options) ? $options : '') . "<option value=\"{$tmp[$i]['id']}\"
          style=\"background-color:{$tmp[$i]['farbe']};\">{$tmp[$i]['name']}</option>";
      }
    }
    return !empty($options)?$options:'';
  }

  /**
   * @param int $id
   *
   * @return string
   */
  public function GetAdressName($id)
  {
    return (String)$this->app->DB->Select(
      sprintf('SELECT name FROM adresse WHERE id=%d AND geloescht=0 LIMIT 1', $id)
    );
  }

  function GetAdressSubject()
  {
    return array('Kunde','Lieferant','Mitarbeiter','Mitglied');//'Externer Mitarbeiter','Projektleiter
  }

  function GetAdressPraedikat()
  {
    return array('','von','fuer','ist');
  }

  function GetAdressObjekt()
  {
    return array('','Projekt');
  }


  function GetVersandartAuftrag($projekt = 0)
  {
    $check = $this->app->DB->Select("SELECT COUNT(id) FROM versandarten");
    if($check <=0)
    {

      $modul = "";

      $tmp = array(
           'keinversand'=>'Kein Versand',
           'selbstabholer'=>'Selbstabholer',
           'spedition'=>'Spedition',
       );
      foreach($tmp as $key=>$value)
      {
        if($key == 'keinversand'){$modul='';}
        if($key == 'selbstabholer'){$modul='selbstabholer';}
        if($key == 'spedition'){$modul='';}

        $this->app->DB->Insert("INSERT INTO versandarten (id,type,bezeichnung,aktiv,modul) VALUES ('','$key','$value','1','$modul')");
      }
    }

    $tmp = $this->app->DB->SelectArr("SELECT type,bezeichnung FROM versandarten WHERE aktiv='1' AND geloescht!='1' AND (projekt = '$projekt' OR projekt = 0) ORDER by bezeichnung");
    if($tmp)
    {
      for($i=0;$i<(!empty($tmp)?count($tmp):0);$i++)
      {
        $result[$tmp[$i]['type']]=$tmp[$i]['bezeichnung'];
      }
    }

    return $result;
  }



  function GetVersandartLieferant()
  {
    return array('DHL','DPD','Hermes','UPS','GLS','Post','Spedition','Selbstabholer','Packstation');
  }


  function GetArtikeleigenschaft($projekt="")
  {
    if($projekt > 0)
    {
      $result = $this->app->DB->SelectArr("SELECT id,name FROM artikeleigenschaften WHERE projekt='$projekt' AND geloescht!=1 ORDER by name");
      // gibt es keine projekt gruppen dann die ohne projekt verwenden
      if((!empty($result)?count($result):0)<=0)
        $result = $this->app->DB->SelectArr("SELECT id,name FROM artikeleigenschaften WHERE geloescht!=1 AND projekt <=0 ORDER by name");
    } else
    {
      $result = $this->app->DB->SelectArr("SELECT id,name FROM artikeleigenschaften WHERE geloescht!=1 AND projekt <=0 ORDER by name");
    }

    if((!empty($result)?count($result):0) > 0)
    {

      for($i=0;$i<(!empty($result)?count($result):0);$i++)
      {
        $tmp[$result[$i]['id']]=$result[$i]['name'];
      }

      return $tmp;

    }
  }


    function GetArtikelgruppe($projekt="")
    {
      if($projekt > 0)
      {
        $result = $this->app->DB->SelectArr("SELECT id,bezeichnung FROM artikelkategorien WHERE (projekt='$projekt' OR projekt = 0) AND parent = 0 AND geloescht!=1 ORDER by bezeichnung");
        // gibt es keine projekt gruppen dann die ohne projekt verwenden
        if((!empty($result)?count($result):0)<=0)
          $result = $this->app->DB->SelectArr("SELECT id,bezeichnung FROM artikelkategorien WHERE geloescht!=1 AND projekt <=0 AND parent = 0 ORDER by bezeichnung");
      } else
      {
        $result = $this->app->DB->SelectArr("SELECT id,bezeichnung FROM artikelkategorien WHERE geloescht!=1 AND projekt <=0 AND parent = 0 ORDER by bezeichnung");
      }

      if($result && (!empty($result)?count($result):0) > 0)
      {

        for($i=0;$i<(!empty($result)?count($result):0);$i++)
        {
          $tmp[$result[$i]['id']."_kat"]=$result[$i]['bezeichnung'];
        }

        return $tmp;

      }
      return array("produkt"=>"Ware f&uuml;r Verkauf (700000)",
          "module"=>"Module / Hardware (600000)",
          "produktion"=>"Produktionsmaterial (400000)",
          "material"=>"Sonstiges (100000)",
          "fremdleistung"=>"Fremdleistung (100000)",
          "gebuehr"=>"Geb&uuml;hr / Miete (100000)");
    }


      function GetZahlungsstatus()
      {
        return array('offen','bezahlt');
      }

  /**
   * @param null|int $id
   *
   * @return array
   */
      public function GetZahlungsweiseGutschrift($id = null)
      {
        $zahlungsweise = '';
        $projectId = 0;
        $tmp = [];
        if($id) {
          $returnOrder = $this->app->DB->SelectRow(
            sprintf(
              'SELECT `zahlungsweise`, `projekt` FROM `gutschrift` WHERE `id` = %d LIMIT 1',
              $id
            )
          );
          if(!empty($returnOrder)) {
            $projectId = $returnOrder['projekt'];
            $zahlungsweise = $returnOrder['zahlungsweise'];
          }
        }
        $extra = $this->app->DB->SelectPairs(
            sprintf(
              'SELECT z.`type`, z.`bezeichnung`
              FROM `zahlungsweisen` AS `z`
              INNER JOIN 
              (
                SELECT `type`, max(`projekt`) as projekt 
                FROM `zahlungsweisen` 
                WHERE `aktiv` = 1 AND `projekt` = 0 OR `projekt` = %d
                GROUP BY `type`
              ) AS `t` ON z.`type` = t.`type` AND z.`projekt` = t.`projekt`',
              $projectId
            )
        );


      //    return array('ueberweisung'=>'&Uuml;berweisung','bar'=>'Bar','paypal'=>'PayPal');

        foreach(
            [
              'kreditkarte'        => 'Kreditkarte',
              'lastschrift'        => 'Verrechnen mit Lastschriften',
              'paypal'             => 'Paypal',
              'amazon'             => 'Amazon Payments',
              'amazon_bestellung'  => 'Amazon Bestellung',
              'secupay'            => 'Secupay',
              'sofortueberweisung' => 'Sofort&uuml;berweisung',
              'eckarte'            => 'EC-Karte',
            ]
        as $paymentType => $paymentName) {
          if(!empty($extra[$paymentType])) {
            continue;
          }
          if($zahlungsweise === $paymentType || $this->Firmendaten('zahlung_'.$paymentType)) {
            $tmp[$paymentType] = $paymentName;
          }
        }

        if(!empty($extra)){
          foreach($extra as $type => $name) {
            $tmp[$type] = $name;
          }
        }

        if($zahlungsweise && empty($tmp[$zahlungsweise])) {
          if($zahlungsweise === 'ueberweisung') {
            $tmp['ueberweisung'] = '&Uuml;berweisung';
          }
          else {
            $tmp[$zahlungsweise] = ucfirst($zahlungsweise);
          }
        }
        asort($tmp);

        return $tmp;
      }

      public function GetZahlungsweise($table = null, $id = null, $projekt = null)
      {
        $zahlungsweise = '';
        if($projekt === null){
          $projekt = (int)$this->Firmendaten('projekt');
          if(!empty($table) && !empty($id))
          {
            $arr = $this->app->DB->SelectRow("SELECT zahlungsweise, projekt FROM $table WHERE id = '$id' LIMIT 1");
            if(!empty($arr))
            {
              $zahlungsweise = $arr['zahlungsweise'];
              $projekt = (int)$arr['projekt'];
            }
          }
        }
        if($this->Firmendaten("zahlung_rechnung") || $zahlungsweise == 'rechnung'){
          $tmp['rechnung'] = "Rechnung";
        }

        if($this->Firmendaten("zahlung_vorkasse") || $zahlungsweise == 'vorkasse'){
          $tmp['vorkasse'] = "Vorkasse";
        }

        if($this->Firmendaten("zahlung_nachnahme") || $zahlungsweise == 'nachnahme'){
          $tmp['nachnahme'] = "Nachnahme";
        }

        if($this->Firmendaten("zahlung_kreditkarte") || $zahlungsweise == 'kreditkarte'){
          $tmp['kreditkarte'] = "Kreditkarte";
        }


        if($this->Firmendaten("zahlung_eckarte") || $zahlungsweise == 'eckarte'){
          $tmp['eckarte'] = "EC-Karte";
        }


        if($this->Firmendaten("zahlung_bar") || $zahlungsweise == 'bar'){
          $tmp['bar'] = "Bar";
        }

        if($this->Firmendaten("zahlung_paypal") || $zahlungsweise == 'paypal'){
          $tmp['paypal'] = "Paypal";
        }

        if($this->Firmendaten("zahlung_amazon") || $zahlungsweise == 'amazon'){
          $tmp['amazon'] = "Amazon Payments";
        }

        if($this->Firmendaten("zahlung_amazon_bestellung") || $zahlungsweise == 'amazon_bestellung'){
          $tmp['amazon_bestellung'] = "Amazon Bestellung";
        }

        if($this->Firmendaten("zahlung_secupay") || $zahlungsweise == 'secupay'){
          $tmp['secupay'] = "Secupay";
        }

        if($this->Firmendaten("zahlung_sofortueberweisung") || $zahlungsweise == 'sofortueberweisung'){
          $tmp['sofortueberweisung'] = "Sofort&uuml;berweisung";
        }

        if($this->Firmendaten("zahlung_lastschrift") || $zahlungsweise == 'lastschrift'){
          $tmp['lastschrift'] = "Lastschrift";
        }

        if($this->Firmendaten("zahlung_ratenzahlung") || $zahlungsweise == 'ratenzahlung'){
          $tmp['ratenzahlung'] = "Ratenzahlung";
        }

        $extra = $this->app->DB->SelectArr("
              SELECT z.`type`, z.`bezeichnung`
              FROM zahlungsweisen z
              INNER JOIN 
              (
              SELECT `type`, max(projekt) as projekt 
              FROM zahlungsweisen WHERE aktiv=1 AND projekt = 0 OR projekt = $projekt
              GROUP BY `type`
              ) t ON z.`type` = t.`type` AND z.`projekt` = t.`projekt`
        ");
        $cextra = !empty($extra)?count($extra):0;
        for($i=0;$i<$cextra;$i++)
        {
          $tmp[$extra[$i]['type']] = $extra[$i]['bezeichnung'];
        }
        if($zahlungsweise && empty($tmp[$zahlungsweise]))$tmp[$zahlungsweise] = ucfirst($zahlungsweise);
        if (!empty($tmp)) {
            asort($tmp);
        }
        return $tmp;
        //              return array('rechnung'=>'Rechnung','vorkasse'=>'Vorkasse','nachnahme'=>'Nachnahme','kreditkarte'=>'Kreditkarte','einzugsermaechtigung'=>'Einzugsermaechtigung','bar'=>'Bar','paypal'=>'PayPal','lastschrift'=>'Lastschrift');
      }

      function GetPinwandSelect()
      {
        $tmp = $this->app->DB->SelectArr("SELECT DISTINCT p.id,p.name FROM pinwand p
          LEFT JOIN pinwand_user pu ON pu.pinwand=p.id WHERE (pu.user='".$this->app->User->GetID()."' OR p.user='".$this->app->User->GetID()."') ORDER by p.name");

        $result['0']="Eigene Pinnwand";
        if(empty($tmp)) {
          return $result;
        }
        foreach($tmp as $row) {
          $result[$row['id']] = $row['name'];
        }
        return $result;
      }

      function GetSprachenSelect($wert = null)
      {
        $check = $this->app->DB->Select("SELECT id FROM sprachen WHERE aktiv = 1 LIMIT 1");
        if($check <=0)
        {
          $this->app->erp->CheckTable("sprachen");
          $this->app->erp->CheckColumn("id", "int(11)", "sprachen", "NOT NULL AUTO_INCREMENT");
          $this->app->erp->CheckColumn("iso", "varchar(2)", "sprachen", "NOT NULL");
          $this->app->erp->CheckColumn("bezeichnung_de", "varchar(255)", "sprachen", "NOT NULL DEFAULT ''");
          $this->app->erp->CheckColumn("bezeichnung_en", "varchar(255)", "sprachen", "NOT NULL DEFAULT ''");
          $this->app->erp->CheckColumn("alias", "varchar(255)", "sprachen", "NOT NULL DEFAULT ''");
          $this->app->erp->CheckColumn("aktiv", "tinyint(1)", "sprachen", "NOT NULL DEFAULT '0'");
          $arr = array('DE'=>array('Deutsch','German','deutsch','1'),
          'EN'=>array('Englisch','English','englisch','1'),
          'FR'=>array('Französisch','French','franzoesisch','1'),
          'NL'=>array('Holländisch','Dutch','hollaendisch','1'),
          'IT'=>array('Italienisch','Italian','italienisch','1'),
          'ES'=>array('Spanisch','Spanish','spanisch','1'),
          'CZ'=>array('Tschechisch','Czech','tschechisch','1'),
          'DK'=>array('Dänisch','Danish','daenisch','1'),
          'SK'=>array('Slowakisch','Slovak','slowakisch','1'),
          'SW'=>array('Schwedisch','Swedish','schwedisch','1'),
          'PL'=>array('Polnisch','Polish','polnisch','1')
          );
          foreach($arr as $k => $v)
          {
            $check = $this->app->DB->SelectArr("SELECT * FROM sprachen WHERE iso = '$k' LIMIT 1");
            if($check)
            {
              if($check[0]['alias'] != $v[2])$this->app->DB->Update("UPDATE sprachen SET alias = '".$v[2]."', aktiv = 1 WHERE id = '".$check[0]['id']."' LIMIT 1");
            }else{
              $this->app->DB->Insert("INSERT INTO sprachen (iso, bezeichnung_de,bezeichnung_en, alias, aktiv) VALUES ('".$k."','".$v[0]."','".$v[1]."','".$v[2]."','1')");
            }
          }
        }
        $land = $this->Firmendaten('land');
        $tmp = $this->app->DB->SelectArr("SELECT iso,alias, bezeichnung_de,aktiv FROM sprachen WHERE iso <> '' ORDER BY iso = '$land' DESC, bezeichnung_de");
        $deutschfound = false;
        $englischfound = false;
        for($i=0;$i<(!empty($tmp)?count($tmp):0);$i++)
        {
          if($tmp[$i]['alias'] != '' && $wert != $tmp[$i]['iso'])
          {
            if($tmp[$i]['aktiv'])
            {
              if($tmp[$i]['alias'] == 'deutsch')$deutschfound = true;
              if($tmp[$i]['alias'] == 'englisch')$englischfound = true;
              $result[$tmp[$i]['alias']] = $tmp[$i]['bezeichnung_de'];
            }
          }else{
            if($wert == $tmp[$i]['alias'] && $wert <> '')
            {
              $result[$tmp[$i]['alias']] = $tmp[$i]['bezeichnung_de'];
              if($tmp[$i]['alias'] == 'deutsch')$deutschfound = true;
              if($tmp[$i]['alias'] == 'englisch')$englischfound = true;
            }elseif($wert == $tmp[$i]['iso'] && $wert <> '')
            {
              $result[$tmp[$i]['iso']] = $tmp[$i]['bezeichnung_de'];
            }elseif($tmp[$i]['aktiv'])
            {
              $result[$tmp[$i]['iso']] = $tmp[$i]['bezeichnung_de'];
            }
          }
        }
        if(!$deutschfound)$result['deutsch'] = 'Deutsch';
        if(!$englischfound)$result['englisch'] = 'Englisch';
        return $result;
      }


      function GetTypSelect()
      {
        $check = $this->app->DB->Select("SELECT COUNT(id) FROM adresse_typ");
        if($check <=0)
        {
          $tmp = array('firma'=>'Firma','herr'=>'Herr','frau'=>'Frau');
          foreach($tmp as $key=>$value)
          {
            if($key=="firma") $netto=1;else $netto=0;
            $this->app->DB->Insert("INSERT INTO adresse_typ (id,type,bezeichnung,aktiv,netto) VALUES ('','$key','$value','1','$netto')");
          }
        }

        $tmp = $this->app->DB->SelectArr("SELECT type,bezeichnung FROM adresse_typ WHERE aktiv='1' AND geloescht!='1' ORDER by bezeichnung");

        $result['']='Bitte w&auml;hlen';

        for($i=0;$i<(!empty($tmp)?count($tmp):0);$i++)
          $result[$tmp[$i]['type']]=$tmp[$i]['bezeichnung'];


        return $result;
      }

      function GetArtikelWarengruppe()
      {
        //return array('SMD','THT','EBG','BGP');
        $tmp = array('','Bauteil','Eval-Board','Adapter','Progammer','Ger&auml;t','Kabel','Software','Dienstleistung','Spezifikation');
        sort($tmp);
        return $tmp;
      }

      function GetBezahltWieAssoc()
      {
        return array('privat'=>"Privat",'firma_bar'=>"Firma (Kasse/Bar)",'firma_ecr'=>"Firma (EC-Karte)",'firma_cc'=>"Firma (Kreditkarte)",'firma_sonst'=>"Firma (Sonstige)");
      }

      function GetStatusArbeitsnachweis()
      {
        return array('offen','freigegeben','versendet');
      }


      function GetStatusAnfrage()
      {
        return array('offen','abgeschlossen');
      }

      function GetStatusInventur()
      {
        return array('offen','abgeschlossen');
      }

      function GetStatusReisekosten()
      {
        return array('offen','freigegeben','versendet','buchhaltung');
      }


      function GetStatusLieferschein()
      {
        return array('offen','freigegeben','versendet');
      }


      function GetStatusAuftrag()
      {
        return array('offen','freigegeben','abgeschlossen');
      }


      function GetStatusAngebot()
      {
        return array('offen','freigegeben','bestellt','angemahnt','empfangen');
      }


      function GetStatusGutschrift()
      {
        return array('offen','freigegeben','bezahlt');
      }

      function GetStatusRechnung()
      {
        return array('offen','freigegeben','gestellt','zahlungserinnerung','mahnung');
      }

      function GetFirmaFieldsCheckbox()
      {
        $tmp =  array('paketmarke_mit_waage','artikel_beschleunigte_suche','internebemerkungminidetails','briefpapier_bearbeiter_ausblenden','briefpapier_vertrieb_ausblenden','versand_gelesen','zahlung_rechnung','zahlung_vorkasse','zahlung_bar','zahlung_lastschrift','zahlung_paypal','zahlung_amazon','artikel_bilder_uebersicht','artikel_baum_uebersicht','internetnummerimbeleg','wiedervorlage_mitarbeiter',
            'zahlung_amazon_bestellung','zahlung_billsafe','zahlung_sofortueberweisung','zahlung_secupay','zahlung_eckarte','zeiterfassung_schliessen','zeiterfassung_pflicht',
            'zahlung_kreditkarte','zahlung_nachnahme','zahlung_ratenzahlung','knickfalz','begrenzen_artikeltabelle','begrenzen_adressetabelle','begrenzen_belege','schnellsuche','schnellsuchecount','versandmail_zwischenspeichern','keinhauptmenurahmen','bordertabnav','steuerfrei_inland_ausblenden','auftragexplodieren_unterstuecklisten',
            'standardaufloesung','immerbruttorechnungen','immernettorechnungen','bestellvorschlaggroessernull','erweiterte_positionsansicht','schnellanlegen','kleinunternehmer','steuerspalteausblenden','api_enable','api_importwarteschlange','warnung_doppelte_nummern','warnung_doppelte_seriennummern','wareneingang_zwischenlager','bestellungohnepreis','zahlung_lastschrift_konditionen','porto_berechnen','breite_artikelbeschreibung','deviceenable','auftrag_eantab','bestellungmitartikeltext','bestellungeigeneartikelnummer','bestellunglangeartikelnummern','steuer_standardkonto_aufwendungen',
            'iconset_dunkel','api_cleanutf8','mahnwesenmitkontoabgleich','briefhtml','absenderunterstrichen','seite_von_ausrichtung_relativ','wareneingang_gross','datatables_export_button_flash','viernachkommastellen_belege','stornorechnung_standard','angebotersatz_standard','rechnungersatz_standard','geburtstagekalender','footer_zentriert','auftragmarkierenegsaldo','wareneingangauftragzubestellung','freifelderimdokument','zeiterfassung_anderemitarbeiter','zeiterfassung_beschreibungssperre','zeiterfassung_ort','zeiterfassung_kommentar','zeiterfassung_erweitert','footer_reihenfolge_angebot_aktivieren','footer_reihenfolge_auftrag_aktivieren','footer_reihenfolge_rechnung_aktivieren','footer_reihenfolge_gutschrift_aktivieren','footer_reihenfolge_lieferschein_aktivieren','footer_reihenfolge_bestellung_aktivieren','position_quantity_change_price_update',
          'beleg_pos_ean','beleg_pos_charge','beleg_pos_mhd','beleg_pos_sn','beleg_pos_zolltarifnummer',
            'schnellanlegen_ohnefreigabe','langeartikelnummern','noauth','belege_subpositionen',
            'belege_subpositionenstuecklisten','briefpapier_ohnedoppelstrich','bearbeiteremailimdokument',
            'bearbeitertelefonimdokument','seite_belegnr','eigener_skontotext','proformarechnung_ohnebriefpapier',
          'footer_reihenfolge_proformarechnung_aktivieren','zeiterfassung_abrechnenvorausgewaehlt','festetrackingnummer',
          'guenstigste_vk','oneclickrelease','cleaner_logfile','cleaner_protokoll','cleaner_shopimport','cleaner_shopexportlog',
          'cleaner_versandzentrum','cleaner_uebertragungen','cleaner_adapterbox','angebot_auftrag_bestellung_ansprechpartner',
          'ampellager','ampelporto','ampelust','ampelzahlung','ampelnachnahme','ampelautoversand','ampelkunde',
          'ampelliefertermin','ampelkreditlimit','ampelliefersperre','ampelproduktion','freitext1aktiv','freitext2aktiv',
          'reisekosten_ohnebriefpapier','lieferdatumkw','vertriebbearbeiterfuellen','typimdokument','staffelpreiseanzeigen',
          'abmessungimdokument','projektoeffentlich','verkaufspreisevpe','einkaufspreisevpe','apiohnehtmlumwandlung',
          'externeurlsblockieren','auftragabschliessen','belegnummersortierungint',
          'dienstleistungsartikel_nicht_zu_lieferschein','dateienweiterfuehren','systemmailsabschalten','belegeinanhang',
          'lagerbestand_in_auftragspositionen_anzeigen','positionenkaufmaenischrunden','wareneingang_lagerartikel',
          'stuecklistegewichtnurartikel','bestellungabschliessen','gutschriftkursvonrechnung','wareneingangdmsdrucker',
          'dsgvoversandunternehmen','produktionskorrektur_nichtverwenden','disableproductionautostart','closesubproductions',
          'disablecreateproductiononextern',
          'beleg_artikelbild','lieferschein_artikelbild','rechnung_artikelbild','bestellung_artikelbild','gutschrift_artikelbild','angebot_artikelbild',
          'shopexportlog','autoversand_locked_orders','beleg_pos_herkunftsland',
          'loadcurrencyrate','versandzentrum_bild','onlyemployeeprojects','proformainvoice_juststorgearticles'
        );

        return $tmp;
      }


      function GetFirmaFields()
      {
        $fields =  array('additionalcspheader','zahlung_rechnung_de','zahlung_kreditkarte_de','breite_position','breite_menge','breite_nummer','breite_einheit','land','abstand_seiten_unten','beschriftunginternetnummer','breite_artikel','breite_steuer','angebot_anzahltage','angebot_anzahlwiedervorlage','angebot_pipewiedervorlage',
            'zahlung_vorkasse_de','zahlung_nachnahme_de','zahlung_lastschrift_de','zahlung_bar_de','zahlung_paypal_de','zahlung_amazon_de','zahlung_amazon_bestellung_de','zahlung_ratenzahlung_de',
            'zahlung_sofortueberweisung_de','zahlung_billsafe_de','testmailempfaenger','zahlung_secupay_de','zahlung_eckarte_de','abstand_umbruchunten',
            'zahlung_rechnung_sofort_de','api_importwarteschlange_name','footer_farbe','zahlung_auftrag_sofort_de','zahlung_auftrag_de',
            'zahlungszieltage','zahlungszieltageskonto','zahlungszielskonto','api_initkey','api_remotedomain','api_eventurl','steuer_erloese_inland_normal','devicekey','deviceserials','steuer_standardkonto','bcc3',
            'steuer_aufwendung_inland_normal','tabsnavigationfarbe','tabsnavigationfarbeschrift',
            'steuer_erloese_inland_ermaessigt',
            'steuer_aufwendung_inland_ermaessigt',
            'steuer_erloese_inland_steuerfrei',
            'steuer_aufwendung_inland_steuerfrei',
            'steuer_erloese_inland_innergemeinschaftlich',
            'steuer_aufwendung_inland_innergemeinschaftlich',
            'steuer_erloese_inland_eunormal',
            'steuer_erloese_inland_euermaessigt',
            'steuer_erloese_inland_nichtsteuerbar',
            'steuer_aufwendung_inland_nichtsteuerbar',
            'steuer_aufwendung_inland_eunormal',
            'steuer_aufwendung_inland_euermaessigt',
            'steuer_erloese_inland_export',
            'etikettendrucker_wareneingang','schriftgroesseabsender','aufgaben_bondrucker',
            'steuer_aufwendung_inland_import','versandart','zahlungsweise','zahlungsweiselieferant','bezeichnungstornorechnung','steuer_anpassung_kundennummer','abstand_seitenrandlinks','abstand_adresszeilelinks','sepaglaeubigerid','abstand_gesamtsumme_lr',
            'schriftgroesse_gesamt','schriftgroesse_gesamt_steuer','abstand_seitenrandrechts',

            'bezeichnungangebotersatz',
            'bezeichnungauftragersatz',
            'bezeichnungproformarechnungersatz',
            'bezeichnungrechnungersatz',
            'bezeichnunglieferscheinersatz',
            'bezeichnungbestellungersatz',
            'barcode_x','barcode_y','barcode_x_header','barcode_y_header','abseite2y','mailgrussformel',
            'email_html_template',
            'footer_reihenfolge_angebot',
            'footer_reihenfolge_auftrag',
            'footer_reihenfolge_rechnung',
            'footer_reihenfolge_proformarechnung',
            'footer_reihenfolge_gutschrift',
            'footer_reihenfolge_lieferschein',
            'footer_reihenfolge_bestellung','reihenfolge_zwischenspeicher','adresse_vorlage','eigener_skontotext_re','eigener_skontotext_anab',
            'footer_reihenfolge_bestellung','cleaner_logfile_tage','cleaner_protokoll_tage','cleaner_shopimport_tage','cleaner_versandzentrum_tage','cleaner_uebertragungen_tage','cleaner_adapterbox_tage','begrenzenanzahl_artikeltabelle','begrenzenanzahl_adressetabelle','begrenzenanzahl_belege','versandmails_max','autoversand_maxauftraege'
            ,'gewichtzukgfaktor','gewichtbezeichnung','zeiterfassung_schliessentage','freitext1x','freitext1y','freitext1schriftgroesse','freitext1breite','freitext1inhalt',
              'freitext2x','freitext2y','freitext2schriftgroesse','freitext2breite','freitext2inhalt','kommissionskonsignationslager','bezeichnungaktionscodes','belege_stuecklisteneinrueckenmm','ldap_host','ldap_bindname','ldap_searchbase','ldap_filter','systemmailsempfaenger',
          'server_url','server_port','cronjob_limit','cleaner_shopexportlog_tage','poll_repeattime','wareneingangbildtypvorauswahl','wareneingangscanverhalten', 'group_sales', 'group_employee'
              );

      for($ki=1;$ki<=15;$ki++)
      {
        $fields[]='steuer_art_'.$ki;
        $fields[]='steuer_art_'.$ki.'_normal';
        $fields[]='steuer_art_'.$ki.'_ermaessigt';
        $fields[]='steuer_art_'.$ki.'_steuerfrei';
      }

      return $fields;
    }

      function GetMLMAuszahlungWaehrung()
      {
        return array('EUR','CHF');
      }

      function GetWaehrungUmrechnungskurs($von,$nach,$onlytable = false)
      {
        /** @var Waehrungumrechnung $obj */
        $obj = $this->LoadModul('waehrungumrechnung');
        if(!empty($obj) && method_exists($obj,'GetWaehrungUmrechnungskurs'))
        {
          return $obj->GetWaehrungUmrechnungskurs($von,$nach,$onlytable);
        }
        return 0;
      }

      function GetSchriftarten()
      {
        return array(
          'arial' => 'Arial'
        );
      }

      function GetFonts()
      {
        $ret['times'] = array('b' => true,'bi' => true,'i' => true, 'name' => 'Times');
        $ret['arial'] = array('b' => true,'bi' => true,'i' => true, 'name' => 'Arial');
        if(!file_exists(__DIR__.'/pdf/font') || !is_dir(__DIR__.'/pdf/font')) {
          return $ret;
        }
        $handle = opendir(__DIR__.'/pdf/font');
        if(!$handle) {
          return $ret;
        }

        while (false !== ($entry = readdir($handle))) {
          $b = false;
          $bi = false;
          $i = false;
          $pathinfo = pathinfo($entry);
          if(isset($pathinfo['extension']) && strtolower($pathinfo['extension']) == 'php') {
            if(strpos($entry,'helvetica') !== 0 && strpos($entry,'times') !== 0)
            {
              $basis = $pathinfo['filename'];
              if(substr($pathinfo['filename'],-2) == 'bi')
              {
                if(file_exists(__DIR__.'/pdf/font/'.substr($pathinfo['filename'],0,strlen($pathinfo['filename'])-2).'.php'))
                {
                  $bi = true;
                  $basispathinfo = pathinfo(__DIR__.'/pdf/font/'.substr($pathinfo['filename'],0,strlen($pathinfo['filename'])-2));
                  $basis = $basispathinfo['basename'];
                }
              }elseif(substr($pathinfo['filename'],-1) == 'i')
              {
                if(file_exists(__DIR__.'/pdf/font/'.substr($pathinfo['filename'],0,strlen($pathinfo['filename'])-1).'.php'))
                {
                  $i = true;
                  $basispathinfo = pathinfo(__DIR__.'/pdf/font/'.substr($pathinfo['filename'],0,strlen($pathinfo['filename'])-1));
                  $basis = $basispathinfo['basename'];
                }
              }elseif(substr($pathinfo['filename'],-1) == 'b')
              {
                if(file_exists(__DIR__.'/pdf/font/'.substr($pathinfo['filename'],0,strlen($pathinfo['filename'])-1).'.php'))
                {
                  $b = true;
                  $basispathinfo = pathinfo(__DIR__.'/pdf/font/'.substr($pathinfo['filename'],0,strlen($pathinfo['filename'])-1));
                  $basis = $basispathinfo['basename'];
                }

              }
              if(isset($file))unset($file);
              if(isset($name))unset($name);
              include_once(__DIR__.'/pdf/font/'.$entry);
              if(isset($file)&& file_exists(__DIR__.'/pdf/font/'.$file) && isset($name))
              {
                if(!isset($ret[$basis]))$ret[$basis]['name'] = $name;
                if(!$bi && !$i && !$b)$ret[$basis]['name'] = $name;
                if($bi)$ret[$basis]['bi'] = true;
                if($i)$ret[$basis]['i'] = true;
                if($b)$ret[$basis]['b'] = true;
              }
            }

          }
        }
        closedir($handle);

        return $ret;
      }

      function GetMLMAbrechnung()
      {
        return array('sammelueberweisung'=>'Sammel&uuml;berweisung','manuell'=>'Manuelle Auszahlung');
      }

      function GetMLMPositionierung()
      {
        return array('1'=>'1. Junior Consultant',
            '2'=>'2. Consultant',
            '3'=>'3. Associate',
            '4'=>'4. Manager',
            '5'=>'5. Senior Manager',
            '6'=>'6. General Director',
            '7'=>'7. General Manager',
            '8'=>'8. Chief Manager',
            '9'=>'9. Vice President',
            '10'=>'10. President',
            '11'=>'11. ',
            '12'=>'12. ',
            '13'=>'13. ',
            '14'=>'14. ',
            '15'=>'15. '
            );
      }

      function GetStatusBestellung()
      {
        return array('offen','freigegeben','bestellt','angemahnt','empfangen');
      }

      function GetSelectAsso($array, $selected)
      {
        foreach($array as $key=>$value)
        {
          if($selected==$key) $tmp = "selected"; else $tmp="";
          $ret .= "<option value=\"$key\" $tmp>$value</option>";
        }
        return $ret;
      }

      function GetSelect($array, $selected)
      {
        foreach($array as $value)
        {
          if($selected==$value) $tmp = "selected"; else $tmp="";
          $ret .= "<option value=\"$value\" $tmp>$value</option>";
        }
        return $ret;
      }
      function CreateAdresse($name,$firma="1")
      {
        $projekt = $this->app->DB->Select("SELECT standardprojekt FROM firma WHERE id='".$this->app->User->GetFirma()."' LIMIT 1");

        $projekt_bevorzugt=$this->app->DB->Select("SELECT projekt_bevorzugen FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        if($projekt_bevorzugt=="1")
        {
          $projekt = $this->app->DB->Select("SELECT projekt FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        }

        $zahlungsweise = $this->StandardZahlungsweise($projekt);
        $zahlungsweiselieferant = $this->StandardZahlungsweiseLieferant($projekt);
        $versandart = $this->StandardVersandart($projekt);

        $this->app->DB->Insert("INSERT INTO adresse (id,name,firma,zahlungsweise,zahlungsweiselieferant,projekt,versandart) VALUES ('','$name','$firma','$zahlungsweise','$zahlungsweiselieferant','$projekt','$versandart')");

        $returnId = $this->app->DB->GetInsertID();
        $this->RunHook('AfterAddressCreate', 1, $returnId);
        return $returnId;
      }

      function CreateLieferadresse($adresse,$data)
      {
        $this->app->DB->Insert("INSERT INTO lieferadressen (id,adresse) VALUES ('','$adresse')");
        $id = $this->app->DB->GetInsertID();
        if($data['land']=="") $data['land']='DE';

        $type="lieferadressen";
        $this->app->erp->ObjektProtokoll($type,$id,$type."_create",ucfirst($type)." angelegt");

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE lieferadressen SET $key='".$value."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function CreateAnsprechpartner($adresse,$data)
      {
        $this->app->DB->Insert("INSERT INTO ansprechpartner (id,adresse) VALUES ('','$adresse')");
        $id = $this->app->DB->GetInsertID();
        if($data['land']=="") $data['land']='DE';
        if (!empty($id)) {
          $this->app->erp->RunHook('contact_person_created', 1, $id);
        }
        $type="ansprechpartner";
        $this->app->erp->ObjektProtokoll($type,$id,$type."_create",ucfirst($type)." angelegt");

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE ansprechpartner SET $key='".$value."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function CreateAccount($adresse, $data)
      {
        $this->app->DB->Insert("INSERT INTO adresse_accounts (id, adresse) VALUES ('', '$adresse')");
        $id = $this->app->DB->GetInsertID();

        if($data['aktiv'] == ""){
          $data['aktiv'] = 0;
        }
        if($data['art'] == ""){
          $data['art'] = "";
        }
        if($data['gueltig_ab'] == "" || $data['gueltig_ab'] == "0000-00-00" || $data['gueltig_ab'] == "00.00.0000"){
          $data['gueltig_ab'] = '0000-00-00';
        }else{
          $data['gueltig_ab'] = date('Y-m-d',strtotime($data['gueltig_ab']));
        }
        if($data['gueltig_bis'] == "" || $data['gueltig_bis'] == "0000-00-00" || $data['gueltig_bis'] == "00.00.0000"){
          $data['gueltig_bis'] = "0000-00-00";
        }else{
          $data['gueltig_bis'] = date('Y-m-d',strtotime($data['gueltig_bis']));
        }

        foreach($data as $key => $value){
          $this->app->DB->Update("UPDATE adresse_accounts SET $key = '".$value."' WHERE id = '$id' LIMIT 1");
        }
        return $id;
      }


      function FallbackRolle($adresse)
      {
        if(is_numeric($adresse))
        {
          $projekt = $this->app->DB->Select("SELECT ar.parameter FROM adresse_rolle ar INNER JOIN projekt pr ON ar.parameter = pr.id AND pr.geloescht <> 1 WHERE (ar.bis <= CURDATE() OR ar.bis = '0000-00-00') AND ar.adresse='$adresse' AND ar.objekt='Projekt' LIMIT 1");
          if($projekt <=0)
          {
            $projekt = $this->app->DB->Select("SELECT ar.projekt FROM adresse_rolle ar INNER JOIN projekt pr ON ar.projekt = pr.id AND pr.geloescht <> 1 WHERE (ar.bis <= CURDATE() OR ar.bis = '0000-00-00') AND ar.adresse='$adresse' AND ar.objekt!='Gruppe' LIMIT 1");
          }
          return $projekt;
        }
      }

      function AddRolleZuAdresse($adresse, $subjekt, $praedikat="", $objekt="", $parameter="")
      {
        if(!$adresse) {
          return;
        }
        $tmp_data_adresse = $this->app->DB->SelectRow("SELECT * FROM adresse WHERE id='$adresse' LIMIT 1");
        if(!$tmp_data_adresse) {
          return;
        }
        $projekt = $tmp_data_adresse['projekt'];
        if(strtoupper($objekt)=="PROJEKT")
        {
          $parameter = $this->app->DB->Select("SELECT id FROM projekt WHERE id='$parameter' LIMIT 1");
          if($parameter<=0) $parameter=0;
          if($parameter > 0 ) $projekt=$parameter;
          else {
            $parameter ="";
            $projekt = 0;
          }
        }

        $check = $this->app->DB->Select("SELECT id FROM adresse_rolle WHERE
            subjekt='$subjekt' AND objekt='$objekt' AND praedikat='$praedikat' AND parameter='$parameter' AND adresse='$adresse'
            AND (bis >= NOW() OR bis='0000-00-00')  LIMIT 1");

        if($check > 0)
          return $check;

        // Insert ....
        $sql ="INSERT INTO adresse_rolle (id, adresse, subjekt, praedikat, objekt, parameter,von,projekt)
          VALUES ('','$adresse','$subjekt','$praedikat','$objekt','$parameter',NOW(),'$projekt')";

        $this->app->DB->Insert($sql);
        $id =  $this->app->DB->GetInsertID();


        $kundennummer = trim($tmp_data_adresse['kundennummer']);

        // wenn adresse zum erstenmal die rolle erhält wird kundennummer bzw. lieferantennummer vergeben
        if($subjekt=="Kunde" && ($kundennummer=="" || is_array($kundennummer)))
        {
          $kundennummer = $this->GetNextKundennummer($projekt,$tmp_data_adresse);
          $this->ObjektProtokoll("adresse",$adresse,"adresse_next_kundennummer","Kundennummer erhalten: $kundennummer");
          $this->app->DB->Update("UPDATE adresse SET kundennummer='$kundennummer' WHERE id='$adresse' AND (kundennummer='0' OR kundennummer='') LIMIT 1");
        }

        $lieferantennummer = trim($this->app->DB->Select("SELECT lieferantennummer FROM adresse WHERE id='$adresse' LIMIT 1"));
        //$data = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$adresse' LIMIT 1");
        //$this->LogFile("DEBUG subjekt = $subjekt, projekt=$projekt,adresse=$adresse,lieferantennummer=$lieferantennummer");
        if($subjekt=="Lieferant" && ($lieferantennummer=="" || is_array($lieferantennummer)))
        {
          $lieferantennummer = $this->GetNextLieferantennummer($projekt,$tmp_data_adresse);
          $this->ObjektProtokoll("adresse",$adresse,"adresse_next_lieferantennummer","Lieferantennummer erhalten: $lieferantennummer");

          $this->app->DB->Update("UPDATE adresse SET lieferantennummer='$lieferantennummer' WHERE id='$adresse' AND (lieferantennummer='0' OR lieferantennummer='') LIMIT 1");
        }

        $mitarbeiternummer = trim($this->app->DB->Select("SELECT mitarbeiternummer FROM adresse WHERE id='$adresse' LIMIT 1"));
        if($subjekt=="Mitarbeiter" && ($mitarbeiternummer=="" || is_array($mitarbeiternummer)))
        {
          $mitarbeiternummer = $this->GetNextMitarbeiternummer($projekt,$tmp_data_adresse);
          $this->ObjektProtokoll("adresse",$adresse,"adresse_next_mitarbeiternummer","Mitarbeiternummer erhalten: $mitarbeiternummer");

          $this->app->DB->Update("UPDATE adresse SET mitarbeiternummer='$mitarbeiternummer' WHERE id='$adresse' AND (mitarbeiternummer='0' OR mitarbeiternummer='') LIMIT 1");
        }

        $this->app->DB->Delete("DELETE FROM adresse_rolle WHERE von > bis AND bis!='0000-00-00'");
        return $id;
      }


      function UpdateArbeitszeit($id,$adr_id, $vonZeit, $bisZeit, $aufgabe, $beschreibung,$ort, $projekt, $paketauswahl,$art,$kunde="",$abrechnen="0",$verrechnungsart="",$kostenstelle="",$abgerechnet="0",$gps="",$internerkommentar="",$auftrag=0,$produktion=0, $preis = 0,$auftragpositionid="")
      {
        //Update

        $myArr = $this->app->DB->SelectRow("SELECT aufgabe, beschreibung, projekt, kostenstelle FROM arbeitspaket WHERE id = $paketauswahl");

        if($paketauswahl!=0 && $kunde <=0)
        {
          $kunde = $this->app->DB->Select("SELECT kunde FROM projekt WHERE id='".$myArr["projekt"]."'");
          $projekt = $myArr["projekt"];
        }
        else if($kunde=="NULL")
          $kunde = 0;
        else if($kunde=="")
          $kunde = $this->app->DB->Select("SELECT adresse_abrechnung FROM zeiterfassung WHERE  id='$id'");

        if($auftrag > 0 && $kunde <=0)
            $kunde = $this->app->DB->Select("SELECT adresse FROM auftrag WHERE id='$auftrag' LIMIT 1");
        if($produktion > 0 && $kunde <=0)
            $kunde = $this->app->DB->Select("SELECT adresse FROM produktion WHERE id='$produktion' LIMIT 1");

        $this->app->DB->Update("UPDATE zeiterfassung SET aufgabe='$aufgabe',adresse='$adr_id',arbeitspaket='$paketauswahl',ort='$ort',beschreibung='$beschreibung', projekt='$projekt',art='$art',
            von='$vonZeit',bis='$bisZeit',adresse_abrechnung='$kunde',abrechnen='$abrechnen',kostenstelle='$kostenstelle', verrechnungsart='$verrechnungsart', abgerechnet='$abgerechnet', ist_abgerechnet='$abgerechnet',gps='$gps',internerkommentar='$internerkommentar',auftrag='$auftrag',produktion='$produktion',auftragpositionid='$auftragpositionid' WHERE id='$id'");

          // wenn arbeitszeit in arbeistnachweis verwendet wurden ist dann dort auch updaten

          $arbeitsnachweisposid = $this->app->DB->Select("SELECT arbeitsnachweispositionid FROM zeiterfassung WHERE id='$id'");
        if($arbeitsnachweisposid > 0){
          $von = $this->app->DB->Select("SELECT DATE_FORMAT(von,'%H:%i') FROM zeiterfassung WHERE id='$id'");
          $bis = $this->app->DB->Select("SELECT DATE_FORMAT(bis,'%H:%i') FROM zeiterfassung WHERE id='$id'");
          $this->app->DB->Update("UPDATE arbeitsnachweis_position SET bezeichnung='$aufgabe',beschreibung='$beschreibung',ort='$ort', von='$von',bis='$bis',
              adresse='$adr_id' WHERE id='$arbeitsnachweisposid' LIMIT 1");
        }
        if(!$preis)$preis = $this->app->DB->Select("SELECT stundensatz FROM zeiterfassung WHERE id = '$id' LIMIT 1");
        if(!$preis)
        {
          $stundensatz = (float)$this->app->DB->Select("SELECT stundensatz FROM `zeiterfassung_kosten` WHERE adresse = '$adr_id' AND (gueltig_ab >= date(von) OR gueltig_ab = '0000-00-00') ORDER by gueltig_ab = '0000-00-00', gueltig_ab LIMIT 1");
          if($stundensatz)$this->app->DB->Update("UPDATE zeiterfassung SET stundensatz = '$stundensatz' WHERE id = '$id' LIMIT 1");
        }
      }

      function AddArbeitszeit($adr_id, $vonZeit, $bisZeit, $aufgabe, $beschreibung,$ort, $projekt, $paketauswahl,$art,$kunde="",$abrechnen="",$verrechnungsart="",$kostenstelle="",$abgerechnet="0",$gps="",$aufgabeid=0,$internerkommentar="",$auftrag=0,$produktion=0, $preis = 0,$auftragpositionid="",$serviceauftrag=0)
      {
        if(str_replace(array('-',':'),'',$vonZeit) == 0 || str_replace(array('-',':'),'',$bisZeit) == 0)
          return;

        $insert = "";
        if($paketauswahl==0){

          if($auftrag > 0 && $kunde <=0)
            $kunde = $this->app->DB->Select("SELECT adresse FROM auftrag WHERE id='$auftrag' LIMIT 1");

          if($produktion > 0 && $kunde <=0)
            $kunde = $this->app->DB->Select("SELECT adresse FROM produktion WHERE id='$produktion' LIMIT 1");



          if($abrechnen!="1") $abrechnen=0;
          //if($projekt<=0) $projekt = $this->app->DB->Select("SELECT projekt FROM adresse WHERE id='$kunde' LIMIT 1");
          if($projekt=="") $projekt=0;
          $insert = 'INSERT INTO zeiterfassung (adresse, von, bis, aufgabe, beschreibung, projekt, buchungsart,art,adresse_abrechnung,abrechnen,gebucht_von_user,ort,kostenstelle,verrechnungsart,abgerechnet,ist_abgerechnet,gps,aufgabe_id,internerkommentar,auftrag,produktion,auftragpositionid,serviceauftrag)
            VALUES ('.$adr_id.',"'.$vonZeit.'","'.$bisZeit.'","'.$aufgabe.'", "'.$beschreibung.'",'.$projekt.', "manuell","'.$art.'","'.$kunde.'","'.$abrechnen.'","'.$this->app->User->GetID().'","'.$ort.'","'.$kostenstelle.'","'.$verrechnungsart.'","'.$abgerechnet.'","'.$abgerechnet.'","'.$gps.'","'.$aufgabeid.'","'.$internerkommentar.'","'.$auftrag.'","'.$produktion.'","'.$auftragpositionid.'","'.$serviceauftrag.'")';

        }else{

          $projekt = $this->app->DB->SelectArr("SELECT aufgabe, beschreibung, projekt, kostenstelle FROM arbeitspaket WHERE id = $paketauswahl");
          $myArr = $projekt[0];

          if($kunde<=0) // wenn kunde angeben wird dann da drauf buchen paralell
            $kunde = $this->app->DB->Select("SELECT kunde FROM projekt WHERE id='".$myArr["projekt"]."' LIMIT 1");

        $insert = 'INSERT INTO zeiterfassung (adresse, von, bis, arbeitspaket, aufgabe, beschreibung, projekt, buchungsart,art,gebucht_von_user,ort,adresse_abrechnung,abrechnen,abgerechnet,ist_abgerechnet,gps,aufgabe_id,internerkommentar,auftrag,produktion,auftragpositionid,serviceauftrag) VALUES
          ('.$adr_id.',"'.$vonZeit.'","'.$bisZeit.'",'.$paketauswahl.' , "'.$aufgabe.'", "'.$beschreibung.'",'.$myArr["projekt"].', "AP","'.$art.'","'.$this->app->User->GetID().'","'.$ort.'","'.$kunde.'","'.$abrechnen.'","'.$abgerechnet.'","'.$abgerechnet.'","'.$gps.'","'.$aufgabeid.'","'.$internerkommentar.'","'.$auftrag.'","'.$produktion.'","'.$auftragpositionid.'","'.$serviceauftrag.'")';
      }
      $this->app->DB->Insert($insert);
      $ret = $this->app->DB->GetInsertID();

      if(!$preis)
      {
/*         $stundensatz = (float)$this->app->DB->Select("SELECT stundensatz 
          FROM `zeiterfassung_kosten` 
          WHERE adresse = '$adr_id' AND (gueltig_ab <= curdate() OR gueltig_ab = '0000-00-00') 
          ORDER BY gueltig_ab DESC  LIMIT 1");*/

        if($stundensatz)$this->app->DB->Update("UPDATE zeiterfassung SET stundensatz = '$stundensatz' WHERE id = '$ret' LIMIT 1");
      }
      return $ret;

        // wenn art=="AP" hole projekt und kostenstelle aus arbeitspaket beschreibung
        // und update zuvor angelegten datensatz
      }


      /**
       * \brief   Anlegen eines Arbeitspakets
       *
       *         Diese Funktion legt ein Arbeitspaket an.
       *
       * \param   aufgabe      Kurzbeschreibung (ein paar Woerter)
       * \param   beschreibung  Textuelle Beschreibung
       * \param   projekt      Projekt ID
       * \param   zeit_geplant  Stundenanzahl Integer Wert
       * \param   kostenstelle  Kostenstelle
       * \param   initiator            user id des Initiators
       * \param   abgabedatum   Datum fuer Abgabe
       * \return                Status-Code
       *
       */
      function CreateArbeitspaket($adresse, $aufgabe,$beschreibung,$projekt,$zeit_geplant,$kostenstelle,$initiator,$abgabedatum="")
      {
        if(($aufgabe != '') && ($beschreibung != '') && ($projekt != '') && ($zeit_geplant != '') && ($kostenstelle != '') && ($initiator != '')){
          $this->app->DB->Insert('INSERT INTO arbeitspakete  (adresse, aufgabe, beschreibung, projekt, zeit_geplant, kostenstelle, initiator, abgabedatum)                                                                VALUES (                                                                                                                                                      '.$adresse.',"'.$aufgabe.'", "'.$beschreibung.'", '.$projekt.', '.$zeit_geplant.','.$kostenstelle.', '.$initiator.',"'.$abgabedatum.'")');
          return 1;
        }
        return 0;
      }

      function CreateBenutzerVorlage($felder)
      {
        $this->app->DB->Insert("INSERT INTO uservorlage (id,bezeichnung,beschreibung)
            VALUES ('','{$felder['bezeichnung']}', '{$felder['beschreibung']}')");

        $id = $this->app->DB->GetInsertID();

        //standard rechte damit man sich anmelden kann
        $this->app->DB->Update("INSERT INTO uservorlagerights (vorlage, module,action,permission) VALUES ('$id','welcome','login',1)");
        $this->app->DB->Update("INSERT INTO uservorlagerights (vorlage, module,action,permission) VALUES ('$id','welcome','logout',1)");
        $this->app->DB->Update("INSERT INTO uservorlagerights (vorlage, module,action,permission) VALUES ('$id','welcome','start',1)");
        $this->app->DB->Update("INSERT INTO uservorlagerights (vorlage, module,action,permission) VALUES ('$id','welcome','startseite',1)");
        $this->app->DB->Update("INSERT INTO uservorlagerights (vorlage, module,action,permission) VALUES ('$id','welcome','settings',1)");
        return $id;
      }


      function CreateBenutzer($felder)
      {
        $settings = base64_encode(serialize($felder['settings']));
        $firma = $this->app->User->GetFirma();

        $passwordunenescaped = $felder['passwordunenescaped'];

        $this->app->DB->Insert(
          sprintf(
            "INSERT INTO `user` 
                (`username`, `passwordmd5`, `password`, 
                `description`, `settings`, `parentuser`, `activ`, `type`, `adresse`, 
                `fehllogins`, `standarddrucker`, `startseite`, 
                `hwtoken`, `hwkey`, `hwcounter`, `hwdatablock`, 
                `motppin`, `motpsecret`, `externlogin`, 
                `gpsstechuhr`, `firma`, `kalender_passwort`, `kalender_aktiv`, `vorlage`,
                `projekt_bevorzugen`, `projekt`, `docscan_aktiv`, `docscan_passwort`, `repassword`)
            VALUES (
                '%s', MD5('%s'), '', 
                '%s', '%s', '0', '%d', '%s', %d, 
                %d, %d, '%s',
                %d, '%s', %d, '%s', 
                '%s', '%s', '%d', 
                '%d', '%d', '%s', '%d', '%s',
                '%d', '%d', '%d', '%s', 0
            )",
            $felder['username'], $felder['password'],
            $felder['description'], $settings, $felder['activ'], $felder['type'], $felder['adresse'],
            $felder['fehllogins'], $felder['standarddrucker'], $felder['startseite'],
            $felder['hwtoken'], $felder['hwkey'], $felder['hwcounter'], $felder['hwdatablock'],
            $felder['motppin'], $felder['motpsecret'], $felder['externlogin'],
            $felder['gpsstechuhr'], $firma, $felder['kalender_passwort'], $felder['kalender_aktiv'], $felder['vorlage'],
            $felder['projekt_bevorzugen'], $felder['projekt'], $felder['docscan_aktiv'], $felder['docscan_passwort']
          )
        );

        $id = $this->app->DB->GetInsertID();
        if(empty($id)) {
          return $id;
        }
        $salt = $this->app->DB->Select("SELECT salt FROM user WHERE id = '$id' LIMIT 1");
        if(!$this->app->DB->error()) {
          $salt = hash('sha512',microtime(true));
          $passwordsha512 = hash('sha512', $passwordunenescaped.$salt);
          $this->app->DB->Update("UPDATE user SET password='', salt = '$salt', passwordsha512 = '$passwordsha512' WHERE id='$id' LIMIT 1");
        }

        //standard rechte damit man sich anmelden kann
        $this->insertDefaultUserRights($id);
        $this->AbgleichBenutzerVorlagen($id);

        return $id;
      }

  /**
   * @param int $userId
   */
      public function insertDefaultUserRights($userId)
      {
        if($userId <= 0) {
          return;
        }
        foreach(['login','logout','start','startseite','settings'] as $action) {
          $this->app->DB->Update(
            sprintf(
              "INSERT INTO `userrights` (`user`, `module`, `action`, `permission`) VALUES (%d, 'welcome', '%s', 1)",
              $userId, $action
            )
          );
        }
      }

      function IsAdresseInGruppe($adresse,$gruppe)
      {

        $check = $this->app->DB->Select("SELECT a.parameter FROM adresse_rolle a WHERE
            (a.bis='0000-00-00' OR a.bis <=NOW()) AND a.adresse='$adresse' AND a.parameter='$gruppe' AND a.objekt='Gruppe' LIMIT 1");

        return ($check == $gruppe) && $gruppe > 0;
      }

      function IsAdresseSubjekt($adresse,$subjekt)
      {
        $id = $this->app->DB->Select("SELECT id FROM adresse_rolle WHERE adresse='$adresse' AND subjekt='$subjekt' LIMIT 1");
        return $id > 0?1:0;
      }

      function AddOffenenVorgang($adresse, $titel, $href, $beschriftung="", $linkremove="")
      {
        $sql = "INSERT INTO offenevorgaenge (id,adresse,titel,href,beschriftung,linkremove) VALUES
          ('','$adresse','$titel','$href','$beschriftung','$linkremove')";
        $this->app->DB->Insert($sql);
      }


      function RenameOffenenVorgangID($id,$titel)
      {
        $sql = "UPDATE offenevorgaenge SET titel='$titel' WHERE id='$id' LIMIT 1";
        $this->app->DB->Update($sql);
      }

      function RemoveOffenenVorgangID($id)
      {
        $sql = "DELETE FROM offenevorgaenge WHERE id='$id' LIMIT 1";
        $this->app->DB->Delete($sql);
      }

      function CalcNextNummer($nummer)
      {
        $nummer = trim($nummer);

        //Nummer von rechts abknabbern
        for($i=strlen($nummer)-1; $i >= 0; $i--)
        {
          $checkvalue = $nummer[$i];
          if(is_numeric($checkvalue))
            $nummer_anteil[] = $checkvalue;
          else break;
        }
        // nummer string erstellen
        if(isset($nummer_anteil))
        {
          $nummer_anteil_string = implode("",$nummer_anteil);
          $nummer_anteil_string = strrev($nummer_anteil_string);
          $laenge_nummer_anteil_string = strlen($nummer_anteil_string);
        } else {
          $nummer_anteil_string = 0;
          $laenge_nummer_anteil_string = 0;
        }

        // buchstaben teil extrahieren
        $buchstaben_anteil_string = substr($nummer,0,strlen($nummer) - $laenge_nummer_anteil_string);
        if($laenge_nummer_anteil_string == 0)$laenge_nummer_anteil_string = 1;
        // nummer erhoehen
        $neue_nummer = $nummer_anteil_string+1;


        // nummer von links auffuellen mit nullern
        $neue_nummer = str_pad($neue_nummer, $laenge_nummer_anteil_string, "0", STR_PAD_LEFT);

        //zusammensetzen
        return $buchstaben_anteil_string.$neue_nummer;
      }

      function CalcNextArtikelNummer($nummer) {
        $check = null;
        do {
           $nummer = $this->CalcNextNummer($nummer);
           $sql = "SELECT id FROM artikel WHERE nummer = '".$nummer."'";
           $check = $this->app->DB->Select($sql);
        } while (!empty($check));
        return ($nummer);
      }

      function GetNextNummer($type,$projekt="",$data="")
      {
        $doctype = $type;
        if(in_array($doctype,['kundennummer', 'lieferantennummer', 'mitarbeiternummer'])) {
          $doctype = 'adresse';
        }
        $checkprojekt = $this->app->DB->Select("SELECT id FROM projekt WHERE id='$projekt' LIMIT 1");

        $process_lock = $this->app->erp->ProzessLock("erpapi_getnextnummer");

        $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
        $belegnr = '';
        if($eigenernummernkreis=='1')
        {
          $allowedtypes = ['angebot', 'auftrag', 'rechnung', 'lieferschein', 'arbeitsnachweis', 'reisekosten',
              'bestellung', 'gutschrift', 'kundennummer', 'lieferantennummer', 'mitarbeiternummer', 'waren',
              'produktion', 'sonstiges', 'anfrage', 'artikelnummer', 'kalkulation', 'preisanfrage', 'proformarechnung',
              'retoure', 'verbindlichkeit','lieferantengutschrift', 'goodspostingdocument', 'receiptdocument'];

          $dbfield = "next_$type";
          $belegnr = $this->app->DB->Select("SELECT $dbfield FROM projekt WHERE id='$projekt' LIMIT 1");
          if (!empty($belegnr)) {
            $newbelegnr = $this->CalcNextNummer($belegnr);
            $this->app->DB->Update("UPDATE projekt SET $dbfield='$newbelegnr' WHERE id='$projekt' LIMIT 1");
          }
        }
        if (empty($belegnr)) {
          // naechste
          switch($type)
          {
            case "preisanfrage":
              $belegnr = $this->Firmendaten("next_preisanfrage");
              if($belegnr == "0" || $belegnr == "") $belegnr = 100000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "angebot":
              $belegnr = $this->Firmendaten("next_angebot");
              if($belegnr == "0" || $belegnr == "") $belegnr = 100000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "auftrag":
              $belegnr = $this->Firmendaten("next_auftrag");
              if($belegnr == "0" || $belegnr=="") $belegnr = 200000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "rechnung":
              $belegnr = $this->Firmendaten("next_rechnung");
              if($belegnr == "0" || $belegnr=="") $belegnr = 400000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "gutschrift":
              $belegnr = $this->Firmendaten("next_gutschrift");
              if($belegnr == "0" || $belegnr=="") $belegnr = 900000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "lieferschein":
              $belegnr = $this->Firmendaten("next_lieferschein");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "retoure":
              $belegnr = $this->Firmendaten("next_retoure");
              if($belegnr == "0" || $belegnr=="") $belegnr = 500000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "bestellung":
              $belegnr = $this->Firmendaten("next_bestellung");
              if($belegnr == "0" || $belegnr=="") $belegnr = 100000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "arbeitsnachweis":
              $belegnr = $this->Firmendaten("next_arbeitsnachweis");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "anfrage":
              $belegnr = $this->Firmendaten("next_anfrage");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "preisanfrage":
              $belegnr = $this->Firmendaten("next_preisanfrage");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "proformarechnung":
              $belegnr = $this->Firmendaten("next_proformarechnung");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "kalkulation":
              $belegnr = $this->Firmendaten("next_kalkulation");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "reisekosten":
              $belegnr = $this->Firmendaten("next_reisekosten");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "produktion":
              $belegnr = $this->Firmendaten("next_produktion");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "kundennummer":
              $belegnr = $this->Firmendaten("next_kundennummer");
              if($belegnr == "0" || $belegnr=="") $belegnr = 10000;
              while($this->app->DB->Select("SELECT id FROM adresse WHERE kundennummer = '$belegnr' and kundennummer <> '' and geloescht <> 1 LIMIT 1"))
              {
                $belegnr++;
              }
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "lieferantennummer":
              $belegnr = $this->Firmendaten("next_lieferantennummer");
              if($belegnr == "0" || $belegnr=="") $belegnr = 70000;
              while($this->app->DB->Select("SELECT id FROM adresse WHERE lieferantennummer = '$belegnr' and lieferantennummer <> '' and geloescht <> 1 LIMIT 1"))
              {
                $belegnr++;
              }
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "mitarbeiternummer":
              $belegnr = $this->Firmendaten("next_mitarbeiternummer");
              if($belegnr == "0" || $belegnr=="") $belegnr = 90000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "projektnummer":
              $belegnr = $this->Firmendaten("next_projektnummer");
              if($belegnr == "0" || $belegnr=="") $belegnr = 90000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "serviceauftrag":
              $belegnr = $this->Firmendaten("next_serviceauftrag");
              if($belegnr == "0" || $belegnr=="") $belegnr = 300000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "verbindlichkeit":
              $belegnr = $this->Firmendaten("next_verbindlichkeit");
              if($belegnr == "0" || $belegnr=="") $belegnr = 10000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case "lieferantengutschrift":
              $belegnr = $this->Firmendaten("next_lieferantengutschrift");
              if($belegnr == "0" || $belegnr=="") $belegnr = 20000;
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            case 'receiptdocument':
              $belegnr = $this->Firmendaten('next_receiptdocument');
              if($belegnr == '0' || $belegnr=='') {
                $belegnr = 10000;
              }
              $newbelegnr = $this->CalcNextNummer($belegnr);
              break;
            default:
              $belegnr = null;
              $newbelegnr = null;
              $this->RunHook('next_number', 3, $type, $belegnr, $newbelegnr);
              if($belegnr === null && $newbelegnr === null){
                $begelnr = 'Fehler';
              }
              break;
          }

          $this->FirmendatenSet("next_$type",$newbelegnr);
        }
        $this->app->erp->ProzessUnlock($process_lock);

        // alle spalten aus Adress als Variable
        $doctypeid = $data;
        if($doctype === 'adresse') {
          if(is_numeric($data)) {
            $adresse = $this->app->DB->SelectRow(
              sprintf(
                'SELECT a.* FROM `adresse` AS a WHERE a.id=%d LIMIT 1',
                 $doctypeid
              )
            );
          }elseif(is_array($data)) {
            if(empty($data['id']) && !empty($data[0])) {
              $data = reset($data);
            }
            if(!empty($data['id'])) {
              $adresse = $data;
            }
          }
        } elseif(is_array($data)) {
          if(empty($data['id']) && !empty($data[0])) {
            $data = reset($data);
          }
          if(!empty($data['id'])) {
            $data = $data['id'];
          }
        }
        if(is_numeric($data)){
          $adresse = $this->app->DB->SelectRow(
            sprintf(
              "SELECT a.* FROM `%s` b LEFT JOIN adresse a ON a.id=b.adresse WHERE b.id=%d LIMIT 1",
              $doctype, $data
            )
          );
        }
        if(!empty($adresse)) {
          foreach($adresse as $key=>$value) {
            $belegnr = str_ireplace('{ADRESSE_' . strtoupper($key) . '}', $value, $belegnr);
          }
        }

        $belegnr = str_ireplace('{JAHR}',date('Y'),$belegnr);
        $belegnr = str_ireplace('{MONAT}',date('m'),$belegnr);
        $belegnr = str_ireplace('{TAG}',date('d'),$belegnr);
        $belegnr = str_ireplace('{KW}',date('W'),$belegnr);
        return $belegnr;
      }

      function InsertUpdateAdresse($data)
      {
        $created = false;
        if(!is_array($data)) {
          return false;
        }
        $projekt = $this->app->DB->Select("SELECT standardprojekt FROM firma WHERE id='".$this->app->User->GetFirma()."' LIMIT 1");
        if(isset($data['projekt'])){
          $projekt = $data['projekt'];
        } else {
          $data['projekt'] = $projekt;
        }
        if(isset($data['id']))
        {
          $adresse = $this->app->DB->SelectRow("select * from adresse where id = ".$data['id']." limit 1");
        }
        if(!isset($adresse) || !$adresse)
        {
          $where = " geloescht <> 1 ";
          if(isset($data['lieferantennummer']) && $data['lieferantennummer'] !== '')
          {
            if($where != "")$where .= " and ";
            $where .= " lieferantennummer like '".$this->app->DB->real_escape_string($data['lieferantennummer'])."' ";
          }
          if(isset($data['kundennummer']) && $data['kundennummer'] !== '')
          {
            if($where != "")$where .= " and ";
            $where .= " kundennummer like '".$this->app->DB->real_escape_string($data['kundennummer'])."' ";
          }
          if(isset($data['mitarbeiternummer']) && $data['mitarbeiternummer'] !== '')
          {
            if($where != "")$where .= " and ";
            $where .= " mitarbeiternummer like '".$this->app->DB->real_escape_string($data['mitarbeiternummer'])."' ";
          }
          if($where != " geloescht <> 1 ") {
            $adresse = $this->app->DB->SelectRow("select * from adresse where ".$where." limit 1");
          }
        }
        if(!isset($adresse) || !$adresse)
        {
          $this->app->DB->Insert("insert into adresse (id) values ('')");
          $id = $this->app->DB->GetInsertID();
          $created = true;
          if($id)
          {
            $adresse = $this->app->DB->SelectRow("select * from adresse where id = '".$id."' limit 1");

          } else return false;
          if(isset($data['lieferantennummer']) && $data['lieferantennummer'] !== '')
          {
            $this->AddRolleZuAdresse($id, "Lieferant", "von", "Projekt", $projekt);
          }
          if(isset($data['kundennummer']) && $data['kundennummer'] !== '')
          {
            $this->AddRolleZuAdresse($id, "Kunde", "von", "Projekt", $projekt);
          }
          if(isset($data['mitarbeiternummer']) && $data['mitarbeiternummer'] !== '')
          {
            $this->AddRolleZuAdresse($id, "Mitarbeiter", "von", "Projekt", $projekt);
          }
        }
        if(!$adresse)return false;
        if(isset($adresse['id']))$id = $adresse['id'];
        if(isset($data['lieferantennummer']) && $data['lieferantennummer'] !== '')
        {
          $this->AddRolleZuAdresse($id, "Lieferant", "von", "Projekt", $projekt);
        }
        if(isset($data['kundennummer']) && $data['kundennummer'] !== '')
        {
          $this->AddRolleZuAdresse($id, "Kunde", "von", "Projekt", $projekt);
        }
        if(isset($data['mitarbeiternummer']) && $data['mitarbeiternummer'] !== '')
        {
          $this->AddRolleZuAdresse($id, "Mitarbeiter", "von", "Projekt", $projekt);
        }

        $zielspalten = $this->app->DB->SelectArr("show columns from `adresse`");
        if($zielspalten)
        {
          foreach($zielspalten as $val)$ziel[$val['Field']] = true;
        }

        foreach($data as $k => $v)
        {
          $k = trim($k);
          if(empty($ziel))
          {
            $ka = explode(' ',$k);
            $k = $ka[0];
          }
          if($k !== '' && $k != 'id' && (String)$adresse[$k] !== (String)$v && (empty($ziel) || isset($ziel[$k])))
          {
            $sqla[] = $this->app->DB->real_escape_string($k). " = ".(!is_null($v)?"'".$this->app->DB->real_escape_string($v)."'":"NULL")." ";
          }
        }

        if(!empty($sqla))$this->app->DB->Update("update adresse set ".implode(', ',$sqla)." where id = '".$adresse['id']."' LIMIT 1");

        if($this->app->DB->error() != '' || empty($sqla))
        {
          foreach($data as $k => $v)
          {
            $k = trim($k);
            if(empty($ziel))
            {
              $ka = explode(' ',$k);
              $k = $ka[0];
            }
            if($k !== '' && $k != 'id' && (String)$adresse[$k] !== (String)$v && (empty($ziel) || isset($ziel[$k])))
            {
              $this->app->DB->Update("update adresse set ".$this->app->DB->real_escape_string($k)." = ".(!is_null($v)?"'".$this->app->DB->real_escape_string($v)."'":"NULL")." where id = '".$adresse['id']."' LIMIT 1");
            }
          }
        }
        if($created) {
          $addressId = $adresse['id'];
          $this->RunHook('adresse_create', 1, $addressId);
          $this->RunHook('AfterAddressCreate', 1, $addressId);
        }
        else {
          $addressId = $adresse['id'];
          $this->RunHook('adresse_update', 1, $addressId);
        }

        return $adresse['id'];
      }

      public function InsertUpdateArtikel($data, $onlyUpdate = false) {
        if(!is_array($data)){
          return false;
        }
        $created = false;
        $projekt = $this->app->erp->Firmendaten('projekt');
        if(isset($data['projekt'])){
          $projekt = $data['projekt'];
        } else {
          $data['projekt'] = $projekt;
        }
        if(isset($data['id']) && $data['id']) {
          $artikel = $this->app->DB->SelectRow("select * from artikel where id = ".$data['id']." limit 1");
        }
        else {
          $artikel = null;
        }
        if(!$artikel && isset($data['nummer']) && $data['nummer'] != '') {
          $order = "";
          $where = " geloescht <> 1 AND  nummer = '".$this->app->DB->real_escape_string($data['nummer'])."'";

          if(isset($data['projekt']) && $data['projekt'] && (int)$data['projekt'] > 0) {
            if($this->app->DB->Select("SELECT id FROM projekt WHERE eigenernummernkreis = 1 AND id = '".(int)$data['projekt']."'")) {
              $where .= " AND projekt = '".(int)$data['projekt']."' ";
            }else {
              $order .= " ORDER BY projekt = '".(int)$data['projekt']."' DESC ";
            }
          }
          if(isset($data['typ']) && $data['typ'] !== '') {
            $kat = (int)str_replace('_kat','',$data['typ']);
            if($kat && $this->app->DB->Select("SELECT id FROM artikelkategorien WHERE id = '$kat' AND externenummer = 0 AND geloescht = 0 LIMIT 1")) {
              if($order === '') {
                $order .= " ORDER BY ";
              }
              else{
                $order .= " , ";
              }
              $order .= " typ = '".$kat.'_kat'."' DESC ";
            }
          }
          $artikel = $this->app->DB->SelectRow("select * from artikel where ".$where." $order limit 1");
        }
        if(!(isset($artikel['id']) && $artikel['id'] > 0)) {
          if($onlyUpdate) {
            return false;
          }
          $this->app->DB->Insert("insert into artikel (id) values (NULL)");
          $created = true;
          $id = $this->app->DB->GetInsertID();
          $artikel = $this->app->DB->SelectRow("select * from artikel where id = ".$id." limit 1");
          if(empty($data['nummer'])){
            $data['nummer'] = $this->GetNextArtikelnummer(!empty($data['typ'])?$data['typ']:"", 1, $data['projekt']);
          }
        }
        if(isset($artikel['id']) && $artikel['id'] > 0) {
          $id = $artikel['id'];
          $zielspalten = $this->app->DB->SelectArr("show columns from `artikel`");
          if($zielspalten) {
            foreach($zielspalten as $val) {
              $ziel[$val['Field']] = true;
            }
          }

          foreach($data as $k => $v)  {
            $k = trim($k);
            if(empty($ziel)) {
              $ka = explode(' ',$k);
              $k = $ka[0];
            }
            $artikelValue = isset($artikel[$k])?(String)$artikel[$k]:'';
            if($k !== '' && $k !== 'id' && $artikelValue !== (String)$v && (empty($ziel) || isset($ziel[$k]))) {
              $sqla[] = $this->app->DB->real_escape_string($k). ' = '.($v !== null?"'".$this->app->DB->real_escape_string($v)."'":'NULL').' ';
            }
          }

          if(!empty($sqla)) {
            $this->app->DB->Update("update artikel set ".implode(', ',$sqla)." where id = '".$id."' LIMIT 1");
          }
          if($this->app->DB->error() != '' || empty($sqla)) {
            foreach($data as $k => $v)  {
              if(empty($ziel)){
                $ka = explode(' ',trim($k));
                $k = $ka[0];
              }
              $artikelValue = isset($artikel[$k])?(String)$artikel[$k]:'';
              if($k !== '' && $k !== 'id' && $artikelValue !== (String)$v && (empty($ziel) || isset($ziel[$k]))) {
                $this->app->DB->Update("update artikel set ".$this->app->DB->real_escape_string($k)." = ".($v !== null?"'".$this->app->DB->real_escape_string($v)."'":'NULL')." where id = '".$id."' LIMIT 1");
              }
            }
          }
          if(!empty($data['shop']) || !empty($data['shop2']) || !empty($data['shop3'])) {
            $this->CheckShopTabelle($id);
          }
          $articleId = $id;
          if($created) {
            $this->app->erp->RunHook('artikel_create', 1, $articleId);
          }
          else {
            $this->app->erp->RunHook('artikel_update', 1, $articleId);
          }
          return $id;
        }
        return false;
      }

      function GetNextArtikelnummer($artikelart="",$firma="1",$projekt="")
      {
        // neue artikel nummer holen
        $process_lock = $this->app->erp->ProzessLock("erpapi_getnextartikelnummer");
        if(is_numeric($artikelart)) $artikelart = $artikelart."_kat";

        $check = str_replace("_kat","",$artikelart);
        $check = $this->app->DB->Select("SELECT id FROM artikelkategorien WHERE id='$check' AND geloescht!=1 LIMIT 1");

        if($check > 0)
        {
          $next_nummer_alt = $this->app->DB->Select("SELECT next_nummer FROM artikelkategorien WHERE id='$check' AND geloescht!=1");
          $externenummer = $this->app->DB->Select("SELECT externenummer FROM artikelkategorien WHERE id='$check' AND geloescht!=1");

          if($externenummer!="1")
          {
            if($next_nummer_alt=="")
            {
              $next_nummer_alt = 100000;
              $neue_nummer = $next_nummer_alt;
              $this->app->DB->Update("UPDATE artikelkategorien SET next_nummer='$neue_nummer' WHERE id='$check' AND geloescht!=1");
            } else {
              $nurbuchstaben = preg_replace("/[^a-zA-Z]/","",$next_nummer_alt);
              $nurzahlen = preg_replace("/[^0-9]/","",$next_nummer_alt);
              $laenge = strlen($nurzahlen);

              $next_nummer = $this->CalcNextArtikelNummer($next_nummer_alt);
              //$nurbuchstaben.str_pad($nurzahlen+1, $laenge  ,'0', STR_PAD_LEFT);
              $neue_nummer = $next_nummer;

              $this->app->DB->Update("UPDATE artikelkategorien SET next_nummer='$next_nummer' WHERE id='$check' AND geloescht!=1");
            }
          } else {
            // externe nummer holen
            // TODO pruefen ob es im Projekt ueberladen gehoert
            $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
            if($eigenernummernkreis=="1")
            {
              $neue_nummer = $this->app->DB->Select("SELECT next_artikelnummer FROM projekt WHERE id='$projekt' LIMIT 1");
              if($this->app->DB->Select("SELECT id FROM artikel WHERE nummer = '".$this->app->DB->real_escape_string($neue_nummer)."' LIMIT 1"))$neue_nummer = $this->CalcNextArtikelNummer($neue_nummer);
              $next_nummer = $this->CalcNextArtikelNummer($neue_nummer);
              $this->app->DB->Update("UPDATE projekt SET next_artikelnummer='".$next_nummer."' WHERE id='$projekt' LIMIT 1");
            } else {
              //zentraler nummernkreis mit prefix
              $next_nummer = $this->CalcNextArtikelNummer($this->Firmendaten("next_artikelnummer"));
              $this->FirmendatenSet("next_artikelnummer",$next_nummer);
              if($next_nummer_alt!="") $neue_nummer=$next_nummer_alt.$next_nummer;
              else $neue_nummer = $next_nummer;
            }

            //$nurbuchstaben = preg_replace("/[^a-zA-Z]/","",$next_nummer_alt);
            //$neue_nummer = $nurbuchstaben.$next_nummer;
            //$neue_nummer = $this->CalcNextNummer($next_nummer_alt);
          }
        } else {
          $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
          if($eigenernummernkreis)
          {
            $neue_nummer = $this->app->DB->Select("SELECT next_artikelnummer FROM projekt WHERE id='$projekt' LIMIT 1");
            if($this->app->DB->Select("SELECT id FROM artikel WHERE nummer = '".$this->app->DB->real_escape_string($neue_nummer)."' LIMIT 1"))$neue_nummer = $this->CalcNextArtikelNummer($neue_nummer);
            $next_nummer = $this->CalcNextArtikelNummer($neue_nummer);
            $this->app->DB->Update("UPDATE projekt SET next_artikelnummer='".$next_nummer."' WHERE id='$projekt' LIMIT 1");
          }else{
            $firmennummer = $this->app->erp->Firmendaten('next_artikelnummer');
            if($firmennummer)
            {
              $next_nummer = $firmennummer;
              $neue_nummer = $this->CalcNextArtikelNummer($next_nummer);
              $this->FirmendatenSet('next_artikelnummer', $neue_nummer);
              $neue_nummer = $this->app->erp->Firmendaten('next_artikelnummer');
            } else {
              switch($artikelart)
              {
                case "produkt":
                  $neue_nummer = $this->app->DB->Select("SELECT MAX(nummer) FROM artikel WHERE nummer LIKE '7%'");
                  if($neue_nummer=="" || $neue_nummer=="0") $neue_nummer = "700000";
                  break;
                case "produktion":
                  $neue_nummer = $this->app->DB->Select("SELECT MAX(nummer) FROM artikel WHERE nummer LIKE '4%'");
                  if($neue_nummer=="" || $neue_nummer=="0") $neue_nummer = "400000";
                  break;
                case "module":
                  $neue_nummer = $this->app->DB->Select("SELECT MAX(nummer) FROM artikel WHERE nummer LIKE '6%'");
                  if($neue_nummer=="" || $neue_nummer=="0") $neue_nummer = "600000";
                  break;
                default:
                  $neue_nummer = $this->app->DB->Select("SELECT MAX(CAST(nummer AS UNSIGNED)) FROM artikel WHERE nummer LIKE '1%'");
                  if(($neue_nummer=="" || $neue_nummer=="0")) $neue_nummer = "100000";
              }
              $neue_nummer = $this->CalcNextArtikelNummer($neue_nummer);//$neue_nummer + 1;
            }
          }
        }

        $this->app->erp->ProzessUnlock($process_lock);
        $neue_nummer = str_replace('{JAHR}',date('Y'),$neue_nummer);
        $neue_nummer = str_replace('{MONAT}',date('m'),$neue_nummer);
        $neue_nummer = str_replace('{TAG}',date('d'),$neue_nummer);
        return $neue_nummer;
      }

      function GetNextMitarbeiternummer($projekt="",$data="")
      {
        return $this->GetNextNummer("mitarbeiternummer",$projekt,$data);
      }


      function GetNextKundennummer($projekt="",$data="")
      {
        return $this->GetNextNummer("kundennummer",$projekt,$data);
      }

      function GetNextLieferantennummer($projekt="",$data="")
      {
        return $this->GetNextNummer("lieferantennummer",$projekt,$data);
      }

      function ArbeitsnachweisProtokoll($id,$text)
      {
        /** @var Arbeitsnachweis $obj */
        $obj = $this->app->erp->LoadModul('arbeitsnachweis');
        if(!empty($obj) && method_exists($obj, 'addArbeitsnachweisProtokoll')) {
          $obj->addArbeitsnachweisProtokoll($id, $text);
        }
      }


      function KalkulationProtokoll($id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO kalkulation_protokoll (id,reisekosten,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }

      function ReisekostenProtokoll($id,$text)
      {
        /** @var Reisekosten $obj */
        $obj = $this->app->erp->LoadModul('reisekosten');
        if(!empty($obj) && method_exists($obj, 'AddReisekostenProtokoll')) {
          $obj->AddReisekostenProtokoll($id, $text);
        }
      }


      function AnfrageProtokoll($id,$text)
      {
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO anfrage_protokoll (id,anfrage,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }


      function BelegProtokoll($typ,$id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO ".$typ."_protokoll (id,".$typ.",zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }


      function PreisanfrageProtokoll($id,$text)
      {
        /** @var Preisanfrage $obj */
        $obj = $this->app->erp->LoadModul('preisanfrage');
        if(!empty($obj) && method_exists($obj,'addPreisanfrageProtokoll')) {
          $obj->addPreisanfrageProtokoll($id, $text);
        }
      }


      function ProformarechnungProtokoll($id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO proformarechnung_protokoll (id,proformarechnung,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }



      function InventurProtokoll($id,$text)
      {
        /** @var Inventur $obj */
        $obj = $this->LoadModul('inventur');
        if(!empty($obj) && method_exists($obj, 'AddInventurProtokoll'))
        {
          $obj->AddInventurProtokoll($id,$text);
        }
      }

      function RetoureProtokoll($id,$text)
      {
        /** @var Retoure $obj */
        $obj = $this->app->erp->LoadModul('retoure');
        if($obj && method_exists($obj,'addRetoureProtokoll')) {
          $obj->addRetoureProtokoll($id, $text);
        }
      }

      function LieferscheinProtokoll($id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO lieferschein_protokoll (id,lieferschein,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }


      function AuftragProtokoll($id, $text, $bearbeiter = '')
      {
        if(!$id){
          return;
        }
        if(empty($bearbeiter)){
          $bearbeiter = '';
          if((isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))){
            $bearbeiter = $this->app->DB->real_escape_string($this->app->User->GetName());
          }
        }
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO auftrag_protokoll (id,auftrag,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }

      function AngebotProtokoll($id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO angebot_protokoll (id,angebot,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }

      function BestellungProtokoll($id,$text)
      {
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO bestellung_protokoll (id,bestellung,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }

      function RechnungProtokoll($id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO rechnung_protokoll (id,rechnung,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'".$bearbeiter."','$text')");
      }

      function GutschriftProtokoll($id,$text)
      {
        if(!$id)return;
        $bearbeiter = (isset($this->app->User) && $this->app->User && method_exists($this->app->User, 'GetName'))?$this->app->DB->real_escape_string($this->app->User->GetName()):'';
        $text = $this->app->DB->real_escape_string($text);
        $this->app->DB->Insert("INSERT INTO gutschrift_protokoll (id,gutschrift,zeit,bearbeiter,grund) VALUES
            ('','$id',NOW(),'$bearbeiter','$text')");
      }


      function LoadArbeitsnachweisStandardwerte($id,$adresse,$projekt="")
      {
        /** @var Arbeitsnachweis $obj */
        $obj = $this->app->erp->LoadModul('arbeitsnachweis');
        if(!empty($obj) && method_exists($obj, 'LoadArbeitsnachweisStandardwerte')) {
          $obj->LoadArbeitsnachweisStandardwerte($id,$adresse,$projekt);
        }
      }


      function LoadInventurStandardwerte($id,$adresse,$projekt="")
      {
        /** @var Inventur $obj */
        $obj = $this->LoadModul('inventur');
        if(!empty($obj) && method_exists($obj, 'LoadInventurStandardwerte'))
        {
          $obj->LoadInventurStandardwerte($id,$adresse,$projekt);
        }
      }

      function KundeHatZR($adresse)
      {
        $verband = $this->GetVerband($adresse);
        $zr = $this->app->DB->Select("SELECT zentralregulierung FROM gruppen WHERE id='$verband' LIMIT 1");

        return $zr=='1';
      }

      function GetVerbandName($gruppe)
      {
        return $this->app->DB->Select("SELECT CONCAT(kennziffer,' ',name) FROM gruppen WHERE id='$gruppe' LIMIT 1");
      }

      function GetVerband($adresse)
      {
        return $this->app->DB->Select("SELECT g.id FROM adresse_rolle a INNER JOIN gruppen g ON g.id=a.parameter WHERE
            (a.bis='0000-00-00' OR a.bis >=NOW()) AND a.adresse='$adresse' AND a.objekt='Gruppe' AND (g.art='verband' OR g.art='preisgruppe') AND g.aktiv = 1 LIMIT 1");
      }

      function LoadAnfrageStandardwerte($id,$adresse,$projekt="")
      {
        // standard adresse von lieferant
        $arr = $this->app->DB->SelectArr("SELECT *,vertrieb as vertriebid,innendienst as bearbeiterid,'' as bearbeiter FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

        $arr[0]['gruppe'] = $this->GetVerband($adresse);
        $field = array('anschreiben','name','abteilung','typ','unterabteilung','strasse','adresszusatz','plz','ort','land','ustid','email','telefon','telefax',
            'kundennummer','projekt','gruppe','vertriebid','bearbeiterid','bearbeiter','titel');

        foreach($field as $key=>$value)
        {

          if($value=="projekt" && $this->app->Secure->POST[$value]!="")
          {
            if(!is_numeric($this->app->Secure->POST[$value]))
            {
              $uparr[$value] = $this->app->DB->Select("SELECT id FROM projekt WHERE abkuerzung <> '' AND abkuerzung = '".$this->app->DB->real_escape_string($this->app->Secure->POST[$value])."' AND (geloescht = 0 OR isnull(geloescht)) LIMIT 1");
            }else{
              $uparr[$value] = $this->app->Secure->POST[$value];
            }
          } else {
            if($value == 'bearbeiterid' || $value=='bearbeiter')
            {
              if($arr[0]['bearbeiterid'])$this->app->Secure->POST[$value] = $arr[0][$value];
              if($arr[0]['bearbeiterid'])$uparr[$value] = $arr[0][$value];
            }else{
              $this->app->Secure->POST[$value] = $arr[0][$value];
              $uparr[$value] = $arr[0][$value];
            }
          }
        }

        if($projekt!="") {
          $this->app->Secure->POST['projekt'] = $projekt;
          $uparr['projekt'] = $this->app->Secure->POST['projekt'];
        }

        $uparr['adresse']=$adresse;
        $this->app->DB->UpdateArr("anfrage",$id,"id",$uparr,true);
        $this->LoadAdresseStandard("anfrage",$id,$adresse);
      }

      function LoadPreisanfrageStandardwerte($id,$adresse,$projekt="")
      {
        /** @var Preisanfrage $obj */
        $obj = $this->app->erp->LoadModul('preisanfrage');
        if(!empty($obj) && method_exists($obj,'LoadPreisanfrageStandardwerte')) {
          $obj->LoadPreisanfrageStandardwerte($id,$adresse,$projekt);
        }
      }


      function LoadProformarechnungStandardwerte($id,$adresse,$projekt="")
      {
        // standard adresse von lieferant
        $arr = $this->app->DB->SelectArr("SELECT *,zollinformationen as verzollinformationen,if(zollinformationen!='',1,0) as verzollungadresse FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

        $field = array('anschreiben','name','abteilung','typ','unterabteilung','strasse','adresszusatz','plz','ort','land','ustid','email','telefon','telefax',
            'kundennummer','projekt','ust_befreit','lieferbedingung','titel','gln','verzollinformationen','verzollungadresse','zahlungsweise','zahlungszieltage','zahlungszieltageskonto','zahlungszielskonto');

        foreach($field as $key=>$value)
        {

          if($value=="projekt" && $this->app->Secure->POST[$value]!="")
          {
            if(!is_numeric($this->app->Secure->POST[$value]))
            {
              $uparr[$value] = $this->app->DB->Select("SELECT id FROM projekt WHERE abkuerzung <> '' AND abkuerzung = '".$this->app->DB->real_escape_string($this->app->Secure->POST[$value])."' AND (geloescht = 0 OR isnull(geloescht)) LIMIT 1");
            }else{
              $uparr[$value] = $this->app->Secure->POST[$value];
            }
          } else {
            $this->app->Secure->POST[$value] = $arr[0][$value];
            $uparr[$value] = $arr[0][$value];
          }
        }

        if($this->Firmendaten("proformarechnung_ohnebriefpapier")=="1")
          $uparr['ohne_briefpapier'] = "1";

        if($projekt!="") {
          $this->app->Secure->POST['projekt'] = $projekt;
          $uparr['projekt'] = $this->app->Secure->POST['projekt'];
        }
        $this->LoadZahlungsweise($adresse,$uparr);


        $uparr['adresse']=$adresse;
        $this->app->DB->UpdateArr("proformarechnung",$id,"id",$uparr,true);
        $this->LoadAdresseStandard("proformarechnung",$id,$adresse);
      }


  /**
   * @deprecated
   */
      function LoadKalkulationStandardwerte($id,$adresse,$projekt="")
      {
        $obj = $this->LoadModul('kalkulation');
        if(!empty($obj) && method_exists($obj,'LoadKalkulationStandardwerte'))
        {
          return $obj->LoadKalkulationStandardwerte($id,$adresse,$projekt);
        }
      }

  /**
   * @deprecated
   */
      public function LoadReisekostenStandardwerte($id,$adresse,$projekt="")
      {
        /** @var Reisekosten $obj */
        $obj = $this->LoadModul('reisekosten');
        if(!empty($obj) && method_exists($obj, 'LoadReisekostenStandardwerte'))
        {
          $obj->LoadReisekostenStandardwerte($id,$adresse,$projekt);
        }
      }

      function LoadRetoureStandardwerte($id,$adresse,$lieferantenretoure=false)
      {
        // standard adresse von lieferant
        $arr = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
        $field = array('anschreiben','name','abteilung','unterabteilung','strasse','adresszusatz','plz','ort','land','bundesstaat','ustid','email','telefon','telefax','kundennummer','projekt','ust_befreit','typ','titel','lieferbedingung');


        $rolle_projekt = $this->app->DB->Select("SELECT parameter FROM adresse_rolle WHERE adresse='$adresse' AND subjekt='Kunde' AND objekt='Projekt' AND (bis ='0000-00-00' OR bis <= NOW()) LIMIT 1");

        if($rolle_projekt > 0)
        {
          $arr[0]['projekt'] = $rolle_projekt;
        }

      foreach($field as $key=>$value)
      {

        if($value=="projekt" && $this->app->Secure->POST[$value]!="" && 0)
        {
          $uparr[$value] = $this->app->Secure->POST[$value];
        } else {
          $this->app->Secure->POST[$value] = str_replace("'", '&apos;',$arr[0][$value]);
          $uparr[$value] = str_replace("'", '&apos;',$arr[0][$value]);
        }

        }
        $uparr['adresse']=$adresse;

        if($lieferantenretoure)
        {
          $uparr['lieferant']=$adresse;
          $uparr['lieferantenretoure'] = 1;
        }

        $this->app->DB->UpdateArr("retoure",$id,"id",$uparr,true);
        $uparr=null;

        //liefernantenvorlage
        $arr = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$adresse' LIMIT 1");

        // falls von Benutzer projekt ueberladen werden soll
        $projekt_bevorzugt=$this->app->DB->Select("SELECT projekt_bevorzugen FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        if($projekt_bevorzugt=="1")
        {
          $uparr['projekt'] = $this->app->DB->Select("SELECT projekt FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
          $arr[0]['projekt'] = $uparr['projekt'];
          $this->app->Secure->POST['projekt']=$this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='".$arr[0]['projekt']."' AND id > 0 LIMIT 1");
        }

        $field = array('versandart');
        foreach($field as $key=>$value)
        {
          $uparr[$value] = $arr[0][$value];
          $this->app->Secure->POST[$value] = $arr[0][$value];
        }
        if($uparr['versandart']=="")
          $uparr['versandart']=$this->StandardVersandart($arr[0]['projekt']);

        $this->app->DB->UpdateArr('retoure', $id, 'id', $uparr, true);

        $this->LoadStandardLieferadresse($adresse,$id,"retoure");
        $this->LoadAdresseStandard("retoure",$id,$adresse);
        $this->RunHook('erpapi_loadretourestandardwerte',2, $id, $adresse);
      }

      function LoadLieferscheinStandardwerte($id,$adresse,$lieferantenretoure=false)
      {
        $obj = $this->LoadModul('lieferschein');
        if(!empty($obj) && method_exists($obj, 'LoadLieferscheinStandardwerte')){
          $obj->LoadLieferscheinStandardwerte($id,$adresse,$lieferantenretoure);
        }
      }


  /**
   * @param string $modul
   * @param int    $id
   */
  public function InfoAuftragsErfassung($modul,$id)
  {
    if(empty($modul) || empty($id)) {
      return;
    }
    $adresse = $this->app->DB->Select(
      sprintf('SELECT `adresse` FROM `%s` WHERE `id` = %d LIMIT 1', $modul, $id)
    );

    $this->app->YUI->CkEditor('readonlybox','none');
    $infoauftragserfassung = $this->app->DB->Select(
      sprintf('SELECT `infoauftragserfassung` FROM `adresse` WHERE `id`= %d LIMIT 1', $adresse)
    );
    $this->app->Tpl->Set(
        'INFOFUERAUFTRAGSERFASSUNG',
        "<fieldset><legend>Info f&uuml;r Angebots- und Auftragserfassung</legend>
          <textarea id=\"readonlybox\" rows=12>$infoauftragserfassung</textarea></fieldset>"
    );
  }

      function MarkerUseredit($feld1,$useredittimestamp)
      {
        $usereditid = str_replace("useredittimestamp","usereditid",$useredittimestamp);

        return "CONCAT($feld1,' ',IFNULL(if(TIME_TO_SEC(TIMEDIFF(NOW(), $useredittimestamp)) < 45,CONCAT('<br><font color=red><b>(in Bearbeitung von ',      (SELECT a2.name FROM user u2 LEFT JOIN adresse a2 ON a2.id=u2.adresse WHERE u2.id=$usereditid LIMIT 1),')</b></font>'),''),''))";
      }

      function TimeoutUseredit($smodule,$sid,$user)
      {
        $sid = (int)$sid;
        if($sid <= 0)return;
        $smodulea = explode(' ',$smodule);
        $smodule = $smodulea[0];
        if(!preg_match('/^[a-zA-Z0-9\_]*$/',$smodule,$trefer))
        {
          $smodule = '';
        }
        if($smodule==='')return;
        if(!in_array($smodule,
          array('adresse', 'anfrage', 'angebot', 'arbeitsnachweis', 'artikel', 'auftrag', 'bestellung', 'gutschrift', 'inventur', 'lieferschein', 'preisanfrage', 'produktion', 'proformarechnung', 'rechnung', 'retoure', 'spedition')
        ))return;
        $this->app->DB->Update("UPDATE $smodule SET useredittimestamp=NOW(),usereditid='$user' WHERE id = '$sid' AND (usereditid='$user' OR ifnull(useredittimestamp,'0000-00-00 00:00:00') = '0000-00-00 00:00:00' OR TIME_TO_SEC(TIMEDIFF(NOW(), useredittimestamp)) > 30) LIMIT 1");
        if(!$this->app->DB->error())return;//Bruno 14.12.17 Querys sparen aber bei Fehler altes Verhalten
        $useredittimestamp = $this->app->DB->Select("SELECT useredittimestamp FROM $smodule WHERE id='$sid' LIMIT 1");
        if($useredittimestamp=="0000-00-00 00:00:00" || $useredittimestamp=="")
        {
          $this->app->DB->Select("UPDATE $smodule SET useredittimestamp=NOW(),usereditid='".$user."' WHERE id='$sid' LIMIT 1");
        }

        // nur wenn timediff > 10
        $timediff = $this->app->DB->Select("SELECT TIME_TO_SEC(TIMEDIFF(NOW(), useredittimestamp)) FROM $smodule WHERE id='$sid' LIMIT 1");
        $timeuser = $this->app->DB->Select("SELECT usereditid FROM $smodule WHERE id='$sid' LIMIT 1");
        if($timeuser == $user)
        {
          $this->app->DB->Select("UPDATE $smodule SET useredittimestamp=NOW() WHERE id='$sid' LIMIT 1");
        } else
        {
          if($timediff>30)
            $this->app->DB->Select("UPDATE $smodule SET useredittimestamp=NOW(),usereditid='$user' WHERE id='$sid' LIMIT 1");
        }
      }

      function DisableModul($modul, $id, $backlink='')
      {
        // Prüfen ob Backlink mit index.php? beginnt; ansonsten ist Open Redirect möglich
        if (!empty($backlink) && strpos($backlink, 'index.php?') !== 0) {
          unset($backlink);
        }

        $user = $this->app->DB->Select("SELECT usereditid FROM $modul WHERE id='$id' LIMIT 1");
        if($this->app->DB->error())return false;
        $user_adresse = $this->app->DB->Select("SELECT adresse FROM user WHERE id='$user' LIMIT 1");
        $user_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$user_adresse' LIMIT 1");

        $this->TimeoutUseredit($modul,$id,$this->app->User->GetID());

        $timeuser = $this->app->DB->Select("SELECT usereditid FROM $modul WHERE id='$id' LIMIT 1");
        if($timeuser==$this->app->User->GetID() || $timeuser=="") // heute wieder aus dem kommentar in echten quelltext genommen
        {
          return false;
        } else if ($user_adresse > 0) {

          if($this->RechteVorhanden("welcome","unlock"))
          {
            $id = $this->app->Secure->GetGET("id");
            $open = "<input type=\"button\" value=\"Dokument &uuml;bernehmen\" onclick=\"if(!confirm('Soll diese Oberfl&auml;che wirklich &uuml;bernommen werden? Alle Aktionen werden bei dem angemeldeten Mitarbeiter abgebrochen.')) return false;else window.location.href='index.php?module=welcome&action=unlock&id=$id&gui=$modul".($backlink?"&backlink=".urlencode($backlink):'')."';\">";
          } else {
            $this->SystemLog("Fehlendes Recht",1,"","welcome","unlock");
          }

          $this->app->Tpl->Set('TAB1',"<div class=\"error\">Achtung dieses Dokument wird aktuell durch Mitarbeiter: <b>$user_name</b> bearbeitet! $open</div>");
          $this->app->Tpl->Parse('PAGE',"tabview.tpl");
          return true;
        }

      }

      function LockModule($modul = null, $action = null)
      {
        if(is_null($modul))$modul = $this->app->Secure->GetGET("module");
        if(is_null($action))$action = $this->app->Secure->GetGET("action");
        //in Modul
        //if($this->app->erp->LockModul())return;
        //benutzen
        $time = microtime(true);
        $salt = md5(microtime(true));
        $saltjs = '

        var lockalert = false;
        var lockstarttime = '.$time.';
        setInterval(function(){
            lockstarttime = lockstarttime + 1;
        },1000
        );
        $(document).ready(function() {
          $( window ).unload(function() {
             $.ajax({
                url: "index.php?module=ajax&action=moduleunlock&salt='.$salt.'"
              });
          });
          window.addEventListener("beforeunload", function(event) {
             $.ajax({
                url: "index.php?module=ajax&action=moduleunlock&salt='.$salt.'"
              });
          });

          if(typeof(Storage) !== "undefined") {
              // Code for localStorage/sessionStorage.
              setInterval(function(){



                if(!localStorage.getItem("lockedmodule"))
                {
                  var data = new Object();
                  localStorage.setItem("lockedmodule",JSON.stringify(data));


                }




                //if(localStorage.getItem("lockedmodule")){

                var lockstr = localStorage.getItem("lockedmodule");
                if(lockstr.indexOf("[") > -1)
                {
                  var data = new Object();
                  localStorage.setItem("lockedmodule",JSON.stringify(data));
                  lockstr = localStorage.getItem("lockedmodule");
                }
                var lockedmodule = JSON.parse(lockstr);
                if(typeof(lockedmodule["'.$modul.'"]) === "undefined")
                {
                  lockedmodule.'.$modul.' = new Object();
                }
                if(typeof(lockedmodule.'.$modul.'.'.$action.') === "undefined")
                {
                  lockedmodule.'.$modul.'.'.$action.' = new Object();
                }
                lockedmodule.'.$modul.'.'.$action.'.x'.$salt.' = lockstarttime;

                var ar = lockedmodule.'.$modul.'.'.$action.';
                var k;
                for (k in ar) {
                  var v = ar[k];
                  if(k === "x'.$salt.'")
                  {
                    lockedmodule.'.$modul.'.'.$action.'.x'.$salt.' = lockstarttime;

                  }else{
                    if(v > lockstarttime - 1)
                    {
                      if(!lockalert){
                        lockalert = true;
                        alert("Sie haben noch ein Tab mit diesem Modul offen!");
                      }
                    }
                    if(v < lockstarttime - 10)
                    {

                    }
                  }

                }
                var lstr = JSON.stringify(lockedmodule);
                localStorage.setItem("lockedmodule", JSON.stringify(lockedmodule));


              },1000);


          } else {
              // Sorry! No Web Storage support..
          }

        });
        ';

        if($this->app->Secure->GetPOST("unlock"))
        {
          if($this->app->erp->RechteVorhanden("welcome","unlock")){
            $this->app->DB->Delete("DELETE FROM module_lock where module like '".addslashes($modul)."' and action like '".addslashes($action)."'");
          }
        }

        if($locked = $this->app->DB->SelectRow("SELECT *, now() as aktzeit from module_lock where module like '".addslashes($modul)."' and action like '".addslashes($action)."' limit 1"))
        {
          if($locked['userid'] && $locked['userid'] != $this->app->User->GetID() && strtotime($locked['aktzeit']) - strtotime($locked['zeit']) < 300)
          {
            $user_adresse = $this->app->DB->Select("SELECT adresse FROM user WHERE id='",$locked['userid']."' LIMIT 1");
            $user_name = $this->app->DB->Select("SELECT name FROM adresse WHERE id='$user_adresse' LIMIT 1");
            if($this->RechteVorhanden("welcome","unlock"))
            {
              $id = $this->app->Secure->GetGET("id");
              //$open = "<input type=\"button\" value=\"Modul &uuml;bernehmen\" onclick=\"if(!confirm('Soll diese Oberfl&auml;che wirklich &uuml;bernommen werden? Alle Aktionen werden bei dem angemeldeten Mitarbeiter abgebrochen.')) return false;else window.location.href='index.php?module=welcome&action=unlockmodul&smodule=$modul&saction=$action';\">";
              $open = '<form method="POST" id="frmLockModul"><input type="hidden" name="unlock" value="1" /><input type="button" onclick="if(!confirm(\'Soll diese Oberfl&auml;che wirklich &uuml;bernommen werden? Alle Aktionen werden bei dem angemeldeten Mitarbeiter abgebrochen.\')) return false;else document.getElementById(\'frmLockModul\').submit();" value="Modul &uuml;bernehmen" /></form>';
            } else {
              $this->SystemLog("Fehlendes Recht",1,"","welcome","unlock");
            }

            $this->app->Tpl->Set('TAB1',"<div class=\"error\">Achtung dieses Modul wird aktuell durch Mitarbeiter: <b>$user_name</b> bearbeitet! $open</div>");
            $this->app->Tpl->Parse('PAGE',"tabview.tpl");
            return true;
          }

          $this->app->DB->Update("UPDATE module_lock set zeit = now(), userid = ".$this->app->User->GetID().", salt = '".$salt."' where module like '".addslashes($modul)."' and action like '".addslashes($action)."'");
          $this->app->Tpl->Add('JAVASCRIPT',$saltjs);
        } else {

          $this->app->DB->Insert("INSERT INTO module_lock (module, action, userid, salt,  zeit) values ('".addslashes($modul)."','".addslashes($action)."','".$this->app->User->GetID()."','".$salt."', now())");
          $this->app->Tpl->Add('JAVASCRIPT',$saltjs);
        }
        return false;
      }

  /**
   * @param int    $adresse
   * @param int    $id
   * @param string $type
   * @param int    $lieferadressenId
   */
      public function LoadStandardLieferadresse($adresse,$id,$type, $lieferadressenId = 0)
      {
        if($lieferadressenId > 0) {
          $standardlieferadresse = $this->app->DB->SelectArr(
            sprintf(
              'SELECT * FROM lieferadressen WHERE (adresse=%d OR adresse = 0) AND id=%d LIMIT 1',
              $adresse, $lieferadressenId
            )
          );
        }
        else{
          $standardlieferadresse = $this->app->DB->SelectArr("SELECT * FROM lieferadressen WHERE adresse='$adresse' AND standardlieferadresse='1' LIMIT 1");
        }

        if($standardlieferadresse[0]['id'] > 0)
        {
          foreach($standardlieferadresse[0] as $k => $v)$standardlieferadresse[0][$k] = $this->app->DB->real_escape_string($v);
          switch($type)
          {
            case "angebot":
            case "auftrag":
              $this->app->DB->Update("UPDATE $type SET abweichendelieferadresse='1',
                  liefername='".$standardlieferadresse[0]['name']."',
                  lieferabteilung='".$standardlieferadresse[0]['abteilung']."',
                  lieferunterabteilung='".$standardlieferadresse[0]['unterabteilung']."',
                  lieferland='".$standardlieferadresse[0]['land']."',
                  lieferstrasse='".$standardlieferadresse[0]['strasse']."',
                  lieferort='".$standardlieferadresse[0]['ort']."',
                  lieferplz='".$standardlieferadresse[0]['plz']."',
                  lieferadresszusatz='".$standardlieferadresse[0]['adresszusatz']."',
                  lieferansprechpartner='".$standardlieferadresse[0]['ansprechpartner']."'
                  WHERE id='$id' LIMIT 1");
              if($standardlieferadresse[0]['ustid']!="") $this->app->DB->Update("UPDATE $type SET ustid = '".$standardlieferadresse[0]['ustid']."' WHERE id='$id' LIMIT 1");
              if($standardlieferadresse[0]['ust_befreit']!="") $this->app->DB->Update("UPDATE $type SET ust_befreit = '".$standardlieferadresse[0]['ust_befreit']."' WHERE id='$id' LIMIT 1");
              if($standardlieferadresse[0]['lieferbedingung']!="") $this->app->DB->Update("UPDATE $type SET lieferbedingung = '".$standardlieferadresse[0]['lieferbedingung']."' WHERE id='$id' LIMIT 1");
              if($type == 'auftrag')$this->app->DB->Update("UPDATE $type SET liefergln = '".$standardlieferadresse[0]['gln']."' WHERE id='$id' LIMIT 1");
              if($type == 'auftrag')$this->app->DB->Update("UPDATE $type SET lieferemail = '".$standardlieferadresse[0]['email']."' WHERE id='$id' LIMIT 1");
              if($type == 'auftrag')$this->app->DB->Update("UPDATE $type SET lieferbundesstaat = '".$standardlieferadresse[0]['bundesstaat']."' WHERE id='$id' LIMIT 1");
              break;
            case "lieferschein":
              $this->app->DB->Update("UPDATE lieferschein SET
                  name='".$standardlieferadresse[0]['name']."',
                  abteilung='".$standardlieferadresse[0]['abteilung']."',
                  unterabteilung='".$standardlieferadresse[0]['unterabteilung']."',
                  land='".$standardlieferadresse[0]['land']."',
                  strasse='".$standardlieferadresse[0]['strasse']."',
                  ort='".$standardlieferadresse[0]['ort']."',
                  plz='".$standardlieferadresse[0]['plz']."',
                  adresszusatz='".$standardlieferadresse[0]['adresszusatz']."',
                  lieferbedingung='".$standardlieferadresse[0]['lieferbedingung']."',
                  ansprechpartner='".$standardlieferadresse[0]['ansprechpartner']."'
                  WHERE id='$id' LIMIT 1");
              $this->app->DB->Update("UPDATE $type SET gln = '".$standardlieferadresse[0]['gln']."' WHERE id='$id' LIMIT 1");
              $this->app->DB->Update("UPDATE $type SET bundesstaat = '".$standardlieferadresse[0]['bundesstaat']."' WHERE id='$id' LIMIT 1");
              break;

          }
        }
      }

      function DisableVerband()
      {
        $module = $this->app->Secure->GetGET('module');
        $id = $this->app->Secure->GetGET('id');
        if($id <= 0 || !in_array($module,['angebot', 'auftrag', 'rechnung', 'gutschrift'])) {
          return;
        }
        if($module=="angebot" || $module=="auftrag" || $module=="rechnung" || $module=="gutschrift")
        {
          $docArr = $this->app->DB->SelectRow(
            sprintf(
              'SELECT realrabatt, gruppe, adresse FROM `%s`WHERE id = %d',
              $module, $id
            )
          );

          $rabatt = !empty($docArr)?$docArr['realrabatt']: $this->app->DB->Select("SELECT realrabatt FROM $module b LEFT JOIN adresse a ON a.id=b.adresse WHERE b.id='$id' LIMIT 1");
          $gruppe = !empty($docArr)?$docArr['gruppe']:$this->app->DB->Select("SELECT gruppe FROM $module b WHERE b.id='$id' LIMIT 1");
          $adresse = !empty($docArr)?$docArr['adresse']:$this->app->DB->Select("SELECT adresse FROM $module WHERE id='$id' LIMIT 1");
          $rabatte_festschreiben = $this->app->DB->Select("SELECT rabatte_festschreiben FROM adresse WHERE id='".$adresse."' LIMIT 1");
          if($rabatt > 0 && $gruppe > 0)//CLAUDI && $this->Firmendaten("modul_verband")=="1")
          {
            if($rabatte_festschreiben=='1' && $gruppe<=0){
              $this->app->Tpl->Set('RABATTANZEIGE', " <br><font color=red>Kundenrabatt: $rabatt%</font>");
            }
            else {
              if($this->Firmendaten('modul_verband')=='1') //CLAUDI
              {
                $this->app->Tpl->Set('RABATTANZEIGE'," <br><font color=red>Verbandsrabatt: $rabatt%</font>");
              }
              else {
                $this->app->Tpl->Set('RABATTANZEIGE'," <br><font color=red>Preisgruppenrabatt: $rabatt%</font>");
              }
            }
          } else {
            $this->app->Tpl->Set('STARTDISABLEVERBAND',"<!--");
            $this->app->Tpl->Set('ENDEDISABLEVERBAND',"-->");
          }

          //if(($rabatte_festschreiben!="1" && $gruppe > 0) || $gruppe > 0) // ANZEIGE VERBAND wenn definiert
          if($gruppe > 0) {
            $gruppenArr = $this->app->DB->SelectRow(
              sprintf(
                "SELECT CONCAT(name,' ',kennziffer) AS name, internebemerkung 
                FROM gruppen 
                WHERE id=%d",
                $gruppe
              )
            );
            $gruppe = !empty($docArr)?$docArr['gruppe']:$this->app->DB->Select("SELECT gruppe FROM $module WHERE id='$id' LIMIT 1");
            $gruppe_name = !empty($gruppenArr)?$gruppenArr['name']: $this->app->DB->Select("SELECT CONCAT(name,' ',kennziffer) FROM gruppen WHERE id='$gruppe' LIMIT 1");
            $gruppeinternebemerkung = !empty($gruppenArr)?$gruppenArr['internebemerkung']:$this->app->DB->Select("SELECT internebemerkung FROM gruppen WHERE id='$gruppe' LIMIT 1");
            $this->app->Tpl->Set('VERBANDINFO',"<textarea cols=\"80\" rows=\"15\" id=\"readonlybox2\">$gruppeinternebemerkung</textarea>");
          }
          else {
            $gruppe_name = '';
            $rabattinformation = $this->app->DB->Select("SELECT rabattinformation FROM adresse WHERE id='$adresse' LIMIT 1");
            $this->app->Tpl->Set('VERBANDINFO',"<textarea cols=\"80\" rows=\"15\" id=\"readonlybox2\">$rabattinformation</textarea>");
          }

          if($this->RechteVorhanden($module,'deleterabatte')) {
            $this->app->Tpl->Set('VERBAND',"<input type=\"text\" value=\"$gruppe_name\" size=\"38\" readonly>&nbsp;<input type=\"button\"
                onclick=\"if(!confirm('Wirklich die Verbandsinformation neu laden?')) return false; else window.location.href='index.php?module=".$module."&action=updateverband&id=".$id."';\"
                value=\"Verband neu laden\">");
          }
          else {
            $this->app->Tpl->Set('VERBAND',"<input type=\"text\" value=\"$gruppe_name\" size=\"38\" readonly>");
          }
        }
      }


      // prueft ob adresse eine filiale ist wenn wird der beleg gekennzeichnet
      function LoadAdresseProjektfiliale($table,$id,$adresse)
      {
        $check = $this->app->DB->Select("SELECT id FROM projekt WHERE filialadresse='$adresse' LIMIT 1");
        if($check > 0)
        {
          $this->app->DB->Update("UPDATE $table SET projektfiliale=1 WHERE id='$id'");
        } else {
          $this->app->DB->Update("UPDATE $table SET projektfiliale=0 WHERE id='$id'");
        }
      }

      function LoadAdresseStandard($table,$id,$adresse)
      {

        if($table=="auftrag" || $table=="rechnung" || $table=="gutschrift" || $table=="lieferschein" || $table=="anfrage" || $table=="produktion" || $table=="bestellung" || $table=="preisanfrage" || $table=="proformarechnung" || $table=="angebot")
        {
          $firma = $this->app->DB->Select("SELECT firma FROM $table WHERE id='$id' LIMIT 1");
          if($firma <=0)
          {
            $firma = $this->app->DB->Select("SELECT MAX(f.id) FROM firma f INNER JOIN firmendaten fd ON f.id = fd.firma LIMIT 1");
            if(!$firma)$firma = $this->app->DB->Select("SELECT max(id) FROM firma LIMIT 1");
            if($firma<=0)$firma = $this->app->DB->Select("SELECT MAX(id) FROM firma LIMIT 1");
            $this->app->DB->Update("UPDATE $table SET firma='$firma' WHERE id='$id' LIMIT 1");
          }
          //Sprache
          $sprache = $this->app->DB->Select("SELECT sprache FROM adresse WHERE id = '$adresse' LIMIT 1");

          if($sprache)$this->app->DB->Update("UPDATE $table SET sprache = '".$this->app->DB->real_escape_string($sprache)."' WHERE id = '$id' LIMIT 1");
          if($table == "auftrag" || $table == "rechnung" || $table == "gutschrift" || $table == "lieferschein" || $table == "angebot" || $table=="proformarechnung")
          {
            $kundennummer = $this->app->DB->Select("SELECT kundennummer FROM adresse WHERE id = '$adresse' LIMIT 1");

            if($kundennummer)$this->app->DB->Update("UPDATE $table SET kundennummer = '".$this->app->DB->real_escape_string($kundennummer)."' WHERE id = '$id' LIMIT 1");

          }elseif($table == "bestellung")
          {
            $kundennummerlieferant = $this->app->DB->Select("SELECT kundennummerlieferant FROM adresse WHERE id = '$adresse' LIMIT 1");
            if($kundennummerlieferant)$this->app->DB->Update("UPDATE $table SET kundennummerlieferant = '".$this->app->DB->real_escape_string($kundennummerlieferant)."' WHERE id = '$id' LIMIT 1");
          }

          $this->LoadAdresseProjektfiliale($table,$id,$adresse);

          $checkemail = $this->app->DB->Select("SELECT ".($table==='rechnung' || $table === 'proformarechnung'?'rechnungs':$table)."_email FROM adresse WHERE id='$adresse' LIMIT 1");
          if($checkemail!="") $this->app->DB->Update("UPDATE $table SET email='$checkemail' WHERE id='$id' LIMIT 1");
        }
      }

      function LoadAuftragStandardwerte($id,$adresse,$lieferantenauftrag=false)
      {
        // standard adresse von lieferant
        $arr = $this->app->DB->SelectArr("SELECT *,vertrieb as vertriebid,'' as bearbeiter,innendienst as bearbeiterid FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

        if($arr[0]['bearbeiterid'] <=0 )
          $arr[0]['bearbeiterid'] = $this->app->User->GetAdresse();

        $arr[0]['gruppe'] = $this->GetVerband($adresse);
        $field = array('anschreiben','name','vorname','abteilung','ansprechpartner','unterabteilung','strasse','adresszusatz','plz','ort','land','bundesstaat','ustid','email','telefon','telefax','kundennummer','projekt','ust_befreit','gruppe','typ','vertriebid','bearbeiter','gln','bearbeiterid','titel','lieferbedingung');


        $rolle_projekt = $this->app->DB->Select("SELECT parameter FROM adresse_rolle WHERE adresse='$adresse'   AND subjekt='Kunde' AND objekt='Projekt' AND (bis ='0000-00-00' OR bis <= NOW()) LIMIT 1");

        if($rolle_projekt > 0)
        {
          $arr[0]['projekt'] = $rolle_projekt;
        }


        foreach($field as $key=>$value)
        {
          if($value=="projekt" && $this->app->Secure->POST[$value]!="" && 0) // immer projekt von adresse
          {
            $uparr[$value] = str_replace("'", '&apos;',$this->app->Secure->POST[$value]);
          } else {
            $this->app->Secure->POST[$value] = $arr[0][$value];
            $uparr[$value] = str_replace("'", '&apos;',$arr[0][$value]);
          }
        }


      $uparr['adresse']=$adresse;
      if($lieferantenauftrag) $uparr['lieferant']=$adresse;

        $this->app->DB->UpdateArr("auftrag",$id,"id",$uparr,true);
        $uparr=null;

        //liefernantenvorlage
        $arr = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$adresse' LIMIT 1");
        if($lieferantenauftrag && $arr) $arr[0]['lieferantkdrnummer']=$arr[0]['lieferantennummer'];
        if(!$lieferantenauftrag && $arr) $arr[0]['lieferantkdrnummer']=$arr[0]['kundennummer'];
        // falls von Benutzer projekt ueberladen werden soll
        $projekt_bevorzugt=$this->app->DB->Select("SELECT projekt_bevorzugen FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        if($projekt_bevorzugt=="1")
        {
          $uparr['projekt'] = $this->app->DB->Select("SELECT projekt FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
          $arr[0]['projekt'] = $uparr['projekt'];
          $arr[0]['standardlager'] = $this->app->DB->Select("SELECT standardlager FROM projekt WHERE id='".$uparr['projekt']."' LIMIT 1");
          $this->app->Secure->POST['projekt']=$this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='".$arr[0]['projekt']."' AND id > 0 LIMIT 1");
        }

        $field = array('zahlungsweise','zahlungszieltage','zahlungszieltageskonto','zahlungszielskonto','versandart');

        $this->LoadZahlungsweise($adresse,$arr);

        if($arr[0]['versandart']==''){
          $arr[0]['versandart'] = $this->StandardVersandart($arr[0]['projekt']);
        }

        $this->app->Secure->POST['zahlungsweise'] = strtolower($arr[0]['zahlungsweise']);
        $this->app->Secure->POST['zahlungszieltage'] = strtolower($arr[0]['zahlungszieltage']);
        $this->app->Secure->POST['zahlungszieltageskonto'] = strtolower($arr[0]['zahlungszieltageskonto']);
        $this->app->Secure->POST['zahlungszielskonto'] = strtolower($arr[0]['zahlungszielskonto']);
        $this->app->Secure->POST['versandart'] = strtolower($arr[0]['versandart']);

        foreach($arr[0] as $k => $v)
        {
          if(strpos((String)$v, "'") !== false)$arr[0][$k] = str_replace("'", '&apos;',$v);
        }
        if(isset($arr[0]['usereditid']))unset($arr[0]['usereditid']);
        $this->app->DB->UpdateArr("auftrag",$id,"id",$arr[0], true);

        // must after called after UpdateArr auftrag because ustid can overridden by StandardLieferadresse
        $this->LoadStandardLieferadresse($adresse,$id,"auftrag");

        $this->LoadSteuersaetzeWaehrung($id,"auftrag");

        $this->LoadAdresseStandard("auftrag",$id,$adresse);
        $this->app->DB->Update("
        UPDATE auftrag a 
        INNER JOIN adresse adr ON a.lieferant = adr.id 
        SET a.lieferantkdrnummer = if(a.lieferantennummer <> '',a.lieferantennummer,adr.lieferantennummer)
        WHERE a.lieferantkdrnummer = '' AND a.lieferantenauftrag = 1 AND a.id = '$id'
        ");
        $this->app->DB->Update("
        UPDATE auftrag a 
        INNER JOIN adresse adr ON a.adresse = adr.id 
        SET a.lieferantkdrnummer = if(a.kundennummer <> '',a.kundennummer, adr.kundennummer)
        WHERE a.lieferantkdrnummer = '' AND a.lieferantenauftrag = 0 AND a.id = '$id'
        ");
        if($arr[0]['art'])$this->app->DB->Update("UPDATE auftrag SET art = '".$this->app->DB->real_escape_string($arr[0]['art'])."' WHERE id = '$id' LIMIT 1");


        $projekt = $this->app->DB->Select("SELECT projekt FROM auftrag WHERE id = '$id' LIMIT 1");
        $deactivateAutoversand = (int)$this->app->erp->Projektdaten($projekt,'deactivateautoshipping');
        if($deactivateAutoversand) {
          $this->app->DB->Update(
            sprintf(
              'UPDATE auftrag SET autoversand = 0 WHERE schreibschutz = 0 AND id = %d',
              $id
            )
          );
        }else{
          $this->app->DB->Update(
            sprintf(
              'UPDATE auftrag SET autoversand = 1 WHERE schreibschutz = 0 AND id = %d',
              $id
            )
          );
        }

        $this->AuftragEinzelnBerechnen($id);
        $this->RunHook('erpapi_loadauftragstandardwerte',3, $id, $adresse, $lieferantenauftrag);
      }

      function GetKategorienbaum(&$baum, $parent = 0, $lvl = 0, $shop = 0)
      {
        if($lvl > 30)return;
        $sprachen = $this->GetSelectSprachenListe(true);
        $elemente = $this->app->DB->SelectArr("SELECT ak.id, ak.parent, ak.bezeichnung, sk.extid FROM artikelkategorien ak 
        LEFT JOIN `shopexport_kategorien` sk ON ak.id = sk.kategorie AND sk.shop = '$shop' AND sk.shop > 0 AND sk.aktiv = 1
        WHERE (ak.geloescht = 0 OR isnull(ak.geloescht)) AND ak.parent = '$parent' ORDER BY ak.bezeichnung");
        if($elemente)
        {
          foreach($elemente as $el)
          {
            $el['lvl'] = $lvl;
            $uebersetzungen = $this->app->DB->SelectArr("SELECT beschriftung,sprache FROM uebersetzung WHERE label='kategorie_".$el['id']."'");
            $texte = array();
            if(is_array($uebersetzungen)){
              foreach ($uebersetzungen as $index => $sprachenarray){
                $kategoriesprache = $sprachenarray['sprache'];
                if(array_key_exists(ucfirst($sprachenarray['sprache']),$sprachen)){
                  $kategoriesprache = $sprachen[ucfirst($sprachenarray['sprache'])];
                }
                $texte[$kategoriesprache] = $sprachenarray['beschriftung'];
              }
            }
            $el['texte'] = $texte;
            $baum[] = $el;
            $this->GetKategorienbaum($baum, $el['id'], $lvl + 1, $shop);
          }
        }
      }

      function LoadZahlungsweise($adresse,&$arr)
      {
        //$arr = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$adresse' LIMIT 1");

        if($arr[0]['zahlungsweise']=="")
          $arr[0]['zahlungsweise']=$this->Firmendaten("zahlungsweise");

        if($arr[0]['zahlungsweise']=="")
          $arr[0]['zahlungsweise']="vorkasse";

        if($arr[0]['zahlungszieltage']==="" && $arr[0]['zahlungsweise']=="rechnung")
          $arr[0]['zahlungszieltage']=$this->ZahlungsZielTage();

        if($arr[0]['zahlungszieltageskonto']==="" && $arr[0]['zahlungsweise']=="rechnung")
          $arr[0]['zahlungszieltageskonto']=$this->ZahlungsZielTageSkonto();

        if($arr[0]['zahlungszielskonto']==="" && $arr[0]['zahlungsweise']=="rechnung")
          $arr[0]['zahlungszielskonto']=$this->ZahlungsZielSkonto();

      }


      function LoadAngebotStandardwerte($id,$adresse)
      {
        // standard adresse von lieferant
        $arr = $this->app->DB->SelectArr("SELECT *,vertrieb as vertriebid,'' as bearbeiter,innendienst as bearbeiterid FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

        if($arr[0]['bearbeiterid'] <=0 )
          $arr[0]['bearbeiterid'] = $this->app->User->GetAdresse();

        $arr[0]['gruppe'] = $this->GetVerband($adresse);

        $rolle_projekt = $this->app->DB->Select("SELECT parameter FROM adresse_rolle WHERE adresse='$adresse' AND subjekt='Kunde' AND objekt='Projekt' AND (bis ='0000-00-00' OR bis <= NOW()) LIMIT 1");

        if($rolle_projekt > 0)
        {
          $arr[0]['projekt'] = $rolle_projekt;
        }

        $field = array('gln','anschreiben','name','abteilung','unterabteilung','strasse','adresszusatz','plz','ort','land','ustid','ust_befreit','email','telefon','telefax','projekt','ansprechpartner','gruppe','typ','vertriebid','bearbeiter','bearbeiterid','titel','lieferbedingung');
        foreach($field as $key=>$value)
        {
          if($value=="projekt" && $this->app->Secure->POST[$value]!="" && 0)
          {
            $uparr[$value] = str_replace("'", '&apos;',$this->app->Secure->POST[$value]);
          } else {
            $this->app->Secure->POST[$value] = str_replace("'", '&apos;',$arr[0][$value]);
            $uparr[$value] = str_replace("'", '&apos;',$arr[0][$value]);
          }
        }
        $uparr['adresse'] = $adresse;
        $this->app->DB->UpdateArr("angebot",$id,"id",$uparr,true);
        $uparr=null;

        //liefernantenvorlage
        $arr = $this->app->DB->SelectArr("SELECT * FROM adresse WHERE id='$adresse' LIMIT 1");
        $this->LoadZahlungsweise($adresse,$arr);

        if($arr[0]['versandart']==''){
          $arr[0]['versandart'] = $this->StandardVersandart($arr[0]['projekt']);
        }

        // falls von Benutzer projekt ueberladen werden soll
        $projekt_bevorzugt=$this->app->DB->Select("SELECT projekt_bevorzugen FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        if($projekt_bevorzugt=="1")
        {
          $uparr['projekt'] = $this->app->DB->Select("SELECT projekt FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
          $arr[0]['projekt'] = $uparr['projekt'];
          $arr[0]['standardlager'] = $this->app->DB->Select("SELECT standardlager FROM projekt WHERE id='".$uparr['projekt']."' LIMIT 1");
          $this->app->Secure->POST['projekt']=$this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='".$arr[0]['projekt']."' AND id > 0 LIMIT 1");
        }

        $this->app->Secure->POST['zahlungsweise'] = strtolower($arr[0]['zahlungsweise']);
        $this->app->Secure->POST['zahlungszieltage'] = strtolower($arr[0]['zahlungszieltage']);
        $this->app->Secure->POST['zahlungszieltageskonto'] = strtolower($arr[0]['zahlungszieltageskonto']);
        $this->app->Secure->POST['zahlungszielskonto'] = strtolower($arr[0]['zahlungszielskonto']);
        $this->app->Secure->POST['versandart'] = strtolower($arr[0]['versandart']);

        if(isset($arr[0]['usereditid']))unset($arr[0]['usereditid']);
        $this->app->DB->UpdateArr("angebot",$id,"id",$arr[0],true);
        $this->LoadStandardLieferadresse($adresse,$id,"angebot");

        $this->LoadSteuersaetzeWaehrung($id,"angebot");

        $this->LoadAdresseStandard("angebot",$id,$adresse);
      }

      function LoadGutschriftStandardwerte($id,$adresse)
      {
        $obj = $this->LoadModul('gutschrift');
        if(!empty($obj) && method_exists($obj,'LoadGutschriftStandardwerte'))
        {
          return $obj->LoadGutschriftStandardwerte($id, $adresse);
        }
      }


    function BerechneDeckungsbeitrag($id,$typ,$extern=false)
    {

        // mit rabatt beruecksichtigen
        if($typ==='rechnung' || $typ==='gutschrift' || $typ==='auftrag' || $typ==='angebot')
        {
          $waehrungProjekt = $this->app->DB->SelectRow(
            sprintf(
              "SELECT waehrung, projekt,steuersatz_normal, steuersatz_ermaessigt 
                FROM `%s`
                WHERE id=%d 
                LIMIT 1",
              $typ, (int)$id
            )
          );
          $waehrung = $waehrungProjekt['waehrung'];
          $projectId = $waehrungProjekt['projekt'];
          $steuersatzNormal = $waehrungProjekt['steuersatz_normal'];
          $steuersatzErmaessigt = $waehrungProjekt['steuersatz_ermaessigt'];
          $method = ucfirst($typ).'MitUmsatzsteuer';
          if(!method_exists($this, $method)) {
            $method = ucfirst($typ).'MitUmsatzeuer';
          }
          $mitumsatzsteuer = method_exists($this, $method)? $this->$method($id):true;
          if(!$mitumsatzsteuer) {
            $steuersatzNormal = 0;
            $steuersatzErmaessigt = 0;
          }
          $preisberechnung = $this->Projektdaten($projectId,'preisberechnung');
          if($waehrung == '') {
            $waehrung = 'EUR';
          }
          $ohneeks = $this->app->DB->SelectArr("SELECT id, artikel, menge, preis, rabatt, ekwaehrung, einkaufspreis, waehrung FROM {$typ}_position ap WHERE 	 $typ = '$id' ");
          if($this->app->DB->error()){
            $ohneeks = $this->app->DB->SelectArr("SELECT id, artikel, menge, preis, rabatt, ekwaehrung, einkaufspreis FROM {$typ}_position ap WHERE 	 $typ = '$id' ");
          }
          if(!empty($ohneeks))
          {
            foreach($ohneeks as $ek)
            {
              if($ek['einkaufspreis'] == 0)
              {
                $originalwaehrung = $ek['waehrung'];
                $originalpreis = $ek['preis'];
                $ekpreis = (double)$this->GetEinkaufspreisWaehrung($ek['artikel'],$ek['menge'],$waehrung,$originalwaehrung, $originalpreis);
                if($originalwaehrung == '')$originalwaehrung = 'EUR';
                switch($typ)
                {
                  case "rechnung": $explodiertspalte = "explodiert_parent_artikel"; break;
                  default: $explodiertspalte = "explodiert_parent";
                }
                $this->app->DB->Update("UPDATE {$typ}_position SET ekwaehrung = '$originalwaehrung', einkaufspreisurspruenglich = '$originalpreis', einkaufspreis = '$ekpreis' WHERE id = '".$ek['id']."' AND $explodiertspalte = 0 AND einkaufspreis=0 LIMIT 1");

              }else{
                $ekpreis = $ek['einkaufspreis'];
              }
              $pdeckungsbeitrag = $ek['preis']*(100-$ek['rabatt'])/100;
              $pdeckungsbeitrag =  ($pdeckungsbeitrag != 0)?(($pdeckungsbeitrag - $ekpreis) / $pdeckungsbeitrag):1;
              $this->app->DB->Update("UPDATE {$typ}_position SET deckungsbeitrag = '$pdeckungsbeitrag' WHERE id = '".$ek['id']."' LIMIT 1");
            }
            if($preisberechnung == 3){
              $sql = sprintf(
                'UPDATE `%s` 
                SET umsatz_netto_einzeln = ROUND(preis * (1 - rabatt / 100),2),
                umsatz_netto_gesamt = ROUND(menge * ROUND(preis * (1 - rabatt / 100),2), 2),
                umsatz_brutto_einzeln = ROUND(preis * (1 - rabatt / 100),2)  *
                    (1 + IF(
                    IFNULL(steuersatz,-1) < 0,
                    IF(
                      umsatzsteuer = \'befreit\',
                      0,
                      IF(umsatzsteuer = \'ermaessigt\',
                        %f,
                        %f
                      )
                    ),
                    steuersatz 
                  ) / 100),
                umsatz_brutto_gesamt = ROUND(menge * ROUND(preis * (1 - rabatt / 100),2), 2)  *
                    (1 + IF(
                    IFNULL(steuersatz,-1) < 0,
                    IF(
                      umsatzsteuer = \'befreit\',
                      0,
                      IF(umsatzsteuer = \'ermaessigt\',
                        %f,
                        %f
                      )
                    ),
                    steuersatz 
                  ) / 100)
                WHERE `%s` = %d',
                  $typ . '_position',
                $steuersatzErmaessigt,
                $steuersatzNormal,
                $steuersatzErmaessigt,
                $steuersatzNormal,
                $typ,
                $id);
            }elseif($preisberechnung == 1) {
              $sql = sprintf(
                  'UPDATE `%s` 
                SET umsatz_netto_einzeln = preis * (1 - rabatt / 100),
                umsatz_netto_gesamt = ROUND(menge * preis * (1 - rabatt / 100), 2),
                umsatz_brutto_einzeln = preis * (1 - rabatt / 100) * 
                  (1 + IF(
                    IFNULL(steuersatz,-1) < 0,
                    IF(
                      umsatzsteuer = \'befreit\',
                      0,
                      IF(umsatzsteuer = \'ermaessigt\',
                        %f,
                        %f
                      )
                    ),
                    steuersatz 
                  ) / 100),
                umsatz_brutto_gesamt = ROUND(menge * preis * (1 - rabatt / 100), 2) *
                    (1 + IF(
                    IFNULL(steuersatz,-1) < 0,
                    IF(
                      umsatzsteuer = \'befreit\',
                      0,
                      IF(umsatzsteuer = \'ermaessigt\',
                        %f,
                        %f
                      )
                    ),
                    steuersatz 
                  ) / 100)
                WHERE `%s` = %d',
                  $typ . '_position',
                  $steuersatzErmaessigt,
                  $steuersatzNormal,
                  $steuersatzErmaessigt,
                  $steuersatzNormal,
                  $typ,
                  $id
              );
            }else{
              $sql = sprintf(
                  'UPDATE `%s` 
                SET umsatz_netto_einzeln = preis * (1 - rabatt / 100),
                umsatz_netto_gesamt = menge * preis * (1 - rabatt / 100),
                umsatz_brutto_einzeln = preis * (1 - rabatt / 100)  *
                    (1 + 
                    IF(
                      IFNULL(steuersatz,-1) < 0,
                      IF(
                        umsatzsteuer = \'befreit\',
                        0,
                        IF(umsatzsteuer = \'ermaessigt\',
                          %f,
                          %f
                        )
                      ),
                      steuersatz 
                    ) / 100),
                umsatz_brutto_gesamt = menge * preis * (1 - rabatt / 100) *
                    (1 + IF(
                    IFNULL(steuersatz,-1) < 0,
                    IF(
                      umsatzsteuer = \'befreit\',
                      0,
                      IF(umsatzsteuer = \'ermaessigt\',
                        %f,
                        %f
                      )
                    ),
                    steuersatz 
                  ) / 100)
                WHERE `%s` = %d',
                  $typ . '_position',
                  $steuersatzErmaessigt,
                  $steuersatzNormal,
                  $steuersatzErmaessigt,
                  $steuersatzNormal,
                  $typ,
                  $id
              );
            }
            $this->app->DB->Update($sql);
          }

        $status=$this->app->DB->Select("SELECT status FROM $typ WHERE id='$id' LIMIT 1");
        $deckungsbeitragcalc=$this->app->DB->Select("SELECT deckungsbeitragcalc FROM $typ WHERE id='$id' LIMIT 1");
        //wenn im richtigen status oder noch nicht berechnet
        if(1)//($status!="storniert" && $status!="versendet" && $status!="abgeschlossen") || $deckungsbeitragcalc!="1")
        {
          $deckungsbeitrag = 0;
          $deckungsbeitragprozent = 0;
          $belegnr = $this->app->DB->Select("SELECT belegnr FROM $typ WHERE id='$id' LIMIT 1");
          if(!$extern)
            $this->Protokoll(strtoupper($typ)." BELEG $belegnr");

          $anzahlStellen = ($this->app->erp->Firmendaten('viernachkommastellen_belege')?4:2);
          if($preisberechnung == 3) {
            if($typ === 'angebot')
            {
              $einnahmen = $this->app->DB->Select(
                sprintf(
                  "SELECT SUM(ap.menge*ROUND(ap.preis*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)),%d))
                  FROM `%s` auf 
                  INNER JOIN `%s` ap ON ap.`%s`=auf.id  
                  WHERE auf.id=%d AND ap.optional <> 1 AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1),0))",
                  $anzahlStellen, $typ, $typ.'_position', $typ, (int)$id
                )
              );
            }else{
              $einnahmen = $this->app->DB->Select(sprintf(
                "SELECT SUM(ap.menge*ROUND(ap.preis*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)),%d))
                  FROM `%s` auf 
                  INNER JOIN `%s` ap ON ap.`%s`=auf.id 
                  WHERE auf.id=%d",
                  $anzahlStellen, $typ, $typ.'_position', $typ, (int)$id
                )
              );
            }
          }elseif($preisberechnung == 1) {

            if($typ === 'angebot')
            {
              $einnahmen = $this->app->DB->Select(
                sprintf(
                  "SELECT SUM(ROUND(ap.preis*ap.menge*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)),%d))
                  FROM `%s` auf 
                  INNER JOIN `%s` ap ON ap.`%s`=auf.id  
                  WHERE auf.id=%d AND ap.optional <> 1 AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1),0))",
                  $anzahlStellen, $typ, $typ.'_position', $typ, (int)$id
                )
              );
            }else{
              $einnahmen = $this->app->DB->Select(sprintf(
                "SELECT SUM(ROUND(ap.preis*ap.menge*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)),%d))
                  FROM `%s` auf 
                  INNER JOIN `%s` ap ON ap.`%s`=auf.id 
                  WHERE auf.id=%d",
                  $anzahlStellen, $typ, $typ.'_position', $typ, (int)$id
                )
              );
            }
          }else{
            if($typ === 'angebot')
            {
              $einnahmen = $this->app->DB->Select(
                sprintf(
                  "SELECT SUM(ap.preis*ap.menge*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)))
                  FROM `%s` auf 
                  INNER JOIN `%s` ap ON ap.`%s`=auf.id  
                  WHERE auf.id=%d AND ap.optional <> 1 AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1),0))",
                  $typ, $typ.'_position', $typ, (int)$id
                )
              );
            }else{
              $einnahmen = $this->app->DB->Select(sprintf(
                "SELECT SUM(ap.preis*ap.menge*(IF(ap.rabatt > 0, (100-ap.rabatt)/100, 1)))
                  FROM `%s` auf 
                  INNER JOIN `%s` ap ON ap.`%s`=auf.id 
                  WHERE auf.id=%d",
                  $typ, $typ.'_position', $typ, (int)$id
                )
              );
            }
          }


          $this->app->DB->Update(
            sprintf(
            "UPDATE `%s` 
               SET deckungsbeitragcalc=1,
                   deckungsbeitrag=%f,
                   erloes_netto=%f,
                   umsatz_netto=%f
               WHERE id= %d 
               LIMIT 1"
              ,$typ,(float)$deckungsbeitragprozent,(float)$deckungsbeitrag,(float)$einnahmen ,(int)$id
            )
          );
        }
      }
      $this->RunHook('BerechneDeckungsbeitragEnde', 3, $id, $typ, $extern);
    }


      function LoadRechnungStandardwerte($id,$adresse)
      {
        /** @var Rechnung $obj */
        $obj = $this->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'LoadRechnungStandardwerte')){
          return $obj->LoadRechnungStandardwerte($id, $adresse);
        }
      }

      function LoadBestellungStandardwerte($id,$adresse)
      {
        /** @var Bestellung $obj */
        $obj = $this->LoadModul('bestellung');
        if(!empty($obj) && method_exists($obj, 'LoadBestellungStandardwerte'))
        {
          $obj->LoadBestellungStandardwerte($id, $adresse);
        }
      }

      function CreateArbeitsnachweis($adresse="",$projekt="")
      {
        /** @var Arbeitsnachweis $obj */
        $obj = $this->app->erp->LoadModul('arbeitsnachweis');
        if(!empty($obj) && method_exists($obj, 'CreateArbeitsnachweis')) {
          return $obj->CreateArbeitsnachweis($adresse,$projekt);
        }
        return 0;
      }


      function CreateInventur($adresse="")
      {
        /** @var Inventur $obj */
        $obj = $this->LoadModul('inventur');
        if(!empty($obj) && method_exists($obj, 'CreateInventur'))
        {
          return $obj->CreateInventur($adresse);
        }
        return 0;
      }




      function CreateAnfrage($adresse='')
      {
        $projekt = $this->GetCreateProjekt($adresse);

        $belegmax = '';
        $ohnebriefpapier = 1;
        $this->app->DB->Insert("INSERT INTO anfrage (id,datum,bearbeiter,firma,belegnr,adresse,ohne_briefpapier,bearbeiterid,projekt)
            VALUES ('',NOW(),'".$this->app->User->GetName()."','".$this->app->User->GetFirma()."','$belegmax','$adresse','".$ohnebriefpapier."',
              '".$this->app->User->GetAdresse()."','$projekt')");

        $id = $this->app->DB->GetInsertID();
        $this->LoadSteuersaetzeWaehrung($id,"anfrage");

        $this->SchnellFreigabe("anfrage",$id);

        $this->EventAPIAdd("EventAnfrageCreate",$id,"anfrage","create");
        return $id;
      }

      function SchnellFreigabe($beleg,$id)
      {
        if($id <= 0 || empty($beleg) || $this->app->erp->Firmendaten('schnellanlegen_ohnefreigabe')!='1') {
          return;
        }
        $doc = $this->app->DB->SelectRow(sprintf('SELECT `projekt`, `status`, `belegnr` FROM `%s` WHERE `id` = %d', $beleg, $id));
        if(
            empty($doc)
          || ($doc['status'] === 'freigegeben' && (string)$doc['belegnr'] !== '0' && (string)$doc['belegnr'] !=='')
        ) {
          return;
        }

        $projekt = $doc['projekt'];
        $belegnr = (String)$doc['belegnr'];
        $status = $doc['status'];
        if($belegnr === '' || $belegnr === '0') {
          $belegnr = $this->app->erp->GetNextNummer($beleg,$projekt,$id);
        }
        $this->app->DB->Update("UPDATE $beleg SET datum=NOW(),belegnr='$belegnr', status='freigegeben' WHERE id='$id' LIMIT 1");
        $methodname = ucfirst($beleg).'Protokoll';
        if(method_exists($this,$methodname) && $status != 'freigegeben') {
          $this->app->erp->$methodname($id,ucfirst($beleg).' freigegeben');
        }

        // automatisch eine wiedervorlage anlegen
        if($beleg === 'angebot') {
          $this->AngebotWiedervorlage($id);
        }
        if($beleg === 'auftrag') {
          $this->app->DB->Update(
            sprintf(
              'UPDATE `artikel` AS `a` 
              INNER JOIN `auftrag_position` AS `ap` ON a.id = ap.artikel AND (a.lagerartikel = 1 OR a.juststueckliste = 1) 
              SET a.`laststorage_changed` = NOW() WHERE `ap`.auftrag = %d', $id
            )
          );
        }
      }

      function SetXMLRechnung($id)
      {
        $obj = $this->app->erp->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'SetXMLRechnung')) {
          return $obj->SetXMLRechnung($id);
        }
        return 0;
      }

      function GetXMLRechnung($id)
      {
        $obj = $this->app->erp->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'RechnungSmarty')) {
          return $obj->RechnungSmarty(id: $id, returnvalue: true);
        }
        return 0;
      }

      function BelegFreigabe($beleg,$id)
      {
        if($id <= 0 || empty($beleg)) {
          return;
        }
        $doc = $this->app->DB->SelectRow(sprintf('SELECT `projekt`, `status`, `belegnr` FROM `%s` WHERE `id` = %d', $beleg, $id));
        if(
            empty($doc)
          || ($doc['status'] === 'freigegeben' && (string)$doc['belegnr'] !== '0' && (string)$doc['belegnr'] !=='')
        ) {
          return;
        }

        $projekt = $doc['projekt'];
        $belegnr = (String)$doc['belegnr'];
        $status = $doc['status'];
        if($belegnr === '' || $belegnr === '0') {
          $belegnr = $this->app->erp->GetNextNummer($beleg,$projekt,$id);
        }

        if(!empty($this->app->User) && method_exists($this->app->User, 'GetParameter')
          &&  $this->app->User->GetParameter($beleg."_create_entwurfsdatumuebernehmen")=='1'){
          $this->app->DB->Update("UPDATE $beleg SET belegnr='$belegnr', `status`='freigegeben' WHERE id='$id' LIMIT 1");
        }
        else{
          $this->app->DB->Update("UPDATE $beleg SET datum=NOW(),belegnr='$belegnr', `status`='freigegeben' WHERE id='$id' LIMIT 1");
        }

        // schutzt fals kein Datum gefunden
        $this->app->DB->Update("UPDATE $beleg SET datum=NOW() WHERE id='$id' AND (datum='0000-00-00' OR datum='1970-01-01' OR datum IS NULL OR datum='') LIMIT 1");

        $methodname = ucfirst($beleg).'Protokoll';
        if(method_exists($this,$methodname) && $status != 'freigegeben') {
          $this->app->erp->$methodname($id,ucfirst($beleg).' freigegeben');
        }

        if($status != 'freigeben') {
          $_beleg = $beleg;
          $_id = $id;
          $this->RunHook('BelegFreigabe', 2, $_beleg, $_id);
        }

        // automatisch eine wiedervorlage anlegen
        if($beleg=='angebot') {
          $this->AngebotWiedervorlage($id);
        }
        if($beleg === 'auftrag') {
          $this->app->DB->Update(
            sprintf(
              'UPDATE `artikel` AS `a` 
              INNER JOIN `auftrag_position` AS `ap` ON a.id = ap.artikel AND (a.lagerartikel = 1 OR a.juststueckliste = 1) 
              SET a.`laststorage_changed` = NOW() WHERE `ap`.auftrag = %d', $id
            )
          );
        }
        if ($beleg === 'rechnung') {        
          $this->SetXMLRechnung($id);
        }
      }

      function CreateWiedervorlage($adresse,$bezeichnung,$beschreibung,$intagen=30,$adresse_mitarbeiter=0,$bearbeiter=0,$typ="",$typid=0)
      {
        if($adresse_mitarbeiter <=0)
          $adresse_mitarbeiter = $this->app->User->GetAdresse();

        if($bearbeiter <= 0)
          $bearbeiter = $this->app->User->GetAdresse();

        $this->app->DB->Insert("INSERT INTO wiedervorlage (
           datum_angelegt, zeit_angelegt,datum_erinnerung, zeit_erinnerung, bezeichnung,beschreibung,abgeschlossen,bearbeiter,adresse_mitarbeiter,module,parameter,adresse) values (
           DATE_FORMAT(NOW(),'%Y-%m-%d'),DATE_FORMAT(NOW(),'%h:%i:00'),DATE_ADD(NOW(), INTERVAL ".$intagen." DAY),
           DATE_FORMAT(NOW(),'%h:%i:00'),'".$this->app->DB->real_escape_string( $bezeichnung)."',
                '".$this->app->DB->real_escape_string( $beschreibung)."','0','$bearbeiter','$adresse_mitarbeiter','$typ','$typid','$adresse')"
           );

        return $this->app->DB->GetInsertID();
      }



      function AngebotWiedervorlage($id)
      {
        if($this->Firmendaten('angebot_anzahlwiedervorlage')<=0) {
          return;
        }
        $check = $this->app->DB->Select("SELECT id FROM wiedervorlage WHERE module='angebot' AND parameter='$id' LIMIT 1");
        if($check > 0) {
          return;
        }

        $angebot_pipewiedervorlage = $this->Firmendaten("angebot_pipewiedervorlage");
        $angebot_pipewiedervorlage = strstr($angebot_pipewiedervorlage, ' ', true);
        if(!is_numeric($angebot_pipewiedervorlage)) $angebot_pipewiedervorlage = 0;

          $belegnr  = $this->app->DB->Select("SELECT belegnr FROM angebot WHERE id='$id' LIMIT 1");

          $bezeichnung = "Nachfassen beim Angebot $belegnr";
          $beschreibung = "Nachfassen beim Angebot";

          $adresse = $this->app->DB->Select("SELECT adresse FROM angebot WHERE id='$id' LIMIT 1");

          $adresse_mitarbeiter = $this->app->DB->Select("SELECT vertriebid FROM angebot WHERE id='$id' LIMIT 1");
          if($adresse_mitarbeiter <=0) $adresse_mitarbeiter = $this->app->User->GetAdresse();

          $bearbeiter = $this->app->User->GetAdresse();

          $projekt = $this->app->DB->Select("SELECT projekt FROM angebot WHERE id = '$id' LIMIT 1");

          $this->app->DB->Insert("INSERT INTO wiedervorlage (
              datum_angelegt, zeit_angelegt,datum_erinnerung, zeit_erinnerung, bezeichnung,beschreibung,abgeschlossen,bearbeiter,adresse_mitarbeiter,module,parameter,adresse,stages,projekt) values (
              DATE_FORMAT(NOW(),'%Y-%m-%d'),DATE_FORMAT(NOW(),'%h:%i:00'),DATE_ADD(NOW(), INTERVAL ".$this->Firmendaten("angebot_anzahlwiedervorlage")." DAY),DATE_FORMAT(NOW(),'%h:%i:00'),'".$this->app->DB->real_escape_string( $bezeichnung)."',
              '".$this->app->DB->real_escape_string( $beschreibung)."','0','$bearbeiter','$adresse_mitarbeiter','angebot','$id','$adresse','$angebot_pipewiedervorlage','$projekt')"
         );
      }

      function CreatePreisanfrage($adresse="")
      {
        /** @var Preisanfrage $obj */
        $obj = $this->app->erp->LoadModul('preisanfrage');
        if(!empty($obj) && method_exists($obj,'CreatePreisanfrage')) {
          return $obj->CreatePreisanfrage($adresse);
        }
        return 0;
      }


      function CreateProformarechnung($adresse="")
      {
        $projekt = $this->GetCreateProjekt($adresse);

        $belegmax = "";
        $ohnebriefpapier = $this->Firmendaten("proformarechnung_ohnebriefpapier");
        $this->app->DB->Insert("INSERT INTO proformarechnung (id,datum,bearbeiter,firma,belegnr,adresse,ohne_briefpapier,bearbeiterid,projekt,zollinformation)
            VALUES ('',NOW(),'".$this->app->User->GetName()."','".$this->app->User->GetFirma()."','$belegmax','$adresse','".$ohnebriefpapier."',
              '".$this->app->User->GetAdresse()."','$projekt',1)");

        $id = $this->app->DB->GetInsertID();
        $this->LoadSteuersaetzeWaehrung($id,"proformarechnung");
        $this->EventAPIAdd("EventAnfrageCreate",$id,"proformarechnung","create");
        return $id;
      }


      function CreateKalkulation($adresse="")
      {
        /** @var Kalkulation $obj */
        $obj = $this->LoadModul('kalkulation');
        if(!empty($obj) && method_exists($obj,'CreateKalkulation')) {
          return $obj->CreateKalkulation($adresse);
        }
        return null;
      }

  /**
   * @deprecated
   */
      public function CreateReisekosten($adresse='')
      {
        /** @var Reisekosten $obj */
        $obj = $this->LoadModul('reisekosten');
        if(!empty($obj) && method_exists($obj,'CreateReisekosten'))
        {
          return $obj->CreateReisekosten($adresse);
        }
        return 0;
      }

      function ZeitSollDatumArbeit($adresse,$datum)
      {
        $erg = $this->app->DB->Select('SELECT stunden FROM mitarbeiterzeiterfassung_sollstunden WHERE datum = "' . $datum . '"
          AND adresse = "' . $adresse . '" LIMIT 1');
        if($erg<=0) $erg=0;
        return $erg;
      }


      function AnzahlWerktageMonat($datum="")
      {
        if($datum=="")
          $query_date = date('Y-m-d');
        else $query_date=$datum;

        // First day of the month.
        $first =  date('Y-m', strtotime($query_date));

        // Last day of the month.
        $last = date('t', strtotime($query_date));

        $anzahlwerktage=0;
        for($day=1;$day<=$last;$day++)
        {
          $checkday = date('w',strtotime($first."-".$day));

          if($checkday!=0 && $checkday!=6)
            $anzahlwerktage++;
        }
        return $anzahlwerktage;
      }

      function ZeitGesamtDatumArbeitAbrechnen($adresse,$datum)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art LIKE 'Arbeit'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')='$datum' AND z.adresse='$adresse' AND z.abrechnen=1";

        $erg=$this->app->DB->Select($sql);
        if($erg<=0) $erg=0;
        return $erg;
      }
      function ZeitGesamtAufgabe($id,$adresse=0)
      {

        if($adresse<=0)
        {
          $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art LIKE 'Arbeit' AND z.aufgabe_id='$id'";
        } else {
          $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art LIKE 'Arbeit' AND z.aufgabe_id='$id' AND z.adresse='$adresse'";
        }

        $erg=$this->app->DB->Select($sql);
        if($erg<=0) $erg=0;
        return $erg;
      }




      function ZeitGesamtDatumArbeit($adresse,$datum)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')='$datum' AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg<=0) $erg=0;
        return $erg;
      }

      function ZeitGesamtHeuteArbeit($adresse)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')=DATE_FORMAT(NOW(),'%Y-%m-%d') AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg<=0) $erg=0;
        return $erg;
      }

      function ZeitGesamtArbeit($adresse,$datum)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')=DATE_FORMAT('$datum','%Y-%m-%d') AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg<=0) $erg=0;
        return $erg;
      }


      function ZeitGesamtDatumPause($adresse,$datum)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')='$datum' AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg <=0) $erg=0;
        return $erg;
      }


      function ZeitGesamtHeutePause($adresse)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')=DATE_FORMAT(NOW(),'%Y-%m-%d') AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg <=0) $erg=0;
        return $erg;
      }

      function ZeitGesamtPause($adresse,$datum)
      {
        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m-%d')=DATE_FORMAT('$datum','%Y-%m-%d') AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg <=0) $erg=0;
        return $erg;
      }



      function ZeitGesamtWocheIst($adresse,$jahr="",$kw="",$datum="")
      {
        if($datum!="")
        {
          $jahr = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%Y')");
          $kw = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%u')");
        }

      if($jahr=="") $jahr=date('Y');
      if($kw=="") $kw=date('W');

        $kw = str_pad($kw, 2, "0", STR_PAD_LEFT);

        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%v')='".$jahr."-".$kw."' AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg <=0) $erg=0;
        return $erg;
      }

      function ZeitGesamtMonatIst($adresse,$jahr="",$monat="",$datum="")
      {
        if($datum!="")
        {
          $jahr = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%Y')");
          $monat = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%m')");
        }

        if($jahr=="") $jahr=date('Y');
        if($monat=="") $monat=date('m');

        $monat = str_pad($monat, 2, "0", STR_PAD_LEFT);

        $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
          AND DATE_FORMAT(z.von,'%Y-%m')='".$jahr."-".$monat."' AND z.adresse='$adresse'";

        $erg=$this->app->DB->Select($sql);
        if($erg <=0) $erg=0;
        return $erg;
      }


      function ZeitGesamtWocheSoll($adresse,$jahr="",$kw="",$datum="")
      {
        return $this->GetArbeitszeitWoche($adresse,$jahr,$kw,$datum);
      }

      function ZeitGesamtWocheOffen($adresse,$jahr="",$kw="",$datum="")
      {
        $ist=$this->ZeitGesamtWocheIst($adresse,$jahr,$kw,$datum);
        $soll=$this->ZeitGesamtWocheSoll($adresse,$jahr,$kw,$datum);
        return $soll-$ist;
      }

    function ZeitUrlaubOffen($adresse, $datum)
    {
      $monat = date('m',  strtotime($datum));
      $jahr = date('Y', strtotime($datum));
      if($this->ModulVorhanden('zeiterfassung_stundenuebersicht'))
      {
        if(!$jahr || !$monat)
        {
          $monat = date('m',  strtotime($datum));
          $jahr = date('Y', strtotime($datum));
        }


        $stundenprowoche = $this->app->DB->Select("SELECT stundenprowoche FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $ueberstundentoleranz = $this->app->DB->Select("SELECT ueberstundentoleranz FROM zeiterfassung_stundenuebersicht_jahre wHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $urlaubimjahr = $this->app->DB->Select("SELECT urlaubimjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $restueberstunden = $this->app->DB->Select("SELECT ueberstundenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $resturlaub = $this->app->DB->Select("SELECT urlaubvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
          $restnotiz = $this->app->DB->Select("SELECT notizenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          if($stundenprowoche == ""){
            $stundenprowoche = 0;
          }
          if($ueberstundentoleranz == ""){
            $ueberstundentoleranz = 0;
          }
          if($urlaubimjahr == ""){
            $urlaubimjahr = 0;
          }

          if($restueberstunden == ""){
            $restueberstunden = 0;
          }
          if($resturlaub == ""){
            $resturlaub = 0;
          }


          $stundenausadresse = $this->app->DB->Select("SELECT arbeitszeitprowoche FROM adresse WHERE id='$adresse' AND id>0");
          if($stundenprowoche <=0 && $stundenausadresse >0)
            $stundenprowoche = $stundenausadresse;

          $this->app->Tpl->Set("STUNDENWOCHE", $stundenprowoche);
          $this->app->Tpl->Set("TOLERANZ", $ueberstundentoleranz);
          $this->app->Tpl->Set("URLAUBJAHR", $urlaubimjahr);

          $this->app->Tpl->Set("RESTUEBERSTUNDEN", $restueberstunden);
          $this->app->Tpl->Set("RESTURLAUB", $resturlaub);
          $this->app->Tpl->Set("RESTNOTIZ", $restnotiz);

          $gesamtsummesoll = $this->app->DB->Select("SELECT SUM(soll) FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");


          for($i = 1; $i<13; $i++){

            //IST
            $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
              AND DATE_FORMAT(z.von,'%Y-%m')='".$jahr."-".($i < 10?'0':'').$i."' AND z.adresse='$adresse'";

            $aist2[$i] = $this->app->DB->Select($sql);

            if($aist2[$i] <= 0){
              $aist2[$i] = 0;
            }

            $aist2[$i] = number_format($aist2[$i], 2, '.', '');

            if($gesamtsummesoll != 0){
              //SOLL
              $asoll2[$i] = $this->app->DB->Select("SELECT soll FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");
              $asoll2[$i] = number_format($asoll2[$i], 2, '.', '');
            }else{
              if($stundenprowoche != ""){
                $asoll2[$i] = $this->app->erp->AnzahlWerktageMonat($jahr."-".str_pad($i, 2, "0", STR_PAD_LEFT)."-"."1")*$stundenprowoche/5;

                //NOCH IN DIE DATENBANK SPEICHERN
                $asoll2[$i] = number_format($asoll2[$i], 2, '.', '');
              }else{
                $asoll2[$i] = 0.00;
              }
            }

            //EINGELÖSTE ÜBERSTUNDEN
            $aueberstunden2[$i] = $this->app->DB->Select("SELECT ueberstunden_eingeloest FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");
            $aueberstunden2[$i] = number_format($aueberstunden2[$i], 2, '.', '');

            //EINGELÖSTER URLAUB
            $aurlaub2[$i] = $this->app->DB->Select("SELECT urlaub_eingeloest FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");
            $aurlaub2[$i] = number_format($aurlaub2[$i], 2, '.', '');

            //NOTIZEN
            $anotizen2[$i] = $this->app->DB->Select("SELECT notizen FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");


            if($aist2[$i] == 0){
              $differenz_stunden2[$i] = -$asoll2[$i];
            }else{
              $differenz_stunden2[$i] = $aist2[$i] - $asoll2[$i];
            }



            $differenz_stunden2[$i] = number_format($differenz_stunden2[$i], 2, '.', '');

            if($aist2[$i] == 0){
              $stunden_minus_toleranz2[$i] = -$asoll2[$i];
            }else{
              if($differenz_stunden2[$i] <= $ueberstundentoleranz){
                $stunden_minus_toleranz2[$i] = 0;
              }else{
                $stunden_minus_toleranz2[$i] = $differenz_stunden2[$i] - $ueberstundentoleranz;
              }
            }


            $stunden_minus_toleranz2[$i] = number_format($stunden_minus_toleranz2[$i], 2, '.', '');

            {
              if($i == 1){
                $ueberstunden_aktuell2[$i] = $restueberstunden;
                $ueberstunden_aktuell2[0] = $restueberstunden;
              }



            if($stunden_minus_toleranz2[$i] > 0.00){
              //$ueberstunden_aktuell2[$i] += $stunden_minus_toleranz2[$i];
            }

            //if($aueberstunden2[$i] != "" && $aueberstunden2[$i] > 0.00){
            if($aist2[$i]>0.00){
              $ueberstunden_aktuell2[$i] = $ueberstunden_aktuell2[$i-1] - $aueberstunden2[$i] + $stunden_minus_toleranz2[$i];

            }else{
              if($stunden_minus_toleranz2[$i]>0.00){
                $ueberstunden_aktuell2[$i] = $ueberstunden_aktuell2[$i-1] - $aueberstunden2[$i] - $asoll2[$i] + $stunden_minus_toleranz2[$i];
              }else{
                $ueberstunden_aktuell2[$i] = $ueberstunden_aktuell2[$i-1] - $aueberstunden2[$i] - $asoll2[$i];

              }
            }
          }
          $ueberstunden_aktuell2[$i] = number_format($ueberstunden_aktuell2[$i], 2, '.', '');

          if($i == 1){
            $urlaub_aktuell2[0] = $resturlaub + $urlaubimjahr;
          }
          $urlaub_aktuell2[$i] = $urlaub_aktuell2[$i-1] - $aurlaub2[$i];
          $urlaub_aktuell2[$i] = number_format($urlaub_aktuell2[$i], 2, '.', '');
          if($i == (int)$monat)return $urlaub_aktuell2[$i];
        }
      }

      return 0;
    }

    function ZeitUrlaubGenommen($adresse, $datum)
    {
      if($this->ModulVorhanden('zeiterfassung_stundenuebersicht'))
      {
        if(!$jahr || !$monat)
        {
          $monat = date('m',  strtotime($datum));
          $jahr = date('Y', strtotime($datum));
        }


        $stundenprowoche = $this->app->DB->Select("SELECT stundenprowoche FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $ueberstundentoleranz = $this->app->DB->Select("SELECT ueberstundentoleranz FROM zeiterfassung_stundenuebersicht_jahre wHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $urlaubimjahr = $this->app->DB->Select("SELECT urlaubimjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $restueberstunden = $this->app->DB->Select("SELECT ueberstundenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $resturlaub = $this->app->DB->Select("SELECT urlaubvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
          $restnotiz = $this->app->DB->Select("SELECT notizenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          if($stundenprowoche == ""){
            $stundenprowoche = 0;
          }
          if($ueberstundentoleranz == ""){
            $ueberstundentoleranz = 0;
          }
          if($urlaubimjahr == ""){
            $urlaubimjahr = 0;
          }

          if($restueberstunden == ""){
            $restueberstunden = 0;
          }
          if($resturlaub == ""){
            $resturlaub = 0;
          }


          $stundenausadresse = $this->app->DB->Select("SELECT arbeitszeitprowoche FROM adresse WHERE id='$adresse' AND id>0");
          if($stundenprowoche <=0 && $stundenausadresse >0)
            $stundenprowoche = $stundenausadresse;

          $this->app->Tpl->Set("STUNDENWOCHE", $stundenprowoche);
          $this->app->Tpl->Set("TOLERANZ", $ueberstundentoleranz);
          $this->app->Tpl->Set("URLAUBJAHR", $urlaubimjahr);

          $this->app->Tpl->Set("RESTUEBERSTUNDEN", $restueberstunden);
          $this->app->Tpl->Set("RESTURLAUB", $resturlaub);
          $this->app->Tpl->Set("RESTNOTIZ", $restnotiz);

          $gesamtsummesoll = $this->app->DB->Select("SELECT SUM(soll) FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $eingeloest = 0;
          for($i = 1; $i<13; $i++){

            //IST
            $sql = "SELECT SUM((TIMESTAMPDIFF(SECOND,z.von, z.bis))/3600) FROM `zeiterfassung` z WHERE z.art NOT LIKE 'Pause'
              AND DATE_FORMAT(z.von,'%Y-%m')='".$jahr."-".($i < 10?'0':'').$i."' AND z.adresse='$adresse'";

            $aist2[$i] = $this->app->DB->Select($sql);

            if($aist2[$i] <= 0){
              $aist2[$i] = 0;
            }

            $aist2[$i] = number_format($aist2[$i], 2, '.', '');

            if($gesamtsummesoll != 0){
              //SOLL
              $asoll2[$i] = $this->app->DB->Select("SELECT soll FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");
              $asoll2[$i] = number_format($asoll2[$i], 2, '.', '');
            }else{
              if($stundenprowoche != ""){
                $asoll2[$i] = $this->app->erp->AnzahlWerktageMonat($jahr."-".str_pad($i, 2, "0", STR_PAD_LEFT)."-"."1")*$stundenprowoche/5;

                //NOCH IN DIE DATENBANK SPEICHERN
                $asoll2[$i] = number_format($asoll2[$i], 2, '.', '');
              }else{
                $asoll2[$i] = 0.00;
              }
            }

            //EINGELÖSTE ÜBERSTUNDEN
            $aueberstunden2[$i] = $this->app->DB->Select("SELECT ueberstunden_eingeloest FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");
            $aueberstunden2[$i] = number_format($aueberstunden2[$i], 2, '.', '');

            //EINGELÖSTER URLAUB
            $aurlaub2[$i] = $this->app->DB->Select("SELECT urlaub_eingeloest FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");
            $aurlaub2[$i] = number_format($aurlaub2[$i], 2, '.', '');
            $eingeloest += $aurlaub2[$i];
            //NOTIZEN
            $anotizen2[$i] = $this->app->DB->Select("SELECT notizen FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$i\" AND jahr = \"$jahr\"");


            if($aist2[$i] == 0){
              $differenz_stunden2[$i] = -$asoll2[$i];
            }else{
              $differenz_stunden2[$i] = $aist2[$i] - $asoll2[$i];
            }



            $differenz_stunden2[$i] = number_format($differenz_stunden2[$i], 2, '.', '');

            if($aist2[$i] == 0){
              $stunden_minus_toleranz2[$i] = -$asoll2[$i];
            }else{
              if($differenz_stunden2[$i] <= $ueberstundentoleranz){
                $stunden_minus_toleranz2[$i] = 0;
              }else{
                $stunden_minus_toleranz2[$i] = $differenz_stunden2[$i] - $ueberstundentoleranz;
              }
            }


            $stunden_minus_toleranz2[$i] = number_format($stunden_minus_toleranz2[$i], 2, '.', '');

            {
              if($i == 1){
                $ueberstunden_aktuell2[$i] = $restueberstunden;
                $ueberstunden_aktuell2[0] = $restueberstunden;
              }



            if($stunden_minus_toleranz2[$i] > 0.00){
              //$ueberstunden_aktuell2[$i] += $stunden_minus_toleranz2[$i];
            }

            //if($aueberstunden2[$i] != "" && $aueberstunden2[$i] > 0.00){
            if($aist2[$i]>0.00){
              $ueberstunden_aktuell2[$i] = $ueberstunden_aktuell2[$i-1] - $aueberstunden2[$i] + $stunden_minus_toleranz2[$i];

            }else{
              if($stunden_minus_toleranz2[$i]>0.00){
                $ueberstunden_aktuell2[$i] = $ueberstunden_aktuell2[$i-1] - $aueberstunden2[$i] - $asoll2[$i] + $stunden_minus_toleranz2[$i];
              }else{
                $ueberstunden_aktuell2[$i] = $ueberstunden_aktuell2[$i-1] - $aueberstunden2[$i] - $asoll2[$i];

              }
            }
          }
          $ueberstunden_aktuell2[$i] = number_format($ueberstunden_aktuell2[$i], 2, '.', '');

          if($i == 1){
            $urlaub_aktuell2[0] = $resturlaub + $urlaubimjahr;
          }
          $urlaub_aktuell2[$i] = $urlaub_aktuell2[$i-1] - $aurlaub2[$i];
          $urlaub_aktuell2[$i] = number_format($urlaub_aktuell2[$i], 2, '.', '');
          if($i == (int)$monat)return $eingeloest;
        }
      }

      return 0;
    }

    function ZeitGesamtMonatSoll($adresse, $jahr = "", $monat = "",$datum="")
    {
      if($datum!="")
      {
        $jahr = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%Y')");
        $monat = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%m')");
      }
      if($this->ModulVorhanden('mitarbeiterzeiterfassung') && $this->app->DB->Select("SELECT id FROM mitarbeiterzeiterfassung_einstellungen WHERE adresse = '$adresse' LIMIT 1"))
      {
        if(!$jahr || !$monat)
        {
          $urlaubkrankheitsstunden = (float)$this->app->DB->Select("SELECT sum(minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden WHERE  adresse = '$adresse' AND month(datum) = month(now()) and year(datum) = year(now()) AND (instr(kuerzel,'U') OR instr(kuerzel,'K'))");

          $urlaubkrankheitsstunden += (float)$this->app->DB->Select("SELECT sum(ms.minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden ms
          INNER JOIN (SELECT distinct datum FROM arbeitsfreietage) a ON a.datum = ms.datum
          WHERE  ms.adresse = '$adresse' AND month(ms.datum) = month(now()) and year(ms.datum) = year(now()) AND NOT (instr(ms.kuerzel,'U') OR instr(ms.kuerzel,'K'))");
          $mitarbeiterzeiterfassung_sollstunden = $this->app->DB->Select("SELECT sum(minuten) / 60 as wochenstunden FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND month(datum) = month(now()) and year(datum) = year(now())");
          if($mitarbeiterzeiterfassung_sollstunden)return $mitarbeiterzeiterfassung_sollstunden-$urlaubkrankheitsstunden;
        }else{
          $urlaubkrankheitsstunden = (float)$this->app->DB->Select("SELECT sum(minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND month(datum) = $monat and year(datum) = $jahr AND (instr(kuerzel,'U') OR instr(kuerzel,'K'))");
          $urlaubkrankheitsstunden += (float)$this->app->DB->Select("SELECT sum(ms.minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden ms
          INNER JOIN (SELECT distinct datum FROM arbeitsfreietage) a ON a.datum = ms.datum
          WHERE  ms.adresse = '$adresse' AND month(ms.datum) = $monat and year(ms.datum) = $jahr AND NOT (instr(ms.kuerzel,'U') OR instr(ms.kuerzel,'K'))");
          $mitarbeiterzeiterfassung_sollstunden = $this->app->DB->Select("SELECT sum(minuten) / 60 as wochenstunden FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND month(datum) = $monat and year(datum) = $jahr");
          if($mitarbeiterzeiterfassung_sollstunden)return $mitarbeiterzeiterfassung_sollstunden-$urlaubkrankheitsstunden;
        }
      }elseif($this->ModulVorhanden('zeiterfassung_stundenuebersicht'))
      {
        if(!$jahr || !$monat)
        {
          $monat = date('m',  strtotime($datum));
          $jahr = date('Y', strtotime($datum));
        }
        $stundenprowoche = $this->app->DB->Select("SELECT stundenprowoche FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $ueberstundentoleranz = $this->app->DB->Select("SELECT ueberstundentoleranz FROM zeiterfassung_stundenuebersicht_jahre wHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $urlaubimjahr = $this->app->DB->Select("SELECT urlaubimjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $restueberstunden = $this->app->DB->Select("SELECT ueberstundenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $resturlaub = $this->app->DB->Select("SELECT urlaubvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
          $restnotiz = $this->app->DB->Select("SELECT notizenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          if($stundenprowoche == ""){
            $stundenprowoche = 0;
          }
          if($ueberstundentoleranz == ""){
            $ueberstundentoleranz = 0;
          }
          if($urlaubimjahr == ""){
            $urlaubimjahr = 0;
          }

          if($restueberstunden == ""){
            $restueberstunden = 0;
          }
          if($resturlaub == ""){
            $resturlaub = 0;
          }


          $stundenausadresse = $this->app->DB->Select("SELECT arbeitszeitprowoche FROM adresse WHERE id='$adresse' AND id>0");
          if($stundenprowoche <=0 && $stundenausadresse >0)
            $stundenprowoche = $stundenausadresse;

          $gesamtsummesoll = $this->app->DB->Select("SELECT SUM(soll) FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

        if($gesamtsummesoll != 0){
          $asoll2 = $this->app->DB->Select("SELECT soll FROM zeiterfassung_stundenuebersicht WHERE adresse = \"$adresse\" AND monat = \"$monat\" AND jahr = \"$jahr\"");
          return number_format($asoll2, 2, '.', '');
        }
        if($stundenprowoche != ""){
          $asoll2 = $this->app->erp->AnzahlWerktageMonat($jahr."-".str_pad($monat, 2, "0", STR_PAD_LEFT)."-"."1")*$stundenprowoche/5;
          return number_format($asoll2, 2, '.', '');
        }
        return 0.00;
      }
      return $this->AnzahlWerktageMonat()*$this->ZeitGesamtWocheSoll($adresse)/5;
    }

    function GetArbeitszeitTag($adresse,$datum="")
    {
      if($datum!="")
      {
        $jahr = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%Y')");
        $kw = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%u')");
      }
      if($this->ModulVorhanden('mitarbeiterzeiterfassung'))
      {
        if($datum!="")
        {
          $urlaubkrankheitsstunden = (float)$this->app->DB->Select("SELECT sum(minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND datum = '$datum' AND (instr(kuerzel,'U') OR instr(kuerzel,'K'))");
          $urlaubkrankheitsstunden += (float)$this->app->DB->Select("SELECT sum(ms.minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden ms
          INNER JOIN (SELECT distinct datum FROM arbeitsfreietage) a ON a.datum = ms.datum
          WHERE ms.adresse = '$adresse' AND datum='$datum' AND not (instr(ms.kuerzel,'U') OR instr(ms.kuerzel,'K'))");
          $mitarbeiterzeiterfassung_sollstunden = $this->app->DB->Select("SELECT sum(minuten) / 60 as wochenstunden FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND datum='$datum'");
          if($mitarbeiterzeiterfassung_sollstunden)return $mitarbeiterzeiterfassung_sollstunden-$urlaubkrankheitsstunden;
        }else{
          $urlaubkrankheitsstunden = (float)$this->app->DB->Select("SELECT sum(minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND datum='$datum' AND (instr(kuerzel,'U') OR instr(kuerzel,'K'))");
          $urlaubkrankheitsstunden += (float)$this->app->DB->Select("SELECT sum(ms.minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden ms
          INNER JOIN (SELECT distinct datum FROM arbeitsfreietage) a ON a.datum = ms.datum
          WHERE ms.adresse = '$adresse' AND datum='$datum' AND not (instr(ms.kuerzel,'U') OR instr(ms.kuerzel,'K'))");
          $mitarbeiterzeiterfassung_sollstunden = $this->app->DB->Select("SELECT sum(minuten) / 60 as wochenstunden FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND datum='$datum'");
          if($mitarbeiterzeiterfassung_sollstunden)return $mitarbeiterzeiterfassung_sollstunden-$urlaubkrankheitsstunden;
        }
      }elseif($this->ModulVorhanden('zeiterfassung_stundenuebersicht'))
      {
        if(!$jahr || !$monat)
        {
          $monat = date('m',  strtotime($datum));
          $jahr = date('Y', strtotime($datum));
        }


        $stundenprowoche = $this->app->DB->Select("SELECT stundenprowoche/5 FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $ueberstundentoleranz = $this->app->DB->Select("SELECT ueberstundentoleranz FROM zeiterfassung_stundenuebersicht_jahre wHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $urlaubimjahr = $this->app->DB->Select("SELECT urlaubimjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $restueberstunden = $this->app->DB->Select("SELECT ueberstundenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $resturlaub = $this->app->DB->Select("SELECT urlaubvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
          $restnotiz = $this->app->DB->Select("SELECT notizenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          if($stundenprowoche == ""){
            $stundenprowoche = 0;
          }
          if($ueberstundentoleranz == ""){
            $ueberstundentoleranz = 0;
          }
          if($urlaubimjahr == ""){
            $urlaubimjahr = 0;
          }

        if($restueberstunden == ""){
          $restueberstunden = 0;
        }
        if($resturlaub == ""){
          $resturlaub = 0;
        }
        $stundenausadresse = $this->app->DB->Select("SELECT arbeitszeitprowoche/5 FROM adresse WHERE id='$adresse' AND id>0");
        if($stundenprowoche <=0 && $stundenausadresse >0)
          $stundenprowoche = $stundenausadresse;
        return $stundenprowoche;
      }

      $arbeitszeitprowoche = $this->app->DB->Select("SELECT arbeitszeitprowoche/5 FROM adresse WHERE id='$adresse' LIMIT 1");
      if($arbeitszeitprowoche<=0 || !is_numeric($arbeitszeitprowoche)) {
        return 0;
      }
      return $arbeitszeitprowoche;
    }



    function GetArbeitszeitWoche($adresse,$jahr,$kw,$datum="")
    {
      if($datum!="")
      {
        $jahr = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%Y')");
        $kw = $this->app->DB->Select("SELECT DATE_FORMAT('$datum','%u')");
      }
      if($this->ModulVorhanden('mitarbeiterzeiterfassung'))
      {
        if(!$jahr || !$kw)
        {
          $urlaubkrankheitsstunden = (float)$this->app->DB->Select("SELECT sum(minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND week(datum,3) = week(now(),3) and year(datum) = year(now()) AND (instr(kuerzel,'U') OR instr(kuerzel,'K'))");
          $urlaubkrankheitsstunden += (float)$this->app->DB->Select("SELECT sum(ms.minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden ms
          INNER JOIN (SELECT distinct datum FROM arbeitsfreietage) a ON a.datum = ms.datum
          WHERE ms.adresse = '$adresse' AND week(ms.datum,3) = week(now(),3) and year(ms.datum) = year(now()) AND not (instr(ms.kuerzel,'U') OR instr(ms.kuerzel,'K'))");
          $mitarbeiterzeiterfassung_sollstunden = $this->app->DB->Select("SELECT sum(minuten) / 60 as wochenstunden FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND week(datum,3) = week(now(),3) and year(datum) = year(now())");
          if($mitarbeiterzeiterfassung_sollstunden)return $mitarbeiterzeiterfassung_sollstunden-$urlaubkrankheitsstunden;
        }else{
          $urlaubkrankheitsstunden = (float)$this->app->DB->Select("SELECT sum(minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND week(datum,3) = $kw and year(datum) = $jahr AND (instr(kuerzel,'U') OR instr(kuerzel,'K'))");
          $urlaubkrankheitsstunden += (float)$this->app->DB->Select("SELECT sum(ms.minuten)/60 FROM mitarbeiterzeiterfassung_sollstunden ms
          INNER JOIN (SELECT distinct datum FROM arbeitsfreietage) a ON a.datum = ms.datum
          WHERE ms.adresse = '$adresse' AND week(ms.datum,3) = $kw and year(ms.datum) = $jahr AND not (instr(ms.kuerzel,'U') OR instr(ms.kuerzel,'K'))");
          $mitarbeiterzeiterfassung_sollstunden = $this->app->DB->Select("SELECT sum(minuten) / 60 as wochenstunden FROM mitarbeiterzeiterfassung_sollstunden WHERE adresse = '$adresse' AND week(datum,3) = $kw and year(datum) = $jahr");
          if($mitarbeiterzeiterfassung_sollstunden)return $mitarbeiterzeiterfassung_sollstunden-$urlaubkrankheitsstunden;
        }
      }elseif($this->ModulVorhanden('zeiterfassung_stundenuebersicht'))
      {
        if(!$jahr || !$monat)
        {
          $monat = date('m',  strtotime($datum));
          $jahr = date('Y', strtotime($datum));
        }


        $stundenprowoche = $this->app->DB->Select("SELECT stundenprowoche FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $ueberstundentoleranz = $this->app->DB->Select("SELECT ueberstundentoleranz FROM zeiterfassung_stundenuebersicht_jahre wHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
        $urlaubimjahr = $this->app->DB->Select("SELECT urlaubimjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $restueberstunden = $this->app->DB->Select("SELECT ueberstundenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          $resturlaub = $this->app->DB->Select("SELECT urlaubvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");
          $restnotiz = $this->app->DB->Select("SELECT notizenvorjahr FROM zeiterfassung_stundenuebersicht_jahre WHERE adresse = \"$adresse\" AND jahr = \"$jahr\"");

          if($stundenprowoche == ""){
            $stundenprowoche = 0;
          }
          if($ueberstundentoleranz == ""){
            $ueberstundentoleranz = 0;
          }
          if($urlaubimjahr == ""){
            $urlaubimjahr = 0;
          }

        if($restueberstunden == ""){
          $restueberstunden = 0;
        }
        if($resturlaub == ""){
          $resturlaub = 0;
        }
        $stundenausadresse = $this->app->DB->Select("SELECT arbeitszeitprowoche FROM adresse WHERE id='$adresse' AND id>0");
        if($stundenprowoche <=0 && $stundenausadresse >0)
          $stundenprowoche = $stundenausadresse;
        return $stundenprowoche;
      }

      $arbeitszeitprowoche = $this->app->DB->Select("SELECT arbeitszeitprowoche FROM adresse WHERE id='$adresse' LIMIT 1");
      if($arbeitszeitprowoche<=0 || !is_numeric($arbeitszeitprowoche)) {
        return 0;
      }
      return $arbeitszeitprowoche;
    }



      function AddArbeitsnachweisPositionZeiterfassung($arbeitsnachweis,$zid)
      {
        $tmp = $this->app->DB->SelectArr("SELECT *,DATE_FORMAT(von,'%Y-%m-%d') as datum,DATE_FORMAT(von,'%H:%i') as von,DATE_FORMAT(bis,'%H:%i') as bis FROM zeiterfassung WHERE id='$zid'");
        $sort = $this->app->DB->Select("SELECT MAX(sort) FROM arbeitsnachweis_position WHERE arbeitsnachweis='$arbeitsnachweis' LIMIT 1");
        $sort = $sort + 1;

        $adresse = $tmp[0]['adresse']; //mitarbeiter
        $bezeichnung = $tmp[0]['aufgabe'];
        $beschreibung = $tmp[0]['beschreibung'];
        $ort = $tmp[0]['ort'];
        $arbeitspaket =$tmp[0]['arbeitspaket'];
        $datum = $tmp[0]['datum'];
        $von=$tmp[0]['von'];
        $bis=$tmp[0]['bis'];

        $this->app->DB->Insert("INSERT INTO arbeitsnachweis_position (id,arbeitsnachweis,artikel,bezeichnung,beschreibung,ort,arbeitspaket,datum,von,bis,sort,status,projekt,adresse)
            VALUES ('','$arbeitsnachweis','$artikel','$bezeichnung','$beschreibung','$ort','$arbeitspaket','$datum','$von','$bis','$sort','angelegt','$projekt','$adresse')");
        $tmpid = $this->app->DB->GetInsertID();
        //markieren als erledigt
        $this->app->DB->Update("UPDATE zeiterfassung SET arbeitsnachweis='$arbeitsnachweis',arbeitsnachweispositionid='$tmpid' WHERE id='$zid'");
      }


      function CreateAufgabe($adresse,$aufgabe,$kunde=0)
      {
        $this->app->DB->Insert("INSERT INTO aufgabe (id,adresse,initiator,aufgabe,status,kunde) 
          VALUES ('','$adresse','".$this->app->User->GetAdresse()."','$aufgabe','offen','$kunde')");
        return $this->app->DB->GetInsertID();
      }

      function AbschlussAufgabe($id)
      {

        // einmalig immer weg
        $intervall_tage = $this->app->DB->Select("SELECT intervall_tage FROM aufgabe WHERE id='$id'");
        $startdatum = $this->app->DB->Select("SELECT abgabe_bis FROM aufgabe WHERE id='$id'");
        $check = $this->app->DB->Select("SELECT id FROM aufgabe WHERE id='$id' AND ((abgabe_bis <= NOW() AND intervall_tage > 0) OR intervall_tage=0)");

        if($check<=0) return -1;

        switch($intervall_tage)
        {
          case 1: //taeglich
            $newaufgabe = $this->CopyAufgabe($id);
            $newstartdatum =date('Y-m-d H:i:s', strtotime("$startdatum +1 days"));
            $this->app->DB->Update("UPDATE aufgabe SET abgabe_bis='$newstartdatum' WHERE id='$newaufgabe'");
          break;

          case 2: //wochen
            $newaufgabe = $this->CopyAufgabe($id);
            $newstartdatum =date('Y-m-d H:i:s', strtotime("$startdatum +7 days"));
            $this->app->DB->Update("UPDATE aufgabe SET abgabe_bis='$newstartdatum' WHERE id='$newaufgabe'");
          break;
          case 3: //monatlich
            $newaufgabe = $this->CopyAufgabe($id);
            $newstartdatum =date('Y-m-d H:i:s', strtotime("$startdatum +1 month"));
            $this->app->DB->Update("UPDATE aufgabe SET abgabe_bis='$newstartdatum' WHERE id='$newaufgabe'");
          break;
          case 4: // jaehrlich
            $newaufgabe = $this->CopyAufgabe($id);
            $newstartdatum =date('Y-m-d H:i:s', strtotime("$startdatum +1 year"));
            $this->app->DB->Update("UPDATE aufgabe SET abgabe_bis='$newstartdatum' WHERE id='$newaufgabe'");
          break;
        }
        // aufgaben kopieren und dann wenn intervall_tage 2 = woechen 3 monatlich 4 jaehrlich
        // alles kopieren 1:1 neue hat mit dem datum von turnus +1 tag + 7 Tage oder monatlich immer wieder dann rein

        // ab taeglich kann man nur abschliessen abgabe_bis <= heute ist
        $this->app->DB->Update("UPDATE aufgabe SET status='abgeschlossen',abgeschlossen_am=NOW() WHERE id='$id' LIMIT 1");
        return 1;
      }

      function CopyAufgabe($id)
      {
        return $this->app->DB->MysqlCopyRow("aufgabe","id",$id);
      }

      function CreateRetoure($adresse="")
      {
        $projekt = $this->GetCreateProjekt($adresse);

        $standardlager = $this->app->DB->Select("SELECT l.id FROM projekt p INNER JOIN lager l ON p.standardlager = l.id WHERE p.id = '$projekt' LIMIT 1");

        $belegmax = "";
        $ohnebriefpapier = $this->Firmendaten("retoure_ohnebriefpapier");
        $this->app->DB->Insert("INSERT INTO retoure (id,datum,bearbeiter,firma,belegnr,adresse,ohne_briefpapier,projekt)
            VALUES ('',NOW(),'".$this->app->User->GetName()."','".$this->app->User->GetFirma()."','$belegmax','$adresse','".$ohnebriefpapier."','".$projekt."')");


        $id = $this->app->DB->GetInsertID();
        $this->app->DB->Update("UPDATE retoure SET 
        liefername = '".$this->app->DB->real_escape_string($this->Firmendaten('name'))."' ,
        lieferstrasse = '".$this->app->DB->real_escape_string($this->Firmendaten('strasse'))."' ,
        lieferort = '".$this->app->DB->real_escape_string($this->Firmendaten('ort'))."' ,
        lieferplz = '".$this->app->DB->real_escape_string($this->Firmendaten('plz'))."' ,
        lieferland = '".$this->app->DB->real_escape_string($this->Firmendaten('land'))."' ,
        abweichendelieferadresse = 1
        
        WHERE id = '$id' LIMIT 1");
        if(!$id)die($this->app->DB->error());
        if($standardlager)$this->app->DB->Update("UPDATE retoure SET standardlager = '$standardlager' WHERE id = '$id' LIMIT 1");
        $type="retoure";
        $this->app->erp->ObjektProtokoll($type,$id,$type."_create",ucfirst($type)." angelegt");
        $this->SchnellFreigabe($type,$id);

        $this->EventAPIAdd("EventREtoureCreate",$id,"retoure","create");
        return $id;
      }

      function CreateLieferschein($adresse="")
      {
        $obj = $this->LoadModul('lieferschein');
        if(!empty($obj) && method_exists($obj, 'CreateLieferschein')){
          return $obj->CreateLieferschein($adresse);
        }
      }

      function AddLieferscheinPositionArtikelID($lieferschein, $artikel,$menge,$bezeichnung,$beschreibung,$datum)
      {
        $obj = $this->LoadModul('lieferschein');
        if(!empty($obj) && method_exists($obj, 'AddLieferscheinPositionArtikelID')){
          $obj->AddLieferscheinPositionArtikelID($lieferschein, $artikel,$menge,$bezeichnung,$beschreibung,$datum);
        }
      }


      function AddLieferscheinPosition($lieferschein, $verkauf,$menge,$datum)
      {
        $obj = $this->LoadModul('lieferschein');
        if(!empty($obj) && method_exists($obj, 'AddLieferscheinPosition')){
          $obj->AddLieferscheinPosition($lieferschein, $verkauf,$menge,$datum);
        }
      }



      function DeleteAnfrage($id)
      {
        $this->app->DB->Delete("DELETE FROM anfrage_position WHERE anfrage='$id'");
        $this->app->DB->Delete("DELETE FROM anfrage_protokoll WHERE anfrage='$id'");
        $this->app->DB->Delete("DELETE FROM anfrage WHERE id='$id' LIMIT 1");
      }


      function DeletePreisanfrage($id)
      {
        /** @var Preisanfrage $obj */
        $obj = $this->app->erp->LoadModul('preisanfrage');
        if(!empty($obj) && method_exists($obj,'DeletePreisanfrage')) {
          $obj->DeletePreisanfrage($id);
        }
      }


      function DeleteProformarechnung($id)
      {
        $this->app->DB->Delete("DELETE FROM proformarechnung_lieferschein WHERE proformarechnung='$id'");
        $this->app->DB->Delete("DELETE FROM proformarechnung_position WHERE proformarechnung='$id'");
        $this->app->DB->Delete("DELETE FROM proformarechnung_protokoll WHERE proformarechnung='$id'");
        $this->app->DB->Delete("DELETE FROM proformarechnung WHERE id='$id' LIMIT 1");
      }



      function DeleteInventur($id)
      {
        /** @var Inventur $obj */
        $obj = $this->LoadModul('inventur');
        if(!empty($obj) && method_exists($obj, 'DeleteInventur'))
        {
          $obj->DeleteInventur($id);
        }
      }


      function DeleteKalkulation($id)
      {
        $this->app->DB->Delete("DELETE FROM kalkulation_position WHERE kalkulation='$id'");
        $this->app->DB->Delete("DELETE FROM kalkulation_protokoll WHERE kalkulation='$id'");
        $this->app->DB->Delete("DELETE FROM kalkulation WHERE id='$id' LIMIT 1");
      }


      function DeleteReisekosten($id)
      {
        /** @var Reisekosten $obj */
        $obj = $this->LoadModul('reisekosten');
        if(!empty($obj) && method_exists($obj, 'DeleteReisekosten'))
        {
          $obj->DeleteReisekosten($id);
        }
      }

      function DeleteArbeitsnachweis($id)
      {
        /** @var Arbeitsnachweis $obj */
        $obj = $this->app->erp->LoadModul('arbeitsnachweis');
        if(!empty($obj) && method_exists($obj, 'DeleteArbeitsnachweis')) {
          $obj->DeleteArbeitsnachweis($id);
        }
      }

      function DeleteRetoure($id)
      {
        $this->app->DB->Delete("DELETE FROM retoure_position WHERE retoure='$id'");
        $this->app->DB->Delete("DELETE FROM retoure_protokoll WHERE retoure='$id'");
        $this->app->DB->Delete("DELETE FROM retoure WHERE id='$id' LIMIT 1");
      }

      function DeleteLieferschein($id)
      {
        $obj = $this->LoadModul('lieferschein');
        if(!empty($obj) && method_exists($obj, 'DeleteLieferschein')){
          $obj->DeleteLieferschein($id);
        }
      }



      function CreateAuftrag($adresse="")
      {
        $ohnebriefpapier = $this->Firmendaten("auftrag_ohnebriefpapier");
        $belegmax = "";

      $projekt = $this->GetCreateProjekt($adresse);
      $standardlager = $this->app->DB->Select("SELECT standardlager FROM projekt WHERE id = '$projekt' LIMIT 1");

      $firma = $this->app->DB->Select("SELECT MAX(f.id) FROM firma f INNER JOIN firmendaten fd ON f.id = fd.firma LIMIT 1");
      if(!$firma)$firma = $this->app->DB->Select("SELECT max(id) FROM firma LIMIT 1");
      if(!$firma)$firma = $this->app->DB->Select("SELECT MAX(id) FROM firma LIMIT 1");

        if($this->StandardZahlungsweise($projekt)=="rechnung")
        {
          $this->app->DB->Insert("INSERT INTO auftrag (id,datum,bearbeiter,firma,belegnr,autoversand,zahlungsweise,zahlungszieltage,
          zahlungszieltageskonto,zahlungszielskonto,status,projekt,adresse,ohne_briefpapier)
            VALUES ('',NOW(),'','','$belegmax',1,'".$this->StandardZahlungsweise($projekt)."',
              '".$this->ZahlungsZielTage($projekt)."',
              '".$this->ZahlungsZielTageSkonto($projekt)."',
              '".$this->ZahlungsZielSkonto($projekt)."',
              'angelegt','$projekt','$adresse','".$ohnebriefpapier."')");
        } else {
          $this->app->DB->Insert("INSERT INTO auftrag (id,datum,bearbeiter,firma,belegnr,autoversand,zahlungsweise,zahlungszieltage,
          zahlungszieltageskonto,zahlungszielskonto,status,projekt,adresse,ohne_briefpapier)
            VALUES ('',NOW(),'','','$belegmax',1,'".$this->StandardZahlungsweise($projekt)."',
              '0',
              '0',
              '0',
              'angelegt','$projekt','$adresse','".$ohnebriefpapier."')");
        }

        $id = $this->app->DB->GetInsertID();
        if($standardlager)$this->app->DB->Update("UPDATE auftrag SET standardlager = '$standardlager' WHERE id = '$id' LIMIT 1");
        $this->CheckVertrieb($id,"auftrag");
        $this->CheckBearbeiter($id,"auftrag");

        $type="auftrag";
        $this->app->erp->ObjektProtokoll($type,$id,$type."_create",ucfirst($type)." angelegt");

        $this->app->erp->AuftragProtokoll($id,"Auftrag angelegt");

        $deliverythresholdvatid = $this->getDeliverythresholdvatid($projekt);
        if($id > 0 && !empty($deliverythresholdvatid)){
          $deliverythresholdvatid = $this->app->DB->real_escape_string($deliverythresholdvatid);
          $this->app->DB->Update("UPDATE auftrag SET deliverythresholdvatid = '$deliverythresholdvatid' WHERE id = $id LIMIT 1");
        }

        $this->SchnellFreigabe("auftrag",$id);

        $this->EventAPIAdd("EventAuftragCreate",$id,"auftrag","create");

        $this->LoadSteuersaetzeWaehrung($id,"auftrag",$projekt);
        return $id;
      }


      function ArtikelIDProjekt($artikelnummer,$projekt=0)
      {
        $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id='$projekt' LIMIT 1");
        if($eigenernummernkreis=="1")
        {
          $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikelnummer' AND projekt='$projekt' AND nummer!='' LIMIT 1");
          if($artikel) {
            return $artikel;
          }
          return $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikelnummer' AND projekt='0' AND nummer!='' LIMIT 1");
        }

        return $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikelnummer' AND nummer!='' LIMIT 1");
      }

      function AddAuftragPositionNummer($auftrag,$nummer,$menge,$projekt,$nullpreis="",$taxfree=false,$typ="", $data = null)
      {
        $doctype = $typ;
        if($doctype !== 'angebot') {
          $doctype = 'auftrag';
        }
        if($typ === 'produktion'){
          $doctype = $typ;
        }
        $artikel = 0;
        if(!empty($data) && !empty($data['forceartikelid']) &&  $data['forceartikelid'] > 0)
        {
          $artikel = (int)$this->app->DB->Select(
            sprintf(
              'SELECT id FROM artikel WHERE id = %d AND geloescht = 0 LIMIT 1',
              (int)$data['forceartikelid']
            )
          );
        }
        if($artikel <= 0) {
          $artikel = (int)$this->ArtikelIDProjekt($nummer,$projekt);
        }

        $artikeldata = $this->app->DB->SelectRow(
          sprintf(
            'SELECT name_de,nummer,anabregs_text,mlmpunkte,mlmbonuspunkte,mlmdirektpraemie,umsatzsteuer 
            FROM artikel WHERE id=%d LIMIT 1',
            $artikel
          )
        );

        $bezeichnunglieferant = $artikeldata['name_de'];
        $bestellnummer = $artikeldata['nummer'];
        $beschreibung = $artikeldata['anabregs_text'];

        $sprache = $this->app->DB->Select("SELECT sprache FROM $doctype WHERE id='$auftrag' LIMIT 1");

        $this->RunHook('AARLGPositionenSprache', 6, $doctype, $auftrag, $artikel, $sprache, $bezeichnunglieferant, $beschreibung);
        $this->app->erp->LogFile("Add $nummer,$menge $artikel $sprache Name: $bezeichnunglieferant");

        $verkaufspreisarr = $this->GetVerkaufspreis($artikel, $menge,0,'', $returnwaehrung,true);
        if($verkaufspreisarr)
        {
          $verkaufsid = (int)$verkaufspreisarr['id'];
        }else{
          $verkaufsid = (int)$this->app->DB->Select(
            sprintf(
              "SELECT id 
              FROM verkaufspreise 
              WHERE artikel=%d
                AND (gueltig_bis='0000-00-00' OR gueltig_bis >=NOW()) AND ab_menge=1
                AND ((objekt='Standard' AND adresse=0) OR (objekt='' AND adresse=0)) AND geloescht=0 
              ORDER BY art = 'gruppe' 
              LIMIT 1",
              $artikel
            )
          );
        }

        $preis = 0;
        $vpe = '';
        $preisVpe = $this->app->DB->SelectRow(sprintf('SELECT preis,vpe FROM verkaufspreise WHERE id=%d LIMIT 1',$verkaufsid));
        if(!empty($preisVpe)){
          $preis = $preisVpe['preis'];
          $vpe = $preisVpe['vpe'];
        }

        if($nullpreis=='1'){
          $preis = 0;
        }

        $umsatzsteuer = $this->app->DB->real_escape_string($artikeldata['umsatzsteuer']);
        $mlmpunkte = $artikeldata['mlmpunkte'];
        $mlmbonuspunkte = $artikeldata['mlmbonuspunkte'];
        $mlmdirektpraemie = $artikeldata['mlmdirektpraemie'];

        $bezeichnunglieferant = $this->app->DB->real_escape_string($bezeichnunglieferant);
        $bestellnummer = $this->app->DB->real_escape_string($bestellnummer);
        $beschreibung = $this->app->DB->real_escape_string($beschreibung);


        if($typ=='produktion')
        {
        } else {
          $sort = 1 + (int)$this->app->DB->Select(
            sprintf(
            'SELECT IFNULL(MAX(sort),0) FROM `%s` WHERE `%s`= %d LIMIT 1',
              $doctype.'_position', $doctype, (int)$auftrag
            )
          );
          $this->app->DB->Insert(
            sprintf(
            "INSERT INTO `%s` (%s,artikel,bezeichnung,nummer,menge,preis, sort,lieferdatum, umsatzsteuer, status,projekt,vpe,punkte,bonuspunkte,mlmdirektpraemie)
              VALUES (%d, %d, '%s', '%s', %f, %f, %d, '%s', '%s','angelegt', %d, '%s', %f, %f, %f)",
              $doctype.'_position',$doctype,(int)$auftrag, $artikel,$bezeichnunglieferant,$bestellnummer,(float)$menge,(float)$preis,$sort,
              $datum,$umsatzsteuer,(int)$projekt,$this->app->DB->real_escape_string($vpe),$mlmpunkte,$mlmbonuspunkte,$mlmdirektpraemie
            )
          );
          $insid = $this->app->DB->GetInsertID();
          if(!empty($data) && !empty($data['parentap'])) {
            $this->app->DB->Update(
              sprintf(
                'UPDATE `%s` AS pp 
                INNER JOIN artikel art ON pp.artikel = art.id AND (art.stueckliste = 1 OR art.juststueckliste = 1) 
                SET pp.explodiert = 1 
                WHERE pp.id = %d',
                $doctype.'_position', (int)$data['parentap']
              )
            );
            $this->app->DB->Update(
              sprintf(
                'UPDATE `%s` 
                SET explodiert_parent = %d 
                WHERE id = %d',
                $doctype.'_position', (int)$data['parentap'], (int)$insid
              )
            );
          }
        }
        return $insid;
      }

      function AddArtikelEigenschaft($artikel, $name, $wert, $einheit = '')
      {
        if($name == ''){
          return;
        }
        if(!$this->app->DB->Select("SELECT id FROM artikel WHERE id = '$artikel' AND nummer <> 'DEL' AND ifnull(geloescht,0) = 0")){
          return;
        }
        $checkkategorie = $this->app->DB->Select("SELECT id FROM artikeleigenschaften WHERE name = '$name' AND geloescht <> 1 LIMIT 1");
        if(!$checkkategorie)
        {
          $this->app->DB->Insert("INSERT INTO artikeleigenschaften (name) values ('$name')");
          $checkkategorie = $this->app->DB->GetInsertID();
        }
        $checkwert = $this->app->DB->Select("SELECT id FROM artikeleigenschaftenwerte WHERE artikeleigenschaften = '$checkkategorie' AND artikel = '$artikel' AND wert = '$wert' LIMIT 1");
        if(!$checkwert){
          $this->app->DB->Insert("INSERT INTO artikeleigenschaftenwerte (wert, artikeleigenschaften, artikel, einheit) values ('$wert','$checkkategorie','$artikel','$einheit')");
        }
      }

    function KopiereArtikelEigenschaften($vonartikel, $nachartikel)
    {
      $vonartikel = $this->app->DB->Select("SELECT id FROM artikel WHERE geloescht <> 1 AND id = '". (int)$vonartikel."' LIMIT 1");
      $nachartikel = $this->app->DB->Select("SELECT id FROM artikel WHERE geloescht <> 1 AND id = '". (int)$nachartikel."' LIMIT 1");
      if(!$vonartikel || !$nachartikel || $vonartikel == $nachartikel){
        return;
      }
      $artikeleigenschaftenwerte = $this->app->DB->SelectArr("SELECT id FROM artikeleigenschaftenwerte WHERE artikel = '$vonartikel' ORDER by id");
      if($artikeleigenschaftenwerte)
      {
        foreach($artikeleigenschaftenwerte as $v)
        {
          $idnew = $this->app->DB->MysqlCopyRow("artikeleigenschaftenwerte","id",$v['id']);
          $this->app->DB->Update("UPDATE artikeleigenschaftenwerte SET artikel = '$nachartikel' WHERE id = '$idnew' LIMIT 1");
        }
      }
    }

    function KopiereArtikelDateistichwoerter($vonartikel, $nachartikel)
    {
      $vonartikel = $this->app->DB->Select("SELECT id FROM artikel WHERE geloescht <> 1 AND id = '". (int)$vonartikel."' LIMIT 1");
      $nachartikel = $this->app->DB->Select("SELECT id FROM artikel WHERE geloescht <> 1 AND id = '". (int)$nachartikel."' LIMIT 1");
      if(!$vonartikel || !$nachartikel || $vonartikel == $nachartikel)return;
      $dateistichwoerter = $this->app->DB->SelectArr("SELECT id FROM datei_stichwoerter WHERE objekt LIKE 'Artikel' AND parameter = '$vonartikel' ORDER by id");
      if($dateistichwoerter)
      {
        foreach($dateistichwoerter as $v)
        {
          $idnew = $this->app->DB->MysqlCopyRow("datei_stichwoerter","id",$v['id']);
          $this->app->DB->Update("UPDATE datei_stichwoerter SET parameter = '$nachartikel' WHERE id = '$idnew' LIMIT 1");
        }
      }
    }

      function AddPositionManuellPreisNummer($typ,$id,$projekt, $artikelnummer,$menge,$name,$preis,$umsatzsteuer,$rabatt=0,$shop=0,$waehrung='EUR',$data = null, &$fulldata = null)
      {
        // wenn es Artikel nicht gibt anlegen! bzw. immer updaten wenn name anders ist
//        $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer='$artikelnummer' AND nummer!='' LIMIT 1");
        $artikelnummershop = $artikelnummer;
        $artikel = 0;
        $artikelnummernummerkreis = false;
        $externeartikelnummer = "";
        $eigenernummernkreis= 0;
        $artikeltexteuebernehmen = 0;
        $multiprojekt = 0;
        $shopArr = null;
        if($shop > 0)
        {
          $shopArr = $this->app->DB->SelectRow(
            sprintf(
              'SELECT artikeltexteuebernehmen,multiprojekt,projekt,artikelbeschreibungauswawision,
                artikelbeschreibungenuebernehmen,artikelnummernummerkreis,bezeichnung 
              FROM shopexport 
              WHERE id= %d',
              $shop
            )
          );
          $artikeltexteuebernehmen = !empty($shopArr)?$shopArr['artikeltexteuebernehmen']:$this->app->DB->Select("SELECT artikeltexteuebernehmen FROM shopexport WHERE id='$shop' LIMIT 1");
          $multiprojekt = !empty($shopArr)?$shopArr['multiprojekt']:$this->app->DB->Select("SELECT multiprojekt FROM shopexport WHERE id='$shop' LIMIT 1");
          if(!$projekt){
            $projekt = !empty($shopArr)?$shopArr['projekt']:$this->app->DB->Select("SELECT projekt FROM shopexport WHERE id='".$shop."' LIMIT 1");
          }
        }
        if($projekt){
          $eigenernummernkreis = $this->app->DB->Select("SELECT eigenernummernkreis FROM projekt WHERE id = '$projekt' LIMIT 1");
        }

        if($shop && isset($data['fremdnummer']) && trim((String)$data['fremdnummer']) !== ''){
          $artikel = $this->app->DB->Select("SELECT a.id FROM artikelnummer_fremdnummern af INNER JOIN artikel a on af.artikel = a.id WHERE af.nummer='{$data['fremdnummer']}' AND af.aktiv = 1 AND af.nummer <> '' AND (a.projekt='$projekt' OR af.shopid = '$shop') AND a.nummer <> 'DEL' AND IFNULL(a.geloescht,0) = 0 ORDER BY af.shopid = '$shop' DESC,IFNULL(a.intern_gesperrt,0) = 0 DESC, af.id LIMIT 1");
        }
        if(empty($artikel)){
          if($eigenernummernkreis && !$multiprojekt)
          {
            $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer = '".$artikelnummer."' AND IFNULL(geloescht,0) = 0 AND IFNULL(intern_gesperrt,0) = 0 AND projekt = '$projekt' LIMIT 1");
          } else {
            $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE nummer = '".$artikelnummer."' AND IFNULL(geloescht,0) = 0 AND IFNULL(intern_gesperrt,0) = 0 ORDER BY  projekt = '$projekt' DESC LIMIT 1");
          }
        }

        if(!$artikel)
        {
          if($eigenernummernkreis && !$multiprojekt)
          {
            $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer = '".$artikelnummer."' AND nummer <> 'DEL' AND projekt = '$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");
          } else {
            $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE herstellernummer = '".$artikelnummer."' AND nummer <> 'DEL' ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC, projekt = '$projekt' AND IFNULL(geloescht,0) = 0 DESC LIMIT 1");
          }
          if($artikel){
            $artikelnummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id = '$artikel' LIMIT 1");
          }
        }

        if(!$artikel)
        {
          if($eigenernummernkreis && !$multiprojekt)
          {
            $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE ean = '".$artikelnummer."' AND nummer <> 'DEL' AND projekt = '$projekt' AND IFNULL(geloescht,0) = 0 ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC LIMIT 1");
          } else {
            $artikel = $this->app->DB->Select("SELECT id FROM artikel WHERE ean = '".$artikelnummer."' AND nummer <> 'DEL' ORDER BY IFNULL(intern_gesperrt,0) = 0 DESC, projekt = '$projekt' AND IFNULL(geloescht,0) = 0 DESC LIMIT 1");
          }
          if($artikel){
            $artikelnummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id = '$artikel' LIMIT 1");
          }
        }

        if(!$artikel){
          $artikel = $this->ArtikelIDProjekt($artikelnummer,$projekt);
        }
        if($artikel <=0)
        {
          if($artikelnummernummerkreis)
          {
            $externeartikelnummer = $artikelnummer;
            $artikelnummer = $this->GetNextArtikelnummer('produkt', 1, $projekt);
          }

        //Artikel anlegen
        $ean = '';
        if(is_array($data) && isset($data['ean'])){
          $ean = $data['ean'];
        }
        $artdata = array('name_de'=>$name,'nummer'=>$artikelnummer,'projekt'=>$projekt,'umsatzsteuer'=>$umsatzsteuer,'lagerartikel'=>1,'shop'=>$shop,'firma'=>(isset($this->app->User)?$this->app->User->GetFirma():1),'ean'=>$ean);
        if(!is_null($data) && is_array($data))
        {
          foreach($data as $k => $v)
          {
            switch($k)
            {
              case 'anabregs_text':
              case 'anabregs_text_en':
              case 'kurztext_de':
              case 'kurztext_en':
              case 'uebersicht_de':
              case 'uebersicht_en':
              case 'metadescription_de':
              case 'metadescription_en':
              case 'metakeywords_de':
              case 'metakeywords_en':
                if($artikeltexteuebernehmen){
                  $artdata[$k] = $v;
                }
              break;
              case 'anabregs_text_de':
                //$artdata['anabregs_text'] = $v;
              break;
              case 'lagerartikel':
              case 'serviceartikel':
              case 'unikat':
              case 'anhang':
                $artdata[$k] = $v;
              break;

            }
            switch($k)
            {
              case 'options':
                $beschreibung = $v;
              break;
            }
          }

          }
          $artikel = $this->AddArtikel($artdata);
          if(!empty($fulldata['generierenummerbeioption'])){
            $this->ObjektProtokoll('artikel',$artikel, 'artikel_create','Automatisch Kopie angelegt');
          }


        $this->AddVerkaufspreis($artikel,1,0,$preis,$waehrung);
      } else {
        $variante_kopietesten = true;
        if(!empty($data) && isset($data['stuecklisteergaenzen']) && $data['stuecklisteergaenzen'] && isset($data['posid']) && !empty($fulldata))
        {
          $stueckliste = $this->app->DB->Select("SELECT stueckliste FROM artikel WHERE id = '$artikel' LIMIT 1");
          if($stueckliste)
          {
            $variante_kopietesten = false;
            $varkopie =  $this->app->DB->Select("SELECT variante_kopie FROM artikel WHERE id = '$artikel' LIMIT 1");
            $copystueckliste = $varkopie;
            if(!$copystueckliste)
            {
              $stuecklistenelemente = $this->app->DB->SelectArr("SELECT a.* FROM stueckliste s INNER JOIN artikel a ON s.artikel = a.id WHERE a.geloescht <> 1 AND s.stuecklistevonartikel = '$artikel' ORDER BY sort");
              if($stuecklistenelemente)
              {
                foreach($stuecklistenelemente as $v3)
                {
                  if($v3['variante_kopie'])$copystueckliste = true;
                }
              }
            }
            if(!$copystueckliste)
            {
              foreach($fulldata as $k2 => $v2)
              {
                $cnummer = $v2['articleid'];
                if(isset($v2['parentid']) && $v2['parentid'] == $data['posid'])
                {
                  $found = false;
                  if($stuecklistenelemente)
                  {
                    foreach($stuecklistenelemente as $v3)
                    {
                      $sfound = false;
                      if($cnummer == $v3['nummer'])$sfound = true;
                      if($cnummer == $v3['herstellernummer'])$sfound = true;
                      if($cnummer == $v3['ean'])$sfound = true;
                      if(!$sfound)
                      {
                        if($this->app->DB->Select("SELECT a.id FROM artikelnummer_fremdnummern af INNER JOIN artikel a on af.artikel = a.id WHERE af.nummer ='".$this->app->DB->real_escape_string($cnummer)."' AND af.nummer <> '' AND af.shopid = '$shop' AND af.aktiv = 1 AND a.nummer <> 'DEL' ORDER by af.id LIMIT 1"))$sfound = true;
                      }
                      if(!$sfound)$copystueckliste = true;
                    }
                  }
                }
              }
            }
            if(!$copystueckliste)
            {
              foreach($fulldata as $k2 => $v2)
              {
                if(isset($v2['parentid']) && $v2['parentid'] == $data['posid'])
                {
                  $fulldata[$k2]['ignorieren'] = true;
                }
              }
            }else{
              $neuerartikel['nummer'] = $this->GetNextArtikelnummer($this->app->DB->Select("SELECT typ FROM artikel WHERE id = '$artikel' LIMIT 1"), 1, $projekt);
              $neuerartikel['stueckliste'] = 1;
              $neuerartikel['variante_kopie'] = $varkopie;
              $neuerartikel['projekt'] = $projekt;
              $tmpArticleArr = $this->app->DB->SelectRow(
                sprintf(
                  'SELECT lagerartikel,name_de,lager_platz,produktion,adresse,umsatzsteuer,juststueckliste 
                  FROM artikel 
                  WHERE id = %d',
                  $artikel
                )
              );
              $neuerartikel['lagerartikel'] = !empty($tmpArticleArr)?$tmpArticleArr['lagerartikel']:$this->app->DB->Select("SELECT lagerartikel FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['name_de'] = !empty($tmpArticleArr)?$tmpArticleArr['name_de']:$this->app->DB->Select("SELECT name_de FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['lager_platz'] = !empty($tmpArticleArr)?$tmpArticleArr['lager_platz']:$this->app->DB->Select("SELECT lager_platz FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['produktion'] = !empty($tmpArticleArr)?$tmpArticleArr['produktion']:$this->app->DB->Select("SELECT produktion FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['adresse'] = !empty($tmpArticleArr)?$tmpArticleArr['adresse']:$this->app->DB->Select("SELECT adresse FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['umsatzsteuer'] = !empty($tmpArticleArr)?$tmpArticleArr['umsatzsteuer']:$this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['juststueckliste'] = !empty($tmpArticleArr)?$tmpArticleArr['juststueckliste']:$this->app->DB->Select("SELECT juststueckliste FROM artikel WHERE id = '$artikel' LIMIT 1");
              $neuerartikel['anabregs_text'] = isset($value['options']) && !empty($value['options'])?$value['options']:'';
              $neuerartikel['bestandalternativartikel'] = $this->app->DB->Select("SELECT bestandalternativartikel FROM artikel WHERE id = '$artikel' LIMIT 1");
              if($this->app->DB->Select("SELECT unikatbeikopie FROM artikel WHERE id = '$artikel' LIMIT 1"))$neuerartikel['unikat'] = 1;
              $this->app->DB->Insert("INSERT INTO artikel (id) VALUES ('')");
              $neuerartikel['id'] = $this->app->DB->GetInsertID();
              $neuerartikelid = $this->InsertUpdateArtikel($neuerartikel);
              $this->CopyArtikelVariante($neuerartikelid, $artikel,isset($value['options']) && !empty($value['options'])?$value['options']:(isset($value['anabregs_text'])?$value['anabregs_text']:''));
              $stuecklistenelementeneu = $this->app->DB->SelectArr("SELECT a.* FROM stueckliste s INNER JOIN artikel a ON s.artikel = a.id WHERE a.geloescht <> 1 AND s.stuecklistevonartikel = '$neuerartikelid' ORDER BY sort");
              foreach($fulldata as $k2 => $v2)
              {
                $cnummer = $v2['articleid'];
                if(isset($v2['parentid']) && $v2['parentid'] == $data['posid'])
                {
                  $found = false;
                  if($stuecklistenelementeneu)
                  {
                    foreach($stuecklistenelementeneu as $v3)
                    {
                      $sfound = false;
                      if($cnummer == $v3['nummer'])$sfound = true;
                      if($cnummer == $v3['herstellernummer'])$sfound = true;
                      if($cnummer == $v3['ean'])$sfound = true;
                      if(!$sfound)
                      {
                        if($this->app->DB->Select("SELECT a.id FROM artikelnummer_fremdnummern af INNER JOIN artikel a on af.artikel = a.id WHERE a.id = '".$v3['id']."' AND af.nummer ='".$this->app->DB->real_escape_string($cnummer)."' AND af.nummer <> '' AND af.shopid = '$shop' AND af.aktiv = 1 AND a.nummer <> 'DEL' ORDER by af.id  LIMIT 1"))$sfound = true;
                      }
                      if(!$sfound)
                      {
                        if($v3['variante_von'])
                        {
                          $va = $this->app->DB->SelectRow("SELECT * FROM artikel where id = '".$v3['variante_von']."' LIMIT 1");
                          if($va)
                          {
                            if($cnummer == $va['nummer'])$sfound = true;
                            if($cnummer == $va['herstellernummer'])$sfound = true;
                            if($cnummer == $va['ean'])$sfound = true;
                            if(!$sfound)
                            {
                              if($this->app->DB->Select("SELECT a.id FROM artikelnummer_fremdnummern af INNER JOIN artikel a on af.artikel = a.id WHERE a.id = '".$va['id']."' AND af.nummer ='".$this->app->DB->real_escape_string($cnummer)."' AND af.nummer <> '' AND af.shopid = '$shop' AND af.aktiv = 1 AND a.nummer <> 'DEL' ORDER by af.id LIMIT 1"))$sfound = true;
                            }
                          }
                        }
                      }
                      if(!$sfound)
                      {
                        $umsatzsteuers = $v2['umsatzsteuer'];
                        if(!empty($v2['steuersatz']) && round((float)str_replace($v2['steuersatz'],',','.'),2)== 7)$umsatzsteuers = 'ermaessigt';
                        $snummer = $this->GetNextArtikelnummer('produkt',1,$projekt);
                        $artdatas = array('name_de'=>$v2['name'],'nummer'=>$snummer

                        ,'projekt'=>$projekt,'umsatzsteuer'=>$umsatzsteuers,'lagerartikel'=>1,'shop'=>$shop,'firma'=>(isset($this->app->User)?$this->app->User->GetFirma():1));
                        $this->app->DB->Insert("INSERT INTO artikel (id) VALUES ('')");
                        $artdatas['id'] = $this->app->DB->GetInsertID();
                        $sneueid = $this->InsertUpdateArtikel($artdatas);
                        $sort = 1 + (int)$this->app->DB->Select("SELECT max(sort) FROM stueckliste WHERE stuecklistevonartikel = '".$neuerartikelid."'");
                        $quant = str_replace($v3['quantity'],',','.');
                        if(!$quant)$quant = 1;
                        $this->app->DB->Insert("INSERT INTO stueckliste (artikel, sort, stuecklistevonartikel, menge) values ('".$sneueid."','".$sort."','".$neuerartikelid."','".$quant."')");
                      }
                    }
                  }
                  $fulldata[$k2]['ignorieren'] = true;
                }
              }
              $artikel = $neuerartikelid;
            }
          }
        }
      }

      if($variante_kopietesten)
      {
        if($this->app->DB->Select("SELECT variante_kopie FROM artikel WHERE id = '$artikel' LIMIT 1"))
        {
          $neuerartikel['nummer'] = $this->GetNextArtikelnummer($this->app->DB->Select("SELECT typ FROM artikel WHERE id = '$artikel' LIMIT 1"), 1, $projekt);
          $neuerartikel['stueckliste'] = 1;
          $neuerartikel['variante_kopie'] = 1;
          $neuerartikel['variante_von'] = $artikel;
          $neuerartikel['projekt'] = $projekt;
          $neuerartikel['lagerartikel'] = $this->app->DB->Select("SELECT lagerartikel FROM artikel WHERE id = '$artikel' LIMIT 1");
          if(isset($data['lagerartikel'])  && $data['lagerartikel'])
          {
            $neuerartikel['lagerartikel'] = 1;
          }elseif(isset($data['lagerartikel'])  && ($data['lagerartikel'] === 0 || $data['lagerartikel'] === '0'))
          {
            $neuerartikel['lagerartikel'] = 1;
          }
          if(isset($data['serviceartikel'])  && $data['serviceartikel'])
          {
            $neuerartikel['serviceartikel'] = 1;
          }elseif(isset($data['serviceartikel'])  && ($data['serviceartikel'] === 0 || $data['serviceartikel'] === '0'))
          {
            $neuerartikel['serviceartikel'] = 1;
          }
          $tmpArticleArr = $this->app->DB->SelectRow(
            sprintf(
              'SELECT name_de,lager_platz,produktion,adresse,umsatzsteuer,juststueckliste,bestandalternativartikel
                  FROM artikel 
                  WHERE id = %d',
              $artikel
            )
          );
          $neuerartikel['name_de'] = !empty($tmpArticleArr)?$tmpArticleArr['name_de']:$this->app->DB->Select("SELECT name_de FROM artikel WHERE id = '$artikel' LIMIT 1");
          $neuerartikel['lager_platz'] = !empty($tmpArticleArr)?$tmpArticleArr['lager_platz']:$this->app->DB->Select("SELECT lager_platz FROM artikel WHERE id = '$artikel' LIMIT 1");
          $neuerartikel['produktion'] = !empty($tmpArticleArr)?$tmpArticleArr['produktion']:$this->app->DB->Select("SELECT produktion FROM artikel WHERE id = '$artikel' LIMIT 1");
          $neuerartikel['adresse'] = !empty($tmpArticleArr)?$tmpArticleArr['adresse']:$this->app->DB->Select("SELECT adresse FROM artikel WHERE id = '$artikel' LIMIT 1");
          $neuerartikel['umsatzsteuer'] = !empty($tmpArticleArr)?$tmpArticleArr['umsatzsteuer']:$this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id = '$artikel' LIMIT 1");
          $neuerartikel['juststueckliste'] = !empty($tmpArticleArr)?$tmpArticleArr['juststueckliste']:$this->app->DB->Select("SELECT juststueckliste FROM artikel WHERE id = '$artikel' LIMIT 1");
          $neuerartikel['anabregs_text'] = isset($value['options']) && !empty($value['options'])?$value['options']:'';
          $neuerartikel['bestandalternativartikel'] = !empty($tmpArticleArr)?$tmpArticleArr['bestandalternativartikel']:$this->app->DB->Select("SELECT bestandalternativartikel FROM artikel WHERE id = '$artikel' LIMIT 1");
          if($this->app->DB->Select("SELECT unikatbeikopie FROM artikel WHERE id = '$artikel' LIMIT 1"))$neuerartikel['unikat'] = 1;
          $this->app->DB->Insert("INSERT INTO artikel (id) VALUES ('')");
          $neuerartikel['id'] = $this->app->DB->GetInsertID();
          $neuerartikelid = $this->InsertUpdateArtikel($neuerartikel);
          if($neuerartikelid)
          {
            $this->ObjektProtokoll('artikel', $neuerartikelid,"artikel_create","Automatisch Kopie angelegt");
            $this->KopiereArtikelEigenschaften($artikel, $neuerartikelid);
            $this->KopiereArtikelDateistichwoerter($artikel, $neuerartikelid);
            $artikel = $neuerartikelid;
            $artikelnummer = $neuerartikel['nummer'];
          }
        }
      }

      //$waehrung = 'EUR';
      $datum ="";
      $belegsprache = $this->app->DB->Select("SELECT sprache FROM $typ WHERE id = $id");
      $adresssprachen = $this->GetAdressSprachen();
      if(!is_null($data) && isset($data['options']))$beschreibung = $data['options'];
      if(empty($beschreibung) && $artikelbeschreibungenuebernehmen)$beschreibung = $this->app->DB->real_escape_string($data['anabregs_text']);
      if($artikelbeschreibungauswawision)
      {
        $beschreibung = $this->app->DB->real_escape_string($this->app->DB->Select("SELECT anabregs_text FROM artikel WHERE id='$artikel' LIMIT 1"));
        if($this->app->DB->Select("SELECT adr.id FROM auftrag auf INNER JOIN adresse adr ON auf.adresse = adr.id AND adr.sprache = 'englisch' WHERE auf.id = '$id' LIMIT 1"))
          $beschreibung = $this->app->DB->Select("SELECT anabregs_text_en FROM artikel WHERE id = '$artikel'");
        if(!$beschreibung && $this->app->DB->Select("SELECT variante FROM artikel WHERE id = '$artikel' LIMIT 1"))
        {
          $variante_von = $this->app->DB->Select("SELECT variante_von FROM artikel WHERE id = '$artikel' LIMIT 1");
          if($variante_von)$beschreibung = $this->app->DB->real_escape_string($this->app->DB->Select("SELECT anabregs_text FROM artikel WHERE id='$variante_von' LIMIT 1"));
        }

        if(array_key_exists($belegsprache,$adresssprachen)){
            $belegsprache = $adresssprachen[$belegsprache];
        }
        $artikelbeschreibung = $this->app->DB->Select("SELECT beschreibung FROM artikel_texte WHERE artikel=$artikel AND sprache='$belegsprache'");
        if($artikelbeschreibung){
            $beschreibung = $artikelbeschreibung;
        }

      }
      //$vpe = $this->app->DB->Select("SELECT vpe FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
      $sort = $this->app->DB->Select("SELECT MAX(sort) FROM ".$typ."_position WHERE $typ='$id' LIMIT 1");
      $sort = $sort + 1;
      $artikelnummeruebernehmen = $this->app->DB->Select("SELECT artikelnummeruebernehmen FROM shopexport WHERE id = '$shop' LIMIT 1");
      if($artikelnummeruebernehmen)$artikelnummer = $artikelnummershop;

      $artikelbezeichnungauswawision = $this->app->DB->Select("SELECT artikelbezeichnungauswawision FROM shopexport WHERE id = '$shop' LIMIT 1");
      if($artikelbezeichnungauswawision)
      {
        $name = '';
        if($this->app->DB->Select("SELECT adr.id FROM auftrag auf INNER JOIN adresse adr ON auf.adresse = adr.id AND adr.sprache = 'englisch' WHERE auf.id = '$id' LIMIT 1"))
          $name = $this->app->DB->Select("SELECT name_en FROM artikel WHERE id = '$artikel'");
        if($name === '')$name = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id = '$artikel'");

        if(array_key_exists($belegsprache,$adresssprachen)){
            $belegsprache = $adresssprachen[$belegsprache];
        }
        $artikelbezeichnung = $this->app->DB->Select(
            "SELECT name 
            FROM artikel_texte 
            WHERE artikel=$artikel AND sprache='$belegsprache' 
            ORDER BY name <> '' DESC 
            LIMIT 1"
        );
        if($artikelbezeichnung){
            $name = $artikelbezeichnung;
        }
      }

      $name = $this->app->DB->real_escape_string($name);
      if($typ === 'retoure') {
        $this->app->DB->Insert("INSERT INTO `retoure_position` 
    (`retoure`,`artikel`,`bezeichnung`,`beschreibung`,`nummer`,`menge`,
        `sort`,`lieferdatum`,  `status`,`projekt`,`vpe`)
          VALUES ('$id','$artikel','$name','$beschreibung','$artikelnummer','$menge',
            '$sort','$datum','angelegt','$projekt','$vpe')");
      }
      else{
        $this->app->DB->Insert("INSERT INTO " . $typ . "_position (id,$typ,artikel,bezeichnung,beschreibung,nummer,menge,preis, waehrung,
        sort,lieferdatum, umsatzsteuer, status,projekt,vpe,rabatt,grundrabatt,rabattsync)
          VALUES ('','$id','$artikel','$name','$beschreibung','$artikelnummer','$menge',
            '$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe','$rabatt','$rabatt',1)");
      }
      $insid = $this->app->DB->GetInsertID();

      $mlmfelder = $this->app->DB->SelectArr("SELECT mlmpunkte, mlmbonuspunkte, mlmdirektpraemie FROM artikel WHERE id = '$artikel' LIMIT 1");
      if($mlmfelder)
      {
        $this->app->DB->Update("UPDATE ".$typ."_position SET 
        punkte = '".$mlmfelder[0]['mlmpunkte']."',
        bonuspunkte = '".$mlmfelder[0]['mlmbonuspunkte']."',
        mlmdirektpraemie = '".$mlmfelder[0]['mlmdirektpraemie']."' WHERE id = '$insid' LIMIT 1
        ");
      }


      if(isset($neuerartikel['juststueckliste']) && $neuerartikel['juststueckliste']) {
        if($typ == 'auftrag') {
          $this->AuftragExplodieren($id);
        }
      }
      if($typ == 'auftrag' && is_array($data) && isset($data['parentap'])) {
        $this->app->DB->Update("UPDATE auftrag_position set explodiert_parent = '".$data['parentap']."' where id = '$insid'");
        $this->app->DB->Update("UPDATE auftrag_position ap 
        INNER JOIN artikel art ON ap.artikel = art.id AND (art.juststueckliste = 1 OR art.stueckliste = 1) 
        SET ap.explodiert = 1 where ap.id = '".$data['parentap']."'");
      }

      if($typ === 'auftrag') {
        $this->app->DB->Update(sprintf('UPDATE `artikel`SET `laststorage_changed` = NOW() WHERE `id` = %d', $artikel));
      }
      return $insid;
    }


      function AddPositionManuellPreis($typ,$id, $artikel,$menge,$name,$preis,$umsatzsteuer,$rabatt=0,$waehrung='EUR',$beschreibung="")
      {
        // wenn es Artikel nicht gibt anlegen! bzw. immer updaten wenn name anders ist
        $artArr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT nummer,mlmpunkte,mlmbonuspunkte,mlmdirektpraemie FROM artikel WHERE id = %d',
            $artikel
          )
        );
        $bestellnummer = !empty($artArr)?$artArr['nummer']:$this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");

        //$vpe = $this->app->DB->Select("SELECT vpe FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $sort = $this->app->DB->Select("SELECT MAX(sort) FROM ".$typ."_position WHERE $typ='$id' LIMIT 1");
        $sort = $sort + 1;

        $mlmpunkte = !empty($artArr)?$artArr['mlmpunkte']:$this->app->DB->Select("SELECT mlmpunkte FROM artikel WHERE id='$artikel' LIMIT 1");
        $mlmbonuspunkte = !empty($artArr)?$artArr['mlmbonuspunkte']:$this->app->DB->Select("SELECT mlmbonuspunkte FROM artikel WHERE id='$artikel' LIMIT 1");
        $mlmdirektpraemie = !empty($artArr)?$artArr['mlmdirektpraemie']:$this->app->DB->Select("SELECT mlmdirektpraemie FROM artikel WHERE id='$artikel' LIMIT 1");

        $name = $this->app->DB->real_escape_string($name);
        $beschreibung = $this->app->DB->real_escape_string($beschreibung);
        $bestellnummer = $this->app->DB->real_escape_string($bestellnummer);

        if($typ=="auftrag" || $typ=="angebot" || $typ=="rechnung")
        {
          $this->app->DB->Insert("INSERT INTO ".$typ."_position (id,$typ,artikel,bezeichnung,
            beschreibung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer, status,projekt,vpe,rabatt,punkte,bonuspunkte,mlmdirektpraemie)
              VALUES ('','$id','$artikel','$name','$beschreibung','$bestellnummer','$menge',
                '$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe','$rabatt','$mlmpunkte','$mlmbonuspunkte','$mlmdirektpraemie')");
        } else {
          $this->app->DB->Insert("INSERT INTO ".$typ."_position (id,$typ,artikel,bezeichnung,
            beschreibung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer, status,projekt,vpe,rabatt)
              VALUES ('','$id','$artikel','$name','$beschreibung','$bestellnummer','$menge','$preis',
                '$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe','$rabatt')");
        }
        return $this->app->DB->GetInsertID();
      }


      function AddPositionManuell($typ,$id, $artikel,$menge,$name=null,$beschreibung=null,$waehrung='EUR')
      {
        $artArr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT nummer,projekt FROM artikel WHERE id = %d',
            $artikel
          )
        );
        $bestellnummer = !empty($artArr)?$artArr['nummer']:$this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");
        $projekt = !empty($artArr)?$artArr['projekt']:$this->app->DB->Select("SELECT projekt FROM artikel WHERE id='$artikel' LIMIT 1");

        $adresse = $this->app->DB->Select("SELECT adresse FROM $typ WHERE id='$id' LIMIT 1");

        

        if($menge<1)
          $preis = $this->GetVerkaufspreis($artikel,1,$adresse,$waehrung);
        else
          $preis = $this->GetVerkaufspreis($artikel,$menge,$adresse,$waehrung);

        $artikelnummerkunde = $this->app->DB->real_escape_string($this->app->DB->Select("SELECT kundenartikelnummer FROM verkaufspreise WHERE adresse='$adresse' AND artikel='$artikel' AND kundenartikelnummer!='' AND ab_menge <='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') ORDER by ab_menge DESC LIMIT 1"));


        $artikeldata = $this->app->DB->SelectRow("SELECT umsatzsteuer,mlmpunkte,mlmbonuspunkte,mlmdirektpraemie,name_de,anabregs_text FROM artikel WHERE id='$artikel' LIMIT 1");
        $vpe = '';
        $datum = null;

        $sort = (int)$this->app->DB->Select("SELECT IFNULL(MAX(sort),0) FROM ".$typ."_position WHERE $typ='$id' LIMIT 1");
        $sort = $sort + 1;

        $umsatzsteuer = $artikeldata['umsatzsteuer'];
        $mlmpunkte = $artikeldata['mlmpunkte'];
        $mlmbonuspunkte = $artikeldata['mlmbonuspunkte'];
        $mlmdirektpraemie = $artikeldata['mlmdirektpraemie'];

        if($name===null) {
          $name = $artikeldata['name_de'];
        }
        if($beschreibung===null) {
          $beschreibung = $artikeldata['anabregs_text'];
        }

        if($typ==='auftrag' || $typ==='angebot' || $typ==='rechnung')
        {
          $this->app->DB->Insert("INSERT INTO ".$typ."_position (id,$typ,artikel,bezeichnung,
            beschreibung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer, status,projekt,vpe,punkte,bonuspunkte,mlmdirektpraemie,artikelnummerkunde)
              VALUES ('','$id','$artikel','$name','$beschreibung','$bestellnummer','$menge','$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt',
                '$vpe','$mlmpunkte','$mlmbonuspunkte','$mlmdirektpraemie','$artikelnummerkunde')");
        } else {
          $this->app->DB->Insert("INSERT INTO ".$typ."_position (id,$typ,artikel,bezeichnung,
            beschreibung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer, status,projekt,vpe)
              VALUES ('','$id','$artikel','$name','$beschreibung','$bestellnummer','$menge','$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe')");
        }

        $posid =  $this->app->DB->GetInsertID();

        $this->RunHook("erpapi_addpositionmanuell", 5, $typ, $id, $artikel, $menge, $posid);
        return $posid;
      }



      function AddAuftragPosition($auftrag, $verkauf,$menge,$datum)
      {
        $artikel = $this->app->DB->Select("SELECT artikel FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $bezeichnunglieferant = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikel' LIMIT 1");
        $bestellnummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");
        $preis = $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $projekt = $this->app->DB->Select("SELECT projekt FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id='$artikel' LIMIT 1");
        $sort = $this->app->DB->Select("SELECT MAX(sort) FROM auftrag_position WHERE auftrag='$auftrag' LIMIT 1");
        $sort = $sort + 1;

        $mlmpunkte = $this->app->DB->Select("SELECT mlmpunkte FROM artikel WHERE id='$artikel' LIMIT 1");
        $mlmbonuspunkte = $this->app->DB->Select("SELECT mlmbonuspunkte FROM artikel WHERE id='$artikel' LIMIT 1");
        $mlmdirektpraemie = $this->app->DB->Select("SELECT mlmdirektpraemie FROM artikel WHERE id='$artikel' LIMIT 1");

        $this->app->DB->Insert("INSERT INTO auftrag_position (id,auftrag,artikel,bezeichnung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer,
          status,projekt,vpe,punkte,bonuspunkte,mlmdirektpraemie)
            VALUES ('','$auftrag','$artikel','$bezeichnunglieferant','$bestellnummer','$menge','$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe',
              '$mlmpunkte','$mlmbonuspunkte','$mlmdirektpraemie')");
      }


      function DeleteAuftrag($id)
      {
        $belegnr = $this->app->DB->Select("SELECT belegnr FROM auftrag WHERE id='$id' LIMIT 1");
        if($belegnr=="" || $belegnr=="0")
        {
          $positionen = $this->app->DB->SelectArr("SELECT id FROM auftrag_position WHERE auftrag = '$id'");
          if($positionen)
          {
            foreach($positionen as $pos)
            {
              $this->app->DB->Delete("DELETE FROM objekt_lager_platz WHERE objekt = 'auftrag' AND parameter = '".$pos['id']."'");
            }
          }
          $this->app->DB->Delete("DELETE FROM auftrag_position WHERE auftrag='$id'");
          $this->app->DB->Delete("DELETE FROM auftrag_protokoll WHERE auftrag='$id'");
          $this->app->DB->Delete("DELETE FROM auftrag WHERE id='$id' LIMIT 1");
          $this->app->DB->Delete("DELETE FROM lager_reserviert WHERE objekt='auftrag' AND parameter='$id'");
        }
      }


      function GetCreateProjekt($adresse=0)
      {
        if($adresse>0)
          $tmp_projekt = $this->app->DB->Select("SELECT projekt FROM adresse WHERE id='$adresse' LIMIT 1");

        if($tmp_projekt > 0)
          $projekt = $tmp_projekt;

        $projekt_bevorzugt=$this->app->DB->Select("SELECT projekt_bevorzugen FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        if($projekt_bevorzugt=="1")
        {
          $projekt = $this->app->DB->Select("SELECT projekt FROM user WHERE id='".$this->app->User->GetID()."' LIMIT 1");
        }

        if($projekt <= 0 && $this->app->User->GetType()=="admin")
        {
          $projekt = $this->app->DB->Select("SELECT standardprojekt FROM firma WHERE id='".$this->app->User->GetFirma()."' LIMIT 1");
        }
        else {
          if($projekt <=0)
          {
            $projekt = $this->FallbackRolle($this->app->User->GetAdresse());
          }
        }
        return $projekt;
      }



      function CreateAngebot($adresse="")
      {
        $projekt = $this->GetCreateProjekt($adresse);
        $standardlager = $this->app->DB->Select("SELECT standardlager FROM projekt WHERE id = '$projekt' LIMIT 1");
        $usereditid = 0;
        if(isset($this->app->User) && $this->app->User && method_exists($this->app->User,'GetID'))$usereditid = $this->app->User->GetID();
        $ohnebriefpapier = $this->Firmendaten("angebot_ohnebriefpapier");
        $belegmax = "";

        $angebotersatz_standard = $this->Firmendaten("angebotersatz_standard");
        if($this->StandardZahlungsweise($projekt)=="rechnung")
        {
        $this->app->DB->Insert("INSERT INTO angebot (id,datum,gueltigbis,bearbeiter,usereditid,vertrieb,firma,belegnr,autoversand,zahlungsweise,
          zahlungszieltage,
          zahlungszieltageskonto,
          zahlungszielskonto,
          status,projekt,adresse,ohne_briefpapier,abweichendebezeichnung )
            VALUES ('',NOW(), DATE_ADD(curdate(), INTERVAL ".((int)$this->Firmendaten("angebot_anzahltage")>0?(int)$this->Firmendaten("angebot_anzahltage"):28)." DAY),'','$usereditid','','".$this->app->User->GetFirma()."','$belegmax',1,'".$this->StandardZahlungsweise($projekt)."',
              '".$this->ZahlungsZielTage($projekt)."',
              '".$this->ZahlungsZielTageSkonto($projekt)."',
              '".$this->ZahlungsZielSkonto($projekt)."',
              'angelegt','$projekt','$adresse','".$ohnebriefpapier."','$angebotersatz_standard')");

        } else {
          $this->app->DB->Insert("INSERT INTO angebot (id,datum,gueltigbis,bearbeiter,usereditid,vertrieb,firma,belegnr,autoversand,zahlungsweise,
          zahlungszieltage,
          zahlungszieltageskonto,
          zahlungszielskonto,
          status,projekt,adresse,ohne_briefpapier,abweichendebezeichnung )
            VALUES ('',NOW(), DATE_ADD(curdate(), INTERVAL ".((int)$this->Firmendaten("angebot_anzahltage")>0?(int)$this->Firmendaten("angebot_anzahltage"):28)." DAY),'','$usereditid','','1','$belegmax',1,'".$this->StandardZahlungsweise($projekt)."',
              '0',
              '0',
              '0',
              'angelegt','$projekt','$adresse','".$ohnebriefpapier."','$angebotersatz_standard')");
        }

        $id = $this->app->DB->GetInsertID();

        $this->CheckVertrieb($id,"angebot");
        $this->CheckBearbeiter($id,"angebot");
        if($standardlager) {
          $this->app->DB->Update("UPDATE angebot SET standardlager = '$standardlager' WHERE id = '$id' LIMIT 1");
        }
        $type="angebot";
        $this->app->erp->ObjektProtokoll($type,$id,$type."_create",ucfirst($type)." angelegt");

        $this->app->erp->AngebotProtokoll($id,"Angebot angelegt");
        $this->SchnellFreigabe("angebot",$id);
        $this->EventAPIAdd("EventAngebotCreate",$id,"angebot","create");
        $this->LoadSteuersaetzeWaehrung($id,"angebot",$projekt);

        return $id;
      }


      function AddAdressePosition($adresse, $verkauf,$menge,$startdatum, $wiederholend = 1, $zahlzyklus = 1)
      {
        $adresse = (int)$adresse;
        $verkauf = (int)$verkauf;
        $menge = (float)str_replace(',','.',$menge);
        $lieferdatum = $this->app->String->Convert($startdatum,"%1.%2.%3","%3-%2-%1");

        $artikel = $this->app->DB->Select("SELECT artikel FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $bezeichnung= $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikel' LIMIT 1");
        $bestellnummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");
        $anabregs_text = $this->app->DB->Select("SELECT anabregs_text FROM artikel WHERE id='$artikel' LIMIT 1");
        $preis = $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $projekt = $this->app->DB->Select("SELECT projekt FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $waehrung = $this->app->DB->Select("SELECT waehrung FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer  FROM artikel WHERE id='$artikel' LIMIT 1");
        $vpe = $this->app->DB->Select("SELECT vpe FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        //$sort = $this->app->DB->Select("SELECT MAX(sort) FROM angebot_position WHERE angebot='$angebot' LIMIT 1");
        $sort = (int)$this->app->DB->Select("SELECT MAX(sort) FROM abrechnungsartikel where adresse = ".$adresse);
        $sort = $sort + 1;
        $this->app->DB->Insert("INSERT INTO abrechnungsartikel (id,artikel,bezeichnung,nummer,menge,preis, sort,
          lieferdatum, steuerklasse, status,projekt,wiederholend,zahlzyklus,adresse,startdatum,waehrung,beschreibung,beschreibungersetzten,dokument,preisart)
            VALUES ('','$artikel','$bezeichnung','$bestellnummer','$menge','$preis','$sort','$lieferdatum',
              '$umsatzsteuer','angelegt','$projekt','$wiederholend','$zahlzyklus','$adresse','$startdatum','$waehrung','$anabregs_text','1','rechnung','monat')");

        return $this->app->DB->GetInsertID();
      }


      function AddAngebotPosition($angebot, $verkauf,$menge,$datum)
      {
        $artikel = $this->app->DB->Select("SELECT artikel FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $bezeichnunglieferant = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikel' LIMIT 1");
        $bestellnummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");
        $beschreibung = $this->app->DB->Select("SELECT anabregs_text FROM artikel WHERE id='$artikel' LIMIT 1");
        $preis = $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $projekt = $this->app->DB->Select("SELECT projekt FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $waehrung = $this->app->DB->Select("SELECT waehrung FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer  FROM artikel WHERE id='$artikel' LIMIT 1");
        $vpe = $this->app->DB->Select("SELECT vpe FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $sort = $this->app->DB->Select("SELECT MAX(sort) FROM angebot_position WHERE angebot='$angebot' LIMIT 1");
        $sort = $sort + 1;
        $this->app->DB->Insert("INSERT INTO angebot_position (id,angebot,artikel,beschreibung,bezeichnung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer, status,projekt,vpe)
            VALUES ('','$angebot','$artikel','$beschreibung','$bezeichnunglieferant','$bestellnummer','$menge','$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe')");
      }

      function DeleteBelegPosition($doctype, $posid)
      {
        $arr = $this->app->DB->SelectArr("SELECT * FROM $doctype"."_position WHERE id = '$posid' LIMIT 1");
        if(!$arr)return false;
        $this->app->DB->Delete("DELETE FROM $doctype"."_position WHERE id = '$posid' LIMIT 1");
        $this->app->DB->Update("UPDATE $doctype"."_position SET sort = sort - 1 WHERE $doctype = '".$arr[0][$doctype]."' AND sort > ".$arr[0]['sort']);
        $akstort = $this->app->DB->SelectArr("SELECT sort FROM beleg_zwischenpositionen WHERE doctype = '$doctype' AND doctypeid = '".$arr[0][$doctype]."' AND pos = '".$arr[0]['sort']."' ORDER BY sort DESC LIMIT 1");
        $offset = 0;
        if($aktsort)$offset = 1 + (int)$aktsort[0]['sort'];
        $this->app->DB->Update("UPDATE beleg_zwischenpositionen SET pos = pos - 1, sort = sort - $offset WHERE doctype = '$doctype' AND doctypeid = '".$arr[0][$doctype]."' AND pos = '".($arr[0]['sort'] + 1)."'");
        $this->app->DB->Update("UPDATE beleg_zwischenpositionen SET pos = pos - 1 WHERE doctype = '$doctype' AND doctypeid = '".$arr[0][$doctype]."' AND pos > '".($arr[0]['sort'] + 1)."'");
        return true;
      }


      function CopyBestellung($id)
      {
        $obj = $this->LoadModul('bestellung');
        if(!empty($obj) && method_exists($obj, 'CopyBestellung'))
        {
          return $obj->CopyBestellung($id);
        }
      }

      function NextProjektnummer($abkuerzung)
      {
        $i = 1;
        $neu = $abkuerzung.$i;
        while($this->app->DB->Select("SELECT id FROM projekt WHERE abkuerzung = '".$this->app->DB->real_escape_string($neu)."' LIMIT 1"))
        {
          $i++;
          $neu =$abkuerzung.$i;
        }
        return $neu;
      }


      function CopyProjektDaten($fromid , $toid, $data = null)
      {
        $id = $fromid;
        $newid = $toid;

        $arbeitspakete = $this->app->DB->SelectArr("SELECT id,vorgaenger FROM arbeitspaket WHERE projekt = '$id'");

        for ($i=0; $i < count($data['arbeitspaket']); $i++) {
          for ($j=0; $j < (!empty($arbeitspakete)?count($arbeitspakete):0); $j++) {
            if(($arbeitspakete[$j]['id'] == $data['arbeitspaket'][$i]) && ($arbeitspakete[$j]['vorgaenger'] != '0')){
              if(!in_array($arbeitspakete[$j]['vorgaenger'], $data['arbeitspaket'])){
                $data['arbeitspaket'][] = $arbeitspakete[$j]['vorgaenger'];
              }
            }
          }
        }


        if($arbeitspakete)
        {
          $alteNeueIds = array();

          foreach($arbeitspakete as $arbeitspaket)
          {
            $do = true;
            if(is_null($data) || (!is_null($data) && !isset($data['arbeitspaket']) || !is_array($data['arbeitspaket']) || !in_array($arbeitspaket['id'], $data['arbeitspaket'])))$do = false;
            if($do)
            {
              $newpaket = $this->app->DB->MysqlCopyRow('arbeitspaket', 'id', $arbeitspaket['id']);
              $alteNeueIds[$arbeitspaket['id']] = $newpaket;
              $idtoid[$arbeitspaket['id']] = $newpaket;
              $newidtoold[$newpaket] = $arbeitspaket['id'];
              $this->app->DB->Update("UPDATE arbeitspaket SET status = 'offen', abgabedatum = '0000-00-00', startdatum = '0000-00-00', projekt = '$newid' WHERE id = '$newpaket' LIMIT 1");
            }
          }
          foreach($arbeitspakete as $arbeitspaket)
          {
            if($arbeitspaket['vorgaenger'] && !empty($idtoid[$arbeitspaket['vorgaenger']]) && !empty($idtoid[$arbeitspaket['id']]))
            {
              $this->app->DB->Update("UPDATE arbeitspaket SET vorgaenger = '".$idtoid[$arbeitspaket['vorgaenger']]."' WHERE id = '".$idtoid[$arbeitspaket['id']]."' LIMIT 1");
            }
          }
          unset($arbeitspakete);
        }
        $artikel = $this->app->DB->SelectArr("SELECT id,parent,teilprojekt FROM projekt_artikel WHERE projekt = '$id' and teilprojekt > 0");
        if($artikel)
        {
          foreach($artikel as $art)
          {
            $do = true;
            if((!isset($idtoid) || !isset($idtoid[$art['teilprojekt']])))$do = false;
            if((!is_null($data) && (!isset($data['artikel']) || !is_array($data['artikel']) || !in_array($art['id'], $data['artikel']))))$do = false;
            if($do)
            {
              $newartikel = $this->app->DB->MysqlCopyRow('projekt_artikel', 'id', $art['id']);
              $this->app->DB->Update("UPDATE projekt_artikel SET projekt = '$newid' WHERE id = '$newartikel' LIMIT 1");
              $this->app->DB->Update("UPDATE projekt_artikel SET teilprojekt = '".$newidtoold[$art['teilprojekt']]."' WHERE id = '$newartikel' LIMIT 1");
              $idtoidart[$art['id']] = $newpaket;
            }
          }
          foreach($artikel as $art)
          {
            if($art['parent'] && !empty($idtoidart[$art['parent']]) && !empty($idtoidart[$art['id']]))
            {
              $this->app->DB->Update("UPDATE projekt_artikel SET parent = '".$idtoidart[$art['parent']]."' WHERE id = '".$idtoidart[$art['id']]."' LIMIT 1");
            }
          }
          unset($idtoidart);
          unset($artikel);
        }
        $adressrollen = $this->app->DB->SelectArr("SELECT id FROM adresse_rolle WHERE projekt = '$id' AND objekt like 'Projekt' AND (bis = '0000-00-00' OR bis >= date(now()))");
        if($adressrollen)
        {
          foreach($adressrollen as $rolle)
          {
            $do = true;
            if(!is_null($data) && (!isset($data['adressrollen']) || !is_array($data['adressrollen']) || !in_array($rolle['id'], $data['adressrollen'])))$do = false;
            if($do)
            {
              $newrolle = $this->app->DB->MysqlCopyRow('adresse_rolle', 'id', $rolle['id']);
              $this->app->DB->Update("UPDATE adresse_rolle SET projekt = '$newid' , parameter = '$newid' WHERE id = '$newrolle' LIMIT 1");
            }
          }
          unset($adressrollen);
        }
        $aufgaben = $this->app->DB->SelectArr("SELECT a.id, a.aufgabe, ap.aufgabe AS teilprojekt, adr.name as mitarbeiter, a.status
                                               FROM aufgabe a 
                                               LEFT JOIN projekt p ON p.id=a.projekt 
                                               LEFT JOIN adresse adr ON a.adresse=adr.id 
                                               LEFT JOIN arbeitspaket ap ON ap.id=a.teilprojekt
                                               WHERE a.projekt = '$id'");

        if($aufgaben){
          foreach($aufgaben as $aufgabe){
            $do = true;
            if((!is_null($data) && (!isset($data['aufgaben']) || !is_array($data['aufgaben']) || !in_array($aufgabe['id'], $data['aufgaben']))))$do = false;
            if($do)
            {
              $newaufgabe = $this->app->DB->MysqlCopyRow('aufgabe', 'id', $aufgabe['id']);
              $this->app->DB->Update("UPDATE aufgabe SET projekt = '$newid', angelegt_am = CURDATE() WHERE id = '$newaufgabe' LIMIT 1");
              $altesTeilprojekt = $this->app->DB->Select("SELECT teilprojekt FROM aufgabe WHERE id = '$newaufgabe' LIMIT 1");
              if($altesTeilprojekt != '' && $altesTeilprojekt > 0){
                if(is_array($alteNeueIds)){
                  if($alteNeueIds[$altesTeilprojekt] > 0){
                    $this->app->DB->Update("UPDATE aufgabe SET teilprojekt = '".$alteNeueIds[$altesTeilprojekt]."' WHERE id = '$newaufgabe' LIMIT 1");
                  }else{
                    $this->app->DB->Update("UPDATE aufgabe SET teilprojekt = 0 WHERE id = '$newaufgabe' LIMIT 1");
                  }
                }
              }
              
            }
          }
          unset($aufgaben);
        }

        $wiedervorlagen = $this->app->DB->SelectArr("SELECT id FROM wiedervorlage WHERE projekt = '$id'");

        if($wiedervorlagen){
          foreach($wiedervorlagen as $wiedervorlage){
            $do = true;
            if(!is_null($data) && (!isset($data['wiedervorlagen']) || !is_array($data['wiedervorlagen']) || !in_array($wiedervorlage['id'], $data['wiedervorlagen']))){
              $do = false;
            }
            if($do){
              $neueWiedervorlage = $this->app->DB->MysqlCopyRow('wiedervorlage', 'id', $wiedervorlage['id']);
              $this->app->DB->Update("UPDATE wiedervorlage SET projekt = '$newid', parameter = '$newid' WHERE id = '$neueWiedervorlage' LIMIT 1");
            }
          }
          unset($wiedervorlagen);
        }
      }

  /**
   * @param $id Project-ID to Copy
   * @param null $data unused
   * @return int|bool return new Project-Id or false on error
   */
      public function CopyProjekt($id, $data = null)
      {
        $id = (int)$id;
        if(!empty($id)){
          $id = $this->app->DB->Select("SELECT id FROM projekt WHERE id = '$id' LIMIT 1");
        }
        if(empty($id)){
          return false;
        }

        $newid = $this->app->DB->MysqlCopyRow('projekt', 'id', $id);
        if(empty($newid))
        {
          return false;
        }
        $abkuerzung = $this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id = '$id' LIMIT 1");
        $abkuerzungneu = $this->NextProjektnummer($abkuerzung);
        if(!empty($abkuerzungneu)){
          $this->app->DB->Update("UPDATE projekt SET abkuerzung = '".$this->app->DB->real_escape_string($abkuerzungneu)."', status = 'gestartet' WHERE id = '$newid' LIMIT 1");
        }
        return $newid;
      }


  /**
   * @param $doctype
   * @param $doctypeid
   * @return int|void
  */
      public function getNextSort($doctype, $doctypeid)
      {
        if($doctypeid <= 0 || !is_numeric($doctypeid) || empty($doctype) || !is_string($doctype) || strpos($doctype,'`') !== false)
        {
          return;
        }
        return 1 + (int)$this->app->DB->Select('SELECT ifnull(max(sort),0) FROM `'.$doctype.'` WHERE id = '.$doctypeid);
      }


      public function CopyVerbindlichkeit($id){
        /** @var Verbindlichkeit $obj */
        $obj = $this->app->erp->LoadModul('verbindlichkeit');
        if(!empty($obj) && method_exists($obj,'copyLiability')) {
          return $obj->copyLiability($id);
        }
        return 0;
      }

      public function CopyAuftrag($id)
      {
        if($id <= 0)
        {
          return;
        }
        // kopiere eintraege aus auftrag_position
        $arr = $this->app->DB->SelectArr(
          sprintf(
            "SELECT NOW() as datum,projekt,freitext,bodyzusatz,adresse,name,shopextid,
            standardlager,ansprechpartner,anschreiben,
            abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,
            ihrebestellnummer,typ,
            versandart,vertrieb,zahlungsweise,zahlungszieltage,lieferdatum,'angelegt' as status,
            rabatt,rabatt1,rabatt2,rabatt3,rabatt4,rabatt5,gruppe,vertriebid,bearbeiterid,provision,provision_summe,
            zahlungszieltageskonto,zahlungszielskonto,firma,'angelegt' as status,abweichendelieferadresse,liefername,
            lieferabteilung,lieferunterabteilung,ust_befreit,angebotid,kommissionskonsignationslager,
            lieferland,lieferstrasse,lieferort,lieferplz,lieferadresszusatz,lieferansprechpartner,autoversand,art,
            sprache,anzeigesteuer,waehrung,kurs,kostenstelle,gln,liefergln,bundesstaat,lieferemail, lieferbedingung
            FROM auftrag WHERE id=%d LIMIT 1",
            $id
          )
        );
        if(empty($arr)) {
          return;
        }
        $this->app->DB->Insert('INSERT INTO auftrag (id) VALUES (NULL)');
        $newid = $this->app->DB->GetInsertID();
        $arr[0]['kundennummer'] = $this->app->DB->Select("SELECT kundennummer FROM adresse WHERE id = '".$arr[0]['adresse']."' LIMIT 1");
        $this->app->DB->UpdateArr('auftrag', $newid, 'id', $arr[0],true);
        $pos = $this->app->DB->SelectArr("SELECT * FROM auftrag_position WHERE auftrag='$id' order by sort, id");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++){
          $this->app->DB->Insert("INSERT INTO auftrag_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $altzuneu[$pos[$i]['id']] = $newposid;
          $pos[$i]['auftrag']=$newid;
          if($pos[$i]['explodiert_parent'] && isset($altzuneu[$pos[$i]['explodiert_parent']]))$pos[$i]['explodiert_parent'] = $altzuneu[$pos[$i]['explodiert_parent']];
          $this->app->DB->UpdateArr('auftrag_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])){
            $this->app->DB->Update("UPDATE auftrag_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }
        $this->CheckFreifelder('auftrag',$newid);
        $this->CopyBelegZwischenpositionen('auftrag',$id,'auftrag',$newid);

        $this->app->DB->Update("UPDATE auftrag_position SET geliefert=0, geliefert_menge=0 WHERE auftrag='$newid'");
        $this->LoadSteuersaetzeWaehrung($newid,'auftrag');
        $this->SchnellFreigabe('auftrag',$newid);
        return $newid;
      }

      function CopyGutschrift($id)
      {
        $obj = $this->LoadModul('gutschrift');
        if(!empty($obj) && method_exists($obj,'CopyGutschrift'))
        {
          return $obj->CopyGutschrift($id);
        }
      }


      function CopyRechnung($id)
      {
        $obj = $this->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'CopyRechnung')){
          return $obj->CopyRechnung($id);
        }
      }

      function CopyPreisanfrage($id)
      {
        /** @var Preisanfrage $obj */
        $obj = $this->app->erp->LoadModul('preisanfrage');
        if(!empty($obj) && method_exists($obj,'CopyPreisanfrage')) {
          return $obj->CopyPreisanfrage($id);
        }
        return 0;
      }

      function CopyProformarechnung($id)
      {
        $this->app->DB->Insert("INSERT INTO proformarechnung (id) VALUES ('')");
        $newid = $this->app->DB->GetInsertID();
        $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,projekt,freitext,bodyzusatz,adresse,'' as belegnr,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,lieferantennummer,bearbeiter,'angelegt' as status,typ,sprache,waehrung,
            firma FROM proformarechnung WHERE id='$id' LIMIT 1");

        $this->app->DB->UpdateArr('proformarechnung', $newid, 'id',$arr[0],true);
        $pos = $this->app->DB->SelectArr("SELECT * FROM proformarechnung_position WHERE proformarechnung='$id'");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++)
        {
          $this->app->DB->Insert("INSERT INTO proformarechnung_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $pos[$i]['proformarechnung']=$newid;
          $this->app->DB->UpdateArr('proformarechnung_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE proformarechnung_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }
        $this->CheckFreifelder("proformarechnung",$newid);
        $this->CopyBelegZwischenpositionen("proformarechnung",$id,"proformarechnung",$newid);
        $this->LoadSteuersaetzeWaehrung($newid,"proformarechnung");
        return $newid;
      }


      function CopyAnfrage($id)
      {
        $this->app->DB->Insert("INSERT INTO anfrage (id) VALUES ('')");
        $newid = $this->app->DB->GetInsertID();
        $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,projekt,bodyzusatz,freitext,adresse,CONCAT(name,' (Kopie)') as name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,bearbeiter,'angelegt' as status,typ,
            firma FROM anfrage WHERE id='$id' LIMIT 1");
        $this->app->DB->UpdateArr('anfrage', $newid, 'id',$arr[0],true);
        $pos = $this->app->DB->SelectArr("SELECT * FROM anfrage_position WHERE anfrage='$id'");

        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++)
        {
          $this->app->DB->Insert("INSERT INTO anfrage_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $pos[$i]['anfrage']=$newid;
          $this->app->DB->UpdateArr('anfrage_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE anfrage_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }
        $this->CheckFreifelder("anfrage",$newid);
        $this->CopyBelegZwischenpositionen("anfrag",$id,"anfrage",$newid);
        $this->LoadSteuersaetzeWaehrung($newid,"anfrage");
        return $newid;
      }

      function CopyInventur($id)
      {
        /** @var Inventur $obj */
        $obj = $this->LoadModul('inventur');
        if(!empty($obj) && method_exists($obj, 'CopyInventur'))
        {
          return $obj->CopyInventur($id);
        }
        return 0;
      }

  /**
   * @deprecated
   *
   */
      public function CopyKalkulation($id)
      {
        $obj = $this->LoadModul('kalkulation');
        if(!empty($obj) && method_exists($obj,'CopyKalkulation'))
        {
          return $obj->CopyKalkulation($id);
        }
      }
      
  /**
   * @deprecated
   *
   */
      public function CopyReisekosten($id)
      {
        /** @var Reisekosten $obj */
        $obj = $this->LoadModul('reisekosten');
        if(!empty($obj) && method_exists($obj,'CopyReisekosten'))
        {
          return $obj->CopyReisekosten($id);
        }
        return 0;
      }


  /**
   * @param $id
   *
   * @return int|null
   */
      public function CopyArbeitsnachweis($id)
      {
        /** @var Arbeitsnachweis $obj */
        $obj = $this->app->erp->LoadModul('arbeitsnachweis');
        if(!empty($obj) && method_exists($obj, 'CopyArbeitsnachweis')) {
          return $obj->CopyArbeitsnachweis($id);
        }
        return 0;
      }


  /**
   * @param $id
   *
   * @return int|null
   */
      public function CopyLieferschein($id)
      {
        /** @var Lieferschein $obj */
        $obj = $this->LoadModul('lieferschein');
        if(!empty($obj) && method_exists($obj, 'CopyLieferschein')){
          return $obj->CopyLieferschein($id);
        }
        return null;
      }

  /**
   * @param int $id
   *
   * @return int|null
   */
      public function CopyRetoure($id)
      {
        $this->app->DB->Insert("INSERT INTO retoure (id) VALUES ('')");
        $newid = $this->app->DB->GetInsertID();
        $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,projekt,lieferschein,lieferscheinid,bodyzusatz,freitext,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,versandart,bearbeiter,'angelegt' as status,typ,standardlager,ansprechpartner,titel,anschreiben,
            firma FROM retoure WHERE id='$id' LIMIT 1");
        $this->app->DB->UpdateArr('retoure',$newid,'id',$arr[0],true);

        $pos = $this->app->DB->SelectArr("SELECT * FROM retoure_position WHERE retoure='$id'");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++) {
          $this->app->DB->Insert("INSERT INTO retoure_position (id) VALUES(NULL)");
          $newposid = $this->app->DB->GetInsertID();
          $altzuneu[$pos[$i]['id']] = $newposid;
          $pos[$i]['lagertext']='';
          $pos[$i]['retoure']=$newid;
          $pos[$i]['menge_eingang'] = 0;
          $pos[$i]['menge_gutschrift'] = 0;
          $pos[$i]['geliefert'] = 0;
          if($pos[$i]['explodiert_parent'] && isset($altzuneu[$pos[$i]['explodiert_parent']])) {
            $pos[$i]['explodiert_parent'] = $altzuneu[$pos[$i]['explodiert_parent']];
          }
          $this->app->DB->UpdateArr('retoure_position',$newposid,'id',$pos[$i],true);
        }
        $this->CheckFreifelder('retoure',$newid);
        $this->CopyBelegZwischenpositionen('retoure',$id,'retoure',$newid);
        $this->app->DB->Update("UPDATE retoure_position SET geliefert=0, abgerechnet=0 WHERE retoure='$newid'");

        $this->SchnellFreigabe("retoure",$newid);
        return $newid;
      }

    function CopyBelegZwischenpositionen($orgtyp,$orgid,$newtyp,$newid, $zwischenpositionen = null)
    {
      $where = '';
      if($zwischenpositionen) {
        foreach($zwischenpositionen as $v)  {
          $wherea[] = " id = '$v' ";
          $where = ' AND ('.implode(' OR ', $wherea).") ";
        }
      }

      $belegpositionen = $this->app->DB->SelectArr("SELECT * FROM beleg_zwischenpositionen WHERE doctype = '$orgtyp' AND doctypeid = '$orgid' $where ");
      if($belegpositionen) {
        $cpos = !empty($belegpositionen)?count($belegpositionen):0;
        for($i=0;$i<$cpos;$i++) {
          $this->app->DB->Insert('INSERT INTO beleg_zwischenpositionen (id) VALUES (NULL)');
          $newposid = $this->app->DB->GetInsertID();
          $belegpositionen[$i]['doctypeid']=$newid;
          $belegpositionen[$i]['doctype']=$newtyp;
          $this->app->DB->UpdateArr('beleg_zwischenpositionen',$newposid,'id',$belegpositionen[$i],true);
        }
      }
    }


      function CopyAngebot($id)
      {

        // kopiere eintraege aus angebot_position
        $this->app->DB->Insert("INSERT INTO angebot (id) VALUES ('')");
        $newid = $this->app->DB->GetInsertID();
        $arr = $this->app->DB->SelectRow("SELECT NOW() as datum,projekt,anfrage,bodyzusatz,freitext,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,versandart,vertrieb,zahlungsweise,zahlungszieltage,ust_befreit,lieferdatum,DATE_ADD(curdate(),INTERVAL ".((int)$this->app->erp->Firmendaten("angebot_anzahltage")>0?(int)$this->app->erp->Firmendaten("angebot_anzahltage"):28)." DAY) as gueltigbis,'angelegt' as status,rabatt,rabatt1,rabatt2,rabatt3,rabatt4,rabatt5,gruppe,vertriebid,bearbeiterid,provision,provision_summe,typ,aktion,titel,ansprechpartner,anschreiben,keinsteuersatz,
            zahlungszieltageskonto,standardlager,zahlungszielskonto,firma,abweichendelieferadresse,liefername,lieferabteilung,lieferunterabteilung,
            lieferland,lieferstrasse,lieferort,lieferplz,lieferadresszusatz,lieferansprechpartner,liefergln,lieferemail,gln,liefertitel,internebezeichnung,lieferdatumkw,lieferbedingung,gesamtsummeausblenden 
            ,sprache,anzeigesteuer,waehrung,kurs,kostenstelle
            FROM angebot WHERE id='$id' LIMIT 1");

        $this->app->DB->UpdateArr('angebot', $newid, 'id', $arr, true);
        $pos = $this->app->DB->SelectArr("SELECT * FROM angebot_position WHERE angebot='$id'");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++) {

          $this->app->DB->Insert("INSERT INTO angebot_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $pos[$i]['angebot']=$newid;
          $this->app->DB->UpdateArr('angebot_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE angebot_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }

        $this->CopyBelegZwischenpositionen('angebot',$id,'angebot',$newid);

        $this->LoadSteuersaetzeWaehrung($newid,'angebot');
        $this->SchnellFreigabe('angebot',$newid);
        return $newid;
      }


      function WeiterfuehrenDateianhang($vonbelegtyp,$vonbelegid,$nachbelegtyp,$nachbelegid){

        $dateien = $this->app->DB->SelectArr("SELECT datei, subjekt,parameter2,objekt2 FROM datei_stichwoerter WHERE objekt LIKE '$vonbelegtyp' AND parameter = '$vonbelegid'");

        if($dateien != ""){
          foreach($dateien as $key=>$value){
            $this->app->erp->AddDateiStichwort($value['datei'], $value['subjekt'], $nachbelegtyp, $nachbelegid,false,$value['parameter2'],$value['objekt2']);
          }
        }
      }


      function WeiterfuehrenAuftragZuLieferschein($id, $positionen = null, $zwischenpositionen = null)
      {
        if($id <= 0) {
          return null;
        }
        // pruefe ob auftrag status=angelegt, dann vergebe belegnr
        $this->CheckClass('FormHandler');

        $this->RunHook('WeiterfuehrenAuftragZuLieferschein', 1, $id);
        $orderArr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT projekt,status,belegnr FROM auftrag WHERE id=%d LIMIT 1',
            $id
          )
        );
        $projekt = $orderArr['projekt'];
        $nurlagerartikel = $this->app->DB->Select("SELECT nurlagerartikel FROM projekt WHERE id = '$projekt' LIMIT 1");
        $status = $orderArr['status'];
        $checkbelegnr = $orderArr['belegnr'];
        if($status === 'angelegt' && $checkbelegnr == ''){
          $belegnr = $this->GetNextNummer("auftrag", $projekt, $id);

          $this->app->DB->Update("UPDATE auftrag SET belegnr='$belegnr', status='freigegeben'  WHERE id='$id' LIMIT 1");
          $this->AuftragProtokoll($id, "Auftrag freigegeben");

          // auftrag abschliessen und event senden
          $this->EventAPIAdd("EventAuftragEdit", $id, "auftrag", "edit");
        }
        $bundesland = $this->app->DB->Select("SELECT bundesland FROM auftrag WHERE id = '$id' LIMIT 1");
        $bundesstaat = $this->app->DB->Select("SELECT bundesstaat FROM auftrag WHERE id = '$id' LIMIT 1");

        $arr = $this->app->DB->SelectArr("SELECT datum,ihrebestellnummer,projekt,belegnr as auftrag,bodyzusatz,freitext,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,titel,lieferbedingung,ansprechpartner,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,versandart,vertrieb,zahlungsweise,zahlungszieltage,anschreiben, id as auftragid,vertriebid, bearbeiter,bearbeiterid, internebemerkung,projektfiliale,typ,standardlager,ust_befreit,gln, ohne_artikeltext,sprache,kostenstelle,lieferid,
            zahlungszieltageskonto,zahlungszielskonto,firma,'angelegt' as status,internebezeichnung,lieferantenauftrag as lieferantenretoure,lieferant,kommissionskonsignationslager FROM auftrag WHERE id='$id' LIMIT 1");


        $check_mail = $this->app->DB->Select("SELECT lieferschein_email FROM adresse WHERE id='".$arr[0]['adresse']."'");
        if($check_mail!="") {
          $arr[0]['email'] = $check_mail;
        }
        $arr2 = $this->app->DB->SelectArr("SELECT gln, liefergln FROM auftrag WHERE id = '$id' LIMIT 1");
        $abweichendelieferadresse = $this->app->DB->Select("SELECT abweichendelieferadresse FROM auftrag WHERE id='$id' LIMIT 1");
        $tmparrliefer = $this->app->DB->SelectArr("SELECT * FROM auftrag WHERE id='$id' LIMIT 1");
        foreach($tmparrliefer[0] as $k => $v) {
          $tmparrliefer[0][$k] = $this->app->DB->real_escape_string($v);
        }
        $versandart = $this->app->DB->Select("SELECT versandart FROM auftrag WHERE id='$id' LIMIT 1");

        $poswheretmp = '';
        if($this->Firmendaten("dienstleistungsartikel_nicht_zu_lieferschein")=="1"){
          $poswheretmp = ' AND art.dienstleistung = 0';
        }

        if(!empty($positionen))
        {
          $posa = null;
          foreach($positionen as $v)
          {
            $posa[] = " ap.id = '$v' ";
          }
          $poswheretmp .= ' AND ('.implode(' OR ',$posa).') ';
        }

        if($nurlagerartikel)
        {
          $pos = $this->app->DB->SelectArr("SELECT ap.*,art.porto AS artikelporto FROM auftrag_position ap INNER JOIN artikel art ON ap.artikel = art.id AND (art.lagerartikel = 1 OR (art.stueckliste = 1 AND art.juststueckliste = 1)) WHERE ap.auftrag='$id' $poswheretmp order by ap.sort");
        }else{
          $pos = $this->app->DB->SelectArr("SELECT ap.*,art.porto AS artikelporto FROM auftrag_position ap LEFT JOIN artikel art ON ap.artikel = art.id WHERE ap.auftrag='$id' $poswheretmp order by ap.sort");
        }

        if(empty($pos))
        {
          return null;
        }
        $portoartikelArr = [];
        $haspositions = false;
        foreach($pos as $positem)
        {
          $portoartikelArr[$positem['id']] = $positem['artikelporto'];
          if((int)$positem['artikelporto']===0)
          {
            $haspositions = true;
          }
        }
        if(!$haspositions){
          return null;
        }

        $newid = $this->CreateLieferschein($arr[0]['adresse']);

        if($this->Firmendaten('dateienweiterfuehren')){
          $this->WeiterfuehrenDateianhang("Auftrag", $id, "Lieferschein", $newid);
        }

        $this->app->DB->UpdateArr("lieferschein",$newid,'id',$arr[0],true);

        if(!empty($bundesland)){
          $this->app->DB->Update("UPDATE lieferschein SET bundesland='".$this->app->DB->real_escape_string($bundesland)."' WHERE id='$newid' LIMIT 1");
        }

        if(!empty($bundesstaat)){
          $this->app->DB->Update("UPDATE lieferschein SET bundesstaat='".$this->app->DB->real_escape_string($bundesstaat)."' WHERE id='$newid' LIMIT 1");
        }

        $this->app->DB->Update("UPDATE lieferschein SET datum=NOW() WHERE id='$newid' LIMIT 1");



        //lieferadresse wenn abweichend!!!!
        if($abweichendelieferadresse && $versandart!="packstation")
        {
          if($tmparrliefer[0]['lieferemail']=="") {
            $tmparrliefer[0]['lieferemail'] = $arr[0]['email'];
          }

          //liefername  lieferland  lieferstrasse   lieferort   lieferplz   lieferadresszusatz
          $this->app->DB->Update("UPDATE lieferschein SET name='{$tmparrliefer[0]['liefername']}', abteilung='{$tmparrliefer[0]['lieferabteilung']}',
              unterabteilung='{$tmparrliefer[0]['lieferunterabteilung']}',strasse='{$tmparrliefer[0]['lieferstrasse']}',titel='{$tmparrliefer[0]['liefertitel']}',
              email='{$tmparrliefer[0]['lieferemail']}',
              adresszusatz='{$tmparrliefer[0]['lieferadresszusatz']}', plz='{$tmparrliefer[0]['lieferplz']}',ort='{$tmparrliefer[0]['lieferort']}',land='{$tmparrliefer[0]['lieferland']}',ansprechpartner='{$tmparrliefer[0]['lieferansprechpartner']}' WHERE id='$newid' LIMIT 1");
          if($tmparrliefer[0]['liefergln']!="")
            $this->app->DB->Update("UPDATE lieferschein SET gln = '{$tmparrliefer[0]['liefergln']}' WHERE id = '$newid' LIMIT 1");
          if($tmparrliefer[0]['lieferbundesstaat']!='') {
            $this->app->DB->Update("UPDATE `lieferschein` SET `bundesstaat` = '{$tmparrliefer[0]['lieferbundesstaat']}' WHERE `id` = '{$newid}' LIMIT 1");
          }
        }

        //lieferadresse wenn packstation
        if($versandart=="packstation")
        {
          //packstation_inhaber   packstation_station         packstation_ident   packstation_plz   packstation_ort
          $this->app->DB->Update("UPDATE lieferschein SET name='{$tmparrliefer[0]['packstation_inhaber']}', unterabteilung='',strasse='Packstation Nr. {$tmparrliefer[0]['packstation_station']}', adresszusatz='{$tmparrliefer[0]['packstation_ident']}',
              plz='{$tmparrliefer[0]['packstation_plz']}',ort='{$tmparrliefer[0]['packstation_ort']}' WHERE id='$newid' LIMIT 1");
        }

        $portosorts = null;
        $cpos = $pos?count($pos):0;
      
	  for($i=0;$i<$cpos;$i++){
          /* nur lager artikel in den Lieferschein */

          $portoartikel = !empty($portoartikel)?$portoartikelArr[$pos[(int) $i]]:0;
          if($portoartikel==0) {
            $this->app->DB->Insert("INSERT INTO lieferschein_position (id) VALUES('')");
            $newposid = $this->app->DB->GetInsertID();
            $auftragzulieferschein[$pos[$i]['id']] = $newposid;
            $pos[$i]['lieferschein']=$newid;
            $pos[$i]['auftrag_position_id']=$pos[$i]['id'];
            if($pos[$i]['explodiert']) {
              $pos[$i]['bezeichnung'] = $pos[$i]['bezeichnung'];//." (Stückliste)";
            }

            if($pos[$i]['explodiert_parent'] > 0) {

            $aktlvl = 1;
            $aktparent = $pos[$i]['explodiert_parent'];
            while(true)
            {
              if($aktlvl > 10) {
                break;
              }
              $aktparent = $this->app->DB->Select("SELECT explodiert_parent FROM auftrag_position WHERE id = '".$aktparent."' LIMIT 1");

              if(!$aktparent) {
                break;
              }
              $aktlvl++;
            }
            if($aktlvl > 1) {
              $pos[$i]['bezeichnung'] = str_repeat("*", $aktlvl - 1).$pos[$i]['bezeichnung'];
            }

            $pos[$i]['explodiert_parent_artikel'] = $this->app->DB->Select("SELECT artikel FROM auftrag_position WHERE id='".$pos[$i]['explodiert_parent']."' LIMIT 1");

            $pos[$i]['explodiert_parent'] = isset($auftragzulieferschein[$pos[$i]['explodiert_parent']])?$auftragzulieferschein[$pos[$i]['explodiert_parent']]:0;
          }
          $this->app->DB->UpdateArr("lieferschein_position",$newposid,'id',$pos[$i],true);
        }else{
          $portosorts[] = $i;
        }
      }
        
      if($this->Firmendaten('auftragabschliessen')!='1') {
        $this->app->DB->Update("UPDATE auftrag SET status='abgeschlossen',schreibschutz='1' WHERE id='$id' LIMIT 1");
        $this->app->DB->Update("UPDATE auftrag_position SET geliefert_menge=menge WHERE auftrag='$id'");
      }

      $this->CheckFreifelder("lieferschein",$newid);

      if(!empty($positionen) && !empty($zwischenpositionen)){
        $this->CopyBelegZwischenpositionen('auftrag', $id, 'lieferschein', $newid, $zwischenpositionen);
      }
      elseif(empty($positionen)) {
        $this->CopyBelegZwischenpositionen('auftrag', $id, 'lieferschein', $newid);
      }

      if(!empty($portosorts)) {
        foreach($portosorts as $k => $v) {
          if($v == (!empty($pos)?count($pos):0) -1)
          {
            $this->app->DB->Delete("DELETE FROM beleg_zwischenpositionen WHERE doctype = 'lieferschein' AND doctypeid = '$newid' AND pos = '".($v)."' AND postype LIKE 'gruppe'");
          }
          elseif($this->app->DB->Select("SELECT id FROM beleg_zwischenpositionen WHERE doctype = 'lieferschein' AND doctypeid = '$newid' AND pos = '".($v+1)."' AND postype LIKE 'gruppe' LIMIT 1")) {
            $this->app->DB->Delete("DELETE FROM beleg_zwischenpositionen WHERE doctype = 'lieferschein' AND doctypeid = '$newid' AND pos = '".($v)."' AND postype LIKE 'gruppe'");
          }
        }
      }
      $this->BelegNeusortieren('lieferschein', $newid);
      // auftrag freigeben!!!
      $this->SchnellFreigabe("lieferschein",$newid);
      $this->LieferscheinNeuberechnen($newid);
      $this->RunHook('weiterfuehrenauftragzulieferschein_ende', 2, $id, $newid);
      return $newid;
    }

    function BelegNeusortieren($doctype, $id)
    {
      $arr = $this->app->DB->SelectArr("SELECT id, sort FROM $doctype"."_position WHERE $doctype = '$id' ORDER BY sort, id");
      if(empty($arr)) {
        return;
      }
      $altsort = 0;
      foreach($arr as $k => $v) {
        if($v['sort'] > ($k+1)) {
          $diff = $v['sort'] - ($k+1);
          $this->app->DB->Update("UPDATE $doctype"."_position SET sort = sort - $diff WHERE id = '".$v['id']."' LIMIT 1");
          for($sort = ($k+1); $sort < $v['sort']; $sort++) {
            $beleg_zwischenpositionensort = $this->app->DB->SelectArr("SELECT id, sort FROM beleg_zwischenpositionen where doctype = '$doctype' AND doctypeid = '$id' AND pos = '".($sort-1)."' ORDER BY sort DESC LIMIT 1");
            $offset = 0;
            if($beleg_zwischenpositionensort) {
              $offset = 1 + $beleg_zwischenpositionensort[0]['sort'];
            }
            $this->app->DB->Update("UPDATE beleg_zwischenpositionen SET pos = pos - $diff, sort = sort + $offset WHERE doctype = '$doctype' AND doctypeid = '$id' AND pos = '$sort'");
          }
        }
      }
      //Belegpositionen nach letzter Position
      $sort = (!empty($arr)?count($arr):0);
      $restpositionen = $this->app->DB->SelectArr("SELECT id FROM  beleg_zwischenpositionen where doctype = '$doctype' AND doctypeid = '$id' AND pos > $sort ORDER BY pos, sort");
      if($restpositionen) {
        $beleg_zwischenpositionensort = $this->app->DB->SelectArr("SELECT id, sort FROM beleg_zwischenpositionen where doctype = '$doctype' AND doctypeid = '$id' AND pos = '".($sort)."' ORDER BY sort DESC LIMIT 1");
        $offset = 0;
        if($beleg_zwischenpositionensort) {
          $offset = 1 + $beleg_zwischenpositionensort[0]['sort'];
        }
        foreach($restpositionen as $k => $v) {
          $this->app->DB->Update("UPDATE beleg_zwischenpositionen SET pos = '".$sort."', sort = '".($offset + $k)."' WHERE id = '".$v['id']."' LIMIT 1");
        }
      }
      //Luecken in Zwischenpositionen
      $restpositionen = $this->app->DB->SelectArr("SELECT id,pos,sort FROM  beleg_zwischenpositionen where doctype = '$doctype' AND doctypeid = '$id' ORDER BY pos, sort");
      if(empty($restpositionen)) {
        return;
      }

      $aktpos = -1;
      $k2 = -1;
      foreach($restpositionen as $k => $v) {
        if($v['pos'] != $aktpos) {
          $k2 = -1;
          $aktpos = $v['pos'];
        }
        $k2++;
        if($v['sort'] > $k2) {
          $this->app->DB->Update("UPDATE beleg_zwischenpositionen SET sort = $k2 WHERE id = '".$v['id']."' LIMIT 1");
        }
      }
    }


      function CheckFreifelderEinzelPos($table, $id, $force = false, $posid = 0){
        $language = $this->app->erp->GetSpracheBelegISO($table,$id);
        $pos = $this->app->DB->SelectRow("SELECT * FROM ".$table."_position WHERE ".$table."='$id' AND id = '$posid' LIMIT 1");
        if(empty($pos)) {
          return;
        }

        $artikel_id = $pos['artikel'];

        $tmpfreifelder = $this->app->DB->SelectArr("SELECT * FROM artikel WHERE id='".$artikel_id."' LIMIT 1");
        if(empty($tmpfreifelder)) {
          return;
        }

        $langFreifeld = [];
        $freifelderLang = $this->app->DB->SelectArr("SELECT nummer, wert FROM artikel_freifelder WHERE artikel=$artikel_id AND sprache='$language'");
        if(!empty($freifelderLang)) {
          foreach($freifelderLang as $freifelderLangRow)  {
            $langFreifeld[(int)$freifelderLangRow['nummer']] = $freifelderLangRow['wert'];
          }
        }
        for($ifreifeld=1; $ifreifeld<=40; $ifreifeld++)  {
          $check_language = !empty($langFreifeld[$ifreifeld])?$langFreifeld[$ifreifeld]:'';
          $tmpfreifelder[0]['freifeld'.$ifreifeld] = $this->app->DB->real_escape_string(($check_language!=""?$check_language:$tmpfreifelder[0]['freifeld'.$ifreifeld]));
        }

        switch($table){
          case "angebot": $kurz="an"; break;
          case "auftrag": $kurz="ab"; break;
          case "rechnung": $kurz="re"; break;
          case "gutschrift": $kurz="gs"; break;
          case "lieferschein": $kurz="ls"; break;
          case "bestellung": $kurz="be"; break;
          case "proformarechnung": $kurz="pr"; break;
          case "preisanfrage": $kurz="pa"; break;
          case "produktion": $kurz="pd"; break;
        }
        for($ifreifeld=1; $ifreifeld<=40; $ifreifeld++){
          $pos['freifeld'.$ifreifeld] = $this->app->DB->real_escape_string($pos['freifeld'.$ifreifeld]);
          if($this->app->erp->Firmendaten("freifeld".$ifreifeld.$kurz)=="1" && $pos['freifeld'.$ifreifeld] == ""){
            $this->app->DB->Update("UPDATE ".$table."_position SET freifeld".$ifreifeld."='".$tmpfreifelder[0]['freifeld'.$ifreifeld]."' WHERE id='".$pos['id']."'");
          }
          elseif($this->app->erp->Firmendaten("freifeld".$ifreifeld.$kurz)=="1" && $pos['freifeld'.$ifreifeld] != ""){
            $this->app->DB->Update("UPDATE ".$table."_position SET freifeld".$ifreifeld."='".($force?$tmpfreifelder[0]['freifeld'.$ifreifeld]:$pos['freifeld'.$ifreifeld])."' WHERE id='".$pos['id']."'");
          }
          elseif($this->app->erp->Firmendaten("freifeld".$ifreifeld.$kurz)!="1"){
            $this->app->DB->Update("UPDATE ".$table."_position SET freifeld".$ifreifeld."='' WHERE id='".$pos['id']."'");
          }
        }
      }


    // entsprechend der Firmendaten die Freifelder beim Weiterfuehren vom Dokument fuellen
    function CheckFreifelder($table,$id, $force = false)
    {
      $language = $this->app->erp->GetSpracheBelegISO($table,$id);

      $pos = $this->app->DB->SelectArr(
        sprintf(
          'SELECT * FROM `%s` WHERE `%s`=%d', 
          $table.'_position', $table, (int)$id
        )
      );
      if(empty($pos)) {
        return;
      }

      $articles = [];
      foreach($pos as $row) {
        if((int)$row['artikel'] > 0 && !in_array((int)$row['artikel'], $articles)) {
          $articles[] = (int)$row['artikel'];
        }
      }
      $freifelderLangs = [];
      $freifelderLangQuery = $this->app->DB->Query('SELECT artikel, nummer, wert FROM artikel_freifelder WHERE artikel IN ('.implode(', ', $articles).") AND sprache='$language'");
      if(!empty($freifelderLangQuery)) {
        while ($row = $this->app->DB->Fetch_Assoc($freifelderLangQuery)) {
          $freifelderLangs[$row['artikel']][] = $row;
        }
        $this->app->DB->free($freifelderLangQuery);
      }

      $articleQuery = $this->app->DB->Query('SELECT * FROM artikel WHERE id IN ('.implode(', ', $articles).')');
      if(!empty($articleQuery)){
        while ($row = $this->app->DB->Fetch_Assoc($articleQuery)) {
          $articles[$row['id']] = $row;
        }
        $this->app->DB->free($articleQuery);
      }

      switch($table)
      {
        case 'angebot': $kurz='an'; break;
        case 'auftrag': $kurz='ab'; break;
        case 'rechnung': $kurz='re'; break;
        case 'gutschrift': $kurz='gs'; break;
        case 'lieferschein': $kurz='ls'; break;
        case 'bestellung': $kurz='be'; break;
        case 'proformarechnung': $kurz='pr'; break;
        case 'preisanfrage': $kurz='pa'; break;
        case 'produktion': $kurz='pd'; break;
      }
      
      $cpos = (!empty($pos)?count($pos):0);
      for($i=0;$i<$cpos;$i++)
      {
        $artikel_id = $pos[$i]['artikel'];

        $tmpfreifelder = !empty($articles[$artikel_id])?[$articles[$artikel_id]]:null;
        if(!empty($tmpfreifelder))
        {
          $langFreifeld = [];
          $freifelderLang = !empty($freifelderLangs[$artikel_id])?$freifelderLangs[$artikel_id]:null;
          if(!empty($freifelderLang))
          {
            foreach($freifelderLang as $freifelderLangRow)
            {
              $langFreifeld[(int)$freifelderLangRow['nummer']] = $freifelderLangRow['wert'];
            }
          }
          for($ifreifeld=1;$ifreifeld<=40;$ifreifeld++)
          {
            $check_language = !empty($langFreifeld[$ifreifeld])?$langFreifeld[$ifreifeld]:'';
            $tmpfreifelder[0]['freifeld'.$ifreifeld] = $this->app->DB->real_escape_string(($check_language!=""?$check_language:$tmpfreifelder[0]['freifeld'.$ifreifeld]));
          }

          $updateArr = [];

          for($ifreifeld=1;$ifreifeld<=40;$ifreifeld++)
          {
            $isFreifeldKurz = $this->app->erp->Firmendaten('freifeld'.$ifreifeld.$kurz)=='1';
            $posFreifeld = $pos[$i]['freifeld'.$ifreifeld];
            $posFreifeldEscaped = $this->app->DB->real_escape_string($posFreifeld);
            if($isFreifeldKurz && $posFreifeld=='' && $posFreifeld !== $tmpfreifelder[0]['freifeld' . $ifreifeld]){
              $updateArr['freifeld'.$ifreifeld] = $tmpfreifelder[0]['freifeld' . $ifreifeld];
            }
            else if($isFreifeldKurz && $pos[$i]['freifeld'.$ifreifeld]!=''){
              $newValue = ($force ? $tmpfreifelder[0]['freifeld' . $ifreifeld] : $posFreifeldEscaped);
              if($posFreifeld !== $newValue){
                $updateArr['freifeld'.$ifreifeld] = $newValue;
              }
            }
            else if (!$isFreifeldKurz && $posFreifeld !== '') {
              $updateArr['freifeld'.$ifreifeld] = '';
            }
          }
          if(!empty($updateArr)) {
            $this->app->DB->UpdateArr($table.'_position', (int)$pos[$i]['id'], 'id', $updateArr);
          }
        }
      }
    }

      function LagerAuslagernObjektLagerPlatz($artikel,$pos, $regal,$menge, $objekt = 'lieferschein')
      {
        $check = $this->app->DB->SelectArr("SELECT * FROM objekt_lager_platz WHERE lager_platz = '$regal' AND objekt = '$objekt' AND parameter = '$pos' AND artikel = '$artikel' LIMIT 1");
        if($check)
        {
          $this->app->DB->Update("UPDATE objekt_lager_platz set menge = menge + '".$menge."' WHERE id = '".$check[0]['id']."'");
        }else{
          $this->app->DB->Insert("INSERT into objekt_lager_platz (objekt, lager_platz, parameter, artikel,menge) values ('$objekt', '$regal', '$pos','$artikel' ,'$menge')");
        }
      }

      function LagerAuslagernText($artikel,$pos, $regal,$menge, $objekt = 'lieferschein')
      {
        $this->LagerAuslagernObjektLagerPlatz($artikel,$pos, $regal,$menge, $objekt);
        $this->AddLagerPlatzText($pos, $objekt);
      }

      function AddLagerPlatzText($parameter, $objekt = 'lieferschein',$return=false)
      {
        $parameter = (int)$parameter;
        $olp = $this->app->DB->SelectArr("SELECT * FROM objekt_lager_platz WHERE objekt = '$objekt' AND parameter = '$parameter' ORDER BY menge DESC");
        $text = '';
        foreach($olp as $k => $v)
        {
          $kurzbezeichnung = $this->app->DB->Select("SELECT kurzbezeichnung FROM lager_platz WHERE id = '".$v['lager_platz']."' LIMIT 1");
          if($text != '')$text .= ', ';
          if($v['menge'] == round($v['menge']))$v['menge'] = round($v['menge']);
          $text .= $kurzbezeichnung.' ('.$v['menge'].')';
        }

        if($return) return $text;

        switch($objekt)
        {
          case 'lieferschein':
            $this->app->DB->Update("UPDATE ".$objekt."_position SET lagertext = '$text' WHERE id = '$parameter' LIMIT 1");
          break;
        }
        return true;
      }

      function WeiterfuehrenLieferscheinZuRechnung($id)
      {
        $adresse = $this->app->DB->Select("SELECT adresse FROM lieferschein WHERE id='$id' LIMIT 1");
        $newid = $this->CreateRechnung($adresse);

        if($this->Firmendaten('dateienweiterfuehren')){
          $this->WeiterfuehrenDateianhang("Lieferschein", $id, "Rechnung", $newid);
        }

        $this->LoadRechnungStandardwerte($newid,$adresse);
        if($newid)$this->app->DB->Update("UPDATE lieferschein SET rechnungid = '$newid' WHERE (rechnungid = 0 OR isnull(rechnungid)) AND id = '$id' LIMIT 1");
        if($newid)$this->app->DB->Update("UPDATE lieferschein_position SET abgerechnet = '1' WHERE lieferschein = '$id'");
        if($newid)$this->app->DB->Update("UPDATE rechnung SET lieferschein = '$id' WHERE id = '$newid' LIMIT 1");
        if($this->app->erp->Firmendaten("schnellanlegen_ohnefreigabe")=="1")
        {
          $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,ihrebestellnummer,projekt, anschreiben, id as lieferschein,bodyzusatz,auftrag,auftragid, internebemerkung,
            freitext,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,ansprechpartner,titel,lieferbedingung,plz,ort,land,email,telefon,telefax,betreff,kundennummer,ohne_artikeltext,
            versandart, vertriebid,vertrieb,sprache,projektfiliale,typ,internebezeichnung,bearbeiterid,ustid,ust_befreit,kostenstelle,
            gln FROM lieferschein WHERE id='$id' LIMIT 1");
        } else {
          $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,ihrebestellnummer,projekt, anschreiben, id as lieferschein,bodyzusatz,auftrag,auftragid,internebemerkung,
            freitext,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,ansprechpartner,titel,lieferbedingung,plz,ort,land,email,telefon,telefax,betreff,kundennummer,ohne_artikeltext,
            versandart, vertriebid,vertrieb,sprache,projektfiliale,typ,internebezeichnung,bearbeiterid,ustid,ust_befreit,kostenstelle,
            'angelegt' as status, gln FROM lieferschein WHERE id='$id' LIMIT 1");
        }


        $abweichende_rechnungsadresse = $this->app->DB->SelectArr("SELECT abweichende_rechnungsadresse,rechnung_name,rechnung_titel,rechnung_typ,rechnung_strasse,rechnung_ort,rechnung_plz,rechnung_ansprechpartner,
        rechnung_land,rechnung_abteilung,rechnung_unterabteilung,rechnung_adresszusatz,rechnung_telefon,rechnung_telefax,rechnung_anschreiben,	rechnung_email,rechnung_gln
        FROM adresse WHERE id = '$adresse' LIMIT 1");
        if($abweichende_rechnungsadresse && $abweichende_rechnungsadresse[0]['abweichende_rechnungsadresse'] && $abweichende_rechnungsadresse[0]['rechnung_name'])
        {
          // abweichende Rechnungsadresse sticht
          foreach($abweichende_rechnungsadresse[0] as $k => $v)
          {
            if($k != 'abweichende_rechnungsadresse')
              $arr[0][str_replace('rechnung_','',$k)] = $v;
          }
        } else if ($arr[0]['auftragid']) {
          // adresse aus auftrag wenn vorhanden
          $abweichende_rechnungsadresse = $this->app->DB->SelectArr("SELECT name as rechnung_name,titel as rechnung_titel,typ as rechnung_typ,
            strasse as rechnung_strasse,ort as rechnung_ort,plz as rechnung_plz,ansprechpartner as rechnung_ansprechpartner,
            land as rechnung_land,abteilung as rechnung_abteilung,unterabteilung as rechnung_unterabteilung,
            adresszusatz as rechnung_adresszusatz,telefon as rechnung_telefon,telefax as rechnung_telefax,anschreiben as rechnung_anschreiben,	
            email as rechnung_email, gln as rechnung_gln
            FROM auftrag WHERE id = '".$arr[0]['auftragid']."' LIMIT 1");
          foreach($abweichende_rechnungsadresse[0] as $k => $v)
          {
            if($k != 'abweichende_rechnungsadresse')
              $arr[0][str_replace('rechnung_','',$k)] = $v;
          }

        }
        // this is not the different invoice email - this is the forced email for invoices!
        $check_mail = $this->app->DB->Select("SELECT rechnungs_email FROM adresse WHERE id='$adresse'");
        if($check_mail!="") $arr[0]['email'] = $check_mail;

        $this->app->DB->UpdateArr('rechnung', $newid, 'id', $arr[0], true);



      if($arr[0]['auftragid'])
      {
        $aufarr = $this->app->DB->SelectArr("SELECT zahlungsweise,zahlungszieltage,zahlungszieltageskonto,zahlungszielskonto,waehrung,steuersatz_normal,steuersatz_ermaessigt FROM auftrag WHERE id = '".$arr[0]['auftragid']."' LIMIT 1");
        if($aufarr)
        {
          $this->app->DB->UpdateArr('rechnung',$newid,'id',$aufarr[0],true);
        }
      }

      $pos = $this->app->DB->SelectArr("SELECT * FROM lieferschein_position WHERE lieferschein='$id' order by sort");
      $cpos = !empty($pos)?count($pos):0;
      for($i=0;$i<$cpos;$i++) {
          $this->app->DB->Insert("INSERT INTO rechnung_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $lieferscheinzurechnung[$pos[$i]['id']] = $newposid;
          if(!empty($pos[$i]['explodiert_parent'])) {
            $pos[$i]['explodiert_parent'] = isset($lieferscheinzurechnung[$pos[$i]['explodiert_parent']])?$lieferscheinzurechnung[$pos[$i]['explodiert_parent']]:0;
          }
          $pos[$i]['rechnung']=$newid;

          if($pos[$i]['auftrag_position_id'] > 0)
          {
            $tmpap = $this->app->DB->SelectArr("SELECT * FROM auftrag_position WHERE id='".$pos[$i]['auftrag_position_id']."' LIMIT 1");
            foreach($tmpap[0] as $key=>$value)
            {
                if($key!="id" && $key!="menge" && ($key!="bezeichnung" && $value!="") && ($key!="beschreibung" && $value!="")) {
                  $pos[$i][$key]=$value;
                }
            }
          } else {
            $pos[$i]['preis']=$this->GetVerkaufspreis($pos[$i]['artikel'],$pos[$i]['menge'],$adresse);
            $umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id='".$pos[$i]['artikel']."' LIMIT 1");
            if($umsatzsteuer=="ermaessigt") {
              $pos[$i]['umsatzsteuer']=$umsatzsteuer;
            }
            if($umsatzsteuer=="befreit") {
              $pos[$i]['umsatzsteuer']=$umsatzsteuer;
            }
          }
          $this->app->DB->UpdateArr('rechnung_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE rechnung_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }

        if($this->Firmendaten('dateienweiterfuehren')){
          foreach($lieferscheinzurechnung as $oldpos => $newpos){
            $this->app->DB->Update("UPDATE datei_stichwoerter SET parameter2='$newpos' 
            WHERE LOWER(objekt)='rechnung' AND parameter='$newid' AND objekt2='position' AND parameter2=".$oldpos);
          }
          $this->app->DB->Update("UPDATE datei_stichwoerter SET parameter2='0', objekt2='' 
          WHERE LOWER(objekt)='rechnung' AND parameter='$newid' AND objekt2='position' AND NOT parameter2 IN (".implode(',',$lieferscheinzurechnung).")");
        }

        $portoExistsInInvoice = ($this->app->DB->Select("SELECT rp.id FROM rechnung_position rp INNER JOIN artikel art ON rp.artikel = art.id AND art.porto = 1 AND rp.rechnung='".$newid."' LIMIT 1") > 0? true:false);

        if($arr[0]['auftragid'] && !$portoExistsInInvoice)
        {
          $portopositionen = $this->app->DB->SelectArr("SELECT ap.* FROM auftrag_position ap INNER JOIN artikel art ON ap.artikel = art.id AND art.porto = 1 AND ap.auftrag='".$arr[0]['auftragid']."' ORDER by ap.sort");
          if($portopositionen)
          {
            foreach($portopositionen as $portopos)
            {
              $this->app->DB->Insert("INSERT INTO rechnung_position (id) VALUES('')");
              $newposid = $this->app->DB->GetInsertID();
              $sort = 1+$this->app->DB->Select("SELECT ifnull(max(sort),0) FROM rechnung_position WHERE rechnung = '$newid'");
              $portopos['sort'] = $sort;
              unset($portopos['auftrag']);
              $portopos['auftrag_position_id'] = $portopos['id'];
              unset($portopos['id']);
              $portopos['rechnung'] = $newid;
              $this->app->DB->UpdateArr('rechnung_position',$newposid,'id',$portopos,true);
              if(is_null($portopos['steuersatz'])) {
                $this->app->DB->Update("UPDATE rechnung_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
              }
            }
          }
        }

        if(!empty($arr[0]['auftragid'])) {
          $orderRow = $this->app->DB->SelectRow(
              sprintf(
                  'SELECT storage_country,deliverythresholdvatid FROM auftrag WHERE id = %d',
                  $arr[0]['auftragid']
              )
          );
          if(!empty($orderRow['storage_country'])) {
            $this->app->DB->Update(
                sprintf(
                    "UPDATE rechnung SET storage_country = '%s' WHERE id = %d",
                    $this->app->DB->real_escape_string($orderRow['storage_country']), $newid
                )
            );
          }
          if(!empty($orderRow['deliverythresholdvatid'])) {
            $this->app->DB->Update(
              sprintf(
                "UPDATE rechnung SET deliverythresholdvatid = '%s' WHERE id = %d",
                $this->app->DB->real_escape_string($orderRow['deliverythresholdvatid']), $newid
              )
            );
          }
        }

        $ohnebriefpapier = $this->Firmendaten("rechnung_ohnebriefpapier");
        //$stornorechnung = $this->Firmendaten("stornorechhung_standard");

        $this->CheckFreifelder("rechnung",$newid);
        $this->CopyBelegZwischenpositionen("lieferschein",$id,"rechnung",$newid);

        $this->app->DB->Update("UPDATE rechnung SET ohne_briefpapier='".$ohnebriefpapier."' WHERE id='$newid,' LIMIT 1");
        //$this->app->DB->Update("UPDATE rechnung SET stornorechnung='$stornorechnung', ohne_briefpapier='".$ohnebriefpapier."' WHERE id='$newid,' LIMIT 1");

        $this->app->DB->Update("UPDATE lieferschein SET schreibschutz='1' WHERE id='$id' LIMIT 1");

        //$this->SchnellFreigabe("rechnung",$newid); // braucht man nicht wegen create
        $this->ANABREGSNeuberechnen($newid,"rechnung");
        return $newid;
      }


      function WeiterfuehrenRechnungZuGutschrift($id, $grund = "Rechnung storniert")
      {
        $adresse = $this->app->DB->Select("SELECT adresse FROM rechnung WHERE id='$id' LIMIT 1");
        $newid = $this->CreateGutschrift($adresse);


        if($this->Firmendaten('dateienweiterfuehren')){
          $this->WeiterfuehrenDateianhang("Rechnung", $id, "Gutschrift", $newid);
        }

        $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,ihrebestellnummer,projekt, belegnr as rechnung,anschreiben,aktion,ansprechpartner,titel,lieferbedingung,bodyzusatz,
            freitext,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,versandart,zahlungsweise,zahlungszieltage,ust_befreit, keinsteuersatz, id as rechnungid,rabatt,rabatt1,rabatt2,rabatt3,rabatt4,rabatt5,gruppe,vertriebid,bearbeiterid,provision,provision_summe,bearbeiter,projektfiliale,typ,internebezeichnung,ohne_artikeltext,kurs,
            `kundennummer_buchhaltung`,
            zahlungszieltageskonto,zahlungszielskonto,firma,waehrung,steuersatz_normal,steuersatz_zwischen,steuersatz_ermaessigt,steuersatz_starkermaessigt,steuersatz_dienstleistung,'angelegt' as status,gln,kostenstelle, sprache FROM rechnung WHERE id='$id' LIMIT 1");

        $check_mail = $this->app->DB->Select("SELECT gutschrift_email FROM adresse WHERE id='$adresse'");
        if($check_mail!='') {
          $arr[0]['email'] = $check_mail;
        }
        $arr[0]['deliverythresholdvatid'] = $this->app->DB->Select("SELECT deliverythresholdvatid FROM rechnung WHERE id='$id' LIMIT 1");

        $this->app->DB->UpdateArr('gutschrift', $newid, 'id', $arr[0], true);
        $this->LoadKurs($newid,"gutschrift",$arr[0]['projekt'],true);

        $pos = $this->app->DB->SelectArr("SELECT * FROM rechnung_position WHERE rechnung='$id' order by sort");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++) {
          $this->app->DB->Insert("INSERT INTO gutschrift_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $idtoid[$pos[$i]['id']] = $newposid;
          if(!empty($pos[$i]['explodiert_parent']))
          {
            $pos[$i]['explodiert_parent'] = isset($idtoid[$pos[$i]['explodiert_parent']])?$idtoid[$pos[$i]['explodiert_parent']]:0;
          }
          $pos[$i]['gutschrift']=$newid;
          $this->app->DB->UpdateArr('gutschrift_position', $newposid, 'id', $pos[$i], true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE gutschrift_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }

        $ohnebriefpapier = $this->Firmendaten('gutschrift_ohnebriefpapier');
        $stornorechnung = $this->Firmendaten('stornorechnung_standard');

        $this->CopyBelegZwischenpositionen('rechnung',$id,'gutschrift',$newid);
        $this->app->DB->Update("UPDATE gutschrift SET stornorechnung='$stornorechnung', ohne_briefpapier='".$ohnebriefpapier."' WHERE id='$newid,' LIMIT 1");

        $this->app->DB->Update("UPDATE rechnung SET schreibschutz='1',status='storniert' WHERE id='$id' LIMIT 1");
        $this->RechnungProtokoll($id, $grund);
        $this->SchnellFreigabe("gutschrift",$newid);
        return $newid;
      }


      function WeiterfuehrenAuftragZuAnfrage($auftrag)
      {
        $anfrageid = $this->app->DB->Select("SELECT anfrageid FROM auftrag WHERE id='$auftrag' LIMIT 1");
        //angebot aus offene Angebote entfernen

        $arr = $this->app->DB->SelectArr("SELECT projekt,aktion,bodyzusatz,
            freitext,anschreiben,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,email,telefon,telefax,projektfiliale,typ,internebezeichnung,ansprechpartner,titel,
            firma,'angelegt' as status FROM auftrag WHERE id='$auftrag' LIMIT 1");
        $arr[0]['bundesstaat'] = $this->app->DB->Select("SELECT bundesstaat FROM auftrag WHERE id = '$id' LIMIT 1");
        $this->app->DB->UpdateArr('anfrage',$anfrageid,'id',$arr[0],true);

        $this->app->DB->Delete("DELETE FROM anfrage_position WHERE anfrage='$anfrageid'");

        $pos = $this->app->DB->SelectArr("SELECT * FROM auftrag_position WHERE auftrag='$auftrag' order by sort");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++){
          $this->app->DB->Insert("INSERT INTO anfrage_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $idtoid[$pos[$i]['id']] = $newposid;
          if(!empty($pos[$i]['explodiert_parent']))
          {
            $pos[$i]['explodiert_parent'] = isset($idtoid[$pos[$i]['explodiert_parent']])?$idtoid[$pos[$i]['explodiert_parent']]:0;
          }
          $pos[$i]['anfrage']=$anfrageid;

          // Hole Verkaufspreis ab menge
          $this->app->DB->UpdateArr('anfrage_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE anfrage_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }
        $this->app->DB->Update("UPDATE auftrag SET schreibschutz='1' WHERE id='$id' LIMIT 1");
        return $anfrageid;
      }


      function WeiterfuehrenAnfrageZuAngebot($id)
      {

        $adresse = $this->app->DB->Select("SELECT adresse FROM anfrage WHERE id='$id' LIMIT 1");
        //angebot aus offene Angebote entfernen
        $this->app->DB->Insert("INSERT INTO angebot (id) VALUES ('')");
        $newid = $this->app->DB->GetInsertID();

        if($this->Firmendaten('dateienweiterfuehren')){
          $this->WeiterfuehrenDateianhang("Anfrage", $id, "Angebot", $newid);
        }

        $arr = $this->app->DB->SelectArr("SELECT NOW() as datum,projekt,aktion,bodyzusatz,
            freitext,anschreiben,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,projektfiliale,typ,ansprechpartner,titel,
            versandart, id as anfrageid,internebezeichnung,
            firma,'angelegt' as status FROM anfrage WHERE id='$id' LIMIT 1");
        $this->app->DB->UpdateArr('angebot',$newid,'id',$arr[0],true);
        $pos = $this->app->DB->SelectArr("SELECT * FROM anfrage_position WHERE anfrage='$id' order by sort");
        $cpos = !empty($pos)?count($pos):0;
        for($i=0;$i<$cpos;$i++) {
          $this->app->DB->Insert("INSERT INTO angebot_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $idtoid[$pos[$i]['id']] = $newposid;
          if(!empty($pos[$i]['explodiert_parent']))
          {
            $pos[$i]['explodiert_parent'] = isset($idtoid[$pos[$i]['explodiert_parent']])?$idtoid[$pos[$i]['explodiert_parent']]:0;
          }
          $pos[$i]['angebot']=$newid;

          // Hole Verkaufspreis ab menge
          $pos[$i]['preis']=$this->GetVerkaufspreis($pos[$i]['artikel'],$pos[$i]['menge'],$adresse);
          $this->app->DB->UpdateArr('angebot_position',$newposid,'id',$pos[$i],true);
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE angebot_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }
        $this->app->DB->Update("UPDATE anfrage SET schreibschutz='1' WHERE id='$id' LIMIT 1");

        $this->SchnellFreigabe("angebot",$newid);
        return $newid;
      }


      function CheckClass($class)
      {
        switch($class)
        {
          case 'FormHandler':
            if(isset($this->app->FormHandler) && $this->app->FormHandler) {
              return;
            }
            if(!class_exists('FormHandler') && file_exists(__DIR__ .'/../../phpwf/plugins/class.formhandler.php')) {
              include_once dirname(dirname(__DIR__)) .'/phpwf/plugins/class.formhandler.php';
            }
            if(class_exists('FormHandler')) {
              $this->app->FormHandler = new FormHandler($this->app);
            }
          break;
          case 'LieferscheinPDF':
          case 'RechnungPDF':
          case 'AuftragPDF':
          case 'BestellungPDF':
          case 'GutschriftPDF':
          case 'AngebotPDF':
          case 'MahnwesenPDF':
          case 'AnfragePDF':
          case 'LayoutvorlagenPDF':
            if(class_exists($class)) {
              return;
            }
            if(!defined('FPDF_FONTPATH')) {
              define('FPDF_FONTPATH',dirname(__DIR__).'/pdf/font/');
            }

            if(!class_exists('FPDFWAWISION'))
            {
              if(file_exists(dirname(dirname(__DIR__)).'/conf/user_defined.php')){
                include_once dirname(dirname(__DIR__)).'/conf/user_defined.php';
              }
              if(!defined('USEFPDF3'))
              {
                define('USEFPDF3',true);
              }
              if(defined('USEFPDF3') && USEFPDF3 && file_exists(__DIR__.'/pdf/fpdf_3.php'))
              {
                require_once(__DIR__.'/pdf/fpdf_3.php');
              }
              else if(defined('USEFPDF2') && USEFPDF2 && file_exists(__DIR__.'/pdf/fpdf_2.php'))
              {
                require_once(__DIR__.'/pdf/fpdf_2.php');
              } else {
                require_once(__DIR__.'/pdf/fpdf.php');
              }
            }

            if(!class_exists('PDF_EPS'))require_once(__DIR__ .'/pdf/fpdf_final.php');

            if(!class_exists('SuperFPDF'))require_once(__DIR__ ."/dokumente/class.superfpdf.php");
            if(!class_exists('Etikett'))require_once(__DIR__ ."/dokumente/class.etikett.php");
            if(!class_exists('Briefpapier')){
              if(file_exists(__DIR__ ."/dokumente/class.briefpapier_custom.php"))
              {
                require_once(__DIR__ ."/dokumente/class.briefpapier_custom.php");
              }else{
                require_once(__DIR__ ."/dokumente/class.briefpapier.php");
              }
            }
            if(!class_exists($class))
            {
              if(file_exists(__DIR__ .'/dokumente/class.'.strtolower(substr($class,0,strlen($class)-3)).'_custom.php'))
              {
                require_once(__DIR__ .'/dokumente/class.'.strtolower(substr($class,0,strlen($class)-3)).'_custom.php');
              }elseif(file_exists(__DIR__ .'/dokumente/class.'.strtolower(substr($class,0,strlen($class)-3)).'.php'))
              {
                require_once(__DIR__ .'/dokumente/class.'.strtolower(substr($class,0,strlen($class)-3)).'.php');
              }
            }
          break;
        }
      }

      function WeiterfuehrenAuftragZuRechnung($id, $positionen = null, $zwischenpositionen = null, $newid = 0)
      {
        // wenn anfrage vorhanden diese markieren als abgerechnet status='abgerechnet'
        $orderArr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT anfrageid, adresse, status,projekt, belegnr 
            FROM auftrag 
            WHERE id = %d 
            LIMIT 1',
            $id
          )
        );

        $anfrageid = $orderArr['anfrageid'];
        $adresseid = $orderArr['adresse'];
        $abweichende_rechnungsadresse = $this->app->DB->Select("SELECT abweichende_rechnungsadresse
            FROM adresse WHERE id='$adresseid' LIMIT 1");
        if($anfrageid > 0) {
          $this->app->DB->Update("UPDATE anfrage SET status='abgerechnet',schreibschutz='0' WHERE id='$anfrageid'");
        }
        // pruefe ob auftrag status=angelegt, dann vergebe belegnr
        $status = $orderArr['status'];
        $projekt = $orderArr['projekt'];
        $checkbelegnr = $orderArr['belegnr'];
        if($status==='angelegt' && $checkbelegnr=='') {
          $belegnr = $this->GetNextNummer("auftrag",$projekt,$id);

          $this->app->DB->Update("UPDATE auftrag SET belegnr='$belegnr', status='freigegeben'  WHERE id='$id' LIMIT 1");
          $this->AuftragProtokoll($id,"Auftrag freigegeben");

          // auftrag abschliessen und event senden
          $this->EventAPIAdd("EventAuftragEdit",$id,"auftrag","edit");
        }


        //angebot aus offene Angebote entfernen
        if($newid <= 0) {
          $newid = $this->CreateRechnung($adresseid);
        }

        if($this->Firmendaten('dateienweiterfuehren')){
          $this->WeiterfuehrenDateianhang("Auftrag", $id, "Rechnung", $newid);
        }

        $arr = $this->app->DB->SelectArr("SELECT datum,ihrebestellnummer,projekt,gesamtsumme as soll, belegnr as auftrag, id as auftragid,aktion,typ,bodyzusatz,
            freitext,anschreiben,adresse,name,abteilung,unterabteilung,ansprechpartner,titel,lieferbedingung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,versandart,vertrieb,zahlungsweise,zahlungszieltage,ust_befreit,keinsteuersatz,rabatt,rabatt1,rabatt2,rabatt3,rabatt4,rabatt5,gruppe,vertriebid,bearbeiterid,provision,provision_summe,bearbeiter,internebemerkung,typ,internebezeichnung,systemfreitext,ohne_artikeltext,sprache,kostenstelle,
            `kundennummer_buchhaltung`,
            projektfiliale,zahlungszieltageskonto,zahlungszielskonto,firma,einzugsdatum,waehrung,kurs,steuersatz_normal,steuersatz_zwischen,steuersatz_ermaessigt,steuersatz_starkermaessigt,steuersatz_dienstleistung,'angelegt' as status, gln, storage_country 
            FROM auftrag WHERE id='$id' LIMIT 1");

        $arr[0]['deliverythresholdvatid'] = $this->app->DB->Select("SELECT deliverythresholdvatid FROM auftrag WHERE id='$id' LIMIT 1");
        // this is not the different invoice email this is the forec mail for invoices
        $check_mail = $this->app->DB->Select("SELECT rechnungs_email FROM adresse WHERE id='$adresseid' ");
        if($check_mail!="") $arr[0]['email'] = $check_mail;


        $arr_zahlung = $this->app->DB->SelectArr("SELECT zahlungsweise,zahlungszieltage,zahlungszieltageskonto,zahlungszielskonto,versandart,projekt FROM auftrag WHERE id='$id' LIMIT 1");
        $arr[0]['bundesstaat'] = $this->app->DB->Select("SELECT bundesstaat FROM auftrag WHERE id = '$id' LIMIT 1");
        $this->app->DB->UpdateArr('rechnung',$newid,'id',$arr[0], true);
        $bundesland = $this->app->DB->Select("SELECT bundesland FROM auftrag WHERE id = '$id' LIMIT 1");
        if(!empty($bundesland)) {
          $this->app->DB->Update("UPDATE rechnung SET bundesland = '".$this->app->DB->real_escape_string($bundesland)."' WHERE id = '$newid' LIMIT 1");
        }

        $lieferscheinid = $this->app->DB->Select("SELECT id FROM lieferschein WHERE auftragid='$id' LIMIT 1");

        if($lieferscheinid>0)
        {
          $this->app->DB->Update("UPDATE rechnung SET lieferschein='$lieferscheinid' WHERE id='$newid' LIMIT 1");
          $this->app->DB->Update("UPDATE lieferschein SET rechnungid='$newid' WHERE id='$lieferscheinid' LIMIT 1");
        }

        $this->app->DB->Update("UPDATE rechnung SET datum=NOW() WHERE id='$newid' LIMIT 1");

      $where = "";
      if($positionen)
      {
        if($positionen)
        {
          $posa = null;
          foreach($positionen as $v)
          {
            $posa[] = " id = '$v' ";
          }
          $where = ' AND ('.implode(' OR ',$posa).') ';
        }
      }

      $pos = $this->app->DB->SelectArr("SELECT * FROM auftrag_position WHERE auftrag='$id' $where order by sort");
      $cpos = !empty($pos)?count($pos):0;
      $auftragzurechnung= [];
      for($i=0;$i<$cpos;$i++){
        $this->app->DB->Insert("INSERT INTO rechnung_position (id) VALUES('')");
        $newposid = $this->app->DB->GetInsertID();
        $auftragzurechnung[$pos[$i]['id']] = $newposid;
        $pos[$i]['rechnung']=$newid;
        $pos[$i]['auftrag_position_id']=$pos[$i]['id'];
        if($positionen){
          $pos[$i]['sort'] = 1+(int)$this->app->DB->Select("SELECT max(sort) FROM rechnung_position WHERE rechnung = '$newid'");
        }

          //if($pos[$i]['explodiert']) $pos[$i]['bezeichnung'] = $pos[$i]['bezeichnung'];//." (Stückliste)";
          if($pos[$i]['explodiert_parent'] > 0) {
            $pos[$i]['bezeichnung'] = "*** ".$pos[$i]['bezeichnung'];
            if($pos[$i]['explodiert_parent'] > 0){
              $pos[$i]['explodiert_parent_artikel'] = $this->app->DB->Select("SELECT artikel FROM auftrag_position WHERE id='" . $pos[$i]['explodiert_parent'] . "'  LIMIT 1");
            }
            else {
              $pos[$i]['explodiert_parent_artikel'] = 0;
            }

          }
          $idtoid[$pos[$i]['id']] = $newposid;
          if(!empty($pos[$i]['explodiert_parent'])) {
            $pos[$i]['explodiert_parent'] = isset($idtoid[$pos[$i]['explodiert_parent']])?$idtoid[$pos[$i]['explodiert_parent']]:0;
          }
          $this->app->DB->UpdateArr('rechnung_position',$newposid,'id',$pos[$i], true);
          if(is_null($pos[$i]['steuersatz'])){
            $this->app->DB->Update("UPDATE rechnung_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }

        if($this->Firmendaten('dateienweiterfuehren')){
          foreach($auftragzurechnung as $oldpos => $newpos){
            $this->app->DB->Update("UPDATE datei_stichwoerter SET parameter2='$newpos' 
            WHERE LOWER(objekt)='rechnung' AND parameter='$newid' AND objekt2='position' AND parameter2=".$oldpos);
          }
          $this->app->DB->Update("UPDATE datei_stichwoerter SET parameter2='0', objekt2='' 
          WHERE LOWER(objekt)='rechnung' AND parameter='$newid' AND objekt2='position' AND NOT parameter2 IN (".implode(',',$auftragzurechnung).")");
        }
        $this->CheckFreifelder("rechnung",$newid);
        if($positionen)
        {
          if($zwischenpositionen) {
            $this->CopyBelegZwischenpositionen("auftrag",$id,"rechnung",$newid,$zwischenpositionen);
          }
        }
        else{
          $this->CopyBelegZwischenpositionen("auftrag",$id,"rechnung",$newid);
        }
        // wenn adresse abweichende rechnungsadresse hat diese nehmen!
        if($abweichende_rechnungsadresse=="1")
        {
          $this->LoadRechnungStandardwerte($newid,$adresseid);
          $arr_zahlung[0]['vertriebid']=$arr[0]['vertriebid'];
          $arr_zahlung[0]['bearbeiterid']=$arr[0]['bearbeiterid'];
          $arr_zahlung[0]['bearbeiter']=$arr[0]['bearbeiter'];
          $arr_zahlung[0]['vertrieb']=$arr[0]['vertrieb'];
          //$this->app->FormHandler->ArrayUpdateDatabase("rechnung",$newid,$arr_zahlung[0],true);
          $arr_zahlung[0]['ust_befreit'] = $arr[0]['ust_befreit'];
          $arr_zahlung[0]['steuersatz_normal'] = $arr[0]['steuersatz_normal'];
          $arr_zahlung[0]['steuersatz_ermaessigt'] = $arr[0]['steuersatz_ermaessigt'];
          $this->app->DB->UpdateArr('rechnung', $newid, 'id', $arr_zahlung[0],true);
        }

        $this->RunHook('WeiterfuehrenAuftragZuRechnungPositionen', 2, $id, $newid);
        if($this->useTaxFromSettings($arr[0]['projekt'])) {
          $this->LoadSteuersaetze($newid, 'rechnung', $arr[0]['projekt']);
        }
        // wenn auftrag vorkasse rechnung als bezahlt markieren wenn genug geld vorhanden
        $this->RechnungNeuberechnen($newid);
        //summe zahlungseingaenge
        $summe_zahlungseingaenge = 0;
        $rechnungssumme = $this->app->DB->Select("SELECT `soll` FROM `rechnung` WHERE `id` = '{$newid}' LIMIT 1");

        //if(($arr[0][zahlungsweise]=="vorkasse" || $arr[0][zahlungsweise]=="paypal" || $arr[0][zahlungsweise]=="kreditkarte") &&  $summe_zahlungseingaenge >= $rechnungssumme)
        if($summe_zahlungseingaenge > 0) {
          $summe_zahlungseingaenge -= (float)$this->app->DB->Select(
            "SELECT SUM(`ist`) FROM `rechnung` WHERE `auftragid` = {$id} AND `id` != {$newid}"
          );
          if($summe_zahlungseingaenge >= $rechnungssumme){
            $this->app->DB->Update("UPDATE `rechnung` SET `ist` = `soll`, `zahlungsstatus` = 'bezahlt' WHERE `id` = '{$newid}'");
          }
          elseif($summe_zahlungseingaenge > 0){
            $lastDate = $this->app->DB->Select(
              "SELECT MAX(k.buchung) 
              FROM `kontoauszuege_zahlungseingang` AS `ke` 
              INNER JOIN `kontoauszuege` AS `k` ON ke.kontoauszuege = k.id 
              WHERE ke.`objekt` = 'auftrag' AND ke.`parameter` = '{$id}' "
            );
            $invoice = $this->app->DB->SelectRow(
              "SELECT `skontobetrag`, `zahlungszielskonto`, `zahlungszieltageskonto`, 
                DATE_SUB(`datum`, INTERVAL `zahlungszieltageskonto` DAY) <= '{$lastdate}' AS `skonto_ok`
              FROM `rechnung` WHERE `id`= '{$newid}'"
            );
            if(!empty($invoice['skonto_ok'])){
              $minimumPayed = !empty($invoice['skontobetrag'])
                ? $invoice['skontobetrag'] : $rechnungssumme * (100 - $invoice['zahlungszielskonto']) / 100;

              if($summe_zahlungseingaenge >= $minimumPayed){
                $this->app->DB->Update(
                  "UPDATE `rechnung` 
                  SET `ist` = '{$summe_zahlungseingaenge}', `zahlungsstatus` = 'bezahlt' 
                  WHERE `id` = '{$newid}'"
                );
              }
            }
          }
        }
          // was ist denn bei rechnung bar oder nachnahme wenn ein auftragsguthaben vorhanden ist


        if($this->Firmendaten("auftragabschliessen")!="1")
          $this->app->DB->Update("UPDATE auftrag SET status='abgeschlossen',schreibschutz='1' WHERE id='$id' LIMIT 1");
        else {
          // erstmal nicht mehr umstellen
          //if($this->app->DB->Select("SELECT id FROM auftrag WHERE art <> 'rechnung' AND id = '$id' LIMIT 1"))$this->app->DB->Update("UPDATE auftrag SET art='lieferung' WHERE id='$id' LIMIT 1");
        }

        // auftrag freigeben!!!
      $this->SchnellFreigabe("rechnung",$newid);

      $this->ANABREGSNeuberechnen($newid,"rechnung");
      return $newid;
    }


  /**
   * @param int $projectId
   *
   * @return bool
   */
      function useTaxFromSettings($projectId = 0)
      {
        $fromProject = $projectId <= 0?0:(int)$this->Projektdaten($projectId, 'taxfromdoctypesettings');
        if($fromProject === 1) {
          return false;
        }
        if($fromProject === 2) {
          return true;
        }

        return !empty($this->Firmendaten('taxfromdoctypesettings'));
      }

      function WeiterfuehrenAngebotZuAuftrag($id)
      {
        $anfrageid = $this->app->DB->Select("SELECT anfrageid FROM angebot WHERE id='$id' LIMIT 1");
        $adresseid = $this->app->DB->Select("SELECT adresse FROM angebot WHERE id='$id' LIMIT 1");

        if($anfrageid > 0)
          $this->app->DB->Update("UPDATE anfrage SET status='beauftrag',schreibschutz='0' WHERE id='$anfrageid' AND status!='abgeschlossen' AND status!='abgerechnet'");

        //angebot aus offene Angebote entfernen
        $this->app->DB->Insert("INSERT INTO auftrag (id) VALUES ('')");
        $newid = $this->app->DB->GetInsertID();

        if($this->Firmendaten('dateienweiterfuehren')){
          $this->WeiterfuehrenDateianhang("Angebot", $id, "Auftrag", $newid);
        }

        $arr = $this->app->DB->SelectArr("SELECT NOW() as datum, projekt,belegnr as angebot,lieferdatum,aktion,bodyzusatz, '1' as autoversand,
            freitext,anschreiben,adresse,name,abteilung,unterabteilung,strasse,adresszusatz,plz,ort,land,ustid,email,telefon,telefax,betreff,kundennummer,versandart,vertrieb,ansprechpartner,titel,lieferbedingung,
            standardlager,zahlungsweise, zahlungszieltage, id as angebotid, anfrage as ihrebestellnummer, anfrageid,rabatt,rabatt1,rabatt2,rabatt3,rabatt4,rabatt5,gruppe,vertriebid,bearbeiterid,provision,provision_summe,bearbeiter,projektfiliale,typ,internebezeichnung,
            zahlungszieltageskonto,zahlungszielskonto,firma,abweichendelieferadresse,liefername,lieferabteilung,lieferunterabteilung,lieferland,lieferstrasse,lieferort,liefergln,lieferemail,ust_befreit,internebemerkung,liefertitel, ohne_artikeltext,
            lieferplz,lieferadresszusatz,lieferansprechpartner,ust_befreit,keinsteuersatz,keinporto,'angelegt' as status,lieferdatumkw,
            waehrung,steuersatz_normal,steuersatz_zwischen,steuersatz_ermaessigt,steuersatz_starkermaessigt,steuersatz_dienstleistung, gln,sprache,kostenstelle FROM angebot WHERE id='$id' LIMIT 1");
        $arr[0]['bundesstaat'] = $this->app->DB->Select("SELECT bundesstaat FROM angebot WHERE id = '$id' LIMIT 1");

        $check_mail = $this->app->DB->Select("SELECT auftrag_email FROM adresse WHERE id='$adresseid'");
        if($check_mail!="") $arr[0]['email'] = $check_mail;
        $arr[0]['autoversand'] = 1-(int)$this->Projektdaten($arr[0]['projekt'],'deactivateautoshipping');
        $this->app->DB->UpdateArr('auftrag',$newid, 'id', $arr[0], true);
        $pos = $this->app->DB->SelectArr("SELECT * FROM angebot_position WHERE angebot='$id' order by sort");
        for($i=0;$i<(!empty($pos)?count($pos):0);$i++){
          $this->app->DB->Insert("INSERT INTO auftrag_position (id) VALUES('')");
          $newposid = $this->app->DB->GetInsertID();
          $idtoid[$pos[$i]['id']] = $newposid;
          if(!empty($pos[$i]['explodiert_parent']))
          {
            $pos[$i]['explodiert_parent'] = isset($idtoid[$pos[$i]['explodiert_parent']])?$idtoid[$pos[$i]['explodiert_parent']]:0;
          }
          $pos[$i]['auftrag']=$newid;
          $this->app->DB->UpdateArr('auftrag_position',$newposid, 'id', $pos[$i], true);
          if($pos[$i]['berechnen_aus_teile']) {
            $berechnen_aus_teile[$newposid] = true;
          }
          if(is_null($pos[$i]['steuersatz'])) {
            $this->app->DB->Update("UPDATE auftrag_position SET steuersatz = null WHERE id = '$newposid' LIMIT 1");
          }
        }
        if(isset($berechnen_aus_teile))
        {
          foreach($berechnen_aus_teile as $k => $v)
          {
            $this->app->DB->Update("UPDATE auftrag_position SET preis = 0 WHERE explodiert_parent = '$k' AND auftrag = '$newid'");
          }
        }

      //wenn angebot explodiert war dann nicht
      if($this->app->DB->Select("SELECT COUNT(id) FROM angebot_position WHERE angebot='$id' AND explodiert_parent > 0") >0 )
        $this->app->DB->Update("UPDATE auftrag_position ap INNER JOIN artikel art ON ap.artikel = art.id SET ap.explodiert = 1 WHERE art.juststueckliste = 1 AND ap.auftrag = '$newid'");


      $this->CheckFreifelder("auftrag",$newid);
      $this->CopyBelegZwischenpositionen("angebot",$id,"auftrag",$newid);

        $belegnr = $this->app->DB->Select("SELECT belegnr FROM auftrag WHERE id='$newid' LIMIT 1");
        $this->app->DB->Update("UPDATE angebot SET status='beauftragt', schreibschutz='1', auftrag='$belegnr',auftragid='$newid' WHERE id='$id' LIMIT 1");
        // wiedervorlagen als abgeschlossen
        $this->app->DB->Update("UPDATE wiedervorlage SET abgeschlossen='1' WHERE module='angebot' AND parameter='$id' AND parameter > 0");
        if($this->useTaxFromSettings($arr[0]['projekt'])) {
          $this->LoadSteuersaetze($newid, 'auftrag', $arr[0]['projekt']);
        }
        // auftrag freigeben!!!
        $this->SchnellFreigabe("auftrag",$newid);

        $this->app->erp->RunHook('WeiterfuehrenAngebotZuAuftrag', 2, $id, $newid);
        return $newid;
      }

      function DeleteAngebot($id)
      {
        $belegnr = $this->app->DB->Select("SELECT belegnr FROM angebot WHERE id='$id' LIMIT 1");
        if($belegnr=="" || $belegnr=="0")
        {
          $this->app->DB->Delete("DELETE FROM angebot_position WHERE angebot='$id'");
          $this->app->DB->Delete("DELETE FROM angebot_protokoll WHERE angebot='$id'");
          $this->app->DB->Delete("DELETE FROM angebot WHERE id='$id' LIMIT 1");
        }
      }


      function PaketannahmenAbschliessen()
      {
        $arr = $this->app->DB->SelectArr("SELECT id FROM paketannahme WHERE status!='abgeschlossen'");
        for($i=0;$i<(!empty($arr)?count($arr):0);$i++)
        {


        }
      }

      function CreateVerbindlichkeit($adresse="")
      {
        /** @var Verbindlichkeit $obj */
        $obj = $this->app->erp->LoadModul('verbindlichkeit');
        if(!empty($obj) && method_exists($obj,'createLiability')) {
          return $obj->createLiability($adresse);
        }
        return 0;
      }


      function CreateBestellung($adresse="")
      {
        /** @var Bestellung $obj */
        $obj = $this->LoadModul('bestellung');
        if(!empty($obj) && method_exists($obj, 'CreateBestellung'))
        {
          return $obj->CreateBestellung($adresse);
        }
      }

      function AddBestellungPosition($bestellung, $einkauf,$menge,$datum, $beschreibung = '',$artikel="",$einheit="", $waehrung = '')
      {
        /** @var Bestellung $obj */
        $obj = $this->LoadModul('bestellung');
        if(!empty($obj) && method_exists($obj, 'AddBestellungPosition'))
        {
          return $obj->AddBestellungPosition($bestellung, $einkauf,$menge,$datum, $beschreibung,$artikel,$einheit, $waehrung);
        }
      }

      function DeleteBestellung($id)
      {
        /** @var Bestellung $obj */
        $obj = $this->LoadModul('bestellung');
        if(!empty($obj) && method_exists($obj, 'DeleteBestellung'))
        {
          $obj->DeleteBestellung($id);
        }
      }

      function CreateRechnung($adresse="")
      {
        /** @var Rechnung $obj */
        $obj = $this->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'CreateRechnung')){
          return $obj->CreateRechnung($adresse);
        }
      }

      public function GetStandardWaehrung($projekt=0)
      {
        if(is_array($projekt) && isset($projekt['eigenesteuer']) && isset($projekt['waehrung'])) {
          $projekt_arr = $projekt;
        }
        elseif($projekt  > 0) {
          $projekt_arr = $this->app->DB->SelectRow(
            "SELECT eigenesteuer,waehrung FROM projekt WHERE id='$projekt' LIMIT 1"
          );
        }
        if(!empty($projekt_arr['eigenesteuer']))
        {
          $waehrung = $projekt_arr['waehrung'];
        } else {
          $waehrung = $this->Firmendaten('waehrung');
        }
        return $waehrung;
      }

      public function GetStandardSteuersatzErmaessigt($projekt=0)
      {
        /** @var Steuersaetze $objSteuersaetze */
        $objSteuersaetze = $this->app->loadModule('steuersaetze', false);
        if($objSteuersaetze !== null && method_exists($objSteuersaetze, 'checkTaxesToSet')) {
          $objSteuersaetze->checkTaxesToSet();
        }
        if(is_array($projekt) && isset($projekt['eigenesteuer']) && isset($projekt['steuersatz_ermaessigt'])) {
          $projekt_arr = $projekt;
        }
        elseif($projekt > 0){
          $projekt_arr = $this->app->DB->SelectRow(
            "SELECT eigenesteuer,steuersatz_ermaessigt FROM projekt WHERE id='$projekt' LIMIT 1"
          );
        }
        if(!empty($projekt_arr['eigenesteuer']))
        {
          $steuersatz_ermaessigt = $projekt_arr['steuersatz_ermaessigt'];
        }
        else {
          $steuersatz_ermaessigt = $this->Firmendaten('steuersatz_ermaessigt');
        }
        return $steuersatz_ermaessigt;
      }

      public function GetStandardSteuersatzNormal($projekt=0)
      {
        /** @var Steuersaetze $objSteuersaetze */
        $objSteuersaetze = $this->app->loadModule('steuersaetze', false);
        if($objSteuersaetze !== null && method_exists($objSteuersaetze, 'checkTaxesToSet')) {
          $objSteuersaetze->checkTaxesToSet();
        }
        if(is_array($projekt) && isset($projekt['eigenesteuer']) && isset($projekt['steuersatz_normal'])) {
          $projekt_arr = $projekt;
        }
        elseif($projekt > 0){
          $projekt_arr = $this->app->DB->SelectRow(
            "SELECT eigenesteuer,steuersatz_normal FROM projekt WHERE id='$projekt' LIMIT 1"
          );
        }
        if(!empty($projekt_arr['eigenesteuer']))
        {
          $steuersatz_normal = $projekt_arr['steuersatz_normal'];
        } else {
          $steuersatz_normal = $this->Firmendaten("steuersatz_normal");
        }
        return $steuersatz_normal;
      }

      function GetStandardSteuersatzBefreit($projekt=0)
      {
        return 0.00;
      }

      public function LoadSteuersaetze($id,$typ,$projekt='')
      {
        if($id <= 0 || empty($typ)) {
          return;
        }
        $this->app->erp->StartChangeLog($typ, $id);
        /** @var Steuersaetze $objSteuersaetze */
        $objSteuersaetze = $this->app->loadModule('steuersaetze', false);
        if($objSteuersaetze !== null && method_exists($objSteuersaetze, 'checkTaxesToSet')) {
          $objSteuersaetze->checkTaxesToSet();
        }

        if(!(is_array($projekt) && !empty($projekt['id'])) && $projekt <=0) {
          $projekt = $this->app->DB->Select("SELECT projekt FROM `$typ` WHERE id='$id' LIMIT 1");
        }
        if(is_array($projekt) && isset($projekt['eigenesteuer'])
          && isset($projekt['steuersatz_normal']) && isset($projekt['steuersatz_ermaessigt'])) {
          $projekt_arr = $projekt;
        }
        elseif($projekt > 0) {
          $projekt_arr = $this->app->DB->SelectRow(
            "SELECT eigenesteuer,steuersatz_normal,steuersatz_ermaessigt  FROM projekt WHERE id='$projekt' LIMIT 1"
          );
        }
        if(!empty($projekt_arr['eigenesteuer'])) {
          $steuersatz_normal = $projekt_arr['steuersatz_normal'];
          $steuersatz_ermaessigt = $projekt_arr['steuersatz_ermaessigt'];
        }
        else {
          $steuersatz_normal = $this->Firmendaten('steuersatz_normal');
          $steuersatz_ermaessigt = $this->Firmendaten('steuersatz_ermaessigt');
        }

        $this->app->DB->Update("UPDATE $typ SET steuersatz_normal='$steuersatz_normal',steuersatz_ermaessigt='$steuersatz_ermaessigt' WHERE id='$id' LIMIT 1");
        $this->app->erp->WriteChangeLog();
      }


      function formatMoney($value,$currency,$decimals=2)
      {
        // Schweizer Franken
        $decSeparator = ',';
        $thouSeparator = '.';

        if ($currency === 'CHF') {
          $decSeparator = '.';
          $thouSeparator = '\'';
        }

        return number_format((float)$value, $decimals, $decSeparator, $thouSeparator);
      }



      function LoadKurs($id,$typ,$projekt="",$force=false)
      {
        if($id <= 0 || empty($typ) || $typ === 'bestellung')
        {
          return;
        }
        $kurs = 0;
        // wenn GS und Kurs aus RE denn nicht neuladen
        if($typ==='gutschrift' && $this->app->erp->Firmendaten('gutschriftkursvonrechnung'))
        {
          $rechnungid = $this->app->DB->Select("SELECT rechnungid FROM gutschrift WHERE id='$id'");
          if($rechnungid > 0)
          {
            $kurs = $this->app->DB->Select("SELECT kurs FROM rechnung WHERE id='$rechnungid'");
          }
        } 

        // nur ziehen wenn in den Firmendaten aktiviert
        if($this->Firmendaten("loadcurrencyrate"))
        {
          $waehrung=$this->app->DB->Select("SELECT waehrung FROM $typ WHERE id='$id'");
          $kurs = $this->GetWaehrungUmrechnungskurs($this->Firmendaten('waehrung'),$waehrung);
        } 
        if($kurs<>0)
        {
          $this->app->DB->Update("UPDATE $typ SET kurs='$kurs' WHERE id='$id' LIMIT 1");
        }
      }



      public function LoadSteuersaetzeWaehrung($id,$typ,$projekt='')
      {
        if($id <=0 || empty($typ))
        {
          return;
        }
        $this->LoadSteuersaetze($id,$typ,$projekt);

        $waehrung = $this->GetStandardWaehrung($projekt);

        $this->app->DB->Update("UPDATE $typ SET waehrung='$waehrung' WHERE id='$id' AND waehrung='' LIMIT 1"); // AND waehrung=''
        if($typ === 'proformarechnung') {
          return;
        }
        $this->LoadKurs($id,$typ,$projekt);
      }


      function CreateGutschrift($adresse="")
      {
        $projekt = $this->GetCreateProjekt($adresse);

        $belegmax = '';
        $ohnebriefpapier = $this->Firmendaten('gutschrift_ohnebriefpapier');
        $stornorechnung = (int)$this->Firmendaten('stornorechnung_standard');
        if($stornorechnung !== 0 && $stornorechnung !== 1) {
          $stornorechnung = 1;
          $this->FirmendatenSet('stornorechnung_standard', '1');
        }

        if($this->StandardZahlungsweise($projekt)=="rechnung")
        {
        $this->app->DB->Insert("INSERT INTO gutschrift (id,datum,bearbeiter,firma,belegnr,zahlungsweise,zahlungszieltage,status,projekt,adresse,ohne_briefpapier,stornorechnung)
            VALUES ('',NOW(),'".$this->app->User->GetName()."','".$this->app->User->GetFirma()."','$belegmax','".$this->StandardZahlungsweise($projekt)."','".$this->ZahlungsZielTage($projekt)."','angelegt','$projekt','$adresse','".$ohnebriefpapier."','$stornorechnung')");
        } else {
    $this->app->DB->Insert("INSERT INTO gutschrift (id,datum,bearbeiter,firma,belegnr,zahlungsweise,zahlungszieltage,status,projekt,adresse,ohne_briefpapier,stornorechnung)
            VALUES ('',NOW(),'".$this->app->User->GetName()."','".$this->app->User->GetFirma()."','$belegmax','".$this->StandardZahlungsweise($projekt)."','0','angelegt','$projekt','$adresse','".$ohnebriefpapier."','$stornorechnung')");
        }
        $id = $this->app->DB->GetInsertID();
        $this->CheckVertrieb($id,"gutschrift");
        $this->CheckBearbeiter($id,"gutschrift");

        $this->app->erp->GutschriftProtokoll($id,"Gutschrift angelegt");

        $type="gutschrift";
        $this->app->erp->ObjektProtokoll($type,$id,$type."_create",ucfirst($type)." angelegt");
        $deliverythresholdvatid = $this->getDeliverythresholdvatid($projekt);
        if($id > 0 && !empty($deliverythresholdvatid)){
          $deliverythresholdvatid = $this->app->DB->real_escape_string($deliverythresholdvatid);
          $this->app->DB->Update("UPDATE gutschrift SET deliverythresholdvatid = '$deliverythresholdvatid' WHERE id = $id LIMIT 1");
        }
        $this->SchnellFreigabe("gutschrift",$id);


        $this->LoadSteuersaetzeWaehrung($id,"gutschrift");
        $this->EventAPIAdd("EventGutschriftCreate",$id,"gutschrift","create");
        return $id;
      }


      function AddGutschritPosition($gutschrift, $verkauf,$menge,$datum)
      {
        $artikel = $this->app->DB->Select("SELECT artikel FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $bezeichnunglieferant = $this->app->DB->Select("SELECT name_de FROM artikel WHERE id='$artikel' LIMIT 1");
        $bestellnummer = $this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");
        $preis = $this->app->DB->Select("SELECT preis FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $projekt = $this->app->DB->Select("SELECT projekt FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $waehrung = $this->app->DB->Select("SELECT waehrung FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer  FROM artikel WHERE id='$artikel' LIMIT 1");
        $vpe = $this->app->DB->Select("SELECT vpe FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $sort = $this->app->DB->Select("SELECT MAX(sort) FROM gutschrift_position WHERE rechnung='$gutschrift' LIMIT 1");
        $sort = $sort + 1;
        $this->app->DB->Insert("INSERT INTO gutschrift_position (id,gutschrift,artikel,bezeichnung,nummer,menge,preis, waehrung, sort,lieferdatum, umsatzsteuer, status,projekt,vpe)
            VALUES ('','$gutschrift','$artikel','$bezeichnunglieferant','$bestellnummer','$menge','$preis','$waehrung','$sort','$datum','$umsatzsteuer','angelegt','$projekt','$vpe')");
      }


      function AddAuftragPositionManuell($auftrag, $artikel,$preis, $menge,$bezeichnung,$beschreibung="",$waehrung='EUR',$rabatt=0)
      {
        $bezeichnunglieferant = $bezeichnung;
        $artArr = $this->app->DB->SelectRow(
          sprintf(
            'SELECT nummer,projekt,umsatzsteuer,mlmpunkte,mlmbonuspunkte,mlmdirektpraemie FROM artikel WHERE id =%d',
            $artikel
          )
        );
        $bestellnummer = !empty($artArr)?$artArr['nummer']:$this->app->DB->Select("SELECT nummer FROM artikel WHERE id='$artikel' LIMIT 1");
        $projekt = !empty($artArr)?$artArr['projekt']:$this->app->DB->Select("SELECT projekt FROM artikel WHERE id='$artikel' LIMIT 1");

        if($waehrung!=''){
          $this->app->DB->Update("UPDATE auftrag SET waehrung='$waehrung' WHERE id='$auftrag' AND waehrung='' LIMIT 1");
        }

        $umsatzsteuer = !empty($artArr)?$artArr['umsatzsteuer']:$this->app->DB->Select("SELECT umsatzsteuer  FROM artikel WHERE id='$artikel' LIMIT 1");

        $mlmpunkte = !empty($artArr)?$artArr['mlmpunkte']:$this->app->DB->Select("SELECT mlmpunkte FROM artikel WHERE id='$artikel' LIMIT 1");
        $mlmbonuspunkte = !empty($artArr)?$artArr['mlmbonuspunkte']:$this->app->DB->Select("SELECT mlmbonuspunkte FROM artikel WHERE id='$artikel' LIMIT 1");
        $mlmdirektpraemie = !empty($artArr)?$artArr['mlmdirektpraemie']:$this->app->DB->Select("SELECT mlmdirektpraemie FROM artikel WHERE id='$artikel' LIMIT 1");

        $keinrabatterlaubt=0;
        if($rabatt <> 0) {
          $keinrabatterlaubt=1;
        }


        //$vpe = $this->app->DB->Select("SELECT vpe FROM verkaufspreise WHERE id='$verkauf' LIMIT 1");
        $sort = (int)$this->app->DB->Select("SELECT MAX(sort) FROM auftrag_position WHERE auftrag='$auftrag' LIMIT 1");
        $sort++;
        $this->app->DB->Insert("INSERT INTO auftrag_position (auftrag,artikel,bezeichnung,nummer,menge,preis, waehrung, sort, umsatzsteuer, status,projekt,vpe,beschreibung,punkte,bonuspunkte,mlmdirektpraemie,rabatt,keinrabatterlaubt)
            VALUES ('$auftrag','$artikel','$bezeichnunglieferant','$bestellnummer','$menge','$preis','$waehrung','$sort','$umsatzsteuer','angelegt','$projekt','$vpe','$beschreibung','$mlmpunkte','$mlmbonuspunkte','$mlmdirektpraemie','$rabatt','$keinrabatterlaubt')");
        return $this->app->DB->GetInsertID();
      }


      function AddRechnungPositionManuell($rechnung, $artikel,$preis, $menge,$bezeichnung,$beschreibung="",$waehrung='EUR',$rabatt=0)
      {
        $obj = $this->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'AddRechnungPositionManuell')){
          return $obj->AddRechnungPositionManuell($rechnung, $artikel,$preis, $menge,$bezeichnung,$beschreibung,$waehrung,$rabatt);
        }
      }

      function AddRechnungPosition($rechnung, $verkauf,$menge,$datum)
      {
        $obj = $this->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'AddRechnungPosition')){
          $obj->AddRechnungPosition($rechnung, $verkauf,$menge,$datum);
        }
      }

      // Produktion und Auftrag reservieren
      function AuftragReservieren($id,$typ="auftrag")
      {
        $standardlager = 0;
        $projektlager = 0;
        if($typ==='auftrag' && $id > 0){
          $auftragsArr = $this->app->DB->SelectRow(
            sprintf(
              "SELECT id, adresse, projekt, belegnr, standardlager,reservationdate FROM auftrag WHERE status='freigegeben' AND id=%d LIMIT 1",
              (int)$id
            )
          );
          if($this->app->DB->error()) {
            $auftragsArr = $this->app->DB->SelectRow(
              sprintf(
                "SELECT id, adresse, projekt, belegnr, standardlager, NULL AS reservationdate FROM auftrag WHERE status='freigegeben' AND id=%d LIMIT 1",
                (int)$id
              )
            );
          }
          if(empty($auftragsArr)) {
            return 0;
          }
          if(!empty($auftragsArr['reservationdate']) && $auftragsArr['reservationdate'] !== '0000-00-00'
          && strtotime($auftragsArr['reservationdate']) > strtotime(date('Y-m-d'))) {
            return 0;
          }
          $id_check = $auftragsArr['id'];
          $adresse = $auftragsArr['adresse'];
          $projekt = $auftragsArr['projekt'];
          if($projekt) {
            $projektlager = $this->app->DB->Select(
              sprintf(
                'SELECT id FROM projekt WHERE id = %d AND projektlager = 1',
                $projekt
              )
            );
          }
          $belegnr= $auftragsArr['belegnr'];
          $standardlager = $auftragsArr['standardlager'];
        }
        if($typ==='produktion'){
        }

        // nicht reservieren wenn auftrag nicht offen ist
        if($id_check!=$id){
          return 0;
        }


        if($typ==='auftrag')
        {
          $artikelarr= $this->app->DB->SelectArr("SELECT * FROM auftrag_position WHERE auftrag='$id' AND geliefert!=1");
          $this->app->DB->Delete("DELETE FROM lager_reserviert WHERE parameter='$id' AND objekt='auftrag'");

        }


        //schaue artikel fuer artikel an wieviel geliefert wurde und ob bereits reservierungen vorliegen, wenn welche vorliegen auch reservieren auf 9999-01-01
        // Lager Check
        $cArtikelarr = !empty($artikelarr)?count($artikelarr):0;
        for($k=0;$k<$cArtikelarr; $k++)
        {
          if(isset($artikelarr[$k]['gelieferte_menge'])){
            $menge = $artikelarr[$k]['menge'] - $artikelarr[$k]['gelieferte_menge'];
          }
          else{
            $menge = $artikelarr[$k]['menge'];
          }

          $artikel = $artikelarr[$k]['artikel'];
          // pruefe artikel 12 menge 4
          $articleArr = $this->app->DB->SelectRow(
            sprintf(
              "SELECT lagerartikel,stueckliste FROM artikel WHERE id=%d LIMIT 1",$artikel
            )
          );
          $lagerartikel = $articleArr['lagerartikel'];
          $stueckliste = $articleArr['stueckliste'];
          if($lagerartikel>=1)
          {
            // menge = notwendige menge - bereits reserviert
            $zu_reservieren = $menge;// - $anzahl_reserviert;

            if($zu_reservieren>0)
            {
              if($typ==='auftrag'){

                //if($this->LagerFreieMenge($artikel) <  $zu_reservieren) continue;
                $lagerfreiemenge = $this->LagerFreieMenge($artikel, true, $standardlager, $projektlager);
                if($lagerfreiemenge <=0) {
                  continue;
                }

                // die restliche menge auf den Auftrag reservieren
                if($lagerfreiemenge < $zu_reservieren){
                  $zu_reservieren = $lagerfreiemenge;
                }

                // schaue ob es artikel in reserivierungen fuer diesen auftrag schon gibt dann erhoehe
//                $check = $this->app->DB->Select("SELECT menge FROM lager_reserviert WHERE artikel='$artikel'
//                    AND objekt='auftrag' AND parameter='$id' LIMIT 1");
                $check=0;

                if($check > 0)
                {
                  // wenn schon etwas reserviert ist
                  $this->app->DB->Update("UPDATE lager_reserviert SET menge = menge + '$zu_reservieren' WHERE
                      artikel='$artikel'
                      AND objekt='auftrag' AND parameter='$id'");
                } else {
                  $this->app->DB->Insert("INSERT INTO lager_reserviert
                      (id,adresse,artikel,menge,grund,projekt,firma,bearbeiter,datum,objekt,parameter,posid)
                      VALUES('','$adresse','$artikel','$zu_reservieren','Reservierung f&uuml;r Auftrag $belegnr','$projekt',
                        '".$this->app->User->GetFirma()."','".$this->app->User->GetName()."','9999-99-99','auftrag','$id','".$artikelarr[$k]['id']."')");
                }

              }
            }
          }
        }
      }
  
      function AnzeigePositionenBrutto($anrede, $doctyp, $projekt, $adresse,$doctypeid=0)
      {
        // wenn im beleg 3 oder 4 dann zaehlt die einstellung
        if($doctypeid > 0 && in_array($doctyp, ['rechnung', 'angebot','auftrag','gutschrift','bestellung'])) {
          $anzeigesteuer = $this->app->DB->Select("SELECT anzeigesteuer FROM `$doctyp` WHERE id='$doctypeid' LIMIT 1");
          if($anzeigesteuer==3) {
            return false;
          }
          if($anzeigesteuer==4) {
            return true;
          }
        }
        if($adresse)
        {
          $bruttonetto = $this->app->DB->Select("SELECT anzeigesteuerbelege FROM adresse WHERE id = '$adresse' LIMIT 1");
          if($bruttonetto == 1) {
            return false;
          }
          if($bruttonetto == 2) {
            return true;
          }
        }
        if($projekt){
          $bruttonetto = $this->app->DB->Select("SELECT anzeigesteuerbelege FROM projekt WHERE id = '$projekt' LIMIT 1");
          if($bruttonetto == 1) {
            return false;
          }
          if($bruttonetto == 2) {
            return true;
          }
        }
        if($this->app->erp->Firmendaten('immerbruttorechnungen',$projekt)) {
          return true;
        }
        return false;
      }

      function AnzeigeBelegNettoAdresse($anrede, $doctyp, $projekt, $adresse,$doctypeid=0)
      {
        // wenn im beleg 3 oder 4 dann zaehlt die einstellung
        if($doctypeid > 0 && ($doctyp==='rechnung' || $doctyp==='angebot' || $doctyp==='auftrag' || $doctyp==='gutschrift' || $doctyp==='bestellung')) {
          $anzeigesteuer = $this->app->DB->Select("SELECT anzeigesteuer FROM $doctyp WHERE id='$doctypeid' LIMIT 1");
          if($anzeigesteuer==3) {
            return true;
          }
          if($anzeigesteuer==4) {
            return false;
          }
        }

        if($adresse) {
          $bruttonetto = $this->app->DB->Select("SELECT anzeigesteuerbelege FROM adresse WHERE id = '$adresse' LIMIT 1");
          if($bruttonetto == 1) {
            return 1;
          }
          if($bruttonetto == 2) {
            return 0;
          }
        }

        if($doctyp==='bestellung' && $this->app->erp->Firmendaten('immerbruttorechnungen',$projekt)!='1' &&
          $this->Projektdaten($projekt,'anzeigesteuerbelegebestellung') != '1') {
          return 1;
        }
        if($projekt) {
          $bruttonetto = $this->Projektdaten($projekt, 'anzeigesteuerbelege');// $this->app->DB->Select("SELECT anzeigesteuerbelege FROM projekt WHERE id = '$projekt' LIMIT 1");
          if($bruttonetto == 1) {
            return 1;
          }
          if($bruttonetto == 2) {
            return 0;
          }
        }

        if($doctyp==='bestellung' && $this->app->erp->Firmendaten('immerbruttorechnungen',$projekt)!='1') {
          return 1;
        }

        if($this->app->erp->Firmendaten('immerbruttorechnungen',$projekt)!='1' &&
          ($anrede==='firma'  || $doctyp==='bestellung' || $this->app->erp->AnzeigeBelegNetto($anrede,$projekt,$doctyp,$doctypeid) ||
            $this->app->erp->Firmendaten('immernettorechnungen',$projekt)=='1')) {
          return 1;
        }
        return 0;
      }


      function AnzeigeBelegNetto($typ,$projekt,$doctype="",$doctypeid=0)
      {
        // wenn im beleg 3 oder 4 dann zaehlt die einstellung
        if($doctypeid > 0 && ($doctype==='rechnung' || $doctype==='angebot' || $doctype==='auftrag' || $doctype=='gutschrift' || $doctype=='bestellung'))
        {
          $anzeigesteuer = $this->app->DB->Select("SELECT anzeigesteuer FROM $doctype WHERE id='$doctypeid' LIMIT 1");
          if($anzeigesteuer==3) {
            return 1;
          }
        }
        $orderBy = '';
        if($projekt > 0) {
          $orderBy = ' ORDER BY projekt DESC';
        }
        return (int)$this->app->DB->Select(
          sprintf(
            'SELECT netto FROM adresse_typ WHERE type=\'%s\' %s LIMIT 1',
            $typ, $orderBy
          )
        );
      }

      function AuftragNeuberechnenAllen()
      {
        $arrAuftrag = $this->app->DB->SelectArr("SELECT id FROM auftrag WHERE status!='abgeschlossen' AND status!='storniert' AND autoversand=1 ORDER BY fastlane = 1 DESC, datum");
        if(empty($arrAuftrag)) {
          return;
        }
        foreach($arrAuftrag as $rowAuftrag)
        {
          $this->AuftragNeuberechnen($rowAuftrag['id']);
        }
      }

      function BestellungNeuberechnen($id)
      {
        $obj = $this->LoadModul('bestellung');
        if(!empty($obj) && method_exists($obj, 'BestellungNeuberechnen'))
        {
          $obj->BestellungNeuberechnen($id);
        }
      }

      function LieferscheinNeuberechnen($id)
      {

      }

      function AngebotNeuberechnen($id)
      {
        $this->ANABREGSNeuberechnen($id,"angebot");
      }



      function AuftragZahlungaufteilen($auftrag_org,$auftrag_new)
      {
        $gesamtsumme_new = $this->app->DB->Select("SELECT gesamtsumme FROM auftrag WHERE id='$auftrag_new' LIMIT 1");
        $adresse_new = $this->app->DB->Select("SELECT adresse FROM auftrag WHERE id='$auftrag_new' LIMIT 1");

        //pruefe ob es auf auftrag einen Zahlungseingang gibt
        $zahlungen = $this->app->DB->SelectArr("SELECT * FROM kontoauszuege_zahlungseingang WHERE objekt='auftrag' AND parameter='$auftrag_org'");
        for($i=0;$i<(!empty($zahlungen)?count($zahlungen):0);$i++)
        {
          if($zahlungen[$i]['betrag'] > $gesamtsumme_new)
          {
            $betrag_new = $zahlungen[$i]['betrag'] - $gesamtsumme_new;
            $this->app->DB->Update("UPDATE kontoauszuege_zahlungseingang SET betrag='$betrag_new' WHERE id='".$zahlungen[$i]['id']."' LIMIT 1");

            $this->app->DB->Insert("INSERT INTO kontoauszuege_zahlungseingang (id,adresse,bearbeiter,betrag,datum,objekt,parameter,kontoauszuege,firma,abgeschlossen,parameter2)
              VALUES ('','".$adresse_new."','".$zahlungen[$i]['bearbeiter']."','".$gesamtsumme_new."','".$zahlungen[$i]['datum']."','auftrag','".$auftrag_new."','".$zahlungen[$i]['kontoauszuege']."','".$zahlungen[$i]['firma']."','".$zahlungen[$i]['abgeschlossen']."','".$zahlungen[$i]['parameter2']."')");
            break;
          }
        }
        return;
      }


      function AuftragNeuberechnen($id,$force=false)
      {
        $this->ANABREGSNeuberechnen($id,"auftrag",$force);
      }



      function GutschriftNeuberechnen($id)
      {
        $this->ANABREGSNeuberechnen($id,"gutschrift");

        // alle zugehoerigen Rechnungen
        $rechnungid = $this->app->DB->Select("SELECT rechnungid FROM gutschrift WHERE id='$id' LIMIT 1");
        if($rechnungid > 0 && $this->Firmendaten("mahnwesenmitkontoabgleich")=="1")
        {
          $this->app->DB->Update("UPDATE rechnung SET zahlungsstatus='offen' WHERE id='$rechnungid' AND mahnwesenfestsetzen!=1 LIMIT 1");
          $this->RechnungNeuberechnen($rechnungid);
        }
      }


      function DeleteGutschrift($id)
      {
        $belegnr = $this->app->DB->Select("SELECT belegnr FROM gutschrift WHERE id='$id' LIMIT 1");
        if($belegnr==="" || $belegnr==="0")
        {
          $this->app->DB->Delete("DELETE FROM gutschrift_position WHERE gutschrift='$id'");
          $this->app->DB->Delete("DELETE FROM gutschrift_protokoll WHERE gutschrift='$id'");
          $this->app->DB->Delete("DELETE FROM gutschrift WHERE id='$id' LIMIT 1");
        }
      }
      
      function Skontofaehig($id, $art, $mitsteuer=true)
      {
        $name = ucfirst($art).'MitUmsatzeuer';
        if(!method_exists($this->app->erp, $name))
        {
          return;
        }
        $skontofaehig = 0;
        $positionen = $this->app->DB->SelectArr("SELECT ap.*,art.keinskonto as artkeinskonto FROM $art"."_position ap INNER JOIN artikel art ON ap.artikel = art.id  WHERE $art = '$id' ".($art == 'angebot'?" AND ifnull(ap.optional,0) = 0 ":''));
        $steuerfrei = !$this->$name($id);
        
        $steuersatzermaessigt = $this->GetSteuersatzErmaessigt(true,$id,$art);
        $steuersatznormal = $this->GetSteuersatzNormal(true,$id,$art);
        $zahlungszielskonto = $this->app->DB->Select("SELECT zahlungszielskonto FROM $art WHERE id = '$id' LIMIT 1");
        
        foreach($positionen as $k => $v)
        {
          if($v['artkeinskonto'] == 1 && $v['skontobetrag'] !== 0)
          {
            
          }else{
            $steuersatz = 1;
            if(!$steuerfrei)
            {
              if(!is_null($v['steuersatz']) && $v['steuersatz'] >= 0)
              {
                $steuersatz = 1+ $v['steuersatz'];
              }else{
                if($v['umsatzsteuer'] == 'befreit')
                {
                  
                }elseif($v['umsatzsteuer'] == 'ermaessigt')
                {
                  $steuersatz = $steuersatzermaessigt;
                }else{
                  $steuersatz = $steuersatznormal;
                }
              }
              $rabatt = 0;
              if(!$v['keinrabatterlaubt'])$rabatt = (float)$v['rabatt'];
            }
            if($mitsteuer)
              $skontofaehig += $v['menge'] * $v['preis']* (1-$rabatt/100) * $steuersatz;
            else
              $skontofaehig += $v['menge'] * $v['preis']* (1-$rabatt/100);
          }
        }
        return $skontofaehig;
      }

      function BerechneSkonto($id, $art, $force = false)
      {
        if( ($art == '') || ($id <= 0) ){
          return;
        }
        if($art === 'proformarechnung') {
          return;
        }
        if(!$force
          && $this->app->DB->Select(
            sprintf(
              'SELECT schreibschutz FROM `%s` WHERE id = %d LIMIT 1',
              $art, $id
            )
          )
        ) {
          return;
        }
        $name = ucfirst($art).'MitUmsatzeuer';
        if(!method_exists($this->app->erp, $name)) {
          return;
        }
        $positionen = $this->app->DB->SelectArr(
          "SELECT ap.*,art.keinskonto as artkeinskonto, art.umsatzsteuer as artumsatzsteuer 
            FROM $art"."_position ap 
            INNER JOIN artikel art ON ap.artikel = art.id  
            WHERE $art = '$id' ".($art == 'angebot'?" AND ifnull(ap.optional,0) = 0 ":''));
        if(empty($positionen)){
          $this->app->DB->Update("UPDATE $art SET skontobetrag = 0 WHERE id = '$id' LIMIT 1");
          return;
        }
        $steuerfrei = !$this->$name($id);
        $skontobetrag = 0;
        $docArr = $this->app->DB->SelectRow(sprintf('SELECT * FROM `%s` WHERE id = %d', $art, $id));
        if(!empty($docArr)){
          $steuersatzermaessigt = 1 + $docArr['steuersatz_ermaessigt'] / 100;
          $steuersatznormal = 1 + $docArr['steuersatz_normal'] / 100;
          $zahlungszielskonto = $docArr['zahlungszielskonto'];
        }
        else{
          $steuersatzermaessigt = $this->GetSteuersatzErmaessigt(true, $id, $art);
          $steuersatznormal = $this->GetSteuersatzNormal(true, $id, $art);
          $zahlungszielskonto = $this->app->DB->Select("SELECT zahlungszielskonto FROM $art WHERE id = '$id' LIMIT 1");
        }
        foreach($positionen as $k => $v) {
          if($v['artkeinskonto'] == 1 && $v['skontobetrag'] !== 0) {
            $skontobetragpos = 0;
            if(!$v['skontosperre']) {
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag = 0 WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_netto_einzeln = 0 WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_netto_gesamt = 0 WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_brutto_einzeln = 0 WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_brutto_einzeln = 0 WHERE id = '".$v['id']."' LIMIT 1");
            }
            else {
              $skontobetragpos = $v['skontobetrag'];
            }
            $skontobetrag += $skontobetragpos;
          }
          else{
            $steuersatz = 1;
            if(!$steuerfrei)
            {
              if(!is_null($v['steuersatz']) && $v['steuersatz'] >= 0)
              {
                $steuersatz = 1+ $v['steuersatz']/100;
              }else{
                if($v['umsatzsteuer'] == '')
                {
                  $v['umsatzsteuer'] = $v['artumsatzsteuer'];
                  
                }
                if($v['umsatzsteuer'] === 'befreit')
                {
                  
                }elseif($v['umsatzsteuer'] === 'ermaessigt')
                {
                  $steuersatz = $steuersatzermaessigt;
                }else{
                  $steuersatz = $steuersatznormal;
                }
              }
            }
            $rabatt = 0;
            if(!empty($v['rabatt'])) {
              $rabatt = (float)$v['rabatt'];
            }
            $skontobetragpos = $v['menge'] * $v['preis']* (1-$rabatt/100) * $steuersatz * $zahlungszielskonto / 100;
            $skontobetragNettoEinzeln = $v['preis'] * (1-$rabatt/100) * $zahlungszielskonto / 100;
            $skontobetragBruttoEinzeln = $v['preis'] * (1-$rabatt/100) * $steuersatz * $zahlungszielskonto / 100;
            $skontobetragNettoGesamt = $v['menge'] * $v['preis'] * (1-$rabatt/100) * $zahlungszielskonto / 100;
            
            if(empty($v['skontosperre'])) {
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag = '$skontobetragpos' WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_brutto_gesamt = '$skontobetragpos' WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_netto_gesamt = '$skontobetragNettoGesamt' WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_brutto_einzeln = '$skontobetragBruttoEinzeln' WHERE id = '".$v['id']."' LIMIT 1");
              $this->app->DB->Update("UPDATE $art"."_position SET skontobetrag_netto_einzeln = '$skontobetragNettoEinzeln' WHERE id = '".$v['id']."' LIMIT 1");
            }
            else {
              $skontobetragpos = $v['skontobetrag'];
            }
            $skontobetrag += $skontobetragpos;
          }
        }
        $this->app->DB->Update("UPDATE $art SET skontobetrag = '$skontobetrag' WHERE id = '$id' LIMIT 1");
        if(!empty($positionen) && (empty($docArr) || empty($docArr['skontoberechnet']))) {
          $this->app->DB->Update("UPDATE $art SET skontoberechnet = '1' WHERE id = '$id' LIMIT 1");
        }
      }
      
        /*
        * Retrieve the associated documents regarding payments
        * Gutschrift -> Rechnung -> Auftrag OR Verbindlichkeit
        * Results array of ids, types, belegnr
        */
        public function GetZahlungenAssociatedDocuments(int $id, string $type, string $lastlevel = 'auftrag') : array {

            $assocs = array(
                array(
                    'type' => 'auftrag',
                    'below' => 'rechnung',
                ),
                array(
                    'above' => 'auftrag',
                    'type' => 'rechnung',
                    'below' => 'gutschrift'
                ),
                array(
                    'above' => 'rechnung',
                    'type' => 'gutschrift'
                ),
                array(
                    'type' => 'verbindlichkeit'
                )
            );


            if ($id <= 0) {
                throw new exception('no id provided');
            }

            if (!in_array($type, array('rechnung','gutschrift','auftrag','verbindlichkeit'))) {
                throw new exception('invalid type '.$type);
            }            

            $id = $this->app->Secure->GetGET('id');

            // Go to highest level         
            $above = $assocs[array_search($type,array_column($assocs,'type'))]['above'];
            while ($above) {

                if ($type == $lastlevel) {
                    break;
                }

                $sql = "SELECT ".$above."id as id FROM ".$type." WHERE id = ".$id;          
                $above_id = $this->app->DB->SelectArr($sql)[0];
                if (!empty($above)) {
                    $type = $above;
                    $id = $above_id['id'];
                }
                $above = $assocs[array_search($type,array_column($assocs,'type'))]['above'];
            }

            // Cascade down and retrieve all documents
            $result_documents = array();
            $ids = array($id);
            $ref = 'id';
            do {
                $sql = "SELECT id, '".$type."' AS type, belegnr FROM ".$type." WHERE ".$ref." IN (".implode(",",$ids).")";
                $result = $this->app->DB->SelectArr($sql);
                if (!empty($result)) {
                    $result_documents = array_merge($result_documents, $result);
                    $ids = array_column($result,'id');
                    $ref = $type."id";
                    $type = $assocs[array_search($type,array_column($assocs,'type'))]['below'];
                } else {
                    break;
                }
            } while ($type); 

            return($result_documents);               
        }

        /*
        * Calculate the payments of a document (rechnung, gutschrift, auftrag, verbindlichkeit)
        * Results array of payments (datum, doc_type, doc_id, doc_inof, betrag, waehrung)
        * Gutschrift -> Rechnungid, Rechnung -> Auftragid
        */

        public function GetZahlungen(int $id, string $type, string $cascadelevel = '') : array {

            if ($cascadelevel != '') {
                $documents = $this->GetZahlungenAssociatedDocuments($id, $type, $cascadelevel);
            } else {
                $documents = array(array('id' => $id, 'type' => $type));
            }

            if (empty($documents)) {
                return(array());
            }

            $ids = array();

            foreach ($documents as $document) {
                $ids[] = $document['type'].$document['id'];
            }

            $sql = "
                SELECT
                    typ,
                    id,
                    ".$this->app->erp->FormatDate('datum')." as datum,
                    doc_typ,
                    doc_id,
                    doc_info,
                    ".$this->app->erp->FormatMenge('betrag',2)." as betrag,
                    waehrung
                FROM
                    fibu_buchungen_alle
                WHERE
                    CONCAT(typ,id) IN ('".implode("','",$ids)."')
                ORDER BY 
                    (SELECT datum) ASC
                ";            

            $result = $this->app->DB->SelectArr($sql);

            if (empty($result)) {
                return(array());
            } 
            return($result);
        }

        /*
        * Calculate the payment saldo information of a document
        * Auftrag: gesamtsumme, rechnung: soll, gutschrift: soll verbindlichkeit: betrag
        * returns array(array(betrag, waehrung)) one line per waehrung
        */
        public function GetSaldenDokument(int $id, string $type, string $cascadelevel = '') : array {

            if ($cascadelevel != '') {
                $documents = $this->GetZahlungenAssociatedDocuments($id, $type, $cascadelevel);
            } else {
                $documents = array(array('id' => $id, 'type' => $type));
            }

            if (empty($documents)) {
                return(array());
            }

            $ids = array();

            foreach ($documents as $document) {
                $ids[] = $document['type'].$document['id'];
            }

            $sql = "
                SELECT
                    ".$this->app->erp->FormatMenge('SUM(betrag)',2)." as betrag,
                    waehrung
                FROM
                    fibu_buchungen_alle
                WHERE
                    CONCAT(typ,id) IN ('".implode("','",$ids)."')
                GROUP BY
                    waehrung";            

            $result = $this->app->DB->SelectArr($sql);

            if (!empty($result)) {
                return($result);
            } 
            return(array());
        }


        /*
        * Calculate the payment amount of a document
        * Auftrag: gesamtsumme, rechnung: soll, gutschrift: soll verbindlichkeit: betrag
        * returns array(betrag, waehrung) or empty array if multiple
        */
        public function GetSaldoDokument(int $id, string $type, string $buchungsart = '', string $datum_bis = '') : array {

            $sql = "
                SELECT
                    SUM(betrag) as betrag,
                    waehrung
                FROM
                    fibu_buchungen_alle
                WHERE
                    typ = '".$type."' 
                        AND 
                    id = ".$id." 
                        AND 
                    (buchungsart = '".$buchungsart."' OR '".$buchungsart."' = '')
                        AND
                    (datum <=  '".$datum_bis."' OR '".$datum_bis."' = '')                   
                GROUP BY
                    waehrung";            
            $result = $this->app->DB->SelectArr($sql);

            if (!empty($result)) {
                if (count($result) == 1) {
                    return($result[0]);
                }         
            }
            return(array());            
        }

        /*
        * Create a fibu buchung
        * using module fibu_buchungen
        */
        public function fibu_buchungen_buchen(string $von_typ, int $von_id, string $nach_typ, int $nach_id, $betrag, string $waehrung, $datum, string $internebemerkung) {
            $fibu_buchungen = $this->app->loadModule('fibu_buchungen', false);
            if($fibu_buchungen !== null && method_exists($fibu_buchungen, 'fibu_buchungen_buchen')) {
              return $fibu_buchungen->fibu_buchungen_buchen($von_typ, $von_id, $nach_typ, $nach_id, $betrag, $waehrung, $datum, $internebemerkung);
            }          
        }

        /*
        * Refresh fibu buchung_alle tables
        * using module fibu_buchungen
        */
        public function fibu_rebuild_tables() {
            $fibu_buchungen = $this->app->loadModule('fibu_buchungen', false);
            if($fibu_buchungen !== null && method_exists($fibu_buchungen, 'fibu_buchungen_buchen')) {
              return $fibu_buchungen->fibu_rebuild_tables();
            }          
        }

         /*
        * Recalculate payment status and skonto
        * using module rechnung
        */
        public function rechnung_zahlstatus_berechnen($id = null) {
            $rechnung = $this->app->loadModule('rechnung', false);
            if($rechnung !== null && method_exists($rechnung, 'rechnung_zahlstatus_berechnen')) {
              return $rechnung->rechnung_zahlstatus_berechnen($id);
            }          
        }


      public function ANABREGSNeuberechnen($id,$art,$force=false)
      {
        if($id <= 0 || empty($art))
        {
          return;
        }

        //$this->LoadSteuersaetze($id,$art); //03.01.2019 Bruno entfernt, da Shopaufträge umsgestellt werden
        //$this->LoadKurs($id,$art); //03.01.2019 Bruno entfernt
        $belegarr = $this->app->DB->SelectRow("SELECT * FROM $art WHERE id='$id' LIMIT 1");
        if(empty($belegarr))
        {
          return;
        }

        $belegnr = $belegarr['belegnr'];
        $adresse =  $belegarr['adresse'];
        $status =  $belegarr['status'];
        $waehrung =  $belegarr['waehrung'];
        $rabatteportofestschreiben = 0;

        if($art === 'auftrag' && $belegarr['lieferantkdrnummer'] == '') {
          if($belegarr['lieferantenauftrag'] == 1){
            if($belegarr['lieferantenauftrag'] != 1 || empty($belegarr['lieferantkdrnummer'])){
              $this->app->DB->Update("
              UPDATE auftrag a 
              INNER JOIN adresse adr ON a.lieferant = adr.id 
              SET a.lieferantkdrnummer = if(a.lieferantennummer <> '',a.lieferantennummer,adr.lieferantennummer)
              WHERE a.lieferantkdrnummer = '' AND a.lieferantenauftrag = 1 AND a.id = '$id'
            ");
            }
          }
          else{
            if($belegarr['lieferantenauftrag'] != 0 || empty($belegarr['lieferantkdrnummer'])){
              $this->app->DB->Update("
              UPDATE auftrag a 
              INNER JOIN adresse adr ON a.adresse = adr.id 
              SET a.lieferantkdrnummer = if(a.kundennummer <> '',a.kundennummer, adr.kundennummer)
              WHERE a.lieferantkdrnummer = '' AND a.lieferantenauftrag = 0 AND a.id = '$id'
            ");
            }
          }
        }

        $schreibschutz = $belegarr['schreibschutz'];
        if($force!=true && $schreibschutz=='1'){
          return;
        }
        //waehrungen

        if($waehrung!='') {
          $this->app->DB->Update("UPDATE ".$art."_position SET waehrung='$waehrung' WHERE $art='".$id."' AND waehrung=''");
        }

        if($art==='auftrag')
        {
          // abweichende lieferadresse name loeschen wenn es keine gibt
          $abweichendelieferadresse = $belegarr['abweichendelieferadresse'];
          $rabatteportofestschreiben = $belegarr['rabatteportofestschreiben'];
          $liefername = $belegarr['liefername'];
          if($liefername=='' && $abweichendelieferadresse=='1'){
            $this->app->DB->Update("UPDATE auftrag SET abweichendelieferadresse=0 WHERE id='$id' LIMIT 1");
          }
        }
        
        $this->RunHook('ANABREGSNeuberechnen_1', 2, $art, $id);

        $this->CheckFreifelder($art,$id);
        
        $artikelarr = $this->app->DB->SelectArr(
          sprintf(
            'SELECT pos.*, 
                art.keinrabatterlaubt as art_keinrabatterlaubt, art.porto AS art_porto, art.rabatt AS art_rabatt,
                art.rabatt_prozent AS art_rabatt_prozent 
              FROM `%s` AS pos 
              LEFT JOIN artikel AS art ON pos.artikel = art.id 
              WHERE pos.`%s`= %d 
              ORDER BY pos.sort',
            $art.'_position', $art, (int)$id
          )
        );
        $adresse = $belegarr['adresse'];
        $cartikelarr = $artikelarr?count($artikelarr):0;

        if($art!=='bestellung')//$this->Firmendaten("modul_verband")=="1") //CLAUDI
        {
          $grundrabatt = 0;
          $rabatt1 = 0;
          $rabatt2 = 0;
          $rabatt3 = 0;
          $rabatt4 = 0;
          $rabatt5 = 0;
          if($art==='angebot' || $art==='auftrag' || $art==='rechnung' || $art==='gutschrift' || $art==='proformarechnung')
          {
            $rabattarr = $this->app->DB->SelectRow("SELECT * FROM $art WHERE id='$id' LIMIT 1");
            if(!empty($rabattarr)){
              $grundrabatt = $rabattarr['rabatt'];
              $rabatt1 = $rabattarr['rabatt1'];
              $rabatt2 = $rabattarr['rabatt2'];
              $rabatt3 = $rabattarr['rabatt3'];
              $rabatt4 = $rabattarr['rabatt4'];
              $rabatt5 = $rabattarr['rabatt5'];
            }

            if($grundrabatt>0) $rabattarr[] =  ((100-$grundrabatt)/100.0);
            if($rabatt1>0) $rabattarr[] = ((100-$rabatt1)/100.0);
            if($rabatt2>0) $rabattarr[] = ((100-$rabatt2)/100.0);
            if($rabatt3>0) $rabattarr[] = ((100-$rabatt3)/100.0);
            if($rabatt4>0) $rabattarr[] = ((100-$rabatt4)/100.0);
            if($rabatt5>0) $rabattarr[]=  ((100-$rabatt5)/100.0);

            $rabatt=1;
            if(!empty($rabattarr))
            {
              foreach($rabattarr as $rabattRow) {
                if($rabattRow > 0 && $rabattRow < 1) {
                  $rabatt *= $rabattRow;
                }
              }
            }

            $rabatt=(1-$rabatt)*100;
        
            if($grundrabatt >= 100 || $rabatt1 >= 100 || $rabatt2 >= 100 || $rabatt3 >= 100 || $rabatt4 >= 100 || $rabatt5 >= 100)
            {
              $rabatt = 100;
            }

            if($rabatt > 0 && $rabattarr['realrabatt'] != $rabatt) {
              $this->app->DB->Update(
                sprintf(
                  'UPDATE `%s` SET realrabatt=%f WHERE id=%d LIMIT 1',
                  $art,(float)$rabatt, (int)$id
                )
              );
            }
          }


          // Rabatt Sync starten
          
          $cartikelarr = $artikelarr?count($artikelarr):0;
          for($i=0;$i<$cartikelarr;$i++)
          {
            // kopiere rabatte zum ersten mal
            if($artikelarr[$i]['rabattsync']!='1')
            {
              // pruefe ob artikel rabatt bekommen darf
              $check_keinrabatterlaubt = $artikelarr[$i]['art_keinrabatterlaubt'];
              $check_porto = $artikelarr[$i]['art_porto'];
              $check_rabatt = $artikelarr[$i]['art_rabatt'];
              
              if($check_keinrabatterlaubt!="1" && $check_porto!="1" && $check_rabatt!="1")
              {

                  $this->app->DB->Update("UPDATE ".$art."_position SET rabattsync='1',
                      grundrabatt='$grundrabatt', rabatt1='$rabatt1', rabatt2='$rabatt2', rabatt3='$rabatt3', rabatt4='$rabatt4', rabatt5='$rabatt5',
                      keinrabatterlaubt='0' WHERE id='".$artikelarr[$i]['id']."' AND rabatt=0 AND keinrabatterlaubt!='1' LIMIT 1");


                if($this->app->DB->affected_rows() > 0){
                  $artikelarr[$i]['rabattsync'] = 1;
                  $artikelarr[$i]['grundrabatt'] = $grundrabatt;
                  $artikelarr[$i]['rabatt1'] = $rabatt1;
                  $artikelarr[$i]['rabatt2'] = $rabatt2;
                  $artikelarr[$i]['rabatt3'] = $rabatt3;
                  $artikelarr[$i]['rabatt4'] = $rabatt4;
                  $artikelarr[$i]['rabatt5'] = $rabatt5;
                }
              } else {
                if($check_porto=="1")
                {
                  $this->app->DB->Update("UPDATE ".$art."_position SET rabattsync='1',keinrabatterlaubt='".($rabatteportofestschreiben?'1':'0')."',rabatt='0' WHERE id='".$artikelarr[$i]['id']."' LIMIT 1");
                  $artikelarr[$i]['keinrabatterlaubt'] = $rabatteportofestschreiben?'1':'0';
                  $artikelarr[$i]['rabattsync'] = 1;
                  $artikelarr[$i]['rabatt'] = 0;
                }
                elseif($check_keinrabatterlaubt=="1")
                {
                  $this->app->DB->Update("UPDATE ".$art."_position SET rabattsync='1',keinrabatterlaubt='1',rabatt='0' WHERE id='".$artikelarr[$i]['id']."' LIMIT 1");
                  $artikelarr[$i]['keinrabatterlaubt'] = 1;
                  $artikelarr[$i]['rabattsync'] = 1;
                  $artikelarr[$i]['rabatt'] = 0;
                }
              }
            }
            $keinrabatterlaubt_sub = $artikelarr[$i]['keinrabatterlaubt'];
            if($keinrabatterlaubt_sub=='1') {
              $rabatt=0;
            }else{
              // rechne rabatt fuer position aus
              $posarr = $artikelarr[$i];
              if(!empty($posarr)){
                $grundrabatt_sub = $posarr['grundrabatt'];
                $rabatt1_sub = $posarr['rabatt1'];
                $rabatt2_sub = $posarr['rabatt2'];
                $rabatt3_sub = $posarr['rabatt3'];
                $rabatt4_sub = $posarr['rabatt4'];
                $rabatt5_sub = $posarr['rabatt5'];
                $keinrabatterlaubt_sub = $posarr['keinrabatterlaubt'];
              }else{
                $grundrabatt_sub = 0;
                $rabatt1_sub = 0;
                $rabatt2_sub = 0;
                $rabatt3_sub = 0;
                $rabatt4_sub = 0;
                $rabatt5_sub = 0;
                $keinrabatterlaubt_sub = 0;
              }
              $rabattarr = array();

              if($grundrabatt_sub>0) $rabattarr[] =  ((100-$grundrabatt_sub)/100.0);
              if($rabatt1_sub>0) $rabattarr[] = ((100-$rabatt1_sub)/100.0);
              if($rabatt2_sub>0) $rabattarr[] = ((100-$rabatt2_sub)/100.0);
              if($rabatt3_sub>0) $rabattarr[] = ((100-$rabatt3_sub)/100.0);
              if($rabatt4_sub>0) $rabattarr[] = ((100-$rabatt4_sub)/100.0);
              if($rabatt5_sub>0) $rabattarr[]=  ((100-$rabatt5_sub)/100.0);

              $rabatt=1;
              if(!empty($rabattarr)) {
                foreach($rabattarr as $rabattRow)
                {
                  if($rabattRow > 0 && $rabattRow < 1) {
                    $rabatt *= $rabattRow;
                  }
                }
              }

              $rabatt=(1-$rabatt)*100;
              if($grundrabatt_sub >= 100 || $rabatt1_sub >= 100 || $rabatt2_sub >= 100 || $rabatt3_sub >= 100 || $rabatt4_sub >= 100 || $rabatt5_sub >= 100)
              {
                $rabatt = 100;
              }
            }
            // wenn kein rabatt fuer die Position erlaubt ist

            if($this->Firmendaten("modul_verband")=="1" && $this->ModulVorhanden('verband')) //CLAUDI
              $this->app->DB->Update("UPDATE ".$art."_position SET rabatt='$rabatt' WHERE id='".$artikelarr[$i]['id']."' LIMIT 1");
            elseif($rabatt != 0) {
              $this->app->DB->Update("UPDATE ".$art."_position SET rabatt='$rabatt' WHERE id='".$artikelarr[$i]['id']."' AND rabatt=0 LIMIT 1");
            }
          }
        }

        // rabatt positionen berechnen also die, die auf den gesamten auftrag gehen
        $betrag = $this->ANABREGSNeuberechnenGesamtsummeOhnePortoUndKeinRabatt($id,$art);
        $cartikelarr = $artikelarr?count($artikelarr):0;
        for($i=0;$i<$cartikelarr;$i++)
        {
          $check_rabatt_artikel = $artikelarr[$i]['art_rabatt'];
          if($check_rabatt_artikel=='1')
          {
            $check_rabatt_artikel_prozente = $artikelarr[$i]['art_rabatt_prozent'];

            if($check_rabatt_artikel_prozente<>0)
            {
              $this->app->DB->Update("UPDATE ".$art."_position SET menge='1', preis='".((($betrag/100)*$check_rabatt_artikel_prozente)*-1)."' WHERE id='".$artikelarr[$i]['id']."' LIMIT 1");
            }
          }
        }

        // porto berechnen
        $portoRow = $this->app->DB->SelectRow(
          sprintf(
            'SELECT tp.*
            FROM `%s` AS tp 
            INNER JOIN artikel AS a ON a.id=tp.artikel
            WHERE a.porto=1 AND a.geloescht!=1 AND tp.`%s`= %d 
            LIMIT 1',
            $art.'_position', $art, (int)$id
          )
        );
        $portoid = !empty($portoRow['id'])?$portoRow['id']:0;
        $portoartikel = !empty($portoRow['artikel'])?$portoRow['artikel']:0;
        $keinrabatterlaubt_sub = !empty($portoRow['keinrabatterlaubt'])?$portoRow['keinrabatterlaubt']:0;

        $betrag = $this->ANABREGSNeuberechnenGesamtsummeOhnePorto($id,$art);
        if($portoid > 0 && $keinrabatterlaubt_sub!="1" && $this->Firmendaten("porto_berechnen"))
        {
          $realpreis = false;
          $portoberechnen = $this->PortoBerechnen($adresse,$betrag,$portoartikel, $realpreis);

          if($portoberechnen || $realpreis) {
            $this->app->DB->Update("UPDATE ".$art."_position SET menge='1',preis='".$this->PortoBerechnen($adresse,$betrag,$portoartikel)."' WHERE id='".$portoid ."' LIMIT 1");
          }
        }
        $this->ANABREGSNeuberechnenGesamtsumme($id,$art);

        if($art==="auftrag")
        {
          //tatsaechlicheslieferdatum
          $orderRow = $this->app->DB->SelectRow(
            sprintf(
              'SELECT tatsaechlicheslieferdatum, projekt, lieferdatum,land FROM auftrag WHERE id = %d LIMIT 1',
              (int)$id
            )
          );
          $tatsaechlicheslieferdatum = $orderRow['tatsaechlicheslieferdatum'];
          $projekt = $orderRow['projekt'];
          $differenztage = $this->Projektdaten($projekt,'differenz_auslieferung_tage');
          if($differenztage<0 || empty($differenztage)) {
            $differenztage=0;
          }
          $lieferdatum = $orderRow['lieferdatum'];
          $land = $orderRow['land'];
          if(($tatsaechlicheslieferdatum==='0000-00-00' || $tatsaechlicheslieferdatum=='') && $lieferdatum!=='0000-00-00')
          {
            while($this->app->DB->Select("SELECT id FROM auftrag WHERE weekday(DATE_SUB(lieferdatum, INTERVAL $differenztage DAY)) >= 5 AND id='$id' LIMIT 1") ||
                  $this->app->DB->Select("SELECT id FROM arbeitsfreietage WHERE datum = DATE_SUB((SELECT lieferdatum FROM auftrag WHERE id = '$id' LIMIT 1), INTERVAL $differenztage DAY) AND (projekt='$projekt' OR projekt=0) AND (land='$land' OR land='') ORDER by land='$land' LIMIT 1"))
            {
              $differenztage++;
            }
            
            $this->app->DB->Update("UPDATE auftrag SET tatsaechlicheslieferdatum=DATE_SUB(lieferdatum, INTERVAL $differenztage DAY) WHERE id='$id' LIMIT 1");
          }

          $this->EventAPIAdd("EventAuftragEdit",$id,"auftrag","edit");
        }
        
        $this->BerechneDeckungsbeitrag($id,$art);
        $this->BerechneSkonto($id, $art);
        

        $teillieferung = false;
        $systemfreitext = '';
        if($art === 'rechnung') {
          $systemfreitext = $this->app->DB->Select(sprintf('SELECT systemfreitext FROM rechnung WHERE id = %d', $id));
        }
        elseif($art === 'auftrag') {
          $systemfreitext = $this->app->DB->Select(sprintf('SELECT systemfreitext FROM auftrag WHERE id = %d', $id));
        }

        if($systemfreitext == '' && ($art==='rechnung' || $art==='auftrag')) {
          if($art==='auftrag') {
            $tmprechnung = $this->app->DB->SelectArr("SELECT projekt, id as auftragid, zahlungsweise,transaktionsnummer,teillieferungvon FROM $art WHERE id='$id' LIMIT 1");
            $teillieferung = ($tmprechnung[0]['teillieferungvon']>0?true:false);
          }
          else{
            $tmprechnung = $this->app->DB->SelectArr("SELECT projekt, auftragid, zahlungsweise FROM $art WHERE id='$id' LIMIT 1");
          }

          if($tmprechnung[0]['transaktionsnummer']==''){
            $tmprechnung[0]['transaktionsnummer'] = $this->app->DB->Select("SELECT transaktionsnummer FROM auftrag WHERE id='" . $tmprechnung[0]['auftragid'] . "' LIMIT 1");
          }

        }
        $this->RunHook('ANABREGSNeuberechnenEnde',2, $id, $art);
      }

  /**
   * @param array $taxes
   * @param array $posTaxes
   *
   * @return array
   */
      public function addErloesFromPos($taxes, $posTaxes)
      {
        if(empty($taxes) || empty($posTaxes)) {
          return $taxes;
        }
        $posByErloes = [];
        $hasErloes = false;
        foreach($posTaxes as $posTax) {
          if(!empty($posTax['erloese'])) {
            $hasErloes = true;
          }
          $posByErloes[(string)$posTax['steuersatz']][!empty($posTax['erloese'])?(string)$posTax['erloese']:''][]
            = $posTax;
        }
        if(!$hasErloes) {
          return $taxes;
        }
        $taxesToAdd = [];
        foreach($taxes as $key => $tax)  {
          $taxRate = $tax['steuersatz'];
          if(empty($posByErloes[$taxRate])) {
            continue;
          }
          if(count($posByErloes[$taxRate]) === 1) {
            $erloes = array_keys($posByErloes[$taxRate]);
            $taxes[$key]['erloese'] = reset($erloes);
            continue;
          }
          $first = true;
          foreach($posByErloes[$taxRate] as $erloes => $positions) {
            $brutto = 0.0;
            $netto = 0.0;
            foreach($positions as $position) {
              $brutto += $position['brutto'];
              $netto += $postion['netto'];
            }
            if($first) {
              $taxesToAdd[] = $tax;
              $taxToaddKey = (!empty($taxesToAdd)?count($taxesToAdd):0)-1;
              $taxesToAdd[$taxToaddKey]['brutto'] -= $brutto;
              $taxesToAdd[$taxToaddKey]['netto'] -= $netto;
              $tax['brutto'] = $brutto;
              $tax['netto'] = $netto;
              $tax['erloese'] = $erloes;
              $taxes[$key]['brutto'] = $tax['brutto'];
              $taxes[$key]['netto'] = $tax['netto'];
              $taxes[$key]['erloese'] = $tax['erloese'];
              $first = false;
              continue;
            }
            $taxToaddKey = (!empty($taxesToAdd)?count($taxesToAdd):0)-1;
            $taxesToAdd[] = $taxesToAdd[$taxToaddKey];
            $taxToaddKey = (!empty($taxesToAdd)?count($taxesToAdd):0)-1;
            $taxesToAdd[$taxToaddKey]['brutto'] -= $brutto;
            $taxesToAdd[$taxToaddKey]['netto'] -= $netto;
            $taxesToAdd[$taxToaddKey - 1]['brutto'] = $brutto;
            $taxesToAdd[$taxToaddKey - 1]['netto'] = $netto;
            $taxesToAdd[$taxToaddKey - 1]['erloese'] = $erloes;
          }
        }
        foreach($taxesToAdd as $tax) {
          if($tax['netto'] != 0.0) {
            $taxes[] = $tax;
          }
        }

        return $taxes;
      }

  /**
   * @param int         $artikel
   * @param int         $ust_befreit
   * @param bool|int    $aufwendung
   * @param float       $tmpsteuersatz
   * @param string      $tmpsteuertext
   * @param string      $tmperloes
   * @param string      $umsatzsteuerpos
   * @param null|string $ustid
   * @param int         $projekt
   */
      public function getErloesFirmendaten($artikel, $ust_befreit,$aufwendung,  &$tmpsteuersatz,  &$tmpsteuertext, &$tmperloes, $umsatzsteuerpos, $ustid = null, $projekt = 0) {
        $tmperloes = '';
        $artikeldata = $this->app->DB->SelectRow("SELECT * FROM artikel WHERE id = '$artikel' LIMIT 1");
        if(empty($artikeldata)) {
          return;
        }
        $umsatzsteuer = $artikeldata['umsatzsteuer'] === 'ermaessigt'?'ermaessigt':($artikeldata['umsatzsteuer']==='befreit'?'befreit':'normal');
        if($umsatzsteuerpos) {
          $umsatzsteuer = $umsatzsteuerpos;
        }
        switch($ust_befreit) {
          case 1:
            if($aufwendung) {
              if(trim((String)$ustid) !== '') {
                $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_euermaessigt');
                return;
              }
              if($umsatzsteuer === 'ermaessigt')
              {
                $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_euermaessigt');
                return;
              }
              $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_eunormal');
              return;
            }
            if(trim((String)$ustid) !== '') {
              $tmperloes = $this->Firmendaten('steuer_erloese_inland_innergemeinschaftlich');
              return;
            }
            if($umsatzsteuer === 'ermaessigt')
            {
              $tmperloes = $this->Firmendaten('steuer_erloese_inland_euermaessigt');
              return;
            }
            $tmperloes = $this->Firmendaten('steuer_erloese_inland_eunormal');
            return;
            break;
          case 2:
            if($aufwendung) {
              $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_import');
              return;
            }
            $tmperloes = $this->Firmendaten('steuer_erloese_inland_export');
            return;
            break;
          case 3:
            if($aufwendung) {
              $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_nichtsteuerbar');
              return;
            }
            $tmperloes = $this->Firmendaten('steuer_erloese_inland_nichtsteuerbar');
            return;
            break;
          default:
            if($aufwendung) {
              if($umsatzsteuer === 'ermaessigt') {
                $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_ermaessigt');
                return;
              }
              if($umsatzsteuer === 'befreit'){
                $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_nichtsteuerbar');
                return;
              }
              $tmperloes = $this->Firmendaten('steuer_aufwendung_inland_normal');
              return;
            }
            if($umsatzsteuer === 'ermaessigt') {
              $tmperloes = $this->Firmendaten('steuer_erloese_inland_ermaessigt');
              return;
            }
            if($umsatzsteuer === 'befreit') {
              $tmperloes = $this->Firmendaten('steuer_erloese_inland_nichtsteuerbar');
              return;
            }
            $tmperloes = $this->Firmendaten('steuer_erloese_inland_normal');
            return;

            break;
        }
      }

     /**
      * @param int         $artikel
      * @param int         $ust_befreit
      * @param bool|int    $aufwendung
      * @param float       $tmpsteuersatz
      * @param string      $tmpsteuertext
      * @param string      $tmperloes
      * @param string      $umsatzsteuerpos
      * @param null|string $ustid
      * @param int         $projekt
      */
      function GetArtikelSteuer($artikel, $ust_befreit,$aufwendung,  &$tmpsteuersatz,  &$tmpsteuertext, &$tmperloes, $umsatzsteuerpos, $ustid = null, $projekt = 0)
      {
        $tmperloes = '';
        $artikeldata = $this->app->DB->SelectRow("SELECT * FROM artikel WHERE id = '$artikel' LIMIT 1");
        if(empty($artikeldata)) {
          return;
        }
        $umsatzsteuer = $artikeldata['umsatzsteuer'] === 'ermaessigt'?'ermaessigt':($artikeldata['umsatzsteuer']==='befreit'?'befreit':'normal');
        if($umsatzsteuerpos) {
          $umsatzsteuer = $umsatzsteuerpos;
        }
        $projectRow = null;
        if($projekt) {
          $projectRow = $this->app->DB->SelectRow(
            sprintf(
              'SELECT * FROM projekt WHERE id = %d',
              $projekt
            )
          );
        }
        $tmpsteuertext = '';
        $kategorie = null;
        switch($ust_befreit)
        {
          case 1:
            $tmpsteuertext = $artikeldata['steuertext_innergemeinschaftlich'];
            if($aufwendung)
            {
              if(trim((String)$ustid) !== '')
              {
                $tmperloes = $artikeldata['steuer_aufwendung_inland_innergemeinschaftlich'];
              }else{
                if($umsatzsteuer === 'ermaessigt')
                {
                  $tmperloes = $artikeldata['steuer_aufwendung_inland_euermaessigt'];
                }else{
                  $tmperloes = $artikeldata['steuer_aufwendung_inland_eunormal'];
                }
              }
            }else{
              if(trim((String)$ustid) !== '')
              {
                $tmperloes = $artikeldata['steuer_erloese_inland_innergemeinschaftlich'];
              }else{
                if($umsatzsteuer === 'ermaessigt')
                {
                  $tmperloes = $artikeldata['steuer_erloese_inland_euermaessigt'];
                }else{
                  $tmperloes = $artikeldata['steuer_erloese_inland_eunormal'];
                }
              }              
            }
          break;
          case 2:
            $tmpsteuertext = $artikeldata['steuertext_export'];
            if($aufwendung)
            {
              $tmperloes = $artikeldata['steuer_aufwendung_inland_import'];
             }else{
              $tmperloes = $artikeldata['steuer_erloese_inland_export'];
            }
          break;
          case 3:
            if($aufwendung)
            {
              $tmperloes = $artikeldata['steuer_aufwendung_inland_nichtsteuerbar'];
            }else{
              $tmperloes = $artikeldata['steuer_erloese_inland_nichtsteuerbar'];
            }
          break;
          default:
            if($aufwendung)
            {
              if($umsatzsteuer === 'ermaessigt')
              {
                $tmperloes = $artikeldata['steuer_aufwendung_inland_ermaessigt'];
              }elseif($umsatzsteuer === 'befreit'){
                $tmperloes = $artikeldata['steuer_aufwendung_inland_nichtsteuerbar'];
              }else{
                $tmperloes = $artikeldata['steuer_aufwendung_inland_normal'];
              }
            }else{
              if($umsatzsteuer === 'ermaessigt')
              {
                $tmperloes = $artikeldata['steuer_erloese_inland_ermaessigt'];
              }elseif($umsatzsteuer === 'befreit'){
                $tmperloes = $artikeldata['steuer_erloese_inland_nichtsteuerbar'];
              }else{
                $tmperloes = $artikeldata['steuer_erloese_inland_normal'];
              }              
            }
          break;
        }
        if(strpos($artikeldata['typ'],'_kat') !== false)
        {
          $kategorie = $this->app->DB->SelectRow("SELECT * FROM artikelkategorien WHERE id = '".(int)str_replace('_kat','',$artikeldata['typ'])."' LIMIT 1");
        }
        if($kategorie && ($tmpsteuertext ===  '' || $tmpsteuertext === false || is_null($tmpsteuertext)))
        {
          switch($ust_befreit)
          {
            case 1:
              $tmpsteuertext = $kategorie['steuertext_innergemeinschaftlich'];
            break;
            case 2:
              $tmpsteuertext = $kategorie['steuertext_export'];
            break;
          }
        }
        if(!$tmperloes)
        {
          switch($ust_befreit)
          {
            case 1:
              if($aufwendung)
              {
                if(trim((String)$ustid) !== '')
                {
                  $tmperloes = $kategorie['steuer_aufwendung_inland_euermaessigt'];
                }else{
                  if($umsatzsteuer === 'ermaessigt')
                  {
                    $tmperloes = $kategorie['steuer_aufwendung_inland_euermaessigt'];
                    
                  }else{
                    $tmperloes = $kategorie['steuer_aufwendung_inland_eunormal'];
                  }
                }
              }else{
                if(trim((String)$ustid) !== '')
                {
                  $tmperloes = $kategorie['steuer_erloese_inland_innergemeinschaftlich'];
                }else{
                  if($umsatzsteuer === 'ermaessigt')
                  {
                    $tmperloes = $kategorie['steuer_erloese_inland_euermaessigt'];
                  }else{
                    $tmperloes = $kategorie['steuer_erloese_inland_eunormal'];
                  }
                }
              }
            break;
            case 2:
              if($aufwendung)
              {
                $tmperloes = $kategorie['steuer_aufwendung_inland_import'];
               }else{
                $tmperloes = $kategorie['steuer_erloese_inland_export'];
              }
            break;
            case 3:
              if($aufwendung)
              {
                $tmperloes = $kategorie['steuer_aufwendung_inland_nichtsteuerbar'];
              }else{
                $tmperloes = $kategorie['steuer_erloese_inland_nichtsteuerbar'];
              }
            break;
            default:
              if($aufwendung)
              {
                if($umsatzsteuer === 'ermaessigt')
                {
                  $tmperloes = $kategorie['steuer_aufwendung_inland_ermaessigt'];
                }elseif($umsatzsteuer == 'befreit'){
                  $tmperloes = $kategorie['steuer_aufwendung_inland_nichtsteuerbar'];
                }else{
                  $tmperloes = $kategorie['steuer_aufwendung_inland_normal'];
                }
              }else{
                if($umsatzsteuer === 'ermaessigt')
                {
                  $tmperloes = $kategorie['steuer_erloese_inland_ermaessigt'];
                }elseif($umsatzsteuer === 'befreit'){
                  $tmperloes = $kategorie['steuer_erloese_inland_nichtsteuerbar'];
                }else{
                  $tmperloes = $kategorie['steuer_erloese_inland_normal'];
                }              
              }
            break;
          }
        }
        if(!$tmperloes && !empty($projectRow)) {
          switch($ust_befreit)
          {
            case 1:
              if($aufwendung)
              {
                if(trim((String)$ustid) !== '')
                {
                  $tmperloes = $projectRow['steuer_aufwendung_inland_euermaessigt'];
                }else{
                  if($umsatzsteuer === 'ermaessigt')
                  {
                    $tmperloes = $projectRow['steuer_aufwendung_inland_euermaessigt'];

                  }else{
                    $tmperloes = $projectRow['steuer_aufwendung_inland_eunormal'];
                  }
                }
              }else{
                if(trim((String)$ustid) !== '')
                {
                  $tmperloes = $projectRow['steuer_erloese_inland_innergemeinschaftlich'];
                }else{
                  if($umsatzsteuer === 'ermaessigt')
                  {
                    $tmperloes = $projectRow['steuer_erloese_inland_euermaessigt'];
                  }else{
                    $tmperloes = $projectRow['steuer_erloese_inland_eunormal'];
                  }
                }
              }
              break;
            case 2:
              if($aufwendung)
              {
                $tmperloes = $projectRow['steuer_aufwendung_inland_import'];
              }else{
                $tmperloes = $projectRow['steuer_erloese_inland_export'];
              }
              break;
            case 3:
              if($aufwendung)
              {
                $tmperloes = $projectRow['steuer_aufwendung_inland_nichtsteuerbar'];
              }else{
                $tmperloes = $projectRow['steuer_erloese_inland_nichtsteuerbar'];
              }
              break;
            default:
              if($aufwendung)
              {
                if($umsatzsteuer === 'ermaessigt')
                {
                  $tmperloes = $projectRow['steuer_aufwendung_inland_ermaessigt'];
                }elseif($umsatzsteuer === 'befreit'){
                  $tmperloes = $projectRow['steuer_aufwendung_inland_nichtsteuerbar'];
                }else{
                  $tmperloes = $projectRow['steuer_aufwendung_inland_normal'];
                }
              }else{
                if($umsatzsteuer === 'ermaessigt')
                {
                  $tmperloes = $projectRow['steuer_erloese_inland_ermaessigt'];
                }elseif($umsatzsteuer === 'befreit'){
                  $tmperloes = $projectRow['steuer_erloese_inland_nichtsteuerbar'];
                }else{
                  $tmperloes = $projectRow['steuer_erloese_inland_normal'];
                }
              }
              break;
          }
        }
      }

      /**
       * @param string      $typ
       * @param int         $posid
       * @param null|string $tmpsteuersatz
       * @param null|string $tmpsteuertext
       * @param null|string $erloes
       */
      function GetSteuerPosition($typ, $posid,&$tmpsteuersatz = null, &$tmpsteuertext = null, &$erloes = null)
      {
        if($posid <= 0 || empty($typ)) {
          return;
        }
        $postyp = $typ.'_position';
        $posRow =  $this->app->DB->SelectRow(
          sprintf(
            "SELECT * FROM `%s` WHERE id = %d LIMIT 1",
            $postyp,
            (int)$posid
          )
        );

        if(empty($posRow['artikel'])) {
          return;
        }
        $projekt = (int)$this->app->DB->Select(
          sprintf(
            'SELECT projekt FROM `%s` WHERE id = %d',
            $typ, $posRow[$typ]
          )
        );
        $artikel = $posRow['artikel'];

        $tmpsteuersatz = $posRow['steuersatz'];
        if($tmpsteuersatz === '') {
          $tmpsteuersatz = null;
        }
        $typid = $posRow[$typ];
        if($tmpsteuersatz < 0 || $tmpsteuersatz === null)
        {
          if($posRow['umsatzsteuer'] === 'ermaessigt')
          {
            $tmpsteuersatz = $this->GetSteuersatzErmaessigt(false,$typid,$typ);
          }elseif($posRow['umsatzsteuer'] === 'befreit')
          {
            $tmpsteuersatz = 0;
          }else{
            $tmpsteuersatz = $this->GetSteuersatzNormal(false,$typid,$typ);
          }
        }

        $ust_befreit = $this->app->DB->Select("SELECT ust_befreit FROM $typ WHERE id = '$typid' LIMIT 1");
        $ustid = $this->app->DB->Select("SELECT ustid FROM $typ WHERE id = '$typid' LIMIT 1");
        $aufwendung = false;
        switch($typ)
        {
          case 'bestellung':
          case 'anfrage':
          case 'verbindlichkeit':
            $aufwendung = true;
          break;
        }

        $this->GetArtikelSteuer($artikel, $ust_befreit, $aufwendung, $tmpsteuersatz, $tmpsteuertext, $erloes, $posRow['umsatzsteuer'], $ustid, $projekt);

        $this->getErloesFirmendaten($artikel, $ust_befreit, $aufwendung, $tmpsteuersatzFD, $tmpsteuertextFD, $tmperloesFD, $posRow['umsatzsteuer'], $ustid, $projekt);

        if (!$tmpsteuersatz) {
            $tmpsteuersatz = $tmpsteuersatzFD;
        }
        if (!$tmpsteuertext) {
            $tmpsteuertext = $tmpsteuertextFD;
        }
        if (!$erloes) {
            $erloes = $tmperloesFD;
        }
      }
      
      function PortoBerechnen($adresse,$gesamtsumme,$portoartikel, &$realpreis = false)
      {

        // schaue ob Kunde eine Regel hat
        $checkportofrei = $this->app->DB->Select("SELECT portofrei_aktiv FROM adresse WHERE id='".$adresse."' LIMIT 1");
        if($checkportofrei=="1")
        {
          $checkportofreiab = $this->app->DB->Select("SELECT portofreiab FROM adresse WHERE id='".$adresse."' LIMIT 1");
          if($gesamtsumme >= $checkportofreiab)
          {
            $realpreis = true;
            return 0;
          } else {
            // wenn kundenpreis vorhanden dann den holen sonst verband
            $tmppreis = $this->GetVerkaufspreisKunde($portoartikel,1,$adresse);
            if($tmppreis > 0)
            {
              $realpreis = true;
              return $tmppreis;
            }
            else
            {
              $returnwaehrung = null;
              $ret = $this->GetVerkaufspreis($portoartikel,1,$adresse,'EUR',$returnwaehrung);
              if($ret || $returnwaehrung)$realpreis = true;
              return $ret;
            }
          }
        } else {
          $gruppenarray = $this->GetGruppen($adresse);

          for($gi=0;$gi<(!empty($gruppenarray)?count($gruppenarray):0);$gi++)
          {
            $sql_erweiterung .= " id='".$gruppenarray[$gi]."' ";

            if($gi<(!empty($gruppenarray)?count($gruppenarray):0)-1)
              $sql_erweiterung .= " OR ";
          }
          $checkgruppeportofrei = $this->app->DB->Select("SELECT id FROM gruppen WHERE ($sql_erweiterung) AND portofrei_aktiv='1' ORDER BY portofreiab LIMIT 1");
          if($checkgruppeportofrei>0)
          {
            $checkgruppeportofreiab = $this->app->DB->Select("SELECT portofreiab FROM gruppen WHERE id='".$checkgruppeportofrei."' LIMIT 1");
            if($gesamtsumme >= $checkgruppeportofreiab)
            {
              $realpreis = true;
              return 0;
            } else {
              // hole kunden preis
              // wenn nicht vorhanden dann Standardpreis
              $tmppreis = $this->GetVerkaufspreisKunde($portoartikel,1,$adresse);
              if($tmppreis > 0)
              {
                $realpreis = true;
                return $tmppreis;
              }
              else
              {
                $returnwaehrung = null;
                $ret = $this->GetVerkaufspreis($portoartikel,1,$adresse,'EUR',$returnwaehrung);
                if($ret || $returnwaehrung)$realpreis = true;
                return $ret;
              }

              //return $this->GetVerkaufspreis($portoartikel,1,$adresse);
            }
          }
          // oder gruppe hat einen versandpreis?
          // billigsten versandpreis bei dem betrag
        }

        // sollte nicht passieren
        $returnwaehrung = null;
        $ret = $this->GetVerkaufspreis($portoartikel,1,$adresse,'EUR',$returnwaehrung);
        if($ret || $returnwaehrung)$realpreis = true;
        return $ret;
      }

      function ANABREGSNeuberechnenGesamtsummeOhnePortoUndKeinRabatt($id,$art)
      {
        //inkl. kein rabatt erlaubt
        if($art === 'bestellung') {
          return $this->app->DB->Select(
            sprintf(
              "SELECT IFNULL(SUM(tp.menge*tp.preis),0) 
              FROM bestellung_position tp
              LEFT JOIN artikel a ON a.id=tp.artikel 
              WHERE a.porto!='1' AND (a.rabatt!='1' OR a.rabatt IS NULL) AND 
                  (a.keinrabatterlaubt!='1' OR a.keinrabatterlaubt IS NULL) AND tp.bestellung=%d",
              (int)$id
            )
          );
        }
        return $this->app->DB->Select("SELECT SUM(tp.menge*(tp.preis-(tp.preis/100*tp.rabatt))) FROM ".$art."_position tp
            LEFT JOIN artikel a ON a.id=tp.artikel WHERE a.porto!='1' AND (a.rabatt!='1' OR a.rabatt IS NULL) AND (a.keinrabatterlaubt!='1' OR a.keinrabatterlaubt IS NULL) AND tp.".$art."='$id'");
      }


      function BEGesamtsummeOhnePorto($id,$art)
      {
        //inkl. kein rabatt erlaubt
        $summeNetto = $this->app->DB->Select("SELECT SUM(tp.menge*tp.preis) FROM ".$art."_position tp
            LEFT JOIN artikel a ON a.id=tp.artikel WHERE a.porto!='1' AND tp.".$art."='$id'");
        return $summeNetto;
      }

      function ANABREGSNeuberechnenGesamtsummeOhnePorto($id,$art)
      {
        //inkl. kein rabatt erlaubt
        if($art === 'bestellung') {
          return $this->app->DB->Select(
            sprintf(
              'SELECT IFNULL(SUM(tp.menge*tp.preis),0) 
                FROM `%s` AS tp
                LEFT JOIN artikel a ON a.id=tp.artikel 
                WHERE a.porto!=1 AND (a.rabatt!=1 OR a.rabatt IS NULL) AND tp.`%s` = %d
              ',
              $art.'_position',$art,$id
            )
          );
        }
        $summeNetto = $this->app->DB->Select("SELECT SUM(tp.menge*(tp.preis-(tp.preis/100*tp.rabatt))) FROM ".$art."_position tp
            LEFT JOIN artikel a ON a.id=tp.artikel WHERE a.porto!='1' AND (a.rabatt!='1' OR a.rabatt IS NULL) AND tp.".$art."='$id'");
        return $summeNetto;
      }


      function ANABREGSNeuberechnenGesamtsumme($id,$art,$return_netto=false)
      {

        if(empty($id) || empty($art)) {
          if($return_netto) {
            return 0;
          }
          return;
        }
        $docArr = $this->app->DB->SelectRow(sprintf('SELECT * FROM `%s` WHERE id = %d LIMIT 1', $art, $id));
        if(empty($docArr)) {
          if($return_netto) {
            return 0;
          }
          return;
        }
        $projekt = $docArr['projekt'];
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,"preisberechnung");
        if(!$positionenkaufmaenischrunden)
        {
          $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');

          $sqlvor = '';
          $sqlnach = '';
          $sqlvor2 = '';
          $sqlnach2 = '';
          if($positionenkaufmaenischrunden)
          {
            $sqlvor = 'round(';
            $sqlnach = ',2)';
          }
          if($positionenkaufmaenischrunden == 3)
          {
            $sqlvor2 = 'round(';
            $sqlnach2 = ',2)';
          }
          if($art==='angebot')
          {
            $summeV = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position ap WHERE umsatzsteuer!='ermaessigt' AND umsatzsteuer!='befreit' AND ".$art."='$id' AND optional!=1 AND (isnull(steuersatz) OR steuersatz < 0)  AND (explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))");
            if($this->app->DB->error())
              $summeV = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position ap WHERE umsatzsteuer!='ermaessigt' AND umsatzsteuer!='befreit' AND ".$art."='$id' AND optional!=1  AND (explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))");
            $summeR = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position ap WHERE umsatzsteuer='ermaessigt' AND ".$art."='$id' AND optional!=1 AND (isnull(steuersatz) OR steuersatz < 0)  AND (explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))");
            if($this->app->DB->error())
              $summeR = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position ap WHERE umsatzsteuer='ermaessigt' AND ".$art."='$id' AND optional!=1  AND (explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))");
            if($positionenkaufmaenischrunden != 1 && $positionenkaufmaenischrunden != 3)
            {
              $summeS = (float)$this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach." * if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100)   FROM ".$art."_position ap WHERE  ".$art."='$id' AND optional!=1 AND ((steuersatz >= 0) and not isnull(steuersatz) OR umsatzsteuer='befreit')  AND (explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))");
            }else{
              $summeS = (float)$this->app->DB->Select("SELECT ifnull(SUM(".$sqlvor." s.pos * s.steuer".$sqlnach."),0)

               FROM (
              SELECT SUM(menge*(preis-(preis/100*rabatt))) as pos,  if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100 as steuer  
              FROM ".$art."_position 
              WHERE $art = '$id' AND steuersatz >= 0   AND optional!=1
              GROUP BY if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100

              ) s");
            }
            $summeNetto = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position ap WHERE ".$art."='$id' AND optional!=1  AND (explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))");
          } elseif($art === 'bestellung') {
            $summeV = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis)".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer!='ermaessigt' AND umsatzsteuer!='befreit' AND ".$art."='$id' AND (isnull(steuersatz) OR steuersatz < 0)");
            if($this->app->DB->error())$summeV = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis)".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer!='ermaessigt' AND ".$art."='$id'");
            $summeR = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis)".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer='ermaessigt' AND ".$art."='$id' AND (isnull(steuersatz) OR steuersatz < 0)");
            if($this->app->DB->error())$summeR = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis)".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer='ermaessigt' AND ".$art."='$id'");
            if($positionenkaufmaenischrunden != 1 && $positionenkaufmaenischrunden != 3)
            {
              $summeS = (float)$this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis)".$sqlnach2.$sqlnach." * if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100)  FROM ".$art."_position WHERE  ".$art."='$id' AND ((steuersatz >= 0) and not isnull(steuersatz) OR umsatzsteuer='befreit')");
            }else{
              $summeS = (float)$this->app->DB->Select("SELECT ifnull(SUM(".$sqlvor." s.pos * s.steuer".$sqlnach."),0)

               FROM (
              SELECT SUM(menge*(preis)) as pos,  if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100 as steuer  
              FROM ".$art."_position 
              WHERE $art = '$id' AND steuersatz >= 0   
              GROUP BY if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100

              ) s");
            }
            $summeNetto = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis)".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE ".$art."='$id'");
          } else {
            $summeV = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer!='ermaessigt' AND umsatzsteuer!='befreit' AND ".$art."='$id' AND (isnull(steuersatz) OR steuersatz < 0)");
            if($this->app->DB->error())$summeV = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer!='ermaessigt' AND ".$art."='$id'");
            $summeR = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer='ermaessigt' AND ".$art."='$id' AND (isnull(steuersatz) OR steuersatz < 0)");
            if($this->app->DB->error())$summeR = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE umsatzsteuer='ermaessigt' AND ".$art."='$id'");
            if($positionenkaufmaenischrunden != 1 && $positionenkaufmaenischrunden != 3)
            {
              $summeS = (float)$this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach." * if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100)  FROM ".$art."_position WHERE  ".$art."='$id' AND ((steuersatz >= 0) and not isnull(steuersatz) OR umsatzsteuer='befreit')");
            }else{
              $summeS = (float)$this->app->DB->Select("SELECT ifnull(SUM(".$sqlvor." s.pos * s.steuer".$sqlnach."),0)

               FROM (
              SELECT SUM(menge*(preis-(preis/100*rabatt))) as pos,  if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100 as steuer  
              FROM ".$art."_position 
              WHERE $art = '$id' AND steuersatz >= 0   
              GROUP BY if(umsatzsteuer != 'befreit',steuersatz,if(steuersatz < 0 OR isnull(steuersatz),0,steuersatz))/100

              ) s");
            }
            $summeNetto = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*".$sqlvor2."(preis-(preis/100*rabatt))".$sqlnach2.$sqlnach.") FROM ".$art."_position WHERE ".$art."='$id'");
          }


          $ust_befreit = $docArr['ust_befreit'];// $this->app->DB->Select("SELECT ust_befreit FROM $art WHERE id='$id' LIMIT 1");
          $ustid = $docArr['ustid'];// $this->app->DB->Select("SELECT ustid FROM $art WHERE id='$id' LIMIT 1");

          //UST ID CHECK
          if($ust_befreit==0 || ($ust_befreit==1 && $ustid==""))
          {
            if($positionenkaufmaenischrunden == 1 || $positionenkaufmaenischrunden == 3)
            {
              $betrag = $summeNetto + round($summeV*$this->GetSteuersatzNormal(true,$id,$art)-$summeV,2)+ round($summeR*$this->GetSteuersatzErmaessigt(true,$id,$art)-$summeR,2)+$summeS;
            }else{
              $betrag = $summeNetto + ($summeV*$this->GetSteuersatzNormal(true,$id,$art)-$summeV)+ ($summeR*$this->GetSteuersatzErmaessigt(true,$id,$art)-$summeR)+$summeS;
            }
          } else {
            $betrag = $summeNetto;
          }
        }else{
          $betrag = $this->app->erp->calcBelegBrutto($art, $id);
        }

        if($return_netto) return $betrag;
        $extsoll = 0;
        if($art !== 'bestellung' && $art !== 'proformarechnung'){
          $extsoll = (float)$docArr['extsoll'];//$this->app->DB->Select("SELECT extsoll FROM $art WHERE id = '$id' LIMIT 1");
        }
        if($extsoll == 0)
        {
          if($art==='rechnung' || $art==='gutschrift' || $art==='proformarechnung'){
            if($betrag != $docArr['soll']){
              $this->app->DB->Update("UPDATE $art SET soll='$betrag' WHERE id='$id' LIMIT 1");
            }
          }
          else{
            if($betrag != $docArr['gesamtsumme']){
              $this->app->DB->Update("UPDATE $art SET gesamtsumme='$betrag' WHERE id='$id' LIMIT 1");
            }
          }
        }

      }


      function RechnungZwischensummeSteuersaetzeBrutto2($id,$art="ermaessigt")
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM rechnung WHERE id = '$id' LIMIT 1");
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,"preisberechnung");
        $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');
        $sqlvor = '';
        $sqlnach = '';

        if($art!="ermaessigt")
          $summe = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*(preis-(preis/100*rabatt))".$sqlnach.") FROM rechnung_position WHERE (umsatzsteuer='normal' OR umsatzsteuer='standard' OR umsatzsteuer='') AND rechnung='$id' AND (isnull(steuersatz) OR steuersatz < 0) AND (isnull(erloese) OR erloese = '') ");
        else
          $summe = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*(preis-(preis/100*rabatt))".$sqlnach.") FROM rechnung_position WHERE umsatzsteuer='$art' AND rechnung='$id' AND (isnull(steuersatz) OR steuersatz < 0) AND isnull(erloese)");
        if($art=="ermaessigt")
          $ermaessigt_summe = $summe*$this->GetSteuersatzErmaessigt(true,$id,"rechnung");
        else
          $ermaessigt_summe = $summe*$this->GetSteuersatzNormal(true,$id,"rechnung");
        return $positionenkaufmaenischrunden == 1?round($ermaessigt_summe,2):$ermaessigt_summe;
      }

      function RechungZwischensummeSpezialSteuer($id, $gruppierenpositionen = false, $gruppierenKostenstelle = false)
      {
        /** @var Buchhaltungexport $buchhaltungexport */
        $buchhaltungexport = $this->app->loadModule('buchhaltungexport', false);
        if($buchhaltungexport !== null && method_exists($buchhaltungexport, 'RechungZwischensummeSpezialSteuer')) {
          return $buchhaltungexport->RechungZwischensummeSpezialSteuer($id, $gruppierenpositionen, $gruppierenKostenstelle);
        }

        if($id > 0) {
          $rechnungarr = $this->app->DB->SelectRow(
            sprintf(
              'SELECT `id`, `projekt`, `ust_befreit`, `ustid`, `kostenstelle`, `datum`, 
                `steuersatz_ermaessigt`,  `steuersatz_normal` 
              FROM `rechnung` WHERE `id` = %d LIMIT 1',
              $id
            )
          );
        }
        $projekt = null;
        $ust_befreit = null;
        $ustid = null;
        $kostenstelle = '';
        if(!empty($rechnungarr)){
          $projekt = $rechnungarr['projekt'];
          $ust_befreit = $rechnungarr['ust_befreit'];
          $ustid = $rechnungarr['ustid'];
          $kostenstelle = $this->app->DB->real_escape_string($rechnungarr['kostenstelle']);
        }

        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,'preisberechnung');
        $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');
        $sqlvor = '';
        $sqlnach = '';
        $sqlvor2 = '';
        $sqlnach2 = '';
        if($positionenkaufmaenischrunden == 1){
          $sqlvor = 'round(';
          $sqlnach = ',2)';
        }
        if($positionenkaufmaenischrunden == 3){
          $sqlvor2 = 'round(';
          $sqlnach2 = ',2)';
        }

        if($gruppierenpositionen){
          $arr = $this->app->DB->SelectArr(
            "SELECT rp.`nummer`, rp.`bezeichnung`, rp.`artikel`, rp.`steuersatz`,rp.`erloese`,
            ".$sqlvor."rp.menge*".$sqlvor2."(preis-(rp.preis/100*rp.rabatt))".$sqlnach2.$sqlnach." as netto, 
            rp.menge*(rp.preis-(rp.preis/100*rp.rabatt)) as nettoungerundet, 
            if(rp.umsatzsteuer = 'ermaessigt','ermaessigt',if(rp.umsatzsteuer = 'befreit','befreit','normal'))  as usteuer , 
            sum(rp.einkaufspreis * rp.menge) as summeeinkaufspreis, 
            IF(
              IFNULL(rp.kostenstelle,'') <> '',
              rp.kostenstelle,
              IF('$kostenstelle' <> '', '$kostenstelle', art.kostenstelle)
            ) AS kostenstelle  
            FROM `rechnung_position` AS rp
            LEFT JOIN `artikel` AS art ON rp.artikel = art.id
            WHERE rechnung = '$id' group by rp.`steuersatz`,rp.`erloese`, rp.`umsatzsteuer`,rp.`artikel`, rp.`id` ");
        }else{
          $arr = $this->app->DB->SelectArr(
            "SELECT  rp.`artikel`, rp.`steuersatz`,rp.`erloese`, 
            SUM(" . $sqlvor . "rp.menge*" . $sqlvor2 . "(rp.preis-(rp.preis/100*rp.rabatt))" . $sqlnach2 . $sqlnach . ") as netto, 
            SUM(rp.menge*(rp.preis-(rp.preis/100*rp.rabatt))) as nettoungerundet, 
            if(rp.umsatzsteuer = 'ermaessigt','ermaessigt',if(rp.umsatzsteuer = 'befreit','befreit','normal'))  as usteuer, 
            sum(rp.einkaufspreis * rp.menge) as summeeinkaufspreis, 
            IF(
              IFNULL(rp.kostenstelle,'') <> '',
              rp.kostenstelle,
              IF('$kostenstelle' <> '', '$kostenstelle', art.kostenstelle)
            ) AS kostenstelle
            FROM `rechnung_position` AS rp
            LEFT JOIN artikel AS art ON rp.artikel = art.id 
            WHERE rp.rechnung = '$id'
            group by rp.`steuersatz`,rp.`erloese`, rp.`umsatzsteuer`,rp.`artikel` "
          );
        }
        
        if($arr) {
          $steuersatzermaessigt = $this->GetSteuersatzErmaessigt(true,$id,'rechnung');
          $steuersatznormal = $this->GetSteuersatzNormal(true,$id,'rechnung');
          foreach($arr as $k => $v) {
            $_ust_befreit = $ust_befreit;
            if($v['steuersatz'] !== null && $v['steuersatz'] == 0 && $ust_befreit == 0) {
              $ust_befreit = 3;
            }
            $erloese = $this->Gegenkonto($ust_befreit, $ustid, 'rechnung', $id);
            $this->GetArtikelSteuer(
              $v['artikel'], $ust_befreit,0, $dummysteuersatz, $tmpsteuertext, $tmperloes,$v['usteuer'], $ustid, $projekt
            );
            if(!$this->RechnungMitUmsatzeuer($id)){
              $v['steuersatz'] = 0;
            }
            if($v['steuersatz'] === null || $v['steuersatz'] < 0)
            {
              if($v['usteuer'] === 'ermaessigt')
              {
                $arr[$k]['steuersatz'] = $steuersatzermaessigt;
              }elseif($v['usteuer'] === 'befreit'){
                $arr[$k]['steuersatz'] = 1;
              }else{
                $arr[$k]['steuersatz'] = $steuersatznormal;
              }
            }else {
              $arr[$k]['steuersatz'] = 1+$v['steuersatz']/100;
            }
            if($v['erloese'] === null || $v['erloese'] === '')
            {
              $arr[$k]['erloese'] = $erloese;
              if($tmperloes)
              {
                $arr[$k]['erloese'] = $tmperloes;
              }else{
                if($v['usteuer'] === 'befreit' && $ust_befreit == 0)
                {
                  $arr[$k]['erloese'] = $this->Firmendaten("steuer_erloese_inland_nichtsteuerbar");
                }
                elseif($v['usteuer'] === 'ermaessigt' && $ust_befreit == 0)
                {
                  $arr[$k]['erloese'] = $this->Firmendaten("steuer_erloese_inland_ermaessigt");
                }elseif($v['usteuer'] === 'ermaessigt' && $ust_befreit == 1 && (String)$ustid === '')
                {
                  $arr[$k]['erloese'] = $this->Firmendaten("steuer_erloese_inland_euermaessigt");
                }elseif($ust_befreit == 1 && (String)$ustid !== ''){
                  
                  $arr[$k]['erloese'] = $this->Firmendaten("steuer_erloese_inland_innergemeinschaftlich");
                }elseif($v['usteuer'] !== 'ermaessigt' && $v['usteuer'] !== 'befreit' && $ust_befreit == 1 && (String)$ustid === '')
                {
                  $arr[$k]['erloese'] = $this->Firmendaten("steuer_erloese_inland_eunormal");
                }
              }
            }
            $arr[$k]['summe'] = $v['nettoungerundet'] * $arr[$k]['steuersatz'];
            if($gruppierenpositionen) {
              $arr[$k]['summe'] = round($arr[$k]['summe'], 2);
            }
            $ust_befreit = $_ust_befreit;
          }
        }
        if($gruppierenpositionen) {
          return $arr;
        }

        return $this->SteuerZusammenfassen($arr, $gruppierenKostenstelle);
      }
  
      function steuerAusBelegPDF($belegtyp, $id){
        $arr = $this->steuerAusBelegArray($belegtyp, $id);
        $summe = 0;
        $gesamtsumme = 0;
        $summen = null;
        if($arr)
        {
          foreach($arr as $k => $v)
          {
            $summe += $v['netto'];
            $gesamtsumme += $v['brutto'];
            if(!isset($summen[$v['steuersatz']]))$summen[$v['steuersatz']] = 0;
            $summen[$v['steuersatz']] += $v['brutto'] - $v['netto'];
          }
        }
        return array($summe, $gesamtsumme, $summen);
      }
  
      function calcBelegBrutto($belegtyp, $id)
      {
        $arr = $this->steuerAusBelegArray($belegtyp, $id);
        $summe = 0;
        $gesamtsumme = 0;
        $summen = null;
        if($arr)
        {
          foreach($arr as $k => $v)
          {
            $gesamtsumme += $v['brutto'];
          }
        }
        return $gesamtsumme;
      }

  /**
   * @param string $belegtyp
   * @param int    $id
   * @param bool   $gruppierenpositionen
   * @param bool   $ohneporto
   * @param bool   $mitErloes nur mit gruppierenpositionen
   *
   * @return array|null
   */
      public function steuerAusBelegArray($belegtyp, $id, $gruppierenpositionen = false, $ohneporto = false, $mitErloes = false)
      {
        $projekt = $this->app->DB->Select(
          sprintf(
            'SELECT `projekt` FROM `%s` WHERE id = %d LIMIT 1',
            $belegtyp, $id
          )
        );
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,'preisberechnung');
        $steuerfrei = false;
        $funktionsname = ucfirst($belegtyp).'MitUmsatzeuer';
        if(method_exists($this, $funktionsname)) {
          $steuerfrei = !$this->$funktionsname($id);
        }
        $steuersatzermaessigt = $this->GetSteuersatzErmaessigt(false,$id,$belegtyp);
        $steuersatznormal = $this->GetSteuersatzNormal(false,$id,$belegtyp);
        $join = '';
        if($ohneporto) {
          $join = ' INNER JOIN artikel art ON ap.artikel = art AND art.porto <> 1 ';
        }
        if($positionenkaufmaenischrunden == 2) {
          if($gruppierenpositionen) {
            if($steuerfrei){
              return $this->app->DB->SelectArr(
                "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
                    0 as steuersatz , 
                  round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2) as netto, ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
                  if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
                  round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2) as brutto
                  " . ($mitErloes ? ' ,ap.erloes' : '') . "
                FROM `" . $belegtyp . "_position` ap 
                $join 
                WHERE ap.$belegtyp = '$id' "
                . ($belegtyp === 'angebot'
                  ? " AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                  : '')
              );
            }
            return $this->app->DB->SelectArr(
              "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
              round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2) as steuersatz , 
              round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2) as netto, ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
              if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
              round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))*(1+ round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2)/ 100),2) as brutto
              " . ($mitErloes ? ' ,ap.erloes' : '') . "
              FROM `".$belegtyp."_position` ap 
              $join 
              WHERE ap.$belegtyp = '$id' "
                .($belegtyp==='angebot'
                  ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                  :''
                )
            );
          }
          if($steuerfrei) {
            return $this->app->DB->SelectArr(
              "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
              0 as steuersatz , 
              round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) as netto, 
              sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
              if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
              round( sum(round(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)))),2) as brutto
  
              FROM `" . $belegtyp . "_position` ap $join 
              WHERE ap.$belegtyp = '$id'  "
              . ($belegtyp === 'angebot'
                ? " AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                : '') . "
              group by `steuersatz`, `usteuer` 
              HAVING round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) <> 0"
            );
          }
          return $this->app->DB->SelectArr(
            "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
            round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2) as steuersatz , 
            round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) as netto, 
            sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
            if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
            round( sum(round(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))*(1+ round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2)/ 100),2)),2) as brutto

            FROM `".$belegtyp."_position` ap $join 
            WHERE ap.$belegtyp = '$id'  "
              .($belegtyp==='angebot'
                ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                :''
              )."
            group by round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2), `usteuer` HAVING round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) <> 0"
          );
        }
        if($positionenkaufmaenischrunden == 1 || $positionenkaufmaenischrunden == 3) {
          $mengevor = '';
          $mengenach = '';
          if($positionenkaufmaenischrunden == 3){
            $mengevor = 'ROUND(';
            $mengenach = ',2)';
          }
          if($gruppierenpositionen) {
            if($steuerfrei){
              return $this->app->DB->SelectArr(
                "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
                  0 as steuersatz , 
                  round( ap.menge*" . $mengevor . "(ap.preis-(ap.preis/100*ap.rabatt))" . $mengenach . ",2) as netto, 
                  ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
                  if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
                  round( ap.menge*" . $mengevor . "(ap.preis-(ap.preis/100*ap.rabatt))" . $mengenach . ",2) as brutto
                  " . ($mitErloes ? ' ,ap.erloes' : '') . "
                FROM `" . $belegtyp . "_position` ap 
                $join 
                WHERE ap.$belegtyp = '$id'  "
                  . ($belegtyp === 'angebot'
                    ? " AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                    : '')
              );
            }
            return $this->app->DB->SelectArr(
              "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
                round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2) as steuersatz , 
                round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2) as netto, 
                ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
                if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
                round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))*
                (1+ round(
                  if(ifnull(ap.`steuersatz`,-1) < 0, 
                  if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,
                  if(umsatzsteuer = 'befreit',0,$steuersatznormal)
                  ) ,ap.`steuersatz`
                  )".$mengenach.",2)/ 100),2) as brutto
                " . ($mitErloes ? ' ,ap.erloes' : '') . "
              FROM `".$belegtyp."_position` ap 
              $join 
              WHERE ap.$belegtyp = '$id'  "
                .($belegtyp==='angebot'
                  ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                  :'')
            );
          }

          if($steuerfrei){
            $sql = "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
            0 as steuersatz , 
            round(
              sum(
                round( 
                  ap.menge*
                  " . $mengevor . " (ap.preis-(ap.preis/100*ap.rabatt)) " . $mengenach . "
                  ,2
                )
              )
              ,2
            ) as netto, 
            sum(
              ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))
            ) as nettoungerundet, 
            if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
            
            round(
              sum(
                round( 
                  ap.menge*" . $mengevor . " (ap.preis-(ap.preis/100*ap.rabatt)) " . $mengenach . "
                  ,2
                )
              )
              ,2
            ) 
             as brutto

            FROM `".$belegtyp."_position` ap 
            $join 
            WHERE ap.$belegtyp = '$id'  "
              .($belegtyp==='angebot'
            ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                :'')."
            group by `steuersatz`, 
            `usteuer` 
            HAVING round(sum(round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2)),2) <> 0";
            return $this->app->DB->SelectArr($sql);
          }
          if($positionenkaufmaenischrunden == 3) {
            return $this->app->DB->SelectArr(
              "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
            round(
              if(
                ifnull(ap.`steuersatz`,-1) < 0, 
                if(
                  umsatzsteuer = 'ermaessigt',
                  $steuersatzermaessigt,
                  if(
                    umsatzsteuer = 'befreit',
                    0,
                    $steuersatznormal
                  )
                ) ,
                ap.`steuersatz`
              ),2
            ) as steuersatz , 
            round(sum(round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2)),2) as netto, 
            sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
            if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
            
            round(sum(round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2)),2)+
            round(
              sum(round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2)) *
              round(
              if(
                ifnull(ap.`steuersatz`,-1) < 0, 
                if(
                  umsatzsteuer = 'ermaessigt',
                  $steuersatzermaessigt,
                  if(
                    umsatzsteuer = 'befreit',
                    0,
                    $steuersatznormal
                  )
                ) ,
                ap.`steuersatz`
              ),2
            )/100
            ,2
            ) as brutto
            FROM `".$belegtyp."_position` ap 
            $join 
            WHERE ap.$belegtyp = '$id'  "
            .($belegtyp==='angebot'
                ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                :'')."
            group by round(
              if(
                ifnull(ap.`steuersatz`,-1) < 0, 
                if(
                  umsatzsteuer = 'ermaessigt',
                  $steuersatzermaessigt,
                  if(
                    umsatzsteuer = 'befreit',
                    0,
                    $steuersatznormal
                  )
                ) ,
                ap.`steuersatz`
              ),2
            ), 
            `usteuer` HAVING round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) <> 0"
            );
          }
          return $this->app->DB->SelectArr(
            "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
            round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2) as steuersatz , 
            round(sum(round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2)),2) as netto, 
            sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
            if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
            
            round(sum(round( ap.menge*".$mengevor."(ap.preis-(ap.preis/100*ap.rabatt))".$mengenach.",2)),2) + round( round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) *   round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2)/100 ,2)
             as brutto
  
            FROM `".$belegtyp."_position` ap 
            $join 
            WHERE ap.$belegtyp = '$id'  "
              .($belegtyp==='angebot'
                ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                :'')."
            group by round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2),
            `usteuer` 
            HAVING round(sum(round( ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)),2)),2) <> 0"
          );
        }

        if($gruppierenpositionen) {
          if($steuerfrei){
            return $this->app->DB->SelectArr(
              "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
              round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2) as steuersatz , 
               ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as netto, ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
              0  as usteuer,
               ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as brutto
                " . ($mitErloes ? ' ,ap.erloes' : '') . "
              FROM `" . $belegtyp . "_position` ap 
              $join 
              WHERE ap.$belegtyp = '$id'  "
              . ($belegtyp === 'angebot'
                ? " AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                : '')
            );
          }
          return $this->app->DB->SelectArr(
              "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
              round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2) as steuersatz , 
               ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as netto, ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
              if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
               ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))*(1+ round(if(ifnull(ap.`steuersatz`,-1) < 0, if(umsatzsteuer = 'ermaessigt',$steuersatzermaessigt,if(umsatzsteuer = 'befreit',0,$steuersatznormal)) ,ap.`steuersatz`),2)/ 100) as brutto
            " . ($mitErloes ? ' ,ap.erloes' : '') . "
              FROM `".$belegtyp."_position` ap 
              $join 
              WHERE ap.$belegtyp = '$id'  "
                  .($belegtyp==='angebot'
                    ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                    :'')
          );
        }

        if($steuerfrei){
          return $this->app->DB->SelectArr(
            "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
            0 as steuersatz , 
            sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as netto, 
            sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
            if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
             sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as brutto  
            FROM `" . $belegtyp . "_position` ap 
            $join 
            WHERE ap.$belegtyp = '$id'  " .
              ($belegtyp === 'angebot'
                ? " AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
                : '') . "
            group by `steuersatz`, 
            `usteuer` HAVING sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) <> 0"
          );
        }
        return $this->app->DB->SelectArr(
            "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
          round(
              if(
                  ifnull(ap.`steuersatz`,-1) < 0, 
                  if(
                      ap.umsatzsteuer = 'ermaessigt',
                      $steuersatzermaessigt,
                      if(ap.umsatzsteuer = 'befreit',
                          0,
                          $steuersatznormal
                      )
                  ) ,
                  ap.`steuersatz`
                ),2) as steuersatz , 
          sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as netto, 
          sum(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
          if(ap.umsatzsteuer = 'ermaessigt','ermaessigt',if(ap.umsatzsteuer = 'befreit','befreit','normal'))  as usteuer,
           sum(
               ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))*
               (1+ round(
                   if(
                       ifnull(ap.`steuersatz`,-1) < 0, 
                       if(
                         ap.umsatzsteuer = 'ermaessigt',
                         $steuersatzermaessigt,
                         if(
                           ap.umsatzsteuer = 'befreit',
                             0,
                             $steuersatznormal
                         )
                     ) ,
                       ap.`steuersatz`
                       ),2)/ 100
                   )
               ) as brutto

          FROM `".$belegtyp."_position` ap 
          $join 
          WHERE ap.$belegtyp = '$id'  "
            .($belegtyp==='angebot'
              ?" AND ap.optional!=1  AND (ap.explodiert_parent = 0 OR 0 = ifnull((SELECT id FROM angebot_position WHERE id = ap.explodiert_parent AND berechnen_aus_teile = 1 LIMIT 1),0))"
              :'')."
          group by round(
              if(
                  ifnull(ap.`steuersatz`,-1) < 0, 
                  if(
                      ap.umsatzsteuer = 'ermaessigt',
                      $steuersatzermaessigt,
                      if(ap.umsatzsteuer = 'befreit',
                          0,
                          $steuersatznormal
                      )
                  ) ,
                  ap.`steuersatz`
                ),2), 
          `usteuer` HAVING 
          sum(ap.menge*
          (ap.preis-(ap.preis/100*ap.rabatt))
          ) <> 0"
        );
      }

  /**
   * @param array|null $ret
   * @param string     $belegtyp
   * @param int        $id
   *
   * @return array|null
   */
      public function addErloesSteuerBeleg($ret, $belegtyp, $id) {
        if(empty($ret) || empty($belegtyp) || empty($id)) {
          return $ret;
        }
        $doc = $this->app->DB->SelectRow(
          sprintf(
            'SELECT `ustid`, `ust_befreit`, `projekt` FROM `%s` WHERE `id` = %d',
            $belegtyp,$id
          )
        );
        $aufwendung = null;
        $steuertext = null;
        foreach($ret as $key => $row) {
          if(!empty($row['erloese']) || empty($row['artikel'])) {
            continue;
          }
          $steuersatz = $row['steuersatz'];
          $steuertext = null;
          $umsatzsteuerpos = $row['umsatzsteuer'];
          $this->GetArtikelSteuer(
            $row['artikel'],
            $doc['ust_befreit'],
            $aufwendung,
            $steuersatz,
            $steuertext,
            $row['erloese'],
            $umsatzsteuerpos,
            $doc['ustid'],
            $doc['projekt']
          );
          if(!empty($row['erloese'])) {
            $ret[$key]['erloese'] = $row['erloese'];
            continue;
          }
          $this->getErloesFirmendaten(
            $row['artikel'],
            $doc['ust_befreit'],
            $aufwendung,
            $steuersatz,
            $steuertext,
            $row['erloese'],
            $umsatzsteuerpos,
            $doc['ustid'],
            $doc['projekt']
          );
          if(!empty($row['erloese'])) {
            $ret[$key]['erloese'] = $row['erloese'];
            continue;
          }
        }

        return $ret;
      }

    /**
     * @param string $belegtyp
     * @param int    $id
     * @param bool   $gruppierenpositionen
     * @param bool   $ohneporto
     * @param bool   $mitErloes nur mit gruppierenpositionen
     *
     * @return array|null
     */
      public function SteuerAusBeleg($belegtyp, $id, $gruppierenpositionen = false, $ohneporto = false, $mitErloes = false)
      {
        $projekt = $this->app->DB->Select(
          sprintf(
            'SELECT `projekt` FROM `%s` WHERE `id` = %d LIMIT 1',
            $belegtyp, $id
          )
        );
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,'preisberechnung');
        if($positionenkaufmaenischrunden) {
          $ret = $this->steuerAusBelegArray($belegtyp, $id, $gruppierenpositionen, $ohneporto, $mitErloes);
          if($gruppierenpositionen && $mitErloes) {
            return $this->addErloesSteuerBeleg($ret, $belegtyp, $id);
          }
          return $ret;
        }
        $steuerfrei = false;
        $funktionsname = ucfirst($belegtyp).'MitUmsatzeuer';
        if(method_exists($this, $funktionsname)) {
          $steuerfrei = !$this->$funktionsname($id);
        }
        $steuersatzermaessigt = $this->GetSteuersatzErmaessigt(false,$id,$belegtyp);
        $steuersatznormal = $this->GetSteuersatzNormal(false,$id,$belegtyp);
        $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');

        $sqlvor = '';
        $sqlnach = '';
        if($positionenkaufmaenischrunden == 1) {
          $sqlvor = 'round(';
          $sqlnach = ',2)';
        }
        $sqlvor2 = '';
        $sqlnach2 = '';
        if($positionenkaufmaenischrunden == 3) {
          $sqlvor2 = 'round(';
          $sqlnach2 = ',2)';
        }
        
        $join = '';
        if($ohneporto) {
          $join = ' INNER JOIN artikel art ON ap.artikel = art AND art.porto <> 1 ';
        }
        if($gruppierenpositionen) {
          $arr = $this->app->DB->SelectArr(
            "SELECT ap.`id`,`nummer`, ap.`bezeichnung`, ap.`artikel`, 
              if(ap.`steuersatz` < 0, null,ap.`steuersatz`) as ssatz , 
              ".$sqlvor." ap.menge*".$sqlvor2."(ap.preis-(ap.preis/100*ap.rabatt))".$sqlnach2.$sqlnach." as netto, 
              ap.menge*(ap.preis-(ap.preis/100*ap.rabatt)) as nettoungerundet, 
              if(umsatzsteuer = 'ermaessigt','ermaessigt',if(umsatzsteuer = 'befreit','befreit','normal'))  as usteuer
              ".($mitErloes?',ap.erloese ':'')."  
            FROM `".$belegtyp."_position` ap 
            $join 
            WHERE ap.$belegtyp = '$id' 
            GROUP BY `ssatz`,ap.`erloese`, `usteuer`,ap.`artikel`,ap.`id` "
          );
        }
        else{
          $arr = $this->app->DB->SelectArr(
            "SELECT  if(ap.`steuersatz` < 0, null,ap.`steuersatz`) as ssatz  , 
            SUM(".$sqlvor."ap.menge*".$sqlvor2."(ap.preis-(ap.preis/100*ap.rabatt))".$sqlnach2.$sqlnach.") as netto,  
            SUM(ap.menge*(ap.preis-(ap.preis/100*ap.rabatt))) as nettoungerundet, 
            if(ap.umsatzsteuer = 'ermaessigt','ermaessigt',if(ap.umsatzsteuer = 'befreit','befreit','normal')) as usteuer
            
            FROM `".$belegtyp."_position` ap 
            $join  
            WHERE ap.$belegtyp = '$id' 
            group by `ssatz`, `usteuer` "
          );
        }
        $ret = null;
        if($arr) {
          if(!$gruppierenpositionen) {
            foreach($arr as $k => $v) {
              if($steuerfrei) {
                $satz = 0;
              }
              else{
                if(is_null($v['ssatz']) || $v['ssatz'] < 0) {
                  if($v['usteuer'] === 'ermaessigt') {
                    $satz = $steuersatzermaessigt;
                  }
                  elseif($v['usteuer'] === 'befreit'){
                    $satz = 0;
                  }
                  else{
                    $satz = $steuersatznormal;
                  }
                }
                else {
                  $satz = $v['ssatz'];
                }
              }
              if(!isset($ret[$satz])) {
                $ret[$satz] = 0;
              }
              if(!isset($retgerundet[$satz])){
                $retgerundet[$satz] = 0;
              }
              $ret[$satz] += $v['nettoungerundet'];
              $retgerundet[$satz]+= $v['netto'];
            }
            unset($arr);
            if($ret) {
              foreach($ret as $steuersatz => $summe) {
                $arr[] = array(
                    'steuersatz'=>$steuersatz,
                  'netto'=>$retgerundet[$steuersatz],
                  'brutto'=>$summe*(1+$steuersatz/100)
                );
              }
            }
          }
          else{
            foreach($arr as $k => $v)  {
              if($steuerfrei) {
                $arr[$k]['steuersatz'] = 0;
              }
              else{
                if(is_null($v['ssatz']) || $v['ssatz'] < 0) {
                  if($v['usteuer'] === 'ermaessigt') {
                    $arr[$k]['steuersatz'] = $steuersatzermaessigt;
                  }
                  elseif($v['usteuer'] === 'befreit') {
                    $arr[$k]['steuersatz'] = 0;
                  }
                  else{
                    $arr[$k]['steuersatz'] = $steuersatznormal;
                  }
                }
                else {
                  $arr[$k]['steuersatz'] = $v['ssatz'];
                }
              }
              unset($arr[$k]['ssatz']);
              $arr[$k]['brutto'] = $v['nettoungerundet']*(1+$arr[$k]['steuersatz']/100);
              $arr[$k]['umsatzsteuer'] = $arr[$k]['usteuer'];
              unset($arr[$k]['usteuer']);
            }
          }
        }

        if($gruppierenpositionen && $mitErloes) {
          return $this->addErloesSteuerBeleg($arr, $belegtyp, $id);
        }
        return $arr;
      }

  /**
   * @param int  $id
   * @param bool $gruppierenpositionen
   * @param bool $gruppierenkostenstelle
   *
   * @return array|null
   */
      public function GutschriftZwischensummeSpezialSteuer($id, $gruppierenpositionen = false, $gruppierenkostenstelle = false)
      {
        /** @var Buchhaltungexport $buchhaltungexport */
        $buchhaltungexport = $this->app->loadModule('buchhaltungexport', false);
        if($buchhaltungexport !== null && method_exists($buchhaltungexport, 'GutschriftZwischensummeSpezialSteuer')) {
          return $buchhaltungexport->GutschriftZwischensummeSpezialSteuer(
            $id, $gruppierenpositionen, $gruppierenKostenstelle
          );
        }
        if($id > 0)
        {
          $gutschriftarr = $this->app->DB->SelectRow(
            "SELECT ust_befreit,ustid,projekt,kostenstelle 
            FROM gutschrift WHERE id = '$id' LIMIT 1"
          );
        }
        $ust_befreit = null;
        $ustid = null;
        $projekt = 0;
        $kostenstelle = '';
        if(!empty($gutschriftarr)){
          $ust_befreit = $gutschriftarr['ust_befreit'];
          $ustid = $gutschriftarr['ustid'];
          $projekt = $gutschriftarr['projekt'];
          $kostenstelle = $this->app->DB->real_escape_string($gutschriftarr['kostenstelle']);
        }
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,'preisberechnung');
        $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');

        $sqlvor = '';
        $sqlnach = '';
        if($positionenkaufmaenischrunden) {
          $sqlvor = 'round(';
          $sqlnach = ',2)';
        }
        $sqlvor2 = '';
        $sqlnach2 = '';
        if($positionenkaufmaenischrunden == 3) {
          $sqlvor2 = 'round(';
          $sqlnach2 = ',2)';
        }
        if($gruppierenpositionen)
        {
          $arr = $this->app->DB->SelectArr(
            "SELECT gp.`nummer`, gp.`bezeichnung`, gp.`artikel`, gp.`steuersatz`,gp.`erloese`, 
            ".$sqlvor.'gp.menge*'.$sqlvor2.'(gp.preis-(gp.preis/100*gp.rabatt))'.$sqlnach2.$sqlnach." as netto, 
            gp.menge*(gp.preis-(gp.preis/100*gp.rabatt)) as nettoungerundet ,
             if(gp.umsatzsteuer = 'ermaessigt','ermaessigt',if(gp.umsatzsteuer = 'befreit','befreit','normal'))  as usteuer , 
             sum(gp.einkaufspreis * gp.menge) as summeeinkaufspreis,
             IF(
               IFNULL(gp.kostenstelle,'') <> '',
               gp.kostenstelle, 
               IF('$kostenstelle' <> '', '$kostenstelle', art.kostenstelle)
             )
             AS kostenstelle  
             FROM `gutschrift_position` AS gp
             LEFT JOIN artikel AS art ON gp.artikel = art.id 
             WHERE gp.gutschrift = '$id' 
             GROUP BY gp.`steuersatz`,gp.`erloese`, gp.`umsatzsteuer`,gp.`artikel`,gp.`id` "
          );
        }
        else{
          $arr = $this->app->DB->SelectArr(
            "SELECT  gp.`artikel`, gp.`steuersatz`,gp.`erloese`, 
            SUM(".$sqlvor."gp.menge*".$sqlvor2."(gp.preis-(gp.preis/100*gp.rabatt))".$sqlnach2.$sqlnach.") as netto, 
            SUM(gp.menge*(gp.preis-(gp.preis/100*gp.rabatt))) as nettoungerundet, 
            if(gp.umsatzsteuer = 'ermaessigt','ermaessigt',
            if(gp.umsatzsteuer = 'befreit','befreit','normal'))  as usteuer , 
            sum(gp.einkaufspreis * gp.menge) as summeeinkaufspreis,
            IF(
              IFNULL(gp.kostenstelle,'')<>'',
              gp.kostenstelle,
              IF('$kostenstelle' <> '', '$kostenstelle',art.kostenstelle)
            )
            AS kostenstelle  
            FROM `gutschrift_position` AS gp
            LEFT JOIN artikel AS art ON gp.artikel = art.id 
            WHERE gp.gutschrift = '$id' 
            group by gp.`steuersatz`, gp.`erloese`, gp.`umsatzsteuer`, gp.`artikel` "
          );
        }        
        if($arr) {
          $steuersatzermaessigt = $this->GetSteuersatzErmaessigt(true,$id,'gutschrift');
          $steuersatznormal = $this->GetSteuersatzNormal(true,$id,'gutschrift');
          foreach($arr as $k => $v)  {
            if($v['steuersatz'] !== null && $v['steuersatz'] == 0 && $ust_befreit == 0) {
              $ust_befreit = 3;
            }
            $erloese = $this->Gegenkonto($ust_befreit, $ustid, 'gutschrift', $id);
            $this->GetArtikelSteuer(
              $v['artikel'], $ust_befreit,0, $dummysteuersatz, $tmpsteuertext, $tmperloes, $v['usteuer'], $ustid, $projekt
            );
            if(!$this->GutschriftMitUmsatzeuer($id)){
              $v['steuersatz'] = 0;
            }
            if($v['steuersatz'] === null || $v['steuersatz'] < 0)
            {
              if($v['usteuer'] === 'ermaessigt')
              {
                $arr[$k]['steuersatz'] = $steuersatzermaessigt;
              }elseif($v['usteuer'] === 'befreit')
              {
                $arr[$k]['steuersatz'] = 1;
              }else{
                $arr[$k]['steuersatz'] = $steuersatznormal;
              }
            }else {
              $arr[$k]['steuersatz'] = 1+$v['steuersatz']/100;
            }
            if($v['erloese'] === null || $v['erloese'] === '')
            {
              $arr[$k]['erloese'] = $erloese;
              if($tmperloes)
              {
                $arr[$k]['erloese'] = $tmperloes;
              }else{
                if($v['usteuer'] === 'befreit' && $ust_befreit == 0)
                {
                  $arr[$k]['erloese'] = $this->Firmendaten('steuer_erloese_inland_nichtsteuerbar');
                }elseif($v['usteuer'] === 'ermaessigt' && $ust_befreit == 0)
                {
                  $arr[$k]['erloese'] = $this->Firmendaten('steuer_erloese_inland_ermaessigt');
                }elseif($v['usteuer'] === 'ermaessigt' && $ust_befreit == 1 && (String)$ustid === '')
                {
                  $arr[$k]['erloese'] = $this->Firmendaten('steuer_erloese_inland_euermaessigt');
                }elseif($ust_befreit == 1 && (String)$ustid !== ''){
                  
                  $arr[$k]['erloese'] = $this->Firmendaten('steuer_erloese_inland_innergemeinschaftlich');
                }elseif($v['usteuer'] !== 'ermaessigt' && $v['usteuer'] !== 'befreit' && $ust_befreit == 1 && (String)$ustid === '')
                {
                  $arr[$k]['erloese'] = $this->Firmendaten('steuer_erloese_inland_eunormal');
                }
              }
            }
            $arr[$k]['summe'] = $v['nettoungerundet'] * $arr[$k]['steuersatz'];
            if($gruppierenpositionen) {
              $arr[$k]['summe'] = round($arr[$k]['summe'], 2);
            }
          }
        }
        if($gruppierenpositionen) {
          return $arr;
        }

        return $this->SteuerZusammenfassen($arr, $gruppierenkostenstelle);
      }

  /**
   * @param array $arr
   * @param bool  $gruppierenKostenstelle
   *
   * @return array
   */
      public function SteuerZusammenfassen($arr, $gruppierenKostenstelle = false)
      {
        if(empty($arr)) {
          return $arr;
        }

        $tmparr = null;
        foreach($arr as $k => $v) {
          $kostenstelle = $gruppierenKostenstelle?(String)$v['kostenstelle']:'';
          if(empty($tmparr) || !isset($tmparr[$v['erloese']])
            || !isset($tmparr[$v['erloese']]['s'.$v['steuersatz']])
            || !isset($tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle])
            || !isset($tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle]['s'])) {
            $tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle]['s'] = 0;
          }
          if(empty($tmparr) || !isset($tmparr[$v['erloese']])
            || !isset($tmparr[$v['erloese']]['s'.$v['steuersatz']])
            || !isset($tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle])
            || !isset($tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle]['e'])) {
            $tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle]['e'] = 0;
          }
          $tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle]['s'] += $v['summe'];
          $tmparr[$v['erloese']]['s'.$v['steuersatz']][$kostenstelle]['e'] += $v['summeeinkaufspreis'];
        }
        foreach($tmparr as $k1 => $v1) {
          foreach($v1 as $k2 => $v2)  {
            foreach($v2 as $kostenstelle => $v3) {
              $newarr[] = [
                'erloese'            => $k1,
                'steuersatz'         => str_replace('s', '', $k2),
                'summe'              => round($v3['s'], 2),
                'summeeinkaufspreis' => round($v3['e'], 2),
                'kostenstelle'       => $kostenstelle
              ];
            }
          }
        }
        return $newarr;
      }
      
      function RechnungZwischensummeSteuersaetzeBrutto($id,$art="ermaessigt")
      {
        return number_format($this->RechnungZwischensummeSteuersaetzeBrutto2($id,$art),",");
      }

      function GutschriftZwischensummeSteuersaetzeBrutto2($id,$art="ermaessigt")
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM gutschrift WHERE id = '$id' LIMIT 1");
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,"preisberechnung");
        $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');

        $sqlvor = '';
        $sqlnach = '';

        if($art!="ermaessigt")
          $summe = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*(preis-(preis/100*rabatt))".$sqlnach.") FROM gutschrift_position WHERE (umsatzsteuer='normal' OR umsatzsteuer='') AND gutschrift='$id'");
        else
          $summe = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*(preis-(preis/100*rabatt))".$sqlnach.") FROM gutschrift_position WHERE umsatzsteuer='$art' AND gutschrift='$id'");
        if($art == 'befreit')return $summe;
        if($art=="ermaessigt")
          $ermaessigt_summe = $summe*$this->GetSteuersatzErmaessigt(true,$id,"gutschrift");
        else
          $ermaessigt_summe = $summe*$this->GetSteuersatzNormal(true,$id,"gutschrift");
        if($positionenkaufmaenischrunden == 1 || $positionenkaufmaenischrunden == 3)return round($ermaessigt_summe, 2);
        return $ermaessigt_summe;
      }

      function BelegZwischensummeSteuersaetzeBrutto2($id,$typ="",$art="ermaessigt")
      {
        $projekt = $this->app->DB->Select("SELECT projekt FROM $typ WHERE id = '$id' LIMIT 1");
        $positionenkaufmaenischrunden = $this->app->erp->Projektdaten($projekt,"preisberechnung");
        $viernachkommastellen_belege = $this->app->erp->Firmendaten('viernachkommastellen_belege');

        $sqlvor = '';
        $sqlnach = '';
        if($art!="ermaessigt")
          $summe = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*(preis-(preis/100*rabatt))".$sqlnach.") FROM ".$typ."_position WHERE (umsatzsteuer='normal' OR umsatzsteuer='') AND ".$typ."='$id'");
        else
          $summe = $this->app->DB->Select("SELECT SUM(".$sqlvor."menge*(preis-(preis/100*rabatt))".$sqlnach.") FROM ".$typ."_position WHERE umsatzsteuer='$art' AND ".$typ."='$id'");
        if($art == 'befreit')return $summe;
        if($art=="ermaessigt")
          $ermaessigt_summe = $summe*$this->GetSteuersatzErmaessigt(true,$id,$typ);
        else
          $ermaessigt_summe = $summe*$this->GetSteuersatzNormal(true,$id,$typ);
        if($positionenkaufmaenischrunden == 1 || $positionenkaufmaenischrunden == 3)return round($ermaessigt_summe, 2);
        return $ermaessigt_summe;
      }

      function GutschriftZwischensummeSteuersaetzeBrutto($id,$art="ermaessigt")
      {
        return number_format($this->GutschriftZwischensummeSteuersaetzeBrutto2($id,$art),",");
      }

      function RechnungNeuberechnen($id)
      {
        $this->ANABREGSNeuberechnen($id,"rechnung");
      }


      function DeleteRechnung($id)
      {
        /** @var Rechnung $obj */
        $obj = $this->LoadModul('rechnung');
        if(!empty($obj) && method_exists($obj,'DeleteRechnung')){
          $obj->DeleteRechnung($id);
        }
      }


      function GetUserKalender($adresse)
      {
        return $this->app->DB->SelectArr("SELECT id, name, farbe FROM kalender WHERE id IN (SELECT kalender FROM kalender_user WHERE adresse = $adresse);");
      }

      function GetAllKalender($adresse="")
      {
        return $this->app->DB->SelectArr("SELECT id, name, farbe".($adresse!=""?", IFNULL((SELECT 1 FROM kalender_user WHERE adresse=$adresse AND kalender_user.kalender=kalender.id),0) zugriff":"")." FROM kalender;");
      }

      function GetUserKalenderIds($adresse)
      {
        $arr = array();
        foreach ($this->GetUserKalender($adresse) as $value)
          array_push($arr,$value["id"]);
        return $arr;
      }

      function GetAllKalenderIds($adresse="")
      {
        $arr = array();
        foreach ($this->GetAllKalender($adresse) as $value)
          array_push($arr,$value["id"]);
        return $arr;
      }

      function GetKalenderSelect($adresse,$selectedKalender=array())
      {
        $arr = $this->GetUserKalender($adresse);
        foreach($arr as $value)
        {
          $tmp = (in_array($value["id"],$selectedKalender))?" selected=\"selected\"":"";
          $ret .= "<option value=\"".$value["id"]."\"$tmp>".$value["name"]."</option>";
        }
        return $ret;
      }

      function GetKwSelect($selectedKW="")
      {
        $ret = '';
        foreach(range(1,52) as $kw)
        {
          $tmp = ($selectedKW==$kw)?" selected=\"selected\"":"";
          $ret .= "<option value=\"$kw\"$tmp>$kw</option>";
        }
        return $ret;
      }

      function GetYearSelect($selectedYear="", $yearsBefore=2, $yearsAfter=10)
      {
        $ret = '';
        foreach(range(date("Y")-$yearsBefore, date("Y")+$yearsAfter) as $year)
        {
          $tmp = ($selectedYear==$year)?" selected=\"selected\"":"";
          $ret .= "<option value=\"$year\"$tmp>$year</option>";
        }
        return $ret;
      }

      function DownloadFile($url,$label="tmp",$ending="")
      {
        if($ending!="") $ending = '.'.$ending;

        $tmpname1 = tempnam($this->GetTMP(),$label);
        $tmpname = $tmpname1.$ending;
        unlink($tmpname1);

        set_time_limit(0);
        //This is the file where we save the    information
        $fp = fopen ($tmpname, 'w+');
        //Here is the file we are downloading, replace spaces with %20
        $ch = curl_init(str_replace(" ","%20",$url));
        curl_setopt($ch, CURLOPT_TIMEOUT, 50);
        // write curl response to file
        curl_setopt($ch, CURLOPT_FILE, $fp); 
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        // get curl response
        curl_exec($ch); 
        curl_close($ch);
        fclose($fp);
        return $tmpname;
      }

      function GetDMSPath($id, $path = '', $cache = false)
      {
        $ids = explode('_', $id, 2);
        $id = $ids[0];
        if(isset($ids[1]))$cache = true;
        if($path == '')
        {
          $path = str_replace("index.php", "", $_SERVER['SCRIPT_FILENAME']);
          $path = $path."../userdata/dms/";
          if(isset($this->app->Conf->WFuserdata))$path = rtrim($this->app->Conf->WFuserdata,'/').'/dms/';
          $path = $path.$this->app->Conf->WFdbname;
        }
        if(!is_dir($path))return;
        $_path = $path;
        $ida = str_split($id, 2);
        $path .= '/d'.implode('/d',$ida);
        if(is_file($path.'/'.$id))return $path;
        if($cache && (!empty($ids)?count($ids):0) > 0)
        {
          if(is_file($path.'/'.$ids[0].'_'.$ids[1]))return $path;
          if(is_file($_path.'/'.$ids[0].'_'.$ids[1]))return $_path;
        }
        if($cache && is_dir($path))return $path;
        if($cache && is_dir($_path))return $_path;
      }
  
      function CreateDMSPath($path, $id)
      {
        if($path == '')
        {
          $path = str_replace("index.php", "", $_SERVER['SCRIPT_FILENAME']);
          $path = $path."../userdata/dms/";
          if(isset($this->app->Conf->WFuserdata))$path = rtrim($this->app->Conf->WFuserdata,'/').'/dms/';
          $path = $path.$this->app->Conf->WFdbname;
        }
        $ids = explode('_', $id, 2);
        $id = $ids[0];
        if(!is_dir($path))
        {
          $path_b = $path;
          if (substr(trim($path), -1) == DIRECTORY_SEPARATOR) {
            $path = substr(trim($path), 0, -1);
          }
          @mkdir($path);
          system("chmod 777 ".$path);
          $path = $path_b;
          mkdir($path,0777,true);
          system("chmod 777 ".$path);
        }
        if(!is_dir($path))return;
        $ida = str_split($id, 2);
        foreach($ida as $v)
        {
          $path .= '/d'.$v;
          if(!is_dir($path))
          {
            if(!@mkdir($path,0777,true))
            {
              $path_b = $path;
              if (substr(trim($path), -1) == DIRECTORY_SEPARATOR) {
                $path = substr(trim($path), 0, -1);
              }
              system("chmod 777 ".$path);
              $path = $path_b;
              @mkdir($path,0777,true);
            }
            if(!is_dir($path))return;
          }
          if(!is_dir($path))return;
        }
        return $path;
      }

      public function CheckFileSort($objekt, $parameter)
      {
        $arr = $this->app->DB->SelectArr("SELECT SQL_CALC_FOUND_ROWS s.id, s.sort 
            FROM datei d 
            INNER JOIN datei_stichwoerter s ON d.id=s.datei
            LEFT JOIN (SELECT datei, max(version) as version FROM datei_version GROUP BY datei ) v2  ON v2.datei=d.id
            LEFT JOIN datei_version v ON v.datei=v2.datei AND v.version = v2.version
            WHERE s.objekt LIKE '$objekt' AND s.parameter='$parameter' AND d.geloescht=0 
            ORDER BY s.sort
             ");
        if(!$arr)return;
        $oldsort = false;
        foreach($arr as $v)
        {
          if($oldsort === false)
          {
            $oldsort = $v['sort'];
          }elseif($v['sort'] <= $oldsort){
            $oldsort = $v['sort'] + 1;
            $this->app->DB->Update("UPDATE datei_stichwoerter SET sort = $oldsort WHERE id = '".$v['id']."' LIMIT 1");
          }
        }
      }

      function CreateDateiWithStichwort($name, $titel,$beschreibung,$nummer,$datei, $ersteller ,$subjekt,$objekt,$parameter, $path = "",$without_log=false,$geschuetzt=null)
      {
        $dateien = $this->app->DB->SelectArr("SELECT dv.datei, dv.id FROM datei_stichwoerter ds 
          INNER JOIN datei d ON ds.datei = d.id AND ifnull(d.geloescht,0) = 0
          INNER JOIN datei_version dv ON d.id = dv.datei
          WHERE ds.subjekt = '".$this->app->DB->real_escape_string($subjekt)."' AND 
          ds.objekt = '".$this->app->DB->real_escape_string($objekt)."' AND ds.parameter = '".$this->app->DB->real_escape_string($parameter)."'");
        if($dateien)
        {
          if(is_file($datei))
          {
            $md5 = md5_file($datei);
          }
          else if(is_uploaded_file($datei))
          {
            $_datei = $this->app->erp->GetTMP().$datei;
            if(move_uploaded_file($datei,$_datei))$datei = $_datei;
            $md5 = md5_file($datei);
          }
          else {
            $md5 = md5($datei);
          }
          if($md5 != '') {
            if ($path == "") {
              $path = str_replace("index.php", "", $_SERVER['SCRIPT_FILENAME']);
              $path = $path . "../userdata/dms/";
              if (isset($this->app->Conf->WFuserdata)) $path = rtrim($this->app->Conf->WFuserdata, '/') . '/dms/';
              $path_only = $path;
              $path = $path . $this->app->Conf->WFdbname;
            }
            foreach($dateien as $v)
            {
              if(is_file($path."/".$v['id']) && md5_file($path."/".$v['id']) == $md5)return $v['datei'];
            }
          }
        }
        $fileid = $this->CreateDatei($name,$titel,$beschreibung,$nummer,$datei,$ersteller,$without_log,$path,$geschuetzt);
        $this->AddDateiStichwort($fileid,$subjekt,$objekt,$parameter,$without_log);
        return $fileid;
      }

      function CreateDatei($name,$titel,$beschreibung,$nummer,$datei,$ersteller,$without_log=false,$path="",$geschuetzt=null)
      {
        // Anführungszeichen in Unterstriche wandeln
        $name = str_replace(['\\\'', '\\"', '\'', '"'], '_', $name);

        if(!$without_log)
        {
          $this->app->DB->Insert("INSERT INTO datei (
                id,
                titel,
                beschreibung,
                nummer,
                firma,
                geschuetzt
            ) VALUES (
                '',
                '".$this->app->DB->real_escape_string($titel)."',
                '".$this->app->DB->real_escape_string($beschreibung)."',
                '".$this->app->DB->real_escape_string($nummer)."',
                '".$this->app->User->GetFirma()."',
                '".$geschuetzt."'
            )"
          );
        } else {
          $this->app->DB->InsertWithoutLog("INSERT INTO datei (
                id,
                titel,
                beschreibung,
                nummer,
                firma,
                geschuetzt
            ) VALUES (
                '',
                '".$this->app->DB->real_escape_string($titel)."',
                '".$this->app->DB->real_escape_string($beschreibung)."',
                '".$this->app->DB->real_escape_string($nummer)."',
                1,
                '".$geschuetzt."'
            )
          ");
        }

        $fileid = $this->app->DB->GetInsertID();
        $this->AddDateiVersion($fileid,$ersteller,$name,"Initiale Version",$datei,$without_log,$path);

        return  $fileid;
      }

      function AddDateiVersion($id,$ersteller,$dateiname, $bemerkung,$datei,$without_log=false,$path="")
      {
        // Anführungszeichen in Unterstriche wandeln
        $dateiname = str_replace(['\\\'', '\\"', '\'', '"'], '_', $dateiname);

        // ermittle neue Version
        $version = (int)$this->app->DB->Select("SELECT ifnull(max(version),0) FROM datei_version WHERE datei='$id'") + 1;

        $tmpfilesize = 0;
        if(@is_file($datei)){
          $tmpfilesize = @filesize($datei);
        }

        // speichere werte ab
        if(!$without_log)
        {
          $this->app->DB->Insert("INSERT INTO datei_version (id,datei,ersteller,datum,version,dateiname,bemerkung,size)
              VALUES ('','$id','$ersteller',NOW(),'$version','$dateiname','$bemerkung','$tmpfilesize')");
        } else {
          $this->app->DB->InsertWithoutLog("INSERT INTO datei_version (id,datei,ersteller,datum,version,dateiname,bemerkung,size)
              VALUES ('','$id','$ersteller',NOW(),'$version','$dateiname','$bemerkung','$tmpfilesize')");
        }

        $versionid = $this->app->DB->GetInsertID();

        $parameter = $this->app->DB->Select("SELECT parameter FROM datei_stichwoerter WHERE datei = '$id' and objekt like 'Artikel' LIMIT 1");
        if($parameter){
          $this->app->DB->Update("UPDATE artikel set bildvorschau = '' WHERE id = '$parameter' LIMIT 1");
        }

        //TODO Das ist keine lösung!
        //    if($this->app->Conf->WFdbname=="")
        //      $this->app->Conf->WFdbname="wawision";

        // Pfad anpassen
        if($path=="")
        {
          $path = str_replace("index.php", "", $_SERVER['SCRIPT_FILENAME']);
          $path = $path."../userdata/dms/";
          if(isset($this->app->Conf->WFuserdata)){
            $path = rtrim($this->app->Conf->WFuserdata,'/').'/dms/';
          }
          $path_only = $path;
          $path = $path.$this->app->Conf->WFdbname;
        }  else {
          $path_only = $path;
        }

        if(!is_dir($path))
        {

          $path_b = $path;
          if (substr(trim($path), -1) == DIRECTORY_SEPARATOR) {
            $path = substr(trim($path), 0, -1);
          }
          if(!mkdir($path,0777, true) && !is_dir($path)){
            system("chmod 777 " . $path);
            $path = $path_b;
            //system("mkdir ".$path);
            mkdir($path, 0777, true);
            system("chmod 777 " . $path);
          }
        }
        $userdata = isset($this->app->Conf->WFuserdata)?$this->app->Conf->WFuserdata:(str_replace('index.php', '', $_SERVER['SCRIPT_FILENAME']).'../userdata');

        $cachefile = $this->app->erp->GetDMSPath(
          $versionid.'_100_100',
          $userdata.'/dms/'.$this->app->Conf->WFdbname.'/cache', true
        );
        if(is_file($cachefile)) {
          @unlink($cachefile);
        }

        $path = $this->CreateDMSPath($path, $versionid);

        if(@is_file($datei))
        {
          if(copy($datei,$path."/".$versionid)){
            return $versionid;
          }
          return false;
        }
        if(@is_uploaded_file($datei))
        {
          if(@move_uploaded_file($datei,$path.'/'.$versionid))
          {
            if($tmpfilesize == 0)
            {
              if(@is_file($path.'/'.$versionid))
              {
                $tmpfilesize = @filesize($path.'/'.$versionid);
                $this->app->DB->Update("UPDATE datei_version SET `size` = '$tmpfilesize' WHERE id = '$versionid'");
              }
            }
            return $versionid;
          }
          return false;
        }

        // ACHTUNG !!!! ANGRIFFSGEFAHR!!!!!
        if($handle = fopen ($path.'/'.$versionid, "wb"))
        {
          fwrite($handle, $datei);
          fclose($handle);
          if(@is_file($path.'/'.$versionid))
          {
            $tmpfilesize = @filesize($path.'/'.$versionid);
            $this->app->DB->Update("UPDATE datei_version SET `size` = '$tmpfilesize' WHERE id = '$versionid'");
          }
          return $versionid;
        }
        return false;
      }


      function AddDateiStichwort($id,$subjekt,$objekt,$parameter,$without_log=false,$parameter2=0,$objekt2='')
      {
        if(strtolower($objekt) === 'artikel' && $parameter) {
          $this->app->DB->Update("UPDATE artikel SET bildvorschau = '' WHERE id = '".$parameter."' LIMIT 1");
        }
        $sort = 1 + (int)$this->app->DB->Select("SELECT max(sort) FROM datei_stichwoerter WHERE objekt like '$objekt' AND parameter = '$parameter'");
        if(!$without_log) {
          $this->app->DB->Insert("INSERT INTO datei_stichwoerter (id,datei,subjekt,objekt,parameter, sort, parameter2, objekt2)
              VALUES ('','$id','$subjekt','$objekt','$parameter','$sort','$parameter2','$objekt2')");
        } else {
          $this->app->DB->InsertWithoutLog("INSERT INTO datei_stichwoerter (id,datei,subjekt,objekt,parameter,sort, parameter2, objekt2)
              VALUES ('','$id','$subjekt','$objekt','$parameter','$sort','$parameter2','$objekt2')");
        }
      }

      function DeleteDateiAll($subjekt,$objekt,$parameter)
      {
        $dateien = $this->app->DB->SelectArr("SELECT ds.datei FROM datei_stichwoerter ds WHERE ds.subjekt='$subjekt' AND ds.objekt='$objekt' AND ds.parameter='$parameter' group by ds.datei");
        if($dateien)
        {
          foreach($dateien as $datei)
          {
            if($datei['datei']){
              $this->DeleteDatei($datei['datei']);
            }
          }
        }
      }

  /**
   * @param string $path
   */
      public function deleteEmptyDmsPath($path) {
        $prefix = $this->app->Conf->WFuserdata.'/dms/'.$this->app->Conf->WFdbname.'/';
        if(strpos($path, $prefix) !== 0) {
          return;
        }
        $prefixCache =  $prefix.'cache/';
        $isCacheFolder = strpos($path, $prefixCache) === 0;
        if($isCacheFolder) {
          $prefix = $prefixCache;
        }

        $dirRelative = substr($path, strlen($prefix));
        if($dirRelative[0] !== 'd') {
          return;
        }
        $pathArr = explode('/', rtrim($dirRelative,'/'));

        if(substr($pathArr[(!empty($pathArr)?count($pathArr):0) - 1],0,1) !== 'd') {
          unset($pathArr[(!empty($pathArr)?count($pathArr):0) - 1]);
        }
        if(empty($pathArr) || !is_dir($prefix.'/'.implode('/', $pathArr))) {
          return;
        }
        $glob = glob($prefix.implode('/', $pathArr).'/*'); /**/
        if(!empty($glob)) {
          return;
        }
        if(@rmdir($prefix.implode('/', $pathArr)) && (!empty($pathArr)?count($pathArr):0) > 1) {
          unset($pathArr[(!empty($pathArr)?count($pathArr):0) - 1]);
          $this->deleteEmptyDmsPath($prefix.implode('/', $pathArr));
        }
      }

      function DeleteDatei($id)
      {
        $id = (int)$id;
        if(!$id){
          return false;
        }

        $geschuetzt = $this->app->DB->Select("SELECT geschuetzt FROM datei WHERE id = '".$id."'");
        if ($geschuetzt) {
          return false;
        }

        $error = false;
        $versionen = $this->app->DB->SelectArr("SELECT * FROM datei_version WHERE datei = '".$id."'");
        if($versionen)
        {
          foreach($versionen as $vers)
          {
            //$path = $this->app->Conf->WFuserdata."/dms/".$this->app->Conf->WFdbname."/".$vers['id'];
            $path = $this->GetDMSPath($vers['id'], $this->app->Conf->WFuserdata.'/dms/'.$this->app->Conf->WFdbname);
            if($path){
              $path .= '/'.$vers['id'];
            }
            if($path && file_exists($path))
            {
              if(unlink($path))
              {
                $this->app->DB->Delete("DELETE FROM datei_version WHERE id = '".$vers['id']."'");
              }else{
                $error = true;
              }
            }else{
              $this->app->DB->Delete("DELETE FROM datei_version WHERE id = '".$vers['id']."'");
            }
            $this->deleteEmptyDmsPath($path);
            $cachedir = $this->app->Conf->WFuserdata."/dms/".$this->app->Conf->WFdbname.'/cache/';
            if(is_dir($cachedir))
            {
              $caches = glob($this->app->Conf->WFuserdata."/dms/".$this->app->Conf->WFdbname."/cache/".$vers['id'].'_*');
              if(is_array($caches) && (!empty($caches)?count($caches):0) > 0)
              {
                foreach($caches as $cache)unlink($cache);
              }
            }
            $cachedir = $this->GetDMSPath($vers['id'], $this->app->Conf->WFuserdata."/dms/".$this->app->Conf->WFdbname."/cache", true);
            if(is_dir($cachedir))
            {
              $caches = glob($cachedir.'/'.$vers['id'].'_*');
              if(is_array($caches) && (!empty($caches)?count($caches):0) > 0)
              {
                foreach($caches as $cache){
                  unlink($cache);
                }
              }
              $this->deleteEmptyDmsPath($cachedir);
            }
          }
        }
        if(!$error)
        {
          $ds = $this->app->DB->SelectArr("SELECT id,objekt, parameter FROM datei_stichwoerter WHERE datei = '$id' AND objekt like 'Artikel' AND parameter <> '' AND parameter <> '0'");
          $this->app->DB->Delete("DELETE FROM datei_stichwoerter WHERE datei = '$id'");
          if($ds)
          {
            foreach($ds as $d)
            {
              $this->app->DB->Update("UPDATE artikel SET bildvorschau = '' WHERE id = '".$d['parameter']."' LIMIT 1");
            }
          }
          $this->app->DB->Delete("DELETE FROM datei WHERE id = '$id' LIMIT 1");
          return true;
        }
        return false;
      }

      function GetDateiName($id)
      {
        $version = $this->app->DB->Select("SELECT MAX(version) FROM datei_version WHERE datei='$id'");
        $newid = $this->app->DB->Select("SELECT dateiname FROM datei_version WHERE datei='$id' AND version='$version' LIMIT 1");

//        return $this->UmlauteEntfernen($newid);
        return $newid;
      }


      function GetDateiEndung($id)
      {
        $version = $this->app->DB->Select("SELECT MAX(version) FROM datei_version WHERE datei='$id'");
        $newid = $this->app->DB->Select("SELECT dateiname FROM datei_version WHERE datei='$id' AND version='$version' LIMIT 1");
        $tmp = pathinfo($newid);

        return strtolower($tmp['extension']);
      }

    /*
    * Retrieve files from stichwoerter and provide them in tmp for access
    */

      function GetDateiSubjektObjektDateiname($subjekt,$objekt,$parameter,$prefix="")
      {
        $dateien = $this->app->DB->SelectArr("SELECT datei FROM datei_stichwoerter WHERE subjekt LIKE '$subjekt' AND objekt LIKE '$objekt' AND parameter='$parameter' GROUP by datei");
        if(empty($dateien)) {
          return null;
        }
        $tmp = [];
        foreach($dateien as $datei) {

//          $tmpname = tempnam($this->GetTMP(), $prefix);

          $tmpname = $this->GetTMP().md5(uniqid(mt_rand(), true));
          mkdir ($tmpname);
          $newname = $tmpname."/".$this->GetDateiName($datei['datei']);
          copy($this->GetDateiPfad($datei['datei']),$newname); 
          $tmp[] = $newname;
        }
        return $tmp;
      }

      function GetDateiStichwoerter($dateiid) {
        $stichwoerter = $this->app->DB->SelectArr("SELECT subjekt, objekt, parameter FROM datei_stichwoerter WHERE datei=".$dateiid);
        if (empty($stichwoerter)) {
          return null;
        }
        else {
          return $stichwoerter;
        }
      }

      function GetDateiSubjektObjekt($subjekt,$objekt,$parameter)
      {
        $dateien = $this->app->DB->SelectArr("SELECT datei FROM datei_stichwoerter INNER JOIN datei d on d.id = datei WHERE subjekt LIKE '$subjekt' AND objekt LIKE '$objekt' AND parameter='$parameter' AND d.geloescht <> 1 GROUP by datei");
        if(empty($dateien)) {
          return null;
        }
        $tmp = [];
        foreach($dateien as $datei) {
//          $tmp[] = $this->GetDateiPfad($datei['datei']);
          $tmp[] = $datei['datei']; // return the datei id
        }
        return $tmp;
      }

      function GetDateiPfad($id)
      {
        $version = $this->app->DB->Select("SELECT MAX(version) FROM datei_version WHERE datei='$id'");
        $newid = $this->app->DB->Select("SELECT id FROM datei_version WHERE datei='$id' AND version='$version' LIMIT 1");

        return $this->GetDateiPfadVersion($newid);
      }

      function GetDateiPfadVersion($id)
      {
        $dateipfad = $this->app->DB->Select("SELECT dateiname FROM datei_version WHERE id ='$id' LIMIT 1");
        if(is_file($dateipfad))return $dateipfad;

        $path = $this->GetDMSPath($id, $this->app->Conf->WFuserdata."/dms/".$this->app->Conf->WFdbname);
        if($path)return $path."/".$id;
        $path = $this->app->Conf->WFuserdata."/dms/".$this->app->Conf->WFdbname."/".$id;
        return $path;
      }

      function GetDateiVersion($id)
      {
        $path = $this->GetDateiPfadVersion($id);
        return @file_get_contents($path);
      }
  
      function GetDatei($id)
      {
        $path = $this->GetDateiPfad($id);
        return @file_get_contents($path);
      }

      function GetDateiSize($id) {
        $path = $this->GetDateiPfad($id);
        $size = 0;
        if(@is_file($path)) {
          $size = @filesize($path);
        }

        if($size <= 1024){
          return $size . ' Byte';
        }
        if($size <= 1024*1024){
          return number_format(($size / 1024), 2) . ' KB';
        }
        return number_format(($size/1024/1024),2).' MB';
      }



      function SendDatei($id,$versionid='') {
        session_write_close();
        ob_end_clean();
        set_time_limit(0);

        if($versionid>0){
          $newid = $versionid;
        } else{
          $version = 0;
          $newid = 0;
          if((int)$id > 0) {
            $version = $this->app->DB->Select("SELECT MAX(version) FROM datei_version WHERE datei='$id'");
            $newid = $this->app->DB->Select("SELECT id FROM datei_version WHERE datei='$id' AND version='$version' LIMIT 1");
          }
        }


        $name = $newid <=0?'':$this->app->DB->Select("SELECT dateiname FROM datei_version WHERE id='$newid' LIMIT 1");
        $path = '';
        if($id > 0){
          $path = $this->GetDateiPfad($id);
          if(!@file_exists($path)) {
            $path = '';
          }
        }
        //$name=basename($path);

        //filenames in IE containing dots will screw up the
        //filename unless we add this

        if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
        {
          $header_name =  'Content-Disposition: attachment; filename="' . rawurlencode ( $name ) . '"' ;
        }
        else {
          $header_name =   'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $name ) ;
        }

        $contenttype= $this->content_type($name);

        //required, or it might try to send the serving     //document instead of the file
        header("Content-Type: $contenttype");
        header("Content-Length: " .(string)(empty($path)?0:@filesize($path)) );
        //header('Content-Disposition: inline; filename="'.$name.'"');
        //$name = $this->Dateinamen($name);
        //header('Content-Disposition: attachment; filename="'.$name.'"');
        header($header_name);

        if(!empty($path) && $file = fopen($path, 'rb')){
          while( (!feof($file)) && (connection_status()==0) ){
            print(fread($file, 1024*8));
            flush();
          }
          fclose($file);
        }
        return((connection_status()==0) and !connection_aborted());
      }


      function content_type($name) {
        // Defines the content type based upon the extension of the file
        $contenttype  = 'application/octet-stream';
        $contenttypes = array( 'html' => 'text/html',
            'htm'  => 'text/html',
            'txt'  => 'text/plain',
            'gif'  => 'image/gif',
            'jpg'  => 'image/jpeg',
            'png'  => 'image/png',
            'sxw'  => 'application/vnd.sun.xml.writer',
            'sxg'  => 'application/vnd.sun.xml.writer.global',
            'sxd'  => 'application/vnd.sun.xml.draw',
            'sxc'  => 'application/vnd.sun.xml.calc',
            'sxi'  => 'application/vnd.sun.xml.impress',
            'xls'  => 'application/vnd.ms-excel',
            'ppt'  => 'application/vnd.ms-powerpoint',
            'doc'  => 'application/msword',
            'rtf'  => 'text/rtf',
            'zip'  => 'application/zip',
            'mp3'  => 'audio/mpeg',
            'pdf'  => 'application/pdf',
            'tgz'  => 'application/x-gzip',
            'gz'   => 'application/x-gzip',
            'vcf'  => 'text/vcf' );

        $name = str_replace("§", " ", $name);
        foreach ($contenttypes as $type_ext => $type_name) {
          if (preg_match ("/$type_ext$/i",  $name)) $contenttype = $type_name;
        }
        return $contenttype;
      }

      function getDateiTypen($modul=''){
        $dateiTypen=[];

        switch($modul){
          case 'artikel':
            $dateiTypen[] = ['wert' => 'Shopbild', 'beschriftung' => 'Standard Artikelbild (Shopbild)'];
            $dateiTypen[] = ['wert' => 'Gruppenbild', 'beschriftung' => 'Standard Gruppenbild'];
            $dateiTypen[] = ['wert' => 'Etikettenbild', 'beschriftung' => 'Etikettenbild'];
            $dateiTypen[] = ['wert' => 'Bild', 'beschriftung' => 'Sonstiges Bild'];
            $dateiTypen[] = ['wert' => 'Datenblatt', 'beschriftung' => 'Datenblatt'];
            $dateiTypen[] = ['wert' => 'Druckbild', 'beschriftung' => 'Druckbild (300dpi)'];
            $dateiTypen[] = ['wert' => 'Zertifikat', 'beschriftung' => 'Zertifikat Anhang (PDF)'];
            break;
          case 'projekt':
            $dateiTypen[] = ['wert' => 'Briefpapier1', 'beschriftung' => 'Briefpapier Seite 1'];
            $dateiTypen[] = ['wert' => 'Briefpapier2', 'beschriftung' => 'Briefpapier Seite 2'];
            break;
          case 'verbindlichkeit':
          case 'kasse':
            $dateiTypen[] = ['wert' => 'Belege', 'beschriftung' => 'Beleg'];
            $dateiTypen[] = ['wert' => 'Quittung', 'beschriftung' => 'Quittung'];
            break;
        }

        $dateiTypen[] = ['wert' => 'Sonstige', 'beschriftung' => 'Sonstige Datei'];
        $dateiTypen[] = ['wert' => 'Deckblatt', 'beschriftung' => 'Deckblatt'];
        $dateiTypen[] = ['wert' => 'anhang', 'beschriftung' => 'Anhang'];

        //adresse unter defaulttypen, da profilbild nicht als default ausgewählt werden soll OS148717
        switch($modul){
          case 'adresse':
            $dateiTypen[] = ['wert' => 'Profilbild', 'beschriftung' => 'Profilbild'];
            break;
        }

        if($modul !== ''){
          $zusaetzlicheStichworter = $this->app->DB->SelectArr(
            "SELECT * FROM datei_stichwortvorlagen WHERE modul='$modul' OR modul='' ORDER by beschriftung"
          );
          $cZusaetzlicheStichworter = empty($zusaetzlicheStichworter)?0:(!empty($zusaetzlicheStichworter)?count($zusaetzlicheStichworter):0);
          for($i=0;$i<$cZusaetzlicheStichworter;$i++){
            $dateiTypen[] = ['wert' => $zusaetzlicheStichworter[$i]['beschriftung'], 'beschriftung' => $zusaetzlicheStichworter[$i]['beschriftung']];
          }
        }

        return $dateiTypen;
      }

     function GetEtikettenbild($artikel,$return_dateiid=false)
     {
        $dateiid = $this->app->DB->Select(
          sprintf(
          "SELECT datei 
          FROM datei_stichwoerter 
          WHERE objekt LIKE 'Artikel' AND parameter = '%d' AND (subjekt LIKE 'Etikettenbild' OR subjekt LIKE 'Bild' OR subjekt LIKE 'Shopbild') 
          ORDER BY (subjekt like 'Etikettenbild') DESC, (subjekt like 'Bild') DESC 
          LIMIT 1",
            (int)$artikel
          )
        );

        if($artikel <= 0 || $dateiid <= 0) {
          return false;
        }

        if($return_dateiid) {
          return $dateiid;
        }

        $filename = $this->GetDateiName($dateiid);
        $path_info = pathinfo($filename);
        return array('image'=>$this->GetDatei($dateiid),'filename'=>$filename,'extension'=>$path_info['extension']);
      }


      function GetArtikelStandardbild($artikel,$return_dateiid=false)
      {
        $dateiid = $this->app->DB->Select(sprintf("
           SELECT dv.datei AS datei 
           FROM datei_stichwoerter AS ds 
           JOIN (SELECT datei, MAX(id) AS id FROM datei_version GROUP BY datei) AS dv ON dv.datei = ds.datei
           JOIN datei AS d on ds.datei = d.id
           WHERE ds.objekt LIKE 'Artikel' AND d.geloescht = 0 AND
            ds.parameter = '%d' AND 
             (ds.subjekt LIKE 'Shopbild' OR ds.subjekt LIKE 'Druckbild' OR ds.subjekt LIKE 'Bild') 
           ORDER BY ds.subjekt LIKE 'Shopbild' DESC, ds.subjekt LIKE 'Druckbild' DESC, ds.sort
           LIMIT 1",
           $artikel)
        );

        if($artikel <= 0 || $dateiid <= 0) {
          return false;
        }
        if($return_dateiid) {
          return $dateiid;
        }

        $filename = $this->GetDateiName($dateiid);
        $path_info = pathinfo($filename);
        return array('image'=>$this->GetDatei($dateiid),'filename'=>$filename,'extension'=>$path_info['extension']);
      }

      function DeleteEmailbackupMail($id,$adresse="")
      {
        if($adresse > 0)
        {
          $this->app->DB->Update("UPDATE emailbackup_mails SET geloescht=1 WHERE
            webmail IN (SELECT id FROM emailbackup WHERE emailbackup.adresse = '$adresse' AND emailbackup.geloescht!=1) AND id='$id'");
        } else {
          $this->app->DB->Update("UPDATE emailbackup_mails SET geloescht=1 WHERE id='$id' LIMIT 1");
        }
      }

      function Wochenplan($adr_id,$parsetarget){
        $this->app->Tpl->Set('SUBSUBHEADING', "Wochenplan");
        $this->app->Tpl->Set('INHALT',"");

        $anzWochentage = 5;
        $startStunde = 6;
        $endStunde = 22;

        $wochentage = $this->getDates($anzWochentage);

        $inhalt = "";
        for($i=$startStunde;$i<=$endStunde;$i++){ // fuelle Zeilen 06:00 bis 22:00
          $zeile = array();
          $zeileCount = 0;
          foreach($wochentage as $tag){ // hole Daten fuer Uhrzeit $i und Datum $tage
            $result = $this->checkCell($tag, $i, $adr_id);
            if($result[0]['aufgabe'] != "")
            {
              if($result[0]['adresse']==0) $color = '#ccc'; else $color='#BCEE68';
              if($result[0]['prio']==1) $color = 'red';

              $zeile[$zeileCount] = '<div style="background-color: '.$color.'">'.$result[0]['aufgabe'].'</div>';
            }
            else
              $zeile[$zeileCount] = "&nbsp;";
            $zeileCount++;
          }
          $inhalt = $inhalt.$this->makeRow($zeile, $anzWochentage,$i.":00");
        }
        $this->app->Tpl->Set('WOCHENDATUM', $this->makeRow($wochentage, $anzWochentage));
        $this->app->Tpl->Set('INHALT',$inhalt);

        $this->app->Tpl->Parse($parsetarget,"zeiterfassung_wochenplan.tpl");

        $this->app->Tpl->Add($parsetarget,"<table><tr><td style=\"background-color:#BCEE68\">".$this->app->User->GetName()."</td>
            <td style=\"background-color:red\">Prio: Sehr Hoch (".$this->app->User->GetName().")</td>
            <td style=\"background-color:#ccc\">Allgemein</td></tr></table>");
      }

      function getDates($anzWochentage){
        // hole Datum der Wochentage von Mo bis $anzWochentage
        $montag = $this->app->DB->Select("SELECT DATE_SUB(CURDATE(),INTERVAL WEEKDAY(CURDATE()) day)");
        $week = array();
        for($i=0;$i<$anzWochentage;$i++)
          $week[$i] = $this->app->DB->Select("SELECT DATE_ADD('$montag',INTERVAL $i day)");
        return $week;
      }

      function makeRow($data, $spalten, $erstefrei="frei"){
        // erzeuge eine Zeile in der Tabelle
        // $erstefrei = 1 -> erste Spalte ist leer

        $row = '<tr>';
        if($erstefrei=="frei")
          $row = $row.'<td class="wochenplan">&nbsp;</td>';
        else
          $row = $row.'<td class="wochenplan">'.$erstefrei.'</td>';
        for($i=0;$i<$spalten; $i++)
          $row = $row.'<td class="wochenplan">'.$data[$i].'</td>';
        $row = $row.'</tr>';
        return $row;
      }


      function KundeMitUmsatzsteuer($adresse)
      {
        $addressRow = $this->app->DB->SelectRow("SELECT land, ustid FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");
        $land = $addressRow['land'];
        $ustid = $addressRow['ustid'];
        if($land ==$this->Firmendaten('land')){
          return true;
        }

        // wenn kunde EU
        foreach($this->GetUSTEU() as $value)
        {
          //echo $value;
          if($value==$land && $ustid!='') {
            return false;
          }
        }

        // alle anderen laender = export
        return false;
      }
  
      function AuftragMitUmsatzsteuer($auftrag)
      {
        return $this->AuftragMitUmsatzeuer($auftrag);
      }

      function AuftragMitUmsatzeuer($auftrag)
      {
        $docRow = $this->app->DB->SelectRow(sprintf('SELECT ust_befreit,ustid FROM auftrag WHERE id=%d LIMIT 1', $auftrag));
        return $docRow['ust_befreit'] == 0
          || ($docRow['ust_befreit'] == 1 &&
            $docRow['ustid'] =='');
      }

      function GutschriftMitUmsatzeuer($gutschrift)
      {
        $docRow = $this->app->DB->SelectRow(sprintf('SELECT ust_befreit,ustid FROM gutschrift WHERE id=%d LIMIT 1', $gutschrift));
        return $docRow['ust_befreit'] == 0
          || ($docRow['ust_befreit'] == 1 &&
            $docRow['ustid'] =='');
      }
      
      function PruefeMengeVPE($table, $posid, $menge)
      {
        if($posid <= 0)return $menge;
        $_menge = $menge;
        $beleg = str_replace('_position','',$table);
        switch($table)
        {
          case 'auftrag_position':
          case 'angebot_position':
          case 'rechnung_position':
          case 'gutschrift_position':
            if(!$this->app->erp->Firmendaten('verkaufspreisevpe'))return $menge;
            $artikel = $this->app->DB->Select("SELECT artikel FROM $table WHERE id = '$posid' LIMIT 1");
            $belegid = $this->app->DB->Select("SELECT $beleg FROM $table WHERE id = '$posid' LIMIT 1");
            $adresse = $this->app->DB->Select("SELECT adresse FROM $beleg WHERE id = '$belegid' LIMIT 1");
            $waehrung = $this->app->DB->Select("SELECT waehrung FROM $beleg WHERE id = '$belegid' LIMIT 1");
            $vp = $this->app->erp->GetVerkaufspreisKunde($artikel,$menge,$adresse,$waehrung,true);
            if(!$vp)$vp = $this->app->erp->GetVerkaufspreis($artikel,$menge,$adresse,$waehrung, $returnwaehrung,true, true);
            if($vp && $vp['vpe'] > 0)
            {
              if($vp['vpe'] * ceil($menge / $vp['vpe']) != $_menge) {
                $this->app->DB->Update("UPDATE $table SET preis = '" . $vp['preis'] . "' WHERE id = '$posid' LIMIT 1");
                return $vp['vpe'] * ceil($menge / $vp['vpe']);
              }else return $_menge;
            }
          break;
          case 'bestellung_position':
            if(!$this->app->erp->Firmendaten('einkaufspreisevpe'))return $menge;
            $artikel = $this->app->DB->Select("SELECT artikel FROM $table WHERE id = '$posid' LIMIT 1");
            $belegid = $this->app->DB->Select("SELECT $beleg FROM $table WHERE id = '$posid' LIMIT 1");
            $adresse = $this->app->DB->Select("SELECT adresse FROM $beleg WHERE id = '$belegid' LIMIT 1");
            $waehrung = $this->app->DB->Select("SELECT waehrung FROM $beleg WHERE id = '$belegid' LIMIT 1");
            $ep = $this->app->erp->GetEinkaufspreisArr($artikel, $menge, $adresse, $waehrung, true);
            if($ep && $ep['vpe'] > 0)
            {
              if($_menge != $ep['vpe'] * ceil($menge / $ep['vpe'])) {
                $this->app->DB->Update("UPDATE $table SET preis = '" . $ep['preis'] . "' WHERE id = '$posid' LIMIT 1");
                return $ep['vpe'] * ceil($menge / $ep['vpe']);
              }else return $_menge;
            }
          break;
        }
        return $menge;
      }
      
      
      
      function Belegegesamt($tabellen = null, $where = '')
      {
        if(is_null($tabellen) || in_array('rechnung', $tabellen))$ret[] = "
        select `rechnung`.`id` AS `id`,`rechnung`.`adresse` AS `adresse`,`rechnung`.`datum` AS `datum`,`rechnung`.`belegnr` AS `belegnr`,`rechnung`.`status` AS `status`,`rechnung`.`land` AS `land`,'rechnung' AS `typ`,`rechnung`.`umsatz_netto` AS `umsatz_netto`,`rechnung`.`soll` AS `umsatz_brutto`,`rechnung`.`erloes_netto` AS `erloes_netto`,`rechnung`.`deckungsbeitrag` AS `deckungsbeitrag`,`rechnung`.`provision_summe` AS `provision_summe`,`rechnung`.`vertriebid` AS `vertriebid`,`rechnung`.`gruppe` AS `gruppe`,`rechnung`.`projekt` AS `projekt`,`rechnung`.`waehrung` as `waehrung`
        from `rechnung` $where
        ";
        if(is_null($tabellen) || in_array('gutschrift', $tabellen))$ret[] = "
          select `gutschrift`.`id` AS `id`,`gutschrift`.`adresse` AS `adresse`,`gutschrift`.`datum` AS `datum`,`gutschrift`.`belegnr` AS `belegnr`,`gutschrift`.`status` AS `status`,`gutschrift`.`land` AS `land`,'gutschrift' AS `typ`,(`gutschrift`.`umsatz_netto` * -(1)) AS `umsatz_netto`,(`gutschrift`.`soll` * -(1)) AS `umsatz_brutto`,(`gutschrift`.`erloes_netto` * -(1)) AS `erloes_netto`,(`gutschrift`.`deckungsbeitrag` * -(1)) AS `deckungsbeitrag`,(`gutschrift`.`provision_summe` * -(1)) AS `provision_summe`,`gutschrift`.`vertriebid` AS `vertriebid`,`gutschrift`.`gruppe` AS `gruppe`,`gutschrift`.`projekt` AS `projekt`,`gutschrift`.`waehrung` as `waehrung`
          from `gutschrift` $where
        ";
        
        if(is_null($tabellen) || in_array('auftrag', $tabellen))$ret[] = "
          select `auftrag`.`id` AS `id`,`auftrag`.`adresse` AS `adresse`,`auftrag`.`datum` AS `datum`,`auftrag`.`belegnr` AS `belegnr`,`auftrag`.`status` AS `status`,`auftrag`.`land` AS `land`,'auftrag' AS `typ`,`auftrag`.`umsatz_netto` AS `umsatz_netto`,`auftrag`.`gesamtsumme` AS `umsatz_brutto`,`auftrag`.`erloes_netto` AS `erloes_netto`,`auftrag`.`deckungsbeitrag` AS `deckungsbeitrag`,`auftrag`.`provision_summe` AS `provision_summe`,`auftrag`.`vertriebid` AS `vertriebid`,`auftrag`.`gruppe` AS `gruppe`, `auftrag`.`projekt` AS `projekt`,`auftrag`.`waehrung` as `waehrung`
          from `auftrag` $where
        ";
        if(is_null($tabellen) || in_array('bestellung', $tabellen))$ret[] = "
          union all select `bestellung`.`id` AS `id`,`bestellung`.`adresse` AS `adresse`,`bestellung`.`datum` AS `datum`,`bestellung`.`belegnr` AS `belegnr`,`bestellung`.`status` AS `status`,`bestellung`.`land` AS `land`,'bestellung' AS `typ`,`bestellung`.`gesamtsumme` AS `umsatz_netto`,`bestellung`.`gesamtsumme` AS `umsatz_brutto`,'0' AS `erloes_netto`,'0' AS `deckungsbeitrag`,'0' AS `provision_summe`,'0' AS `vertriebid`,'0' AS `gruppe`, `bestellung`.`projekt` AS `projekt`,`bestellung`.`waehrung` as `waehrung`
          from `bestellung` $where
        ";
        if(is_null($tabellen) || in_array('lieferschein', $tabellen))$ret[] = "
          union all select `lieferschein`.`id` AS `id`,`lieferschein`.`adresse` AS `adresse`,`lieferschein`.`datum` AS `datum`,`lieferschein`.`belegnr` AS `belegnr`,`lieferschein`.`status` AS `status`,`lieferschein`.`land` AS `land`,'lieferschein' AS `typ`,'0' AS `umsatz_netto`,'0' AS `umsatz_brutto`,'0' AS `erloes_netto`,'0' AS `deckungsbeitrag`,'0' AS `provision_summe`,'0' AS `vertriebid`,'0' AS `gruppe`, `lieferschein`.`projekt` AS `projekt`,'' as `waehrung`
          from `lieferschein` $where
        ";
        return ' ('.implode(' UNION ALL ', $ret).') ';
      }
      
      function SQLPosBrutto($belegtab, $postab, $arttab)
      {
        return " sum(
        (if($belegtab.ust_befreit = 0 OR ($belegtab.ust_befreit = 1 AND $belegtab.ustid <> '' AND $belegtab.ustid <> '0'),
          ( if(ifnull($postab.steuersatz,-1) <0,
              if($postab.umsatzsteuer = 'befreit',0,
                if($postab.umsatzsteuer = 'ermaessigt',$belegtab.steuersatz_ermaessigt,
                  if($postab.umsatzsteuer = 'normal',$belegtab.steuersatz_normal,
                    if($arttab.umsatzsteuer = 'befreit',0,
                      if($arttab.umsatzsteuer = 'ermaessigt',$belegtab.steuersatz_ermaessigt,
                        $belegtab.steuersatz_normal
                      )
                    )
                  )
                )
              )
            ,$postab.steuersatz)),0)/100+1
          )
           * 
          $postab.menge *($postab.preis * (1-$postab.rabatt/100)))
           ";
      }

      function RechnungMitUmsatzsteuer($rechnung)
      {
        $docRow = $this->app->DB->SelectRow(sprintf('SELECT ust_befreit,ustid FROM rechnung WHERE id=%d LIMIT 1', $rechnung));
        return $docRow['ust_befreit'] == 0
          || ($docRow['ust_befreit'] == 1 &&
            $docRow['ustid'] =='');
      }

      function RechnungMitUmsatzeuer($rechnung)
      {
        return $this->RechnungMitUmsatzsteuer($rechnung);
      }


      function ProformarechnungMitUmsatzeuer($rechnung)
      {
        $docRow = $this->app->DB->SelectRow(sprintf('SELECT ust_befreit,ustid FROM proformarechnung WHERE id=%d LIMIT 1', $rechnung));
        return $docRow['ust_befreit'] == 0
            || ($docRow['ust_befreit'] == 1 &&
            $docRow['ustid'] =='');

        // wenn lieferant DE dann mit 19% oder 7% einkaufen
        // wenn lieferant in der EU kann man mit 0% bezahlen

        // wenn lieferant in der welt sowieso keine steuer sondern zoll

        // wenn wir von privat EU kaufen dann muss mit steuer gekauft werden! (SPAETER KANN ES SEIN)
        return false;
      }


      function AngebotMitUmsatzeuer($angebot)
      {
        return $this->app->DB->Select("SELECT ust_befreit FROM angebot WHERE id='$angebot' LIMIT 1") == 0
            || ($this->app->DB->Select("SELECT ust_befreit FROM angebot WHERE id='$angebot' LIMIT 1") == 1 &&
              $this->app->DB->Select("SELECT ustid FROM angebot WHERE id='$angebot' LIMIT 1") =="");

        // wenn lieferant DE dann mit 19% oder 7% einkaufen
        // wenn lieferant in der EU kann man mit 0% bezahlen
        // wenn lieferant in der welt sowieso keine steuer sondern zoll

        // wenn wir von privat EU kaufen dann muss mit steuer gekauft werden! (SPAETER KANN ES SEIN)
      }


      function BestellungMitUmsatzeuer($bestellung)
      {
        return $this->app->DB->Select("SELECT ust_befreit FROM bestellung WHERE id='$bestellung' LIMIT 1") == 0;

        // wenn lieferant DE dann mit 19% oder 7% einkaufen
        // wenn lieferant in der EU kann man mit 0% bezahlen

        // wenn lieferant in der welt sowieso keine steuer sondern zoll

        // wenn wir von privat EU kaufen dann muss mit steuer gekauft werden! (SPAETER KANN ES SEIN)

      }


      function BesteuerungKunde($adresse)
      {
        if($this->AdresseUSTCheck($adresse)==0){
          return 'steuer';
        }

        return '';

        // steuer muss gezahlt werden! steuer, euexport, exporr

        // wenn kunde im export muss keine steuer bezahlt werden!

        // wenn kunde  gepruefte ust id hat && lieferung nach EU geht (aber das land verlaesst!)

      }



      function CheckLieferantEU($adresse)
      {
        // lieferant aus der EU
        $land = $this->app->DB->Select("SELECT land FROM adresse WHERE id='$adresse' AND geloescht=0 LIMIT 1");

      }


      function CheckKundeEU($adresse)
      {

      }

      function checkCell($datum, $stunde, $adr_id){
        // ueberprueft ob in der Stunde eine Aufgabe zu erledigen ist
        //echo $datum." ".$stunde."<br>";
        return  $this->app->DB->SelectArr("SELECT aufgabe,adresse,prio
            FROM aufgabe
            WHERE DATE(startdatum) = '$datum'
            AND HOUR(TIME(startzeit)) <= $stunde
            AND HOUR(TIME(startzeit)) + stunden >= $stunde
            AND (adresse = $adr_id OR adresse = 0)
            OR
            ((DATE_SUB('$datum', INTERVAL MOD(DATEDIFF('$datum',DATE_FORMAT(startdatum, '%Y:%m:%d')),intervall_tage) day)='$datum'
              AND DATE_SUB('$datum', INTERVAL MOD(DATEDIFF('$datum',DATE_FORMAT(startdatum, '%Y:%m:%d')),intervall_tage) day)
              > abgeschlossen_am
              AND intervall_tage>0 AND (adresse=$adr_id OR adresse=0))
             AND HOUR(TIME(startzeit)) <= $stunde AND HOUR(TIME(startzeit)) + stunden >= $stunde)
            OR ( DATE (abgabe_bis) = '$datum' AND  abgeschlossen=0 AND adresse = $adr_id AND HOUR(TIME(startzeit)) = $stunde)
            LIMIT 1"); // letztes OR von Bene!
      }

      function WebmailSetReadStatus($mailid,$boolean)
      {
        $this->app->DB->Update("UPDATE emailbackup_mails SET gelesen = ".($boolean?1:0)." WHERE id = $mailid");
      }

      function checkPDF($file,$maxSize=0,$x=0,$y=0)
      {

        return "";
      }
      function checkFile($file,$filetype,$maxSize=0)
      {
        if($file!='')
        {
          if(is_array($file)){
            $pfad = $file['tmp_name'];
          }
          else {
            $pfad = $file;
          }
        }

        $dbtype = mime_content_type($pfad);

        if($dbtype==='application/octet-stream' && $filetype==='application/pdf'){
          return '';
        }

        if($dbtype!=$filetype){
          return "Falscher Dateityp! Es wird $filetype erwartet aber $dbtype wurde &uuml;bergeben!";
        }

        return '';
      }



      public function checkImage($file,$maxSize=0,$x=0,$y=0,$typcheck=2)
      {
        // Prueft ein Bild auf Dateigroesse, Hoehe und Breite
        if($file!='')
        {
          if(is_array($file)){
            $pfad = $file['tmp_name'];
          }
          else {
            $pfad = $file;
          }
        }
        $typ = GetImageSize($pfad);
        $size = $file['size'];


        if($maxSize==0){
          $fileSizeLimit = 16777216; // 16MB in BYTE, 100MB stehen in der upload_max_size
        }
        else{
          $fileSizeLimit = $maxSize;
        }

        //if(0 < $typ[2] && $typ[2] < 4)
        if($typ[2]==$typcheck)
        {
          if($size<$fileSizeLimit)
          {
            if($typ[0]>$x && $x!=0){
              $error = 'Das Bild ist zu breit.';
            }
            if($typ[1]>$y && $y!=0){
              $error = 'Das Bild ist zu hoch.';
            }else{
              $error = '';
            }
          }else{
            $error = 'Die Datei darf eine Gr&ouml;&szlig;e von ' . ($fileSizeLimit / 8388608) . ' MB nicht &uuml;berschreiten.';
          }
        }else{
          $error = 'Die Datei muss vom korrekten Typ sein';
        }
        return $error;
      }
      
      public function uploadSettigsImage($file, $name)
      {
        if(empty($file) || empty($name) || empty($file['tmp_name']))
        {
          return false;
        }
        $pfad = $file['tmp_name'];
        $typ = @GetImageSize($pfad);

        // Bild hochladen
        if($filehandle = fopen($pfad,'r')){
          $filedata = fread($filehandle, @filesize($pfad));
          $dbtype = $typ['mime'];
          fclose($filehandle);
        }else{
          return false;
        }
        $pfad2 = $this->GetUSERDATA();
        if(!is_dir($pfad2))
        {
          if(!mkdir($pfad2) && !is_dir($pfad2))
          {
            return false;
          }
        }
        $pfad2 .= '/dms/';
        if(!is_dir($pfad2))
        {
          if(!mkdir($pfad2) && !is_dir($pfad2))
          {
            return false;
          }
        }
        $pfad2 .= $this->app->Conf->WFdbname;
        if(!is_dir($pfad2))
        {
          if(!mkdir($pfad2) && !is_dir($pfad2))
          {
            return false;
          }
        }
        if(file_put_contents($pfad2.'/'.$name, $filedata)){
          return array('image' => base64_encode($filedata), 'type' => $dbtype);
        }
        return false;
      }

      public function uploadImageIntoDB($file)
      {
        // Wandelt ein Bild fuer einen LONGBLOB um
        $pfad = $file['tmp_name'];
        $typ = @GetImageSize($pfad);

        // Bild hochladen
        $filehandle = fopen($pfad,'r');
        $filedata = base64_encode(fread($filehandle, @filesize($pfad)));
        $dbtype = $typ['mime'];
        fclose($filehandle);
        return array('image'=>$filedata,'type'=>$dbtype);
      }


      function GetEinkaufspreisWaehrung($id, $menge, $waehrung='', &$originalwaehrung=null, &$originalpreis=null, $adresse = '')
      {
        $artikelRow = $this->app->DB->SelectRow(
          sprintf(
            'SELECT adresse,verwendeberechneterek,berechneterekwaehrung,berechneterek,produktion, stueckliste FROM artikel WHERE id = %d LIMIT 1 ',
            (int)$id
          )
        );
        if($adresse == '') {
          $adresse = $artikelRow['adresse'];
        }
        if($waehrung == '') {
          $waehrung = 'EUR';
        }
        if($artikelRow['verwendeberechneterek'])
        {
          $originalwaehrung = (String)$artikelRow['berechneterekwaehrung'];
          if($originalwaehrung === '') {
            $originalwaehrung = 'EUR';
          }
          $originalpreis = $artikelRow['berechneterek'];
          if($originalwaehrung === $waehrung) {
            return $originalpreis;
          }
          $kurs = $this->GetWaehrungUmrechnungskurs($originalwaehrung,$waehrung);
          if($kurs==0) {
            $kurs=1;
          }
          return $originalpreis * $kurs;
        }
        
        
        // wenn produktionsartikel
        $produktion = $artikelRow['produktion'];
        $stueckliste = $artikelRow['stueckliste'];

        if($produktion) {
        }
        else if($stueckliste==1)// && $juststueckliste!=1)
        {
          $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC LIMIT 1");
          if(!$eka) {
            $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC LIMIT 1");
          }
          if(!$eka) {
            $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge LIMIT 1");
          }
          if($eka && $eka[0]['preis'] != 0)
          {
            if($eka[0]['waehrung'] == '') {
              $eka[0]['waehrung'] = 'EUR';
            }
            $originalwaehrung = $eka[0]['waehrung'];
            $originalpreis = $eka[0]['preis'];
            if($eka[0]['waehrung'] == $waehrung) {
              return $originalpreis;
            }
            return $originalpreis * $this->GetWaehrungUmrechnungskurs($originalwaehrung,$waehrung);
          }
          return $this->GetEinkaufspreisStuecklisteWaehrung($id, $waehrung);
        }

        $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC LIMIT 1");
        if(!$eka) {
          $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC LIMIT 1");
        }
        if(!$eka) {
          $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND (gueltig_bis>=NOW() OR ifnull(gueltig_bis,'0000-00-00')='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge LIMIT 1");
        }
        if(!$eka) {
          return 0;
        }
        if($eka[0]['waehrung'] == '') {
          $eka[0]['waehrung'] = 'EUR';
        }
        $originalwaehrung = $eka[0]['waehrung'];
        $originalpreis = $eka[0]['preis'];
        if($eka[0]['waehrung'] == $waehrung) {
          return $originalpreis;
        }
        return $originalpreis * $this->GetWaehrungUmrechnungskurs($originalwaehrung,$waehrung);
      }

      function GetEinkaufspreisArr($id, $menge, $adresse, $waehrung = "EUR", $auchpreisegrmenge = false)
      {
        $ek = $this->app->DB->SelectRow("SELECT * FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER by waehrung = '$waehrung' DESC, waehrung = '' DESC, ab_menge DESC LIMIT 1");
        if(!$ek && $auchpreisegrmenge)$ek = $this->app->DB->SelectRow("SELECT * FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER by waehrung = '$waehrung' DESC, waehrung = '' DESC, ab_menge ASC LIMIT 1");
        if(!$ek)return;

        if($ek['preis'] <=0)
        {
          $ek2 = $this->app->DB->SelectRow("SELECT * FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse'
              AND (gueltig_bis>=NOW() OR ifnull(gueltig_bis,'0000-00-00')='0000-00-00') AND geloescht=0 ORDER by waehrung = '$waehrung' DESC, waehrung = '' DESC,preis LIMIT 1");
          if($ek2)return $ek2;
        }
        return $ek;
      }

      function GetEinkaufspreis($id,$menge,$adresse="")
      {
        // wenn produktionsartikel
        $prodStueckliste = $this->app->DB->SelectRow("SELECT produktion, stueckliste FROM artikel WHERE id='$id' LIMIT 1");
        $produktion = $prodStueckliste['produktion'];
        $stueckliste = $prodStueckliste['stueckliste'];

        if($produktion && $stueckliste) {
        }
        else if($stueckliste==1)// && $juststueckliste!=1)
        {
          $ek = $this->GetEinkaufspreisStueckliste($id);
        }
        else {
          $ek = $this->app->DB->Select("SELECT preis FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR ifnull(gueltig_bis,'0000-00-00')='0000-00-00') AND geloescht=0 ORDER by ab_menge DESC LIMIT 1");
          if($ek <=0)
          {
            $ek = $this->app->DB->Select("SELECT preis FROM einkaufspreise WHERE artikel='$id' AND ab_menge<='$menge'
                AND (gueltig_bis>=NOW() OR ifnull(gueltig_bis,'0000-00-00')='0000-00-00') AND geloescht=0 ORDER by preis LIMIT 1");

            if($ek <=0)
            {
              $ek = $this->app->DB->Select("SELECT MIN(preis) FROM einkaufspreise WHERE artikel='$id'
                  AND (gueltig_bis>=NOW() OR ifnull(gueltig_bis,'0000-00-00')='0000-00-00') AND geloescht=0 ");
            }
          }
        }
        return $ek;
      }

      function Wechselkurs($von,$zu,$datum)
      {
        return 1.3;
      }


      function Rabatt($betrag,$rabatt)
      {
        $result = $betrag*(100-$rabatt)/100;
        return number_format($result, 4, '.', '');
      }

      function GetGruppen($adresse)
      {
        $tmp = $this->app->DB->SelectArr("SELECT * FROM adresse_rolle WHERE adresse='$adresse' AND (bis > NOW() OR ifnull(bis,'0000-00-00')='0000-00-00') AND parameter > 0 AND objekt='Gruppe'");
        if(empty($tmp)) {
          return null;
        }
        $result = [];
        foreach($tmp as $row) {
          $result[] = $row['parameter'];
        }

        return $result;
      }

      function MonatsListe($sprache = 'deutsch') {

        $monatsListe[1] = 'Januar';
        $monatsListe[2] = 'Februar';
        $monatsListe[3] = 'März';
        $monatsListe[4] = 'April';
        $monatsListe[5] = 'Mai';
        $monatsListe[6] = 'Juni';
        $monatsListe[7] = 'Juli';
        $monatsListe[8] = 'August';
        $monatsListe[9] = 'September';
        $monatsListe[10] = 'Oktober';
        $monatsListe[11] = 'November';
        $monatsListe[12] = 'Dezember';

        return $monatsListe;

      }

      function IsSpezialVerkaufspreis($artikel,$menge,$adresse=0,$waehrung='EUR')
      {
        $vkarr = null;
        $guenstigste_vk = $this->Firmendaten('guenstigste_vk');
        $gruppenarr = $this->GetGruppen($adresse);
        $sql_erweiterung = '';
        if(!empty($gruppenarr))
        {
          $sql_erweiterung .= ' OR v.gruppe IN ('.implode(', ', $gruppenarr).') ';
        }
        if(!$guenstigste_vk) {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <= '$menge' AND
              (v.gueltig_bis > NOW() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= curdate() OR v.gueltig_ab = '0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse')
              ORDER by ab_menge ASC, preis DESC LIMIT 1");         
        }
        if(empty($vkarr)) {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <= '$menge' AND
              (v.gueltig_bis > NOW() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= curdate() OR v.gueltig_ab = '0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' $sql_erweiterung)
              ORDER by ab_menge ASC, preis DESC LIMIT 1");
        }

        if(empty($vkarr)) {
          return false;
        }

        $letzte_menge = 0;//$vkarr[0][ab_menge];
        foreach($vkarr as $vkrow) {
          if($vkrow['adresse']==$adresse && $vkrow['adresse']>0 && $vkrow['art']==='Kunde') {
            return true;
          }
          if($vkrow['gruppe'] > 0 && $vkrow['art']==='Gruppe') {
            return true;
          }
        }

        return false;
      }

      var $preisliste;

      function GeneratePreisliste($artikel,$adresse,$rabatt=0, $waehrung = '')
      {
        $waehrungorig = $waehrung;
        $sqlwaehrung = "";
        if($waehrung <> '')
        {
          if($waehrung == 'EUR')
          {
            $sqlwaehrung = " AND (v.waehrung = '$waehrung' OR v.waehrung = '') ";
          }else{
            $sqlwaehrung = " AND v.waehrung = '$waehrung' ";
          }
        }
        $sqlwaehrung2 = $sqlwaehrung;
        if($waehrungorig == '')$sqlwaehrung2 = '';
        $vkarr = null;
        $guenstigste_vk = $this->Firmendaten('guenstigste_vk');

        $keinrabatterlaubt = $this->app->DB->Select("SELECT keinrabatterlaubt FROM artikel WHERE id='".$artikel."' LIMIT 1");

        $gruppenarray = $this->GetGruppen($adresse);
        if($gruppenarray)
        {
          if((!empty($gruppenarray)?count($gruppenarray):0)>0) $sql_erweiterung = " OR ";
          for($gi=0;$gi<(!empty($gruppenarray)?count($gruppenarray):0);$gi++) {
            $sql_erweiterung .= " gruppe='" . $gruppenarray[$gi] . "' ";

            if ($gi < (!empty($gruppenarray)?count($gruppenarray):0) - 1)
              $sql_erweiterung .= " OR ";

          }
        }

	if(is_null($rabatt)) {
		$rabatt = 0;
	}

        if(!$guenstigste_vk)
        {
          $vkarr = $this->app->DB->SelectArr("SELECT v.*,if((v.adresse > 0 OR v.gruppe > 0),v.preis,(v.preis*(100-$rabatt))/100.0) as rabattpreis FROM verkaufspreise v WHERE
              (v.gueltig_bis > NOW() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR v.gueltig_ab='0000-00-00') $sqlwaehrung2 AND v.artikel='".$artikel."' AND (v.adresse='$adresse' AND v.art='Kunde') ORDER by rabattpreis ASC");
          if(!$vkarr)
          {
            $vkarr = $this->app->DB->SelectArr("SELECT v.*,if((v.adresse > 0 OR v.gruppe > 0),v.preis,(v.preis*(100-$rabatt))/100.0) as rabattpreis FROM verkaufspreise v WHERE
              (v.gueltig_bis > NOW() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR v.gueltig_ab='0000-00-00') $sqlwaehrung2 AND v.artikel='".$artikel."' AND (v.adresse='$adresse' $sql_erweiterung ) ORDER by rabattpreis ASC");
          }
          
        }
        if(!$vkarr)
        {
        // reinsortieren
          $vkarr = $this->app->DB->SelectArr("SELECT v.*,if((v.adresse > 0 OR v.gruppe > 0),v.preis,(v.preis*(100-$rabatt))/100.0) as rabattpreis FROM verkaufspreise v WHERE
              (v.gueltig_bis > NOW() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR v.gueltig_ab='0000-00-00')  AND v.artikel='".$artikel."' $sqlwaehrung2 AND (v.adresse='$adresse' $sql_erweiterung OR
                ((v.adresse='' OR v.adresse='0') AND v.art='Kunde')) ORDER by rabattpreis ASC");
        }

        $letzter_preis = 0;

        // einmal rueckwaerts aufraeumen

        $cvkarr = !empty($vkarr)?count($vkarr):0;
        for($vi=0;$vi<$cvkarr;$vi++)
        {
          // rabatt rausrechnen
          if($keinrabatterlaubt!="1")
            $vkarr[$vi]['preis'] = $vkarr[$vi]['rabattpreis'];

          if($vkarr[$vi]['preis'] > $letzter_preis && (($vkarr[$vi]['ab_menge'] < $letzte_menge) || $vi==0))
          {
            // preis behalten
            $letzte_menge = $vkarr[$vi]['ab_menge'];
            $letzter_preis = $vkarr[$vi]['preis'];
          } else {
            // preis loeschen
            $vkarr[$vi]['ab_menge']=0;
            $vkarr[$vi]['preis']=0;
          }
        }

        for($vi=0;$vi<$cvkarr;$vi++)
        {
          if($vkarr[$vi]['ab_menge'] > 0)
            $vkarr2[] = $vkarr[$vi];
        }

	if (!is_null($vkarr2)) {
	        $vkarr = array_reverse($vkarr2);
	}
	else {
		$vkarr = $vkarr2;
	}

        // an schluss pruefen und unnötige rausschmeissen
        return $vkarr;
      }

      /**
       * @param int         $artikel
       * @param float       $menge
       * @param int         $gruppe
       * @param null|string $waehrung
       *
       * @return array|null
       */
      public function getVerkaufspreisGruppeArr($artikel, $menge, $gruppe, $waehrung = null)
      {
        $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= curdate() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND v.gruppe='$gruppe' AND v.art='Gruppe'
            ".($waehrung===null?'':" AND v.waehrung = '$waehrung' ")."
            ORDER by ab_menge DESC, preis ASC");
        if(!$vkarr && ($menge < 1)) {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <=1 AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= curdate() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND v.gruppe='$gruppe' AND v.art='Gruppe'
            ".($waehrung===null?'':" AND v.waehrung = '$waehrung' ")."
            ORDER by ab_menge DESC, preis ASC");
        }
        if(empty($vkarr)) {
          return null;
        }
        $letzte_menge = -1;  //$vkarr[0][ab_menge];
        $letzter_preis = 99999999999;

        foreach($vkarr as $vk)
        {
          if(($vk['ab_menge'] > $letzte_menge) && ($vk['preis']<$letzter_preis) && (($menge < 1?1:$menge) >= $vk['ab_menge']))
          {
            $letzte_menge = $vk['ab_menge'];
            $letzter_preis = $vk['preis'];
            $letztesarr = $vk;
          }
        }

        if(isset($letztesarr)) {
          return $letztesarr;
        }
        return null;
      }
  
      function GetVerkaufspreisGruppe($artikel, $menge, $gruppe = 0,$waehrung='EUR')
      {
        $vkarr = null;
        if($gruppe)
        {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= curdate() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND v.gruppe='$gruppe' AND v.art='Gruppe'
            ORDER by ab_menge DESC, preis ASC");
          if(!$vkarr && ($menge < 1))$vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <=1 AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= curdate() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND v.gruppe='$gruppe' AND v.art='Gruppe'
            ORDER by ab_menge DESC, preis ASC");
        }
        if(!$vkarr)
        {
          return $this->GetVerkaufspreis($artikel, $menge, 0, $waehrung);
        }

        $letzte_menge = -1;  //$vkarr[0][ab_menge];
        $letzter_preis = 99999999999;

        for($vi=0;$vi<(!empty($vkarr)?count($vkarr):0);$vi++)
        {
          if(($vkarr[$vi]['ab_menge'] > $letzte_menge) && ($vkarr[$vi]['preis']<$letzter_preis) && (($menge < 1?1:$menge) >= $vkarr[$vi]['ab_menge']))
          {
            $letzte_menge = $vkarr[$vi]['ab_menge'];
            $letzter_preis = $vkarr[$vi]['preis'];
            if($returnarr)$letztesarr = $vkarr[$vi];
          }
        }

        if($returnarr)
        {
          if(isset($letztesarr))return $letztesarr;
          return null;
        }
        
        if($letzter_preis==99999999999)
          $letzter_preis=0;

        return $letzter_preis;
      }

      function GetVerkaufspreisKunde($artikel,$menge,$adresse=0,$waehrung='EUR',$returnarr = false)
      {
        $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= curdate() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND v.adresse='$adresse' AND v.art='Kunde'
            ORDER by ab_menge DESC, preis ASC");
            
        if(!$vkarr && ($menge < 1))$vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <=1 AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= curdate() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND v.adresse='$adresse' AND v.art='Kunde'
            ORDER by ab_menge DESC, preis ASC");

        $letzte_menge = -1;  //$vkarr[0][ab_menge];
        $letzter_preis = 99999999999;

        for($vi=0;$vi<(!empty($vkarr)?count($vkarr):0);$vi++)
        {
          if(($vkarr[$vi]['ab_menge'] > $letzte_menge) && ($vkarr[$vi]['preis']<$letzter_preis) && (($menge < 1?1:$menge) >= $vkarr[$vi]['ab_menge']))
          {
            $letzte_menge = $vkarr[$vi]['ab_menge'];
            $letzter_preis = $vkarr[$vi]['preis'];
            if($returnarr)$letztesarr = $vkarr[$vi];
          }
        }

        if($returnarr)
        {
          if(isset($letztesarr))return $letztesarr;
          return null;
        }
        
        if($letzter_preis==99999999999)
          $letzter_preis=0;

        return $letzter_preis;
      }

      function GetVerkaufspreisWaehrung($artikel,$menge,$adresse=0)
      {
        $gruppenarr = $this->GetGruppen($adresse);
        $cgruppenarr = !empty($gruppenarr)?count($gruppenarr):0;
        for($i=0;$i<$cgruppenarr;$i++)
        {
          if($gruppenarr[$i]>0)
            $sql_erweiterung .= " OR gruppe='".$gruppenarr[$i]."' ";
        }

        $vkarr = null;
        $guenstigste_vk = $this->Firmendaten('guenstigste_vk');
        $gruppenarr = $this->GetGruppen($adresse);
        $cgruppenarr = !empty($gruppenarr)?count($gruppenarr):0;
        for($i=0;$i<$cgruppenarr;$i++)
        {
          if($gruppenarr[$i]>0)
            $sql_erweiterung .= " OR gruppe='".$gruppenarr[$i]."' ";
        }
        if(!$guenstigste_vk)
        {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
              (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' AND v.art='Kunde') ORDER by preis ASC, ab_menge DESC");
          
          if(!$vkarr && ($menge < 1))$vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <= 1 AND
              (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' AND v.art='Kunde') ORDER by preis ASC, ab_menge DESC");
              
          if(!$vkarr)
          {
            $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
                (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' $sql_erweiterung) ORDER by ab_menge DESC, preis ASC");
            if(!$vkarr && ($menge < 1))$this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <=1 AND
                (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' $sql_erweiterung) ORDER by ab_menge DESC, preis ASC");
          }
          
        }
        if(!$vkarr)
        {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' $sql_erweiterung  OR
              ((v.adresse='' OR v.adresse='0') AND v.art='Kunde')) ORDER by ab_menge DESC, preis ASC");
          if(!$vkarr && ($menge < 1))$vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <=1 AND
            (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' AND (v.adresse='$adresse' $sql_erweiterung  OR
              ((v.adresse='' OR v.adresse='0') AND v.art='Kunde')) ORDER by ab_menge DESC, preis ASC");
        }

        $letzte_menge = -1;  //$vkarr[0][ab_menge];
        $letzter_preis = 99999999999;
        $cvkarr = !empty($vkarr)?count($vkarr):0;
        for($vi=0;$vi<$cvkarr;$vi++)
        {
          if(($vkarr[$vi]['ab_menge'] > $letzte_menge) && ($vkarr[$vi]['preis']<$letzter_preis) && (($menge < 1?1:$menge) >= $vkarr[$vi]['ab_menge']))
          {
            $letzte_menge = $vkarr[$vi]['ab_menge'];
            $letzter_preis = $vkarr[$vi]['preis'];
            $waehrung = $vkarr[$vi]['waehrung'];
          }
        }

        return $waehrung;
      }

      
      function GetVerkaufspreisBrutto($artikel,$menge,$adresse=0,$waehrung='EUR', &$returnwaehrung = '')
      {
        $tmp = $this->app->DB->SelectArr("SELECT *,nummer as artikelnummer, name_de as artikel_name_de FROM artikel WHERE id='$artikel' LIMIT 1");
        $projekt = $tmp[0]['projekt'];
        if($tmp[0]['umsatzsteuer']=="ermaessigt")
          $steuer = ($this->GetStandardSteuersatzErmaessigt($projekt) + 100)/100.0;
        elseif($tmp[0]['umsatzsteuer']=="befreit")
          $steuer = 1;
        else              
          $steuer = ($this->GetStandardSteuersatzNormal($projekt) + 100)/100.0;
        return $this->GetVerkaufspreis($artikel,$menge,$adresse,$waehrung)*$steuer;
      }
  
      function GetSteuersatzBelegpos($doctype, $doctypeid, $pos)
      {
        $arr = $this->app->DB->SelectArr("SELECT steuersatz, umsatzsteuer, artikel FROM $doctype"."_position WHERE id = '$pos' LIMIT 1");
        if($arr)
        {
          if(!is_null($arr[0]['steuersatz']) && $arr[0]['steuersatz'] >= 0)return $arr[0]['steuersatz'];
          if($arr[0]['umsatzsteuer'] == 'befreit')return 0;
          if($arr[0]['umsatzsteuer'] == 'ermaessigt')return (float)$this->app->DB->Select("SELECT steuersatz_ermaessigt FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
          if($arr[0]['umsatzsteuer'] != '')return (float)$this->app->DB->Select("SELECT steuersatz_normal FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
          $umsatzsteuer = $this->app->DB->Select("SELECT umsatzsteuer FROM artikel WHERE id = '".$arr[0]['artikel']."' LIMIT 1");
          if($umsatzsteuer == 'befreit')return 0;
          if($umsatzsteuer == 'ermaessigt')return (float)$this->app->DB->Select("SELECT steuersatz_ermaessigt FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
          return (float)$this->app->DB->Select("SELECT steuersatz_normal FROM $doctype WHERE id = '$doctypeid' LIMIT 1");
        }
      }
  
      function GetVerkaufspreis($artikel,$menge,$adresse=0,$waehrung='', &$returnwaehrung = '',$returnarr = false, $auchpreisegrmenge = false)
      {
        $waehrungold = $waehrung;
        $firmendatenwaehrung = $this->app->erp->Firmendaten('waehrung');
        if($firmendatenwaehrung == '')$firmendatenwaehrung = 'EUR';
        if($waehrung == '')$waehrung = $firmendatenwaehrung;
        if($waehrung == $firmendatenwaehrung)
        {
          $extrasql = " AND (v.waehrung = '$waehrung' OR v.waehrung = '') ";
        }else{
          $extrasql = " AND v.waehrung = '$waehrung' ";
        }

        $extrasql2 = $extrasql;
        if($waehrungold == '')$extrasql2 = '';

        $vkarr = null;
        $guenstigste_vk = $this->Firmendaten('guenstigste_vk');
        $gruppenarr = $this->GetGruppen($adresse);
        $sql_erweiterung = '';
        if($gruppenarr) {
          for ($i = 0; $i < (!empty($gruppenarr)?count($gruppenarr):0); $i++) {
            if ($gruppenarr[$i] > 0)
              $sql_erweiterung .= " OR gruppe='" . $gruppenarr[$i] . "' ";
          }
        }
        if(!$guenstigste_vk)
        {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
              (v.gueltig_bis >= CURDATE() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR v.gueltig_ab='0000-00-00') AND v.artikel='".$artikel."' $extrasql2 AND (v.adresse='$adresse' AND v.art='Kunde') ORDER by ab_menge DESC, preis ASC");
              
          if(!$vkarr && ($menge < 1))$vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <= 1 AND
              (v.gueltig_bis >= CURDATE() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR v.gueltig_ab='0000-00-00') AND v.artikel='".$artikel."' $extrasql2 AND (v.adresse='$adresse' AND v.art='Kunde') ORDER by ab_menge DESC, preis ASC");
              
          if(!$vkarr)
          {
            $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
                (v.gueltig_bis >= CURDATE() OR v.gueltig_bis='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR v.gueltig_ab='0000-00-00') AND v.artikel='".$artikel."' $extrasql2 AND ((v.art <> 'Kunde' AND (0 $sql_erweiterung )) OR
              ((v.adresse='$adresse') AND v.art='Kunde')) ORDER by ab_menge DESC, preis ASC");
            if(!$varr && ($menge < 1))
            {
              $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <= 1 AND
                  (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' $extrasql2 AND ((v.art <> 'Kunde' AND (0 $sql_erweiterung )) OR
                ((v.adresse='$adresse') AND v.art='Kunde')) ORDER by ab_menge DESC, preis ASC");
            }
          }
        }
        if(!$vkarr)
        {
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <='$menge' AND
              (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' $extrasql  AND ((v.art <> 'Kunde' AND (0 $sql_erweiterung )) OR
              ((v.adresse='' OR v.adresse='0' OR v.adresse='$adresse') AND v.art='Kunde')) ORDER by preis ASC, ab_menge DESC");
          
          if(!$vkarr && ($menge < 1))
          {
            $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE v.ab_menge <=1 AND
                (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' $extrasql AND ((v.art <> 'Kunde' AND (0 $sql_erweiterung )) OR
                ((v.adresse='' OR v.adresse='0' OR v.adresse='$adresse') AND v.art='Kunde')) ORDER by preis ASC, ab_menge DESC");            
          }
        }
        
        if(!$vkarr && $auchpreisegrmenge){
          $vkarr = $this->app->DB->SelectArr("SELECT * FROM verkaufspreise v WHERE 
              (v.gueltig_bis >= CURDATE() OR ifnull(v.gueltig_bis,'0000-00-00')='0000-00-00') AND (v.gueltig_ab <= CURDATE() OR ifnull(v.gueltig_ab,'0000-00-00')='0000-00-00') AND v.artikel='".$artikel."' $extrasql AND ((v.art <> 'Kunde' AND (0 $sql_erweiterung )) OR
              ((v.adresse='' OR v.adresse='0' OR v.adresse='$adresse') AND v.art='Kunde')) ORDER by ab_menge ASC LIMIT 1");
        }else{
          $auchpreisegrmenge = false;
        }
        $letzte_menge = -1;  //$vkarr[0][ab_menge];
        $letzter_preis = 99999999999;
        if($vkarr)
        {
          for($vi=0;$vi<(!empty($vkarr)?count($vkarr):0);$vi++)
          {
            if(($vkarr[$vi]['ab_menge'] > $letzte_menge) && ($vkarr[$vi]['preis']<$letzter_preis) && ((($menge >= 1?$menge:1) >= $vkarr[$vi]['ab_menge'])|| $auchpreisegrmenge))
            {
              $letzte_menge = $vkarr[$vi]['ab_menge'];
              $letzter_preis = $vkarr[$vi]['preis'];
              $letzte_gruppe = $vkarr[$vi]['gruppe'];
              if($returnarr)$letztesarr = $vkarr[$vi];
              $returnwaehrung = $vkarr[$vi]['waehrung']?$vkarr[$vi]['waehrung']:'EUR';
            }
          }
        }

        if($letzter_preis==99999999999)
          $letzter_preis=0;
        if($returnarr)
        {
          if(isset($letztesarr))return $letztesarr;
          return null;
        }

        return $letzter_preis;
      }

      function GetEinkaufspreisStatistikWaehrung($id,$waehrung = '', $max=false, $lvl = 0)
      {
        if($lvl > 5)return 0;
        //Falls Einkaufspreis definiert

        $menge = 1;
        $eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND adresse='$adresse' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC, preis ".($max?'DESC':'ASC')." LIMIT 1");
        if(!$eka)$eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND ab_menge<='$menge' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC LIMIT 1");
        if(!$eka)$eka = $this->app->DB->SelectArr("SELECT preis, waehrung FROM einkaufspreise WHERE artikel='$id' AND (gueltig_bis>=NOW() OR gueltig_bis='0000-00-00') AND geloescht=0 ORDER BY waehrung = '$waehrung' DESC, waehrung = '', ab_menge DESC LIMIT 1");
        $originalwaehrung = $eka[0]['waehrung'];
        $originalpreis = $eka[0]['preis'];
        if($eka[0]['waehrung'] == $waehrung)return $originalpreis;
        $ep = $originalpreis * $this->GetWaehrungUmrechnungskurs($originalwaehrung,$waehrung);
        if($ep)return $ep;

        
        
        $sql = "SELECT FORMAT(
            SUM(
              
                (
                  SELECT e.preis * 
                  
                  if(e.waehrung != '',ifnull(
                    (SELECT kurs FROM waehrung_umrechnung WHERE waehrung_von = '$waehrung' AND waehrung_nach = e.waehrung AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),
                    ifnull((SELECT 1/kurs FROM waehrung_umrechnung WHERE waehrung_nach = '$waehrung' AND waehrung_von = e.waehrung AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),1)),
                    ifnull((SELECT kurs FROM waehrung_umrechnung WHERE waehrung_von = '$waehrung' AND waehrung_nach = 'EUR' AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),
                      ifnull((SELECT 1/kurs FROM waehrung_umrechnung WHERE waehrung_nach = '$waehrung' AND waehrung_von = 'EUR' AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),1))

                  ) 
                  FROM einkaufspreise e WHERE e.artikel=s.artikel AND (e.objekt='Standard' OR e.objekt='') ORDER BY waehrung = '$waehrung' DESC, waehrung = '' DESC, preis ".($min?'ASC':'DESC')." LIMIT 1
                
                )
              
              *s.menge)
            ,2)
              FROM stueckliste s
              LEFT JOIN artikel a ON a.id=s.artikel
              WHERE s.stuecklistevonartikel='$id'";
        
        $preis = $this->app->DB->Select($sql);
        //Kein Einkaufspreis definiert => Stückliste
        
        $sql = "SELECT s.artikel
              FROM stueckliste s
              LEFT JOIN artikel a ON a.id=s.artikel
              WHERE s.stuecklistevonartikel='$id' and a.stueckliste = '1'
        ";
        $startikel = $this->app->DB->SelectArr($sql);
        if($startikel)
        {
          foreach($startikel as $art)
          $preis += $this->GetEinkaufspreisStatistikWaehrung($art['artikel'],$waehrung,$max, $lvl + 1);
        }

        return $preis;

      }
      

      function GetEinkaufspreisStatistik($id,$max=false, $lvl = 0)
      {
        if($lvl > 5)return 0;
        //Falls Einkaufspreis definiert
        if($max)
        {
          $ep = $this->app->DB->Select("SELECT FORMAT(MAX(e.preis),2) FROM einkaufspreise e where e.artikel = $id AND (e.objekt='Standard' OR e.objekt='')");
          if($ep)return $ep;
        } else {
          $ep = $this->app->DB->Select("SELECT FORMAT(MIN(e.preis),2) FROM einkaufspreise e where e.artikel = $id AND (e.objekt='Standard' OR e.objekt='')");
          if($ep)return $ep;
        }
        //Kein Einkaufspreis definiert => Stückliste
        if($max) {
          $preis_max = 0;
          $ids = $this->app->DB->SelectArr("SELECT s.artikel from stueckliste s LEFT JOIN artikel a ON a.id=s.artikel WHERE s.stuecklistevonartikel='$id' and a.stueckliste != '1' ");
          if($ids)
          {
            foreach($ids as $v)$subwherea[] = $v['artikel'];
            $swhere = " (a.id = ". implode(' OR a.id = ',$subwherea).")";
            $sql = "

              SELECT format( SUM(if (ep>0,ep,vp)),2)
                from (SELECT MAX(e.preis) as ep, MAX(v.preis) vp FROM artikel a left join einkaufspreise e on a.id = e.artikel left join verkaufspreise v on a.id = v.artikel
              WHERE $swhere ) q

            ";
            $preis_max = $this->app->DB->Select($sql);
          }
          $sql = "SELECT s.artikel
                FROM stueckliste s
                LEFT JOIN artikel a ON a.id=s.artikel
                WHERE s.stuecklistevonartikel='$id' and a.stueckliste = '1'
          ";
          $startikel = $this->app->DB->SelectArr($sql);
          if($startikel)
          {
            foreach($startikel as $art)
            $preis_max += $this->GetEinkaufspreisStatistik($art['artikel'],$max, $lvl + 1);
          }
          return $preis_max;
        }
        $sql = "              SELECT format( SUM(if (ep>0,ep,vp)),2)
              from (SELECT MIN(e.preis) as ep, MIN(v.preis) vp FROM artikel a left join einkaufspreise e on a.id = e.artikel left join verkaufspreise v on a.id = v.artikel
            WHERE a.id in ( SELECT s.artikel from stueckliste s LEFT JOIN artikel a ON a.id=s.artikel WHERE s.stuecklistevonartikel='$id' and a.stueckliste != '1') ) q";
        $preis = $this->app->DB->Select($sql);
        $sql = "SELECT s.artikel
              FROM stueckliste s
              LEFT JOIN artikel a ON a.id=s.artikel
              WHERE s.stuecklistevonartikel='$id' and a.stueckliste = '1'
        ";
        $startikel = $this->app->DB->SelectArr($sql);
        if($startikel)
        {
          foreach($startikel as $art)
          $preis += $this->GetEinkaufspreisStatistik($art['artikel'],$max, $lvl + 1);
        }

        return $preis;
      }

      function GetEinkaufspreisStuecklisteWaehrung($id, $waehrung = '', $min = false)
      {
        if($waehrung == '')$waehrung = 'EUR';
        $sql = "SELECT 
            SUM(
              
                (
                  SELECT e.preis * 
                  
                  if(e.waehrung != '',ifnull(
                    (SELECT kurs FROM waehrung_umrechnung WHERE waehrung_von = '$waehrung' AND waehrung_nach = e.waehrung AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),
                    ifnull((SELECT 1/kurs FROM waehrung_umrechnung WHERE waehrung_nach = '$waehrung' AND waehrung_von = e.waehrung AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),1)),
                    ifnull((SELECT kurs FROM waehrung_umrechnung WHERE waehrung_von = '$waehrung' AND waehrung_nach = 'EUR' AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),
                      ifnull((SELECT 1/kurs FROM waehrung_umrechnung WHERE waehrung_nach = '$waehrung' AND waehrung_von = 'EUR' AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),1))

                  ) 
                  FROM einkaufspreise e WHERE e.artikel=s.artikel AND (e.objekt='Standard' OR e.objekt='') AND (e.gueltig_bis >= CURDATE() OR ifnull(e.gueltig_bis, '0000-00-00') = '0000-00-00') ORDER BY waehrung = '$waehrung' DESC, waehrung = '' DESC, preis ".($min?'ASC':'DESC')." LIMIT 1
                
                )
              
              *s.menge)
            
              FROM stueckliste s
              LEFT JOIN artikel a ON a.id=s.artikel
              WHERE s.stuecklistevonartikel='$id'";


        $preis_max = round((float)$this->app->DB->Select($sql),2);
        
        $sql = "SELECT 
            SUM(
              
                (
                  SELECT e.preis * 
                  
                  if(e.waehrung != '',ifnull(
                    (SELECT kurs FROM waehrung_umrechnung WHERE waehrung_von = '$waehrung' AND waehrung_nach = e.waehrung AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),
                    ifnull((SELECT 1/kurs FROM waehrung_umrechnung WHERE waehrung_nach = '$waehrung' AND waehrung_von = e.waehrung AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),1)),
                    ifnull((SELECT kurs FROM waehrung_umrechnung WHERE waehrung_von = '$waehrung' AND waehrung_nach = 'EUR' AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),
                      ifnull((SELECT 1/kurs FROM waehrung_umrechnung WHERE waehrung_nach = '$waehrung' AND waehrung_von = 'EUR' AND (gueltig_bis >= curdate() OR isnull(gueltig_bis) OR gueltig_bis = '0000-00-00' ) LIMIT 1),1))

                  ) 
                  FROM verkaufspreise e WHERE e.artikel=s.artikel AND (e.objekt='Standard' OR e.objekt='') AND (e.gueltig_bis >= CURDATE() OR ifnull(e.gueltig_bis, '0000-00-00') = '0000-00-00') ORDER BY waehrung = '$waehrung' DESC, waehrung = '' DESC, preis ".($min?'ASC':'DESC')." LIMIT 1
                
                )
              
              *s.menge)
            
              FROM stueckliste s
              LEFT JOIN artikel a ON a.id=s.artikel
              WHERE s.stuecklistevonartikel='$id' AND a.stueckliste = 1";
        
        return round($preis_max + (float)$this->app->DB->Select($sql),2);
        
      }
      
      function GetEinkaufspreisStueckliste($id,$max=false)
      {
        $sql = "SELECT SUM(
              (SELECT MAX(e.preis) FROM einkaufspreise e WHERE e.artikel=s.artikel AND (e.gueltig_bis>=NOW() OR e.gueltig_bis='0000-00-00') AND e.geloescht=0)*s.menge)
              FROM stueckliste s
              LEFT JOIN artikel a ON a.id=s.artikel
              WHERE s.stuecklistevonartikel='$id'";

        $preis_max = $this->app->DB->Select($sql);

        $sql = "SELECT SUM(
            (SELECT MAX(v.preis) FROM verkaufspreise v WHERE v.artikel=s.artikel AND a.stueckliste=1 AND (v.objekt='Standard' OR v.objekt=''))*s.menge)
            FROM stueckliste s
            LEFT JOIN artikel a ON a.id=s.artikel
            WHERE s.stuecklistevonartikel='$id'";

        $preis_max = $preis_max + $this->app->DB->Select($sql);

        $sql = "SELECT SUM(
            (SELECT MIN(e.preis) FROM einkaufspreise e WHERE e.artikel=s.artikel AND (e.gueltig_bis>=NOW() OR e.gueltig_bis='0000-00-00') AND e.geloescht=0)*s.menge)
            FROM stueckliste s
            LEFT JOIN artikel a ON a.id=s.artikel
            WHERE s.stuecklistevonartikel='$id'";

        $preis = $this->app->DB->Select($sql);
          $sql = "SELECT SUM(
            (SELECT MIN(v.preis) FROM verkaufspreise v WHERE v.artikel=s.artikel AND a.stueckliste=1 AND (v.objekt='Standard' OR v.objekt=''))*s.menge)
            FROM stueckliste s
            LEFT JOIN artikel a ON a.id=s.artikel
            WHERE s.stuecklistevonartikel='$id'";

        $preis = $preis + $this->app->DB->Select($sql);

        if($max) return $preis_max;
        else return $preis;
      }


  /**
   * @param string $name Filename
   * @param string $base64encoded if true return base64_encoded File
   * @return string Filecontent
   */
      public function getSettingsFile($name, $base64encoded = false)
      {
        if(empty($name))
        {
          return '';
        }
        $pfad = $this->GetUSERDATA().'/dms/'.$this->app->Conf->WFdbname.'/'.$name;
        if(!is_file($name))
        {
          $ret = $this->Firmendaten($name);
          if(empty($ret))
          {
            return '';
          }
          if($base64encoded)
          {
            return $ret;
          }
          return base64_decode($ret);
        }
        $ret = (String)file_get_contents($pfad);
        if(!$base64encoded)
        {
          return $ret;
        }
        return base64_encode($ret);
      }
  
  
  /**
   * @param array  $file File from Formr
   * @param string $name Filename
   * @return array|bool content and type or false if failed
   */
      public function uploadSettigsFile($file, $name)
      {
        if(empty($file) || empty($name) || empty($file['tmp_name']))
        {
          return false;
        }
        $pfad = $file['tmp_name'];

        $dbtype = mime_content_type($pfad);
        // Bild hochladen
        $filehandle = fopen($pfad,'r');
        if(!empty($filehandle)){
          $filedata = fread($filehandle, @filesize($pfad));
          fclose($filehandle);
        }else{
          return false;
        }
        $pfad2 = $this->GetUSERDATA();
        if(!is_dir($pfad2))
        {
          if(!mkdir($pfad2) && !is_dir($pfad2))
          {
            return false;
          }
        }
        $pfad2 .= '/dms/';
        if(!is_dir($pfad2))
        {
          if(!mkdir($pfad2) && !is_dir($pfad2))
          {
            return false;
          }
        }
        $pfad2 .= $this->app->Conf->WFdbname;
        if(!is_dir($pfad2))
        {
          if(!mkdir($pfad2) && !is_dir($pfad2))
          {
            return false;
          }
        }
        if(file_put_contents($pfad2.'/'.$name,$filedata))
        {
          return array('file'=>base64_encode($filedata),'type'=>$dbtype);
        }

        return false;
      }

      public function uploadFileIntoDB($file)
      {
        // Wandelt ein Bild fuer einen LONGBLOB um
        $pfad = $file['tmp_name'];

        $dbtype = mime_content_type($pfad);
        // Bild hochladen
        $filehandle = fopen($pfad,'r');
        $filedata = base64_encode(fread($filehandle, @filesize($pfad)));
        fclose($filehandle);
        return array('file'=>$filedata,'type'=>$dbtype);
      }

      // im format hh:mm
      public function ZeitinMenge($zeit)
      {
        $zeit = explode(':', $zeit);

        $komma = round(100/(60/$zeit[1]),0);

        $komma = str_pad($komma, 2 ,'0', STR_PAD_LEFT);

        return $zeit[0].','.$komma;
      }

      function get_time_difference($start_time_o, $end_time_o){
        $start_time = explode(':', $start_time_o);
        $end_time = explode(':', $end_time_o);

        $start_time_stamp = mktime($start_time[0], $start_time[1], 0, 0, 0, 0);
        $end_time_stamp = mktime($end_time[0], $end_time[1], 0, 0, 0, 0);

        $time_difference = $end_time_stamp - $start_time_stamp;

        return gmdate('H:i', $time_difference);
      }

      function is_html($str){
        $html = array('A','ABBR','ACRONYM','ADDRESS','APPLET','AREA','B','BASE','BASEFONT','BDO','BIG','BLOCKQUOTE','BODY','BR','BUTTON','CAPTION','CENTER','CITE','CODE','COL','COLGROUP','DD','DEL','DFN','DIR','DIV','DL','DT','EM','FIELDSET','FONT','FORM','FRAME','FRAMESET','H1','H2','H3','H4','H5','H6','HEAD','HR','HTML','I','IFRAME','IMG','INPUT','INS','ISINDEX','KBD','LABEL','LEGEND','LI','LINK','MAP','MENU','META','NOFRAMES','NOSCRIPT','OBJECT','OL','OPTGROUP','OPTION','P','PARAM','PRE','Q','S','SAMP','SCRIPT','SELECT','SMALL','SPAN','STRIKE','STRONG','STYLE','SUB','SUP','TABLE','TBODY','TD','TEXTAREA','TFOOT','TH','THEAD','TITLE','TR','TT','U','UL','VAR');
        return preg_match_all("~(<\/?)\b(".implode('|',$html).")\b([^>]*>)~i",$str,$c);
      }

      function ImportCreateLieferadresse($adresse,$data)
      {
        $this->app->DB->Insert("INSERT INTO lieferadressen (id,adresse) VALUES ('','$adresse')");
        $id = $this->app->DB->GetInsertID();

        if($data['land']=="") $data['land']='DE';

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE lieferadressen SET $key='".$this->app->DB->real_escape_string($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateAnsprechpartner($adresse,$data)
      {
        $this->app->DB->Insert("INSERT INTO ansprechpartner (id,adresse) VALUES ('','$adresse')");
        $id = $this->app->DB->GetInsertID();
        if (!empty($id)) {
          $this->app->erp->RunHook('contact_person_created', 1, $id);
        }
        if($data['land']=="") $data['land']='DE';

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE ansprechpartner SET $key='".$this->app->DB->real_escape_string($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateAdresse($data, $uf8 = true)
      {
        $this->app->DB->Insert("INSERT INTO adresse (id) VALUES ('')");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        $columns = $this->app->DB->GetColArray("adresse");
        foreach ($columns as $keyi => $columnname)
          $arr_columns[] = $columnname;


        foreach ($data as $key => $value) {
          if(in_array($key, $arr_columns))
          {
            if($tmp_fields!="") $tmp_fields .=",";
            if($uf8)
            {
              $tmp_fields .= " $key='".$this->ConvertForDBUTF8($value)."' ";
            } else {
              $tmp_fields .= " $key='".$value."' ";
            }
          }
        }
        $this->app->DB->Update("UPDATE adresse SET $tmp_fields WHERE id='$id'");
        return $id;
      }


      function ImportCreateArtikel($data, $utf8 = true)
      {
        $this->app->DB->Insert("INSERT INTO artikel (id) VALUES ('')");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          if($utf8)
          {
            $this->app->DB->Update("UPDATE artikel SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
          }else{
            $this->app->DB->Update("UPDATE artikel SET $key='".$this->app->DB->real_escape_string( $value)."' WHERE id='$id' LIMIT 1");
          }
        }
        return $id;
      }

      // nicht mehr verwenden
      function ImportCreateEinkaufspreis($data) {
        $this->app->DB->Insert("INSERT INTO einkaufspreise (id) VALUES ('')");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;


        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE einkaufspreise SET $key='".$this->ConvertForDBUFT8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      // nicht mehr verwenden
      function ImportCreateVerkaufspreis($data) {
        $this->app->DB->Insert("INSERT INTO verkaufspreise (id) VALUES ('')");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE verkaufspreise SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateUser($data) {
        $this->app->DB->Insert("INSERT INTO user (id) VALUES ('')");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE user SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }


      function ImportCreateBestellung($data) {
        $this->app->DB->Insert("INSERT INTO bestellung (id,angelegtam) VALUES ('',NOW())");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE bestellung SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }
      
      function ImportCreateRechnung($data) {
        $this->app->DB->Insert("INSERT INTO rechnung (id,angelegtam) VALUES ('',NOW())");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE rechnung SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateAngebot($data) {
        $this->app->DB->Insert("INSERT INTO angebot (id,angelegtam) VALUES ('',NOW())");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE angebot SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateAuftrag($data) {
        $this->app->DB->Insert("INSERT INTO auftrag (id,angelegtam) VALUES ('',NOW())");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE auftrag SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateLieferschein($data) {
        $this->app->DB->Insert("INSERT INTO lieferschein (id,angelegtam) VALUES ('',NOW())");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE lieferschein SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function ImportCreateGutschrift($data) {
        $this->app->DB->Insert("INSERT INTO gutschrift (id,angelegtam) VALUES ('',NOW())");
        $id = $this->app->DB->GetInsertID();

        if($data['firma']=="") $data['firma']=1;
        if($data['projekt']=="") $data['projekt']=1;

        foreach ($data as $key => $value) {
          $this->app->DB->Update("UPDATE gutschrift SET $key='".$this->ConvertForDBUTF8($value)."' WHERE id='$id' LIMIT 1");
        }
        return $id;
      }

      function CheckArtikel($id)
      {
        $standardlieferant = $this->app->DB->Select("SELECT adresse FROM artikel WHERE id='$id' LIMIT 1");
        $standardlieferant_ek = $this->app->DB->Select("SELECT adresse FROM einkaufspreise WHERE artikel='$id' AND geloescht!=1 AND standard=1 LIMIT 1");
        if($standardlieferant <= 0 || ($standardlieferant_ek!=$standardlieferant && $standardlieferant > 0 && $standardlieferant_ek > 0))
        {
          $standardlieferant = $this->app->DB->Select("SELECT adresse FROM einkaufspreise WHERE artikel='$id' AND geloescht!=1
              AND (gueltig_bis='0000-00-00' OR gueltig_bis >= NOW()) ORDER by standard DESC LIMIT 1");

          if($standardlieferant > 0)
          {
            $this->app->DB->Update("UPDATE artikel SET adresse='$standardlieferant' WHERE id='$id' LIMIT 1");
          }
        }
      }


      function FirmenDatenStandard()
      {

        if($this->app->DB->Select("SELECT COUNT(id) FROM firmendaten") > 0) return;
        $this->app->DB->Insert("INSERT INTO `firmendaten` (`id`,`firma`, `logo`, `briefpapier`, `signatur`, `datum`, `steuersatz_normal`, `steuersatz_zwischen`, `steuersatz_ermaessigt`, `steuersatz_starkermaessigt`, `steuersatz_dienstleistung`, `deviceserials`, `lizenz`, `schluessel`, `mlm_mindestbetrag`, `mlm_letzter_tag`, `mlm_erster_tag`, `mlm_letzte_berechnung`, `mlm_01`, `mlm_02`, `mlm_03`, `mlm_04`, `mlm_05`, `mlm_06`, `mlm_07`, `mlm_08`, `mlm_09`, `mlm_10`, `mlm_11`, `mlm_12`, `mlm_13`, `mlm_14`, `mlm_15`, `zahlung_rechnung_sofort_de`, `zahlung_rechnung_de`, `zahlung_vorkasse_de`, `zahlung_lastschrift_de`, `zahlung_nachnahme_de`, `zahlung_bar_de`, `zahlung_paypal_de`, `zahlung_amazon_de`, `zahlung_kreditkarte_de`, `zahlung_ratenzahlung_de`, `briefpapier2`, `freifeld1`, `freifeld2`, `freifeld3`, `freifeld4`, `freifeld5`, `freifeld6`, `firmenfarbehell`, `firmenfarbedunkel`, `firmenfarbeganzdunkel`, `navigationfarbe`, `navigationfarbeschrift`, `unternavigationfarbe`, `unternavigationfarbeschrift`, `firmenlogo`, `rechnung_header`, `lieferschein_header`, `angebot_header`, `auftrag_header`, `gutschrift_header`, `bestellung_header`, `arbeitsnachweis_header`, `provisionsgutschrift_header`, `rechnung_footer`, `lieferschein_footer`, `angebot_footer`, `auftrag_footer`, `gutschrift_footer`, `bestellung_footer`, `arbeitsnachweis_footer`, `provisionsgutschrift_footer`, `eu_lieferung_vermerk`, `export_lieferung_vermerk`, `zahlung_amazon_bestellung_de`, `zahlung_billsafe_de`, `zahlung_sofortueberweisung_de`, `zahlung_secupay_de`, `adressefreifeld1`, `adressefreifeld2`, `adressefreifeld3`, `adressefreifeld4`, `adressefreifeld5`, `adressefreifeld6`, `adressefreifeld7`, `adressefreifeld8`, `adressefreifeld9`, `adressefreifeld10`, `zahlung_eckarte_de`, `benutzername`, `passwort`, `host`, `port`,`mailssl`,`devicekey`,`mailanstellesmtp`,`layout_iconbar`,`name`,`firmenfarbe`,`betreffszeile`,`dokumententext`,`bcc1`,`bcc2`) VALUES
          (1, 1, '', '', 'LS0NCk11c3RlcmZpcm1hIEdtYkgNCk11c3RlcndlZyA1DQpELTEyMzQ1IE11c3RlcnN0YWR0DQoNClRlbCArNDkgMTIzIDEyIDM0IDU2IDcNCkZheCArNDkgMTIzIDEyIDM0IDU2IDc4DQoNCk5hbWUgZGVyIEdlc2VsbHNjaGFmdDogTXVzdGVyZmlybWEgR21iSA0KU2l0eiBkZXIgR2VzZWxsc2NoYWZ0OiBNdXN0ZXJzdGFkdA0KDQpIYW5kZWxzcmVnaXN0ZXI6IE11c3RlcnN0YWR0LCBIUkIgMTIzNDUNCkdlc2Now6RmdHNmw7xocnVuZzogTWF4IE11c3Rlcm1hbg0KVVN0LUlkTnIuOiBERTEyMzQ1Njc4OQ0KDQpBR0I6IGh0dHA6Ly93d3cubXVzdGVyZmlybWEuZGUvDQo=', '0000-00-00 00:00:00', 19.00, 7.00, 7.00, 7.00, 7.00, '', '', '', 50.00, NULL, NULL, NULL, 15.00, 20.00, 28.00, 32.00, 36.00, 40.00, 44.00, 44.00, 44.00, 44.00, 50.00, 54.00, 45.00, 48.00, 60.00, 'Rechnung zahlbar sofort.', 'Rechnung zahlbar innerhalb {ZAHLUNGSZIELTAGE} Tage bis zum {ZAHLUNGBISDATUM}.', '', '', '', '', '', '', '', '', NULL, '', '', '', '', '', '', '', '', '', '#e0e0e0', '#686868', '', '', NULL, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '','mustermann3','passwort','smtp.ihr_mail_server.de','25','1','','0','0','Musterfirma GmbH','#ececec','9','9','',''");
        $tmpid = $this->app->DB->GetInsertID();

        $obj = $this->app->erp->LoadModul('firmendaten');
        if($obj)$obj->FirmendatenBriefpapiervorlage();
      }

  function pruefeDBgen($echo = false)
  {
    $dir = dirname(__FILE__).'/../objectapi/mysql/_gen';
    if(file_exists($dir))
    {
      if ($handle = opendir($dir)) {
        while (false !== ($entry = readdir($handle)))
        {
          if(strpos($entry, 'object.gen.') !== false)
          {
            $table = str_replace('.php','',str_replace('object.gen.','',$entry));
            $Felder = $this->app->DB->SelectArr("Describe ".addslashes($table));
            if(true)
            {
              if(isset($class_methods))unset($class_methods);
              if($fh = fopen($dir.'/'.$entry, 'r'))
              {
                $classfound = false;
                $fertig = false;

                while(!$fertig && $line = fgets($fh))
                {

                  if($classfound)
                  {

                    if(strpos($line, '=') !== false)
                    {

                      $funktion = trim(substr($line, 0,strpos($line, '=')));
                      $class_methods[] = str_replace(';','',$funktion);
                    }
                    elseif(strpos($line, '$this->app->DB->Update') !== false)
                    {

                      $fertig = true;
                    }
                  } else {
                    if(strpos($line,'$sql = "UPDATE') !== false)
                    {

                      $classfound = true;
                    }
                  }



                }
                fclose($fh);

              }


              $class = 'ObjGen'.ucfirst($table);
            }
            if($Felder) {
              //if(!class_exists($class)) include_once($dir.'/'.$entry);

              //$tmp = ;
              //if(class_exists($class)){
              if($classfound && isset($class_methods))
              {
                //$class_methods = get_class_methods(new $class($this->app));
                //$class_methods = get_class_methods($class);
                //echo "Class: ".$class."\r\n";
                foreach($class_methods as $key => $val)
                {
                  if(strpos($val,'Get') !== false)
                  {
                    $found = false;
                    foreach($Felder as $k => $v)
                    {
                      if('get'.strtolower($v['Field']) == strtolower($val))$found = true;
                    }
                    if(!$found)$Feldnichtgefunden[$table][] = $val;
                      //echo "Feld ".substr($val,3)." nicht gefunden\r\n";

                  }

                }
                foreach($Felder as $k => $v)
                {
                  if($v['Field'] != 'id'){
                    $found = false;
                    foreach($class_methods as $key => $val)
                    {
                      if(strtolower($v['Field']) == strtolower($val))$found = true;
                    }
                    if(!$found)$keineFunktion[$table][] = $v['Field'];
                  }
                }
              }

            } else {
              if($classfound && isset($class_methods))
                $tablenotfound[] = $table;

            }

            $ret = false;
            if(isset($tablenotfound))$ret['tablenotfound'] = $tablenotfound;
            if(isset($Feldnichtgefunden))$ret['FeldernichtinDatenbank'] = $Feldnichtgefunden;
            if(isset($keineFunktion))$ret['FeldernichtinGen'] = $keineFunktion;
            if($echo)
            {
              if($ret){
                print_r($ret);
              }else{
                echo "Alles OK";
              }
            }
            @closedir($handle);
            return $ret;

          }



        }
        @closedir($handle);
        return false;
      }
      @closedir($handle);
    }
  }

  function pdfmirrorZuArchiv($id)
  {
    $checkmirror = $this->app->DB->SelectRow("SELECT p.* FROM pdfmirror_md5pool p WHERE id = '$id' LIMIT 1");
    if($checkmirror)
    {
      $filegroup = @filegroup($this->app->Conf->WFuserdata);
      $fileowner = @fileowner($this->app->Conf->WFuserdata);
      $dir = $this->app->Conf->WFuserdata."/pdfmirror/".$this->app->Conf->WFdbname."/".$checkmirror['table_name'];
      $dir_archiv = $this->app->Conf->WFuserdata."/pdfarchiv/".$this->app->Conf->WFdbname."/".$checkmirror['table_name'];
      if(!is_dir($dir))
      {
        return false;
      }

      $vars = glob($dir."/".($checkmirror['checksum']?$checkmirror['checksum'].'_':'').$checkmirror['table_id'].'_*.pdf');
      if(!$vars)
      {
        return false;
      }

      $path_parts = pathinfo($vars[0]);

      $datei = $path_parts['basename'];
      $dateia = explode('_', $path_parts['filename'],($checkmirror['checksum']?4:3));
      $belegnummer = $dateia[($checkmirror['checksum']?3:2)];
      if(strlen($belegnummer) < 3 && !is_numeric($belegnummer))
      {
        $belegnr = $this->app->DB->Select("SELECT belegnr FROM ".$this->app->DB->real_escape_string(strtolower($checkmirror['table_name']))." WHERE id = '".$checkmirror['table_id']."' LIMIT 1");
        if($belegnr)$belegnummer.=$belegnr;

      }

      $datum = $dateia[($checkmirror['checksum']?2:1)];
      if(strlen($datum) == 8)
      {
        $datum = $datum[6].$datum[7].'.'.$datum[4].$datum[5].'.'.$datum[0].$datum[1].$datum[2].$datum[3];
      }else{
        $datum = '';
      }
      $doctyporig = $belegnummer.($datum?' von '.$datum:'');

      if(!file_exists($dir."/".$checkmirror['checksum'].'_'.$checkmirror['table_id']))
      if(!is_dir($this->app->Conf->WFuserdata."/pdfarchiv"))
      {
        mkdir($this->app->Conf->WFuserdata."/pdfarchiv",0700);
        if($fileowner && $fileowner != fileowner($this->app->Conf->WFuserdata."/pdfarchiv"))chown($this->app->Conf->WFuserdata."/pdfarchiv", $fileowner);
        if($filegroup && $filegroup != filegroup($this->app->Conf->WFuserdata."/pdfarchiv"))chgrp($this->app->Conf->WFuserdata."/pdfarchiv", $filegroup);

      }
      if(!is_dir($dir_archiv))
      {
        if(!mkdir($dir_archiv, 0700))
        {
          //echo "Konnte ".$dir_archiv." nicht erstellen\r\n";
          return false;
        } else {
          if($fileowner && $fileowner != fileowner($dir_archiv))chown($dir_archiv, $fileowner);
          if($filegroup && $filegroup != filegroup($dir_archiv))chgrp($dir_archiv, $filegroup);
        }
      }
      $dir_archivnew = Briefpapier::getPDFfolder($dir_archiv,$checkmirror['table_id'], $datei,false,true);
      if($dir_archivnew === false)
      {
        $dir_archivnew = $dir_archiv."/".$datei;
      }
      //if(!copy($dir."/".$datei, $dir_archiv."/".$datei))
      if(!copy($dir."/".$datei, $dir_archivnew))
      {
        //echo "Kopieren von ".$dir."/".$datei." nach ".$dir_archiv."/".$datei." fehlgeschlagen\r\n";
        return false;
      } else {
        /*
        if($fileowner && $fileowner != fileowner($dir_archiv."/".$datei))chown($dir_archiv."/".$datei, $fileowner);
        if($filegroup && $filegroup != filegroup($dir_archiv."/".$datei))chgrp($dir_archiv."/".$datei, $filegroup);        */
      }

      $this->app->DB->Insert("INSERT INTO pdfarchiv (zeitstempel,checksum, table_id, table_name, bearbeiter, erstesoriginal, dateiname,doctypeorig, belegnummer)
      values ('".$checkmirror['zeitstempel']."','".$this->app->DB->real_escape_string($checkmirror['checksum'])."','".$this->app->DB->real_escape_string($checkmirror['table_id'])."','".$this->app->DB->real_escape_string($checkmirror['table_name'])."','".$this->app->DB->real_escape_string($checkmirror['bearbeiter'])."','".$checkmirror['erstesoriginal']."',

      '".$datei."','".$this->app->DB->real_escape_string($doctyporig)."','".$this->app->DB->real_escape_string($belegnummer)."')

      ");
      if($this->app->DB->error()){
        throw new Exception("SQL Error: ".$this->app->DB->error()." SQL: INSERT INTO pdfarchiv (zeitstempel,checksum, table_id, table_name, bearbeiter, erstesoriginal, dateiname,doctypeorig, belegnummer)
      values ('" . $checkmirror['zeitstempel'] . "','" . $this->app->DB->real_escape_string($checkmirror['checksum']) . "','" . $this->app->DB->real_escape_string($checkmirror['table_id']) . "','" . $this->app->DB->real_escape_string($checkmirror['table_name']) . "','" . $this->app->DB->real_escape_string($checkmirror['bearbeiter']) . "','" . $checkmirror['erstesoriginal'] . "',

      '" . $datei . "','" . $this->app->DB->real_escape_string($doctyporig) . "','" . $this->app->DB->real_escape_string($belegnummer) . "')

      ");
      }
      $newid = $this->app->DB->GetInsertID();
      if($newid)$this->app->DB->Update("UPDATE pdfmirror_md5pool set pdfarchiv_id = '$newid' WHERE id = '$id' LIMIT 1");
      return $newid;
    }
    return false;
  }
  function AnzeigeAbweichendeBezeichnung($typ)
  {
    switch($typ)
    {
      case "auftrag":
        $tmp = $this->app->erp->Beschriftung("bezeichnungauftragersatz");
      break;
      case "angebot":
        $tmp = $this->app->erp->Beschriftung("bezeichnungangebotersatz");
      break;
      case "rechnung":
        $tmp = $this->app->erp->Beschriftung("bezeichnungrechnungersatz");
      break;
      case "lieferschein":
        $tmp = $this->app->erp->Beschriftung("bezeichnunglieferscheinersatz");
      break;
      case "bestellung":
        $tmp = $this->app->erp->Beschriftung("bezeichnungbestellungersatz");
      break;


      case "proformarechnung":
        $tmp = $this->app->erp->Beschriftung("bezeichnungproformarechnungersatz");
      break;
 
    }
    if($tmp == "") $tmp = "Abweichende Bezeichnung";
    $this->app->Tpl->Set('ABWEICHENDEBEZEICHNUNGBESCHRIFTUNG',$tmp);
  }



  function AnzeigeFreifelderPositionen($form = null)
  {

    $module = $this->app->Secure->GetGET('module');

    switch($module) {
      case 'angebot': $kurz='an'; break;
      case 'auftrag': $kurz='ab'; break;
      case 'rechnung': $kurz='re'; break;
      case 'gutschrift': $kurz='gs'; break;
      case 'lieferschein': $kurz='ls'; break;
      case 'bestellung': $kurz='be'; break;
      case 'proformarechnung': $kurz='pr'; break;
      case 'preisanfrage': $kurz='pa'; break;
      case 'produktion': $kurz='pd'; break;
      default:
        $kurz = '';
        break;
    }

    for($i=1;$i<=40;$i++) {
      if($this->Firmendaten('freifeld'.$i.$kurz)!='1') {
        $this->app->Tpl->Set('FREIFELD'.$i.'START','<!--');
        $this->app->Tpl->Set('FREIFELD'.$i.'ENDE','-->');
      }
      elseif($this->Firmendaten('freifeld'.$i.'typ') === 'select') {
        $id = $this->app->Secure->GetGET('id');
        $options = explode('|',$this->Firmendaten('freifeld'.$i));
        unset($options[0]);
        if($form !== null) {
          $field = new HTMLSelect('freifeld'.$i,0,'freifeld'.$i,'','','0');

          foreach($options as $option) {
            $option = explode('=>', $option);
            $key = trim($option[0]);
            $value = !empty($option[1])?trim($option[1]):'';
            $field->AddOption($key, $value);
          }
          $form->NewField($field);
        }
      }elseif($this->Firmendaten('freifeld'.$i.'typ') === 'checkbox') {
        $fieldName = 'freifeld'.$i;
        $field = new HTMLCheckbox($fieldName, '','','1');
        $form->NewField($field);
        if(!empty($this->app->Secure->GetPOST('nummer')) && empty($this->app->Secure->GetPOST($fieldName))) {
          $form->HTMLList[$fieldName]->htmlvalue = '0';
        }
      }elseif($this->Firmendaten('freifeld'.$i.'typ') === 'mehrzeilig') {
        $field = new HTMLTextarea('freifeld'.$i, 5,75);
        $form->NewField($field);
      }
    }
  }

  function OpenstreetmapGetLangLat($apikey,$query)
  {
    $query = urlencode(html_entity_decode($query));
    $url = sprintf('https://api.openrouteservice.org/geocode/search?text=%s&api_key=%s', $query, $apikey);

    $timeout=0;
    while(1)
    {
      $timeout++;
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
      curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Charset: utf-8')
      );
      $result = curl_exec($ch);
      if(strpos($result,"404 page not")===false) break;
      if($timeout > 10) {
        $this->app->erp->LogFile("Openstreetmap GetLangLat Timeout: $url");
        break;
      }
    }
    $data = json_decode((string)$result);
    return $data->{'features'}[0]->{'geometry'}->{'coordinates'};
  }

  function OpenstreetmapGetDistance($apikey,$coord1,$coord2)
  {
    $url = "https://api.openrouteservice.org/directions?coordinates=".$coord1[0]."%2C".$coord1[1]."%7C".$coord2[0]."%2C".$coord2[1]."&profile=driving-car&preference=fastest&units=km&language=de&geometry=true&geometry_format=encodedpolyline&geometry_simplify=false&instructions=true&instructions_format=text&elevation=false&options=%7B%7D&api_key=$apikey";

    $timeout=0;
    while(1)
    {
      $timeout++;
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
      curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
      curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Content-Type: application/json',
        'Charset: utf-8')
      );
      $result = curl_exec($ch);
      if(strpos($result,"404 page not")===false) break;
      if($timeout > 10) {
        $this->app->erp->LogFile("Openstreetmap Distance Timeout: $url");
        break;
      }

    }
    $data = json_decode((string)$result);
    return $data->{'routes'}[0]->{'summary'}->{'distance'};
  }

  function GetFloat($str) {
    if(strstr($str, ',') !== false) {
      $str = str_replace(['.',','], ['','.'], $str); // replace dots (thousand seps) with blancs
    }
 
    if(preg_match("#([0-9\.]+)#", $str, $match)) { // search for number that may contain '.'
      return (float)$match[0];
    }
    return (float)$str; // take some last chances with floatval
  } 



  function CheckboxEntwurfsmodus($doctype,$id)
  { 
    $datumentwurf = $this->app->DB->Select("SELECT datum FROM $doctype WHERE id='$id' LIMIT 1");
    $datumentwurf = str_replace('-','',$datumentwurf);
    if($datumentwurf == date('Ymd')) {
      return '';
    }
    $anzeigedatum = $this->app->DB->Select("SELECT DATE_FORMAT(datum,'%d.%m.%Y') FROM $doctype WHERE id='$id' LIMIT 1");

    $check = $this->app->User->GetParameter($doctype."_create_entwurfsdatumuebernehmen");
    $extra = "<input type=\"checkbox\" value=\"1\" ".($check=="1"?"checked":"")." name=\"".$doctype."_create_entwurfsdatumuebernehmen\" id=\"".$doctype."_create_entwurfsdatumuebernehmen\">&nbsp;Entwurfsdatum vom <strong>$anzeigedatum</strong> übernehmen";
    $this->app->YUI->AutoSaveUserParameter($doctype."_create_entwurfsdatumuebernehmen",$doctype."_create_entwurfsdatumuebernehmen");

    return $extra;
  }

  function ZeiterfassungAllowEdit($datum_db)
  {
    if(!$this->app->erp->Firmendaten('zeiterfassung_schliessen')) {
      return true;
    }

    if($this->app->erp->RechteVorhanden('zeiterfassung', 'bearbeitenerlauben')) {
      return true;
    }

    if($datum_db != '--' && $datum_db != '0000-00-00' && $datum_db != '') {
      if(strtotime(date('Y-m-d')) - strtotime($datum_db) > 86400*(int)$this->app->erp->Firmendaten('zeiterfassung_schliessentage')) {
        return false;
      }
    }

    return true;
  }
  
  function GetBundeslaender($land = '', $bundesland = '')
  {
    if($land == '') {
      $land = $this->app->erp->Firmendaten('land');
    }
    $arr = $this->app->DB->SelectArr("SELECT * FROM bundesstaaten WHERE land = '".$this->app->DB->real_escape_string($land)."' AND iso <> '' ORDER BY land, bundesstaat");
    if(empty($arr)) {
      return null;
    }
    $ret = null;
    foreach($arr as $v)
    {
      if($land == $v['iso'] || $land == '')
      {
        if($v['aktiv'] || $v['iso'] == $bundesland)
        {
          $ret[$v['iso']] = $v['bundesland'];
        }
      }
    }
    return $ret;
  } 


  function GetPlacetelSipuid()
  {
    $username = $this->app->User->GetUsername();
    $accounts = $this->GetKonfiguration("placetel_list_accounts");

    $tmp = explode(PHP_EOL,trim($accounts));
    $sipuid = false;

    if($this->RechteVorhanden('placetel','call'))
    {
      foreach($tmp as $row) {
        $subtmp = explode(':',trim($row));

        if((!empty($subtmp)?count($subtmp):0)>0)
        {
          $subtmp[0] = trim($subtmp[0]);
          $subtmp[1] = trim($subtmp[1]);

          if($subtmp[0]==$username)
          {
            $sipuid = $subtmp[1];
            break;
          }
        }
      }
    }
    return $sipuid;
  }
} // END erpAPI


function parse_csv($str,$parse_split_parameter="")
{
  global $parse_split;
  if($parse_split_parameter!="") $parse_split=$parse_split_parameter;
  //match all the non-quoted text and one series of quoted text (or the end of the string)
  //each group of matches will be parsed with the callback, with $matches[1] containing all the non-quoted text,
  //and $matches[3] containing everything inside the quotes
  $str = preg_replace_callback('/([^"]*)("((""|[^"])*)"|$)/s', 'parse_csv_quotes', $str);

        //remove the very last newline to prevent a 0-field array for the last line
        $str = preg_replace('/\n$/', '', $str);

        //split on LF and parse each line with a callback
        return array_map('parse_csv_line', explode("\n", $str));
        }

        //replace all the csv-special characters inside double quotes with markers using an escape sequence
        function parse_csv_quotes($matches)
        {
        global $parse_split;
        if($parse_split=='') {
          $parse_split=';';
        }
        //anything inside the quotes that might be used to split the string into lines and fields later,
        //needs to be quoted. The only character we can guarantee as safe to use, because it will never appear in the unquoted text, is a CR
        //So we're going to use CR as a marker to make escape sequences for CR, LF, Quotes, and Commas.
        $str = str_replace(["\r","\n",'""',$parse_split], ["\rR","\rN","\rQ","\rC"], !empty($matches[3])?$matches[3]:'');

        //The unquoted text is where commas and newlines are allowed, and where the splits will happen
        //We're going to remove all CRs from the unquoted text, by normalizing all line endings to just LF
        //This ensures us that the only place CR is used, is as the escape sequences for quoted text
        return preg_replace('/\r\n?/', "\n", !empty($matches[1])?$matches[1]:'') . $str;
        }

//split on comma and parse each field with a callback
function parse_csv_line($line)
{
  global $parse_split;
  if($parse_split=="") $parse_split=";";
  return array_map('parse_csv_field', explode($parse_split, $line));
}

//restore any csv-special characters that are part of the data
function parse_csv_field($field) {
  global $parse_split;
  if($parse_split=="") $parse_split=";";
  $field = str_replace("\rC", $parse_split, $field);
  $field = str_replace("\rQ", '"', $field);
  $field = str_replace("\rN", "\n", $field);
  $field = str_replace("\rR", "\r", $field);
  return $field;
}


function code2utf($num)
{
  if ($num < 128) return chr($num);
  if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num &
        63) + 128);
  if ($num < 65536) return chr(($num >> 12) + 224) .
    chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128);
  if ($num < 2097152) return chr(($num >> 18) + 240) .
    chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num
          & 63) + 128);
  return '';
}